How to run contracts and create traces with Node.js
Aug 12, 2014
A valid state transition is one which comes about through a transaction. Formally:
σt+1 ≡ Υ(σt , T )
where Υ is the Ethereum state transition function. In ☰thereum, Υ, together with σ are considerably more powerful then any existing comparable system; Υ allows components to carry out arbitrary computation, while σ allows components to store arbitrary state between transactions. - The Yellow Paper
At the core of Etheruem is the state transition function. Within the this function lies the ☰thereum ∇irtual Machine which upon ☰∇M code runs. In this post we will be running transactions thourgh the VM and looking at the results. A note on Terminology: the VM as descibed in the yellow paper is a subset of the state transition function. With an executioner that manipulates accounts and sets up the enviorment for the VM. Here we will just refer to the state transition function as the VM although this may not be techicanally correct. I did not like having an executioner in my code. It’s a bit too barbaric for my taste. Altogether the VM in this sense handles all changes done to the state, which wholly resided in a trie.
This post will explore creating transactions and processing them with the VM. You can find all the code for this post here;
To get stated we will be using two libraries. async and ethereum-lib npm install async npm install ethereum-lib
First import the necessary libraries and initailize some varibles.
Lets set up the state trie. We need to give the sender’s account enougth wei to send the transaction and run the code.
Next we will create a transaction and process it. If you want to know more about generating transaction see this post In this example we will forgo generating a transaction from scratch and just use the some json I generated earlier. Transaction have a toJSON method if you want to do the same. This transaction contains the initializtion code for the name register.
Since running a transaction in the VM is asynchronous lets wrap this in a function which we will use later. Running this transaction should create a new name register contract. It is important to note that vm.runTx() would also need a Block a the second parameter if the EVM code where to use any opcodes that accessed the block propeties.
vm.runTx 1) checks if the sending account has enough wei to run then 2) runs the code and lastly 3) saves the changed accounts in the trie. It uses a callback to returns the results of running the transaction. We are only going to log some of the results here but if you are curious george you can look at the docs
Now lets actully run this!
So you should see how much gas the transaction used and the addrres of the created contract c8b97e77d29c5ccb5e9298519c707da5fb83c442. But not too exciting yet. Lets make sure that things worked. The VM should have created a new account for the contract in the trie. Lets make sure.
Add this to async.series like so
And run. We should see the details of the new created contract. Next thing we can do is send a message to our newly created contract. Lets create another transaction to do so. This transaction should register the sending address as “null_radix”. The data field here is the RLP of pad_32_bytes(‘register’) and pad_32_bytes(‘null_radix’)
So if everything went right we should have “null_radix” stored at “0x9bdf9e2cc4dfa83de3c35da792cdf9b9e9fcfabd”. To see this we need to print out the name register’s storage trie.
After running you should see the contents of the contract’s storage.
Debugging with traces
Lastly lets create a trace of the EMV code. This can be very usefully for debugging (and deherbing, don’t smoke and code m’kay?) contracts.
The VM provides a simple hook for each step the VM takes while running EVM code.
Now when you run you should see a complete trace. onStep provides an object that contians all the information on the current state of the VM.
the vm also provides a runBlock function that will process a block as well as a few other usefull functions.
And now I’m out of stuff to say.