5

I have IoT devices holding keys and generating/signing raw transactions on device and then sending them to a web service. Instead of passing in potentially conflicting parameters with the transaction, I would like to parse the raw transaction and determine what address was used to sign it. Geth seems to know who the transaction is from even if it doesn't have the private key in the keystore.

For example, I have this transaction already in my instance of geth:

eth.getRawTransaction(...):
0xf9010806808407fffd2894e80ab11db5543603cd620a7185fff71c98f54d3b80b8a4b93fa138000000000000000000000000000000009f6f0c2d68a7489c4ec7916fd2c51d88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020dd11395091aa1bd2f8cc16768b286d992faf78a24ec9fa904bc44167e7680bbb8218aea08dfeee407aecbbeb816e3bb3a3957baa78c135b7d9ce66094554184bc80245a6a07a1f9dd58e96a80f5fcca28b819922467e23dab86a3159893b7ae2d09c7ef799

eth.getTransaction(...):
{
  blockHash: "0xff28078ab54bb247ffe6006fe845c5fbc24dc4d7bb64006850480c3440952383",
  blockNumber: 854,
  from: "0x53ae893e4b22d707943299a8d0c844df0e3d5557",
  gas: 134217000,
  gasPrice: 0,
  hash: "0xd904d73321ab5aa9d5ba9d6bca458c07170011ba61bf4f62cdd33bde1baf553f",
  input: "0xb93fa138000000000000000000000000000000009f6f0c2d68a7489c4ec7916fd2c51d88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020dd11395091aa1bd2f8cc16768b286d992faf78a24ec9fa904bc44167e7680bbb",
  nonce: 6,
  r: "0x8dfeee407aecbbeb816e3bb3a3957baa78c135b7d9ce66094554184bc80245a6",
  s: "0x7a1f9dd58e96a80f5fcca28b819922467e23dab86a3159893b7ae2d09c7ef799",
  to: "0xe80ab11db5543603cd620a7185fff71c98f54d3b",
  transactionIndex: 0,
  v: "0x18ae",
  value: 0
}

I'd like to be able to know who the transaction is from before sending it into geth. I'm assuming the secret is the R/S/V values of the signature but I haven't found much documentation about how to handle them to get the address.

How can I determine the from address of a raw transaction without sending the transaction to geth?

1 Answer 1

8

Here's some working code using ethereumjs-tx:

const EthereumTx = require('ethereumjs-tx').Transaction;

const raw = '0xf9010806808407fffd2894e80ab11db5543603cd620a7185fff71c98f54d3b80b8a4b93fa138000000000000000000000000000000009f6f0c2d68a7489c4ec7916fd2c51d88000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020dd11395091aa1bd2f8cc16768b286d992faf78a24ec9fa904bc44167e7680bbb8218aea08dfeee407aecbbeb816e3bb3a3957baa78c135b7d9ce66094554184bc80245a6a07a1f9dd58e96a80f5fcca28b819922467e23dab86a3159893b7ae2d09c7ef799';

console.log(new EthereumTx(raw).getSenderAddress().toString('hex'));

If you want to understand how this is done, the ethereumjs-tx source code is a good read. In short:

  • The raw transaction is the RLP encoding of a bunch of fields, including r, s, and v.
  • r and s constitute a signature, and v is a "recovery parameter," which is needed to recover the public key that created the signature.
  • To recover the public key, you need the message that was signed. In the case of transactions, this is the hash of the RLP encoding of the transaction, but with the v parameter replaced with the chain ID and the r and s values replaced with zeros.
  • Then you do elliptic curve stuff to retrieve the public key, which I couldn't explain here even if I wanted to. :-)
  • An address is Ethereum is the last 20 bytes of the keccak256 hash of the public key.

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.