Walkthrough of an Ethereum Improvement Proposal (EIP)

CodeTract
3 min readFeb 27, 2017

Ethereum, being an open source project, tracks and discusses new ideas for the protocol through the Ethereum Improvement Proposal (EIP) system at Github. Here we take a look at EIP#155 Simple replay attack protection. Before EIP#155, there are 6 inputs to an Ethereum transaction. Namely,

nonce
gasPrice
gasLimit
to
value
data

From our previous article regarding transactions, we have received quite a number of questions regarding what is the transaction object and exactly what values are hashed. To answer that, the values of the 6 inputs can be stored in an array in order without their names. Recursive Length Prefix (RLP) encoding is then applied to obtain a portable representation of the transaction. Keccak-256 is then used to hash it. Here are some more explanation and implementation of RLP. In this article we will also directly use the RLP and hash functions instead of convenient functions to better illustrate this point.

One can easily observe that the transaction is not chain specific, meaning if you are on a private Ethereum network, someone could take your transaction on that network and broadcast it to the public network and it will be valid. Thus if you use the same addresses in different networks, it could lead to unintended sending of transactions. A simple fix was used in the Morden public testnet by having all transactions start with a huge nonce instead of 0. EIP#155 aims to fix this issue in a more general way by including a chainId in the transaction where the main public network have a chainId of 1 and the new Ropsten public testnet have it as 3. Therefore you should use other numbers for your own network. However old transactions are still valid for backward compatibility.

Here we will go through the example given in the EIP. We are using nodejs so we first create a file tx.js and require the dependencies.

var Web3 = require('web3');
var web3 = new Web3();
var util = require('ethereumjs-util');

The example given is

var transaction = [
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
'',
web3.toHex(1),
0x0,
0x0
];

contrast this with an old transaction

var transactionOld = [
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
''
];

Next we will RPL, hash it and print the results

var encoded = util.rlp.encode(transaction);
console.log(util.bufferToHex(encoded));
//0xec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080
var encodedHash = util.sha3(encoded);
console.log(util.bufferToHex(encodedHash));
//0xdaf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53

Next we sign and add to the v value of the signature as per the EIP

var p = new Buffer('4646464646464646464646464646464646464646464646464646464646464646', 'hex');
var sig = util.ecsign(encodedHash, p);
sig.v += 1 * 2 + 8;
console.log(util.bufferToHex(sig.v));
console.log(util.bufferToHex(sig.r));
console.log(util.bufferToHex(sig.s));
//0x25
//0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276
//0x67cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83

Thus the signed transaction becomes

var signedTransaction = util.rlp.encode([
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
'',
sig.v,
sig.r,
sig.s
]);
console.log(util.bufferToHex(signedTransaction));
//0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83

So we have gone through the modifications of this EIP. As mentioned earlier, transactions created by old libraries are still valid, so how many such transactions are still created on the live net? There is a simple way to find out since transactions created by old libraries have a sig.v value of 0x1b and 0x1c while transactions created by new libraries have the values of 0x25 and 0x26. Create a new file find.js and run the following code to see this.

var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/'));
console.log(web3.eth.getTransaction('0x4b420c328f11bbf4cc0043af7bd8b170026e97ef4261e93354bf080c2d04ea6d').v);
//0x26
console.log(web3.eth.getTransaction('0x79fbfd4daa09f7947595f6c1e3d8e78b4032cf64d105292b10f61ebb067d2bcf').v);
//0x1b

Using this methodology, we searched through every transaction from block 3,153,001 to 3,159,000, which is 6,000 blocks or about 1 day’s worth of blocks. The results are

blocks: 6,000
transactions: 53,114
0x1b, 0x1c: 6,856 (12.9%)
0x25, 0x26: 46,258 (87.1%)

There is still a significant number of old transactions, so please update your client/library to prevent your transactions from being replayed.

Now we have gotten to know a little bit more about EIP#155!

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!

Get to know a little bit of what we are doing by reading our whitepaper!

--

--

CodeTract

https://codetract.io/ CodeTract is a startup focused on building smart contracts enforced by blockchains