ethereumjs / ethereumjs-tx

Project is in active development and has been moved to the EthereumJS VM monorepo.
https://github.com/ethereumjs/ethereumjs-vm/tree/master/packages/tx
Mozilla Public License 2.0
779 stars 235 forks source link

Incorrect hash for private unsigned transactions #141

Closed mushketyk closed 5 years ago

mushketyk commented 5 years ago

I am trying to calculate a hash of a private Quorum transaction locally, without relying on a hash returned by web3. I've managed to do this for (locally) signed transactions, but I can't make Tx class to return correct hash for an unsigned private transaction.

Here is the code that I am using:

  const rawTx = ...
  const tx = new Tx(rawTx)
  const hash: Buffer = tx.hash(false)

  return '0x' + hash.toString('hex')

Where rawTx is the following object:

{
     from: "0xb5f30b19c2b2fd418d5ea2e07b26bc1ef90c2c39",
     to: "0x57F4aFA44d2E2370371ED5560B7706E1bB35af77",
     gas: 300000000,
     gasLimit: 804247552,
     gasPrice: "0x0",
     data: "0xd7d58f5b0000000000000000000000000000000000000000000000000000000000000001",
     privateFor: [ "iO8XbAo/r8yHU+f1RK8evDW+vYmiUkxHXb98JIsPCw8=" ],
     nonce: 0,
     chainId: 2017
}

I get the following hash for this transaction:

"0xad9d7064887a2a7d4a10a99eb5faec1e268911d21c2582ead837c383f1145c6c"

but the actual hash of the transaction returned by web3 is the following:

"0x8b8a1c64be6442fcf87af60790df11b035954dc0cfccec8609225ca0fd4a131b"

I've also looked at Quorum source code that calculates transaction hashes (1, 2) but I could not find any discrepancies between how Quorum calculates transaction hash and how ethereumjs-tx does it.

s1na commented 5 years ago

I'd have to look deeper, but if I have to make a guess, it'd have something to do either with the fields in rawTx (from and privateFor are not taken into account in the Tx class), or chainId. Can you try to incrementally go from a rawTx that outputs the correct hash to the rawTx you want to pinpoint what's causing the problem?

mushketyk commented 5 years ago

@s1na Thank you for looking into this. The problem now is that I can't get a rawTx that would generate a correct hash. I would try to remove the from and privateFor and see if this works.

mushketyk commented 5 years ago

@s1na I've tried removing from and privateFor from the rawTx, but it didn't help.

Here is how I get the chain id:

web3.eth.net.getId()
mushketyk commented 5 years ago

I think the answer to this is described in this paragraph from the Quorum documentation:

Private Transactions, however, are not executed per standard Ethereum: prior to the sender's Quorum Node propagating the Transaction to the rest of the network, it replaces the original Transaction Payload with a hash of the encrypted Payload that it receives from Constellation/Tessera. Participants that are party to the Transaction will be able to replace the hash with the actual payload via their Constellation/Tessera instance, whilst those Participants that are not party will only see the hash.

So it seems that Quorum replaces the body of the transaction with the hash, and it seems that it hashes the result transaction.

holgerd77 commented 5 years ago

@mushketyk Thanks for clarifying, will close.

mushketyk commented 5 years ago

I've created an issue in the Quorum repo here: https://github.com/jpmorganchase/quorum/issues/657