Registers API
Registers allow the host function to return the data into a buffer located inside the host oppose to the buffer located on the client. A special operation can be used to copy the content of the buffer into the host. Memory pointers can then be used to point either to the memory on the guest or the memory on the host, see below. Benefits:
- We can have functions that return values that are not necessarily used, e.g. inserting key-value into a trie can also return the preempted old value, which might not be necessarily used. Previously, if we returned something we would have to pass the blob from host into the guest, even if it is not used;
- We can pass blobs of data between host functions without going through the guest, e.g. we can remove the value from the storage and insert it into under a different key;
- It makes API cleaner, because we don't need to pass
buffer_len
andbuffer_ptr
as arguments to other functions; - It allows merging certain functions together, see
storage_iter_next
; - This is consistent with other APIs that were created for high performance, e.g. allegedly Ewasm have implemented SNARK-like computations in Wasm by exposing a bignum library through stack-like interface to the guest. The guest can manipulate then with the stack of 256-bit numbers that is located on the host.
Host → host blob passing
The registers can be used to pass the blobs between host functions. For any function that
takes a pair of arguments *_len: u64, *_ptr: u64
this pair is pointing to a region of memory either on the guest or
the host:
- If
*_len != u64::MAX
it points to the memory on the guest; - If
*_len == u64::MAX
it points to the memory under the register*_ptr
on the host.
For example:
storage_write(u64::MAX, 0, u64::MAX, 1, 2)
-- insert key-value into storage, where key is read from register 0,
value is read from register 1, and result is saved to register 2.
Note, if some function takes register_id
then it means this function can copy some data into this register. If
register_id == u64::MAX
then the copying does not happen. This allows some micro-optimizations in the future.
Note, we allow multiple registers on the host, identified with u64
number. The guest does not have to use them in
order and can for instance save some blob in register 5000
and another value in register 1
.
Specification
read_register(register_id: u64, ptr: u64)
Writes the entire content from the register register_id
into the memory of the guest starting with ptr
.
Panics
- If the content extends outside the memory allocated to the guest. In Wasmer, it returns
MemoryAccessViolation
error message; - If
register_id
is pointing to unused register returnsInvalidRegisterId
error message.
Undefined Behavior
- If the content of register extends outside the preallocated memory on the host side, or the pointer points to a wrong location this function will overwrite memory that it is not supposed to overwrite causing an undefined behavior.
register_len(register_id: u64) -> u64
Returns the size of the blob stored in the given register.
Normal operation
- If register is used, then returns the size, which can potentially be zero;
- If register is not used, returns
u64::MAX