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 installing the dependencies.

$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3

Then creating a file tx.js and requiring the dependencies.

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
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

0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27

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);
//0x53ae893e4b22d707943299a8d0c844df0e3d5557

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);
transaction.sign(p);

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

console.log(util.bufferToHex(transaction.hash(true)));
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662

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

console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff

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

console.log(web3.sha3('transfer(address,uint256)'));
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b

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

0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e

and the unsigned integer is

0x000000000000000000000000000000000000000000000000d02ab486cedbffff

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

console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
//0x950041c1599529a9f64cf2be59ffb86072f00111

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');
console.log(contractTx.from);
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
console.log(contractTx.nonce);
//0

Thus the contract address is

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

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 https://www.ethereum.org/
Mist, one of Ethereum’s client https://github.com/ethereum/mist/releases
Solidity http://solidity.readthedocs.io/en/latest/
Web3 api https://github.com/ethereum/wiki/wiki/JavaScript-API
Community discussions https://www.reddit.com/r/ethereum/

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!

Show your support

Clapping shows how much you appreciated CodeTract’s story.