Inside an Ethereum transaction

Ethereum can be thought of as a transaction based state machine, where transactions can change the state and the state keeps track of interactions. Here we examine at a high level, the constituents of a transaction and explain how most of the gibberish hex values are determined.

We will be using nodejs in this tutorial so we start off by creating a file tx.js and requiring the dependencies.

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider(''));
var util = require('ethereumjs-util');
var tx = require('ethereumjs-tx');

First we start with a private key. Ethereum uses public key cryptography for authentication. More specifically, Elliptic Curve Digital Signature Algorithm (ECDSA) with secp256k1’s curve is used. The private key is just a random 256 bit data except for some restrictions. For example

var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';

To derive the corresponding public key

var publicKey = util.bufferToHex(util.privateToPublic(privateKey));

and you should get the following if you print out publicKey


The Ethereum address associated with this private key is the last 160 bit of the SHA3–256 (Keccak) hash of the public key.

var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);

As you can observe, it is actually possible for multiple private keys to have the same address. An Ethereum account is associated with each address and each have the following attributes

nonce the count of the number of outgoing transactions, starting with 0
balance the amount of ether in the account
storageRoot the hash associated with the storage of the account
codeHash the hash of the code governing the account, if this is empty then the account is a normal account that can be accessed with its private key else it is a smart contract whose interactions are governed by its code

Next we take a look at a transaction, there are 6 input fields

nonce the count of the number of outgoing transactions, starting with 0 
gasPrice the price to determine the amount of ether the transaction will cost
gasLimit the maximum gas that is allowed to be spent to process the transaction
to the account the transaction is sent to, if empty, the transaction will create a contract
value the amount of ether to send
data could be an arbitrary message or function call to a contract or code to create a contract

A transaction to send 1000 wei (1 ether = 10¹⁸ wei) of ether and leaving a 0xc0de message can be constructed as follows

var rawTx = {
nonce: web3.toHex(0),
gasPrice: web3.toHex(20000000000),
gasLimit: web3.toHex(100000),
to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
value: web3.toHex(1000),
data: '0xc0de'

Notice that the from address is not specified, it will be derived from the signature after signing with the private key. To sign the transaction

var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');
var transaction = new tx(rawTx);

The transaction can then be sent to the network and will be tracked by a 256 bit transaction id. This transaction can be viewed at Etherscan. The transaction id is the hash of the transaction


Next we look at what makes up the data for a function call. Take for example the data of this transaction to a contract


In order to know which function it is calling, the functions of the contract must be known beforehand to create a hash table. The first 32 bit a9059cbb is the first 32 bit of the hash of the function. In this case the function is transfer(address _to, uint256 _value) and its hash is


This is followed by 256 bit for each argument, so in this case the address is


and the unsigned integer is


Next, as discussed above, by omitting the to field, a contract will be created. But how is the contract’s address determined? Take for example this transaction


The contract address is the last 160 bit hash of the sender address and its nonce can be determined beforehand. For this transaction, the sender and nonce can be found by

var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');

Thus the contract address is

console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));

Now we have gotten to know a little bit more about these hexadecimals!

Ethereum and smart contracts have huge potential to disrupt many industries. There are many resources online and you can find a few below to continue your journey on exploring Ethereum!

Ethereum main site
Mist, one of Ethereum’s client
Web3 api
Community discussions

If you have any issues regarding this article, you can raise it at our Github under the nightlyHacks repo.

Follow us on Twitter and Medium for more updates!