1

I am trying to decode the v, r, s from a signature and add that to a transaction and broadcast at some point. When I convert the signature into v,r,s and build the raw tx the from: parameter does not match with the signed address.

What am i doing wrong?

const txData = {
    nonce: web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(100000),
    gasPrice: web3.utils.toHex(50 * 1e9), // 5 gwei
    to: destinationAddres,
    value: web3.utils.toHex("0.01", "ether")

}

const transaction = new ethereumjs.Tx(txData, { chain: "mainnet" });

const serializedTx = transaction.serialize().toString("hex");
console.log('SERIALIZED TX: ' + serializedTx);

const signature = await web3.eth.sign(web3.utils.sha3(serializedTx), '0xCd91D6bCA426C655f2b484D1347ebc2cA4e8ac80')

console.log('SIGNATURE: ' + signature);

r = signature.slice(0, 66)
s = '0x' + signature.slice(66, 130)
v = '0x' + signature.slice(130, 132)
v = web3.utils.toDecimal(v)

// var v = '28';
console.log('R: ' + r);
console.log('S: ' + s);
console.log('V: ' + v);

const signedTxData = {
    nonce: web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(100000),
    gasPrice: web3.utils.toHex(50 * 1e9), // 5 gwei
    to: destinationAddres,
    value: web3.utils.toHex("0.01", "ether"),
    chainId: 1,
    r: r,
    s: s,
    v: v
}


console.log('tx signed: ', signedTxData);
const serializedTxRSV = new ethereumjs.Tx(signedTxData).serialize().toString('hex');
console.log('FINAL RAW TX: ' + serializedTxRSV)

When I decode the final raw TX:

  "nonce": 0,
  "gasPrice": 50000000000,
  "gasLimit": 100000,
  "to": "0xcd91d6bca426c655f2b484d1347ebc2ca4e8ac80",
  "value": 33048495391913270,
  "data": "",
  "from": "0x9e8f46060d8eb68d028854c7eee98bce9ff28e9c",
  "r": "a9627386922cb359c523cb34789f7954dff278a54e2e5ab550f75ca17b75226b",
  "v": "1b",
  "s": "36e937e919973b338cfe2dc962bd8c12a7ee627a5bc9f16260b078ab97f7c1ff"
}

As you can see the from: does not match with the signer address

2
  • hi misterBulle i wonder if you were able to solve this Commented Nov 4, 2022 at 14:40
  • if it's like Bitcoin, there is one byte that tells the length of r and s. It should be like this: v is the first byte, length r is second byte, then r, then length s (also 1 byte), then s.
    – T. Rossi
    Commented Aug 24, 2023 at 22:10

1 Answer 1

0

I think that is because you are signing with sha3 but ethereum uses keccak256. use this

 web3.utils.soliditySha3(serializedTx)

or follow the @ethereumjs/tx example

import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { Transaction } from '@ethereumjs/tx'

const txParams = {
  nonce: '0x00',
  gasPrice: '0x09184e72a000',
  gasLimit: '0x2710',
  to: '0x0000000000000000000000000000000000000000',
  value: '0x00',
  data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057',
}

const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Istanbul })
const tx = Transaction.fromTxData(txParams, { common })

const privateKey = Buffer.from(
  'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109',
  'hex'
)

const signedTx = tx.sign(privateKey)

const serializedTx = signedTx.serialize()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.