I'm trying to understand Ethereum transaction signing, but for some reason I'm unable to verify the signature.
I have a test account, 0xb2c899884790aa9e256a2d4b2256ca3319e64e32
, its public key is
e7ab22c376286ccb0616888217bc41ec31eafb090fb77900a3946e39eb5c7fa374c8d5fe191f8001d287e678567bc8058eb49729780d2ac9090ffccbc506a754
I take the following valid transaction:
{
"blockHash": "0x3deebc8e1fe36af7f1268ff077cc086c0653fe6fd67aa200608a7379390365f0",
"blockNumber": "0x613",
"from": "0xb2c899884790aa9e256a2d4b2256ca3319e64e32",
"gas": "0x493e0",
"gasPrice": "0x0",
"hash": "0x6831112de9dc553de7bb111591cabe0c79b5af8c6395c1bc5411ca2fda539735",
"input": "0x760a8c2a",
"nonce": "0x5",
"to": "0x78c215f61ed07929e0084233a3e86bc011bea132",
"transactionIndex": "0x0",
"value": "0x0",
"v": "0x14c3",
"r": "0xbddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25b",
"s": "0x1959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec"
}
Or in raw form: f8660580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a8214c3a0bddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25ba01959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec
According to EIP 155, I need to hash all 9 values, replacing v=chainId (2640)
, r=0
and s=0
. So I come up with the following "signing data":
e60580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a820a508080
It's "signing hash" is:
749a36ed5f7c67b1f5eb83a46b0dd6447e9ac050a3f469354fcc4691781a385c
Which, when fed through ecrecover
, gives the following public key:
f1308d673d1cf8014370fffb43f36d5e866e405b2b5cecb3025bfb98ae47b18e21fa07c66b31423414c38611038c4c35387db8510757f65b7a632a2d48b0276e
Which obviously does not match the actual public key.
What am I doing wrong?
My test code:
var ethutil = require('ethereumjs-util');
var raw = Buffer.from('f8660580830493e09478c215f61ed07929e0084233a3e86bc011bea1328084760a8c2a8214c3a0bddab1b3292ac1102c470d738640bbf91a56a9bbc99a6fc88250800b2b21e25ba01959b4b59d0c8552766294459912862a2ca8a62e0b64eab98a4b5be75e910cec','hex');
var data = ethutil.rlp.decode(raw);
var v = ethutil.bufferToInt(data[6]);
var r = data[7];
var s = data[8];
var chainId = Math.floor((v - 35) / 2);
data[6] = ethutil.intToBuffer(chainId);
data[7] = Buffer.from('');
data[8] = Buffer.from('');
var msg = ethutil.rlp.encode(data);
console.log(msg.toString('hex'));
var msgHash = ethutil.sha3(msg);
console.log(msgHash.toString('hex'));
var publicKey = ethutil.ecrecover(msgHash, (v & 1) + 27, r, s);
console.log(publicKey.toString('hex'));