The WVM uses a resource called gas. In general, the role of gas in VM - to provide a calculation of the cost of resources spent to perform a smart contract (its functions).
Through the principle of mutation, each symbiote individually assigns itself KLY-WVM capabilities and a special table with opcodes prices. You can even make smart contracts run for free, build your own tree of who is allowed to run which smart contract for free, and so on.
Measuring table
Earlier we showed you a simple function in the add.wat file and there you could see that WebAssembly uses bytecodes. For the symbiote, it will be possible to configure the virtual machine in such a way as to independently adjust how much gas each opcode will consume.
How KLYNTAR measure the gas to execute smart contracts
The execution of smart contracts should be controlled - after all, we do not need our processor to burn out and the node to stop. It is necessary to take into account the fact that inside the bytecode an attacker will try to hide an infinite loop or otherwise affect the normal flow of work in some other way.
In addition, it is necessary to control how many resources will be spent during the operation of the node. After all, running a function that simply returns the sum of a + b obviously requires less than a loop with 10,000 iterations.
In KLY-WVM, we will use the project from EWASM to measure the performance of smart contracts. Here is their GitHub
We need the wasm-metering repository which provides a function that needs to be injected into the bytecode to measure its execution
At the output, we will get a bytecode similar in functionality, but now the execution of operations is controlled and the calculation of the resources expended is underway. Let's do a little research
Deep dive
For this, an example is provided in the README of the project:
constfs=require('fs');constmetering=require('wasm-metering');constwasm=fs.readFileSync('fac.wasm');constmeteredWasm=metering.meterWASM(wasm, { meterType:'i32', fieldStr:'burnGas'});constgasLimit=90000000;let gasBurned =0;constmod=WebAssembly.Module(meteredWasm.module);constinstance=WebAssembly.Instance(mod, {'metering': {'burnGas': gasAmount => { gasBurned += gasAmount;if (gasBurned > gasLimit) thrownewError('No more gas for contract!'); } }});constresult=instance.exports.fac(6);console.log(`Result:${result}, gas used ${gasUsed *1e-4}`); // Result:720, gas used 0.4177
This defines the global variable gasBurned and the gas limit. As you can see from these lines, the module takes the bare bytecode and returns the modified bytecode where it injects a function reference from the outside (in this case, the burnGas function from the imported metering object).
If the limit is exceeded, the work stops and we catch exceptions. Although the EWASM documentation describes the principle of operation, we will still not only hear, but also see how it works.
By the way, here is a detailed and good description on GitHub
Check the modified WASM module
After changes are made to our module, let's write this set of bytes to a .wasm file, and then decompile to .wat from where we can look at the insides The original AssemblyScript module. Let's choose something more complex, for example a loop
Thus, everywhere in the code where this function will be called, we will understand that there is an gas count. So you can see that the function is called when entering the main testAdding function, at the beginning of the loop, when returning from the function, and so on.
With the help of these tools you can play and test the mechanics of work yourself
Stay tuned to this page so you don't miss anything important