Overview of the EOSIO WebAssembly Virtual Machine

Some projects are working on Python and even Solidity based programs.

These are all compiled down into platform independent code that can be run on the EOSIO WASM Virtual Machine (WAVM).

So the WAVM does not need to know anything at all about the high level programming language (C++, Python, Solidity etc).

All it knows how to do is to execute its own binary instruction set called WebAssembly.

What is WebAssemblyThe project to develop a new portable, size efficient binary format for the web was driven by the major browser vendors (Mozilla, Google, Apple and Microsoft).

Apart from portability, WebAssembly’s other design goals were for it to be:Fast: Able to execute at near native speedSafe: code executes in a sandboxed environment and eliminating dangerous featuresHardware independent: Implementable by web browsers and other completely different execution environments such as datacenters, IoT devices, mobile/desktops etcNot break the web (allow calls/bindings to JavaScript)A human-editable text format that is convertible to/from the binary formatThese goals, as well as the large browser ecosystem working to continuously improve it, make WASM a great choice for smart contract execution platforms.

Apart from EOSIO, WASM is also planned to be used by Ethereum.

The EOSIO WAVMEOSIO’s WASM Virtual Machine (WAVM) is based on Andrew Scheidecker’s standalone WAVM.

Stack MachineThe WAVM is a stack machine with two main components:a last-in, first-out stack is used to hold temporary values.

Most of the WAVM instructions therefore assume that operands will be taken from the stack and results placed back on the stack.

A program counter that controls the execution of the program and is modified explicitly by control instructions and implicitly advanced when non-control instructions execute.

This is in contrast to most modern computers that implement a register machine where temporary values are held in a set of registers.

Advantages of using a stack machine over a register machine are that stack machines allow for:Compact object code: as instructions deal with values from the stack and do not need to select which registers to useSimple compilers: as no register management is needed making code generation fairly trivialSimple interpreters: particularly for Virtual Machines interpreters for stack machines are simpler as the logic for handling memory accesses is just in one placeEasier control flow: control flow is expressed as structured constructs like blocks, if and loops that have clear labels at their beginning and end.

The WAVM has Implementing control flow like this makes it very easy to compile and manipulate WASM and verify the correctness of control flow in a WASM program.

A simple execution exampleWe can now go review a simple example to illustrate the whole flow from source code to WASM to execution of that code in the WAVM.

As prerequisites we assume that you have:Installed the EOSIO Contract Development Toolkit (CDT)Have access to the Web Assembly Binary Toolkit (WABT pronounced wabbit).

You can do this by running the eosio-wasm2wast/eosio-wast2wasm binaries that come with CDT.

Alternatively you can also download and build the generic WABT version from https://github.

com/WebAssembly/wabt.

(A cursory examination seems to indicate that this versions are compatible if you disable “Generate Names” and “Fold Expressions”)Compiling HelloFor this example we’ll be compiling the basic Hello World program:Running the eosio C++ compiler eosio-cpp:eosio-cpp -o hello.

wasm hello.

cppThis takes the C++ source file and converts it into an intermediate representation (IR) using a compiler tool chain called LLVM.

LLVM performs some optimisations and then a back-end converts from the LLVM IR into WASM.

We get a WASM file, hello.

wasm which is in binary.

To make it readable we need to convert it into a WASM text format as follows:eosio-wasm2wast hello.

wasm -o hello.

wastThis WAST file is typically huge (approximately 900 lines) so we will only concentrate on the first 50 or so lines here to illustrate some important concepts.

WASM sectionsThe WebAssembly module is composed of several sections.

Some sections are required in all WASM modules and some are optional (you may see the optional modules appearing at the end of the WAST file).

Required:Type.

Contains the function signatures for functions defined in this module and any imported functions.

Function.

Gives an index to each function defined in this module.

Code.

The actual function bodies for each function in this module.

Optional:Export.

Makes functions, memories, tables, and globals available to other WebAssembly modules and JavaScript.

This allows separately-compiled modules to be dynamically linked together.

This is WebAssembly’s version of a .

dll.

Import.

Specifies functions, memories, tables, and globals to import from other WebAssembly modules or JavaScript.

Start.

A function that will automatically run when the WebAssembly module is loaded (basically like a main function).

Global.

Declares global variables for the module.

Memory.

Defines the memory this module will use.

Table.

Makes it possible to map to values outside of the WebAssembly module, such as JavaScript objects.

This is especially useful for allowing indirect function calls.

Data.

Initializes imported or local memory.

Element.

Initializes an imported or local table.

Section examplesFor our Hello.

wast file the section part looks like so:Here we see that there are 10 function signatures and indices for the functions in this WASM fileThese signatures are similar to function prototypes and define the expected inputs and outputs for each type of function.

There are also some imported functions such asWe can also see our print statement being initialised in memory:The beginning of the code section contains the actual function bodies for each function in this module.

Looking back at the function definitions we see that there is one function exported which has an index of function 11:This is the apply function that is called when an action is issued to this smart contract:Deploy your smart contract!The last thing to do after compiling your smart contract is to send it to the blockchain by issuing a set code transaction using the cleos command line tool.

cleos set contract hello $YOURDIRECTORY/hello -p hello@activeWhen the block producer (BP) node receives the set code action it proceeds to create an instance of the smart contract WebAssembly module in the EOSIO blockchain’s RAM.

Instantiating the WebAssembly module is what makes it functional and the BP node does so by resolving memory references, linking external C++ functions and giving access to the exported functions like the apply() function.

Once the BP node completes this step the smart contract WebAssembly module will be on the chain’s RAM and any BP node can then access actions intended for the smart contract.

Trigger an action!Now that the smart contract is on chain, you can trigger it by sending an action to the smart contract using cleos:cleos push action hello hi '["bob"]' -p bob@activeThe message will be sent to the BP node which will load the smart contract WebAssembly instance and call the apply() function.

If you are curious, here’s how the WebAssembly virtual machine would execute the first few instructions in the function:get_global 0: gets the value of the global variable at index 0 and pushes it onto the stacki32.

const 16: Pushes the constant value sixteen onto the stacki32.

sub: remember we said WebAssembly was a stack machine earlier?.With a stack machine all values an operand needs are pushed onto the stack before the operation is performed.

The sub instruction knows that it needs two operands and will simply take the last two values from the top of the stack and return the result to the top of the stack.

This means that instructions can be short (one byte for sub) as the instructions don’t need to specify source or destination addresses which makes for more compact WASM files.

Finally after the whole WebAssembly module has been executed, you should then see the smart contract reply:Hello, bobClosing thoughtsWebAssembly allows smart contract developers to write EOSIO applications in C++ (and in future other languages such as Solidity and Python) and ensures that the resulting code can run efficiently across different BP nodes.

It is perfectly possible for a smart contract developer to deply a distributed application (dApp) without knowledge of WebAssembly or how the WAVM works.

However understanding how it works may help you to tackle difficult problems from time to time and deal better with security vulnerabilities in your smart contract.

Originally published at klevoya.

com on March 21, 2019.

.. More details

Leave a Reply