I'm trying to generate a signature for a raw transaction using an ECDSA library implemented in C.
Here are the transaction parameters:
const txParams = {
"nonce": "0x05",
"gasPrice": "0x0ba43b7400",
"gasLimit": "0x5208",
"to": "0x9fbad6ab4b240d7512f863753ad3449f9ad6a530",
"value": "0x0de0b6b3a7640000",
"data": "0x",
"chainId": 4
}
Then I'm generating the RLP encoded Keccak256 hash of the transaction parameters. Below is the RLP hash:
ad7de070ee104a433e37298f70feb6af08da26287efff6af2b25bbf64a56b70b
All of the steps upto here are done using the ethereumjs-tx library.
In the C program I convert the RLP Hash to byte format and store in a byte array.
static uint8_t m_hash[] =
{
0xad,0x7d,0xe0,0x70,0xee,0x10,0x4a,0x43,
0x3e,0x37,0x29,0x8f,0x70,0xfe,0xb6,0xaf,
0x08,0xda,0x26,0x28,0x7e,0xff,0xf6,0xaf,
0x2b,0x25,0xbb,0xf6,0x4a,0x56,0xb7,0x0b
};
This is then signed using the private key.
The output signature is always different each time I run the program, and below are a few samples.
29C1C06C3E60D5BD51F9F803AEE5193ACABFFD6B45FAC48C7DDE737427FB7F2C643B35FABB633E6A6B6ABC52F7907D245457ECAE5F2372D3D6A85BC2B68A4DF0
64FE2A3AF423642EFC989BAD1503CEA2637FC5543963E64F95A0644942D96EF5663267511DB6A8853E666F1877ACEAC86470DF8A710D844177E66DE4A158F0EA
B3C2DA2C5800FE4773BECF5A0690041483AB6C551A8DE6CCB84FD07EDD09857B3B2AAFA0BA268A4B7178B260C8A79BC86EFF60A55D60EFD11247632A9AB11382
I then use the sign function of ethereumjs-util to parse this signature and encode it into v, r, s values.
To calculate v, I've tried out different values of the recovery id in the range 0 - 3 which I directly enter in the sign function of ethereumjs-util, which looks like this.
exports.ecsign = function (msgHash, privateKey) {
// -------------------------------------------------
// Original Implementation
// var sig = secp256k1.sign(msgHash, privateKey);
// --------------------------------------------------
// --------------------------------------------------
// My changes
var sig = {
signature: "",
recovery: 0
}
var signature = "29C1C06C3E60D5BD51F9F803AEE5193ACABFFD6B45FAC48C7DDE737427FB7F2C643B35FABB633E6A6B6ABC52F7907D245457ECAE5F2372D3D6A85BC2B68A4DF0"
sig.signature = Buffer.from(signature, 'hex');
// --------------------------------------------------
var ret = {};
ret.r = sig.signature.slice(0, 32);
ret.s = sig.signature.slice(32, 64);
ret.v = sig.recovery + 27;
return ret;
};
This returns the signed transaction which I then serialize and try to broadcast to the ethereum blockchain
0xf86c05850ba43b7400825208949fbad6ab4b240d7512f863753ad3449f9ad6a530880de0b6b3a7640000802ca029c1c06c3e60d5bd51f9f803aee5193acabffd6b45fac48c7dde737427fb7f2ca0643b35fabb633e6a6b6abc52f7907d245457ecae5f2372d3d6a85bc2b68a4df0
At this point I get an error, stating "Invalid sender".
Can someone help me with what I'm doing wrong here?