0

I'm trying to replay transactions that exist in one chain on another.

I can replicate all transaction arguments that are available through eth_getTransactionByHash, but now need to sign the transaction. How do I extract the signing information from the committed transaction so that I'm able to resubmit with eth_sendRawTransaction.

Also welcome responses in web3.py, web3.js, ethers.js or any other preferred json-rpc SDK.

Existing code using web3.py that doesn't work:

tx = fallback_web3.eth.getTransaction(individual_tx_hash)
transaction = {
  "from": tx["from"],
  "to": tx["to"],
  "gas": tx["gas"],
  "gasPrice": tx["gasPrice"],
  "value": tx["value"],
  "nonce": tx["nonce"],
}
if "data" in tx:
  transaction["data"] = tx["data"]
w3.eth.sendTransaction(transaction)
Peteris
  • 1,005
  • 7
  • 24
  • 1
    Function eth_sendRawTransaction doesn't require you to pass the from value, as it is already embedded in the raw transaction itself (which you need to pass to this function). – goodvibration Sep 08 '20 at 10:55
  • @goodvibration exactly - and the question is how am I able to build up this raw transaction signature. I'm just using the RPC-API because it's most familiar across both JS/Python users. – Peteris Sep 08 '20 at 10:56
  • 1
    Just take the raw transaction as is. – goodvibration Sep 08 '20 at 11:00
  • Is there an API call for getting the raw transaction? If I use getTransactionByHash it's giving me: hash, nonce, v, r, s, etc. individually. – Peteris Sep 08 '20 at 11:02
  • BTW, why don't you simply use web3.js function getTransaction? – goodvibration Sep 08 '20 at 11:02
  • I'm using web3.py so using something very similar. – Peteris Sep 08 '20 at 11:02
  • If it's very similar then you shouldn't have any problem getting the from field value. – goodvibration Sep 08 '20 at 11:03
  • 1
    Note that the signature of the transaction differs from one chain to another since the EIP-155 (https://eips.ethereum.org/EIPS/eip-155) to protect against replay attacks. – clement Sep 08 '20 at 11:07
  • I can get the from field value as long as all the other values but now I need to sign the transaction.

    Thanks @clement - yes I'm keeping the chain_id the same.

    – Peteris Sep 08 '20 at 11:08
  • You can use web3.eth.signTransaction : https://web3js.readthedocs.io/en/v1.2.0/web3-eth.html#signtransaction. It will return the raw tx. – clement Sep 08 '20 at 11:09
  • @clement There is signTransaction in web3.py also but it requires the private key. I don't think signing will work because there is no way to get the private keys for these users. – Peteris Sep 08 '20 at 11:12
  • To send a transaction you must sign it before. So if you don't have the private key there is no way to broadcast the tx. – clement Sep 08 '20 at 11:16
  • @clement are you suggesting that replay attacks were only possible because the attackers knew the private keys? I effectively want to do a replay attack on a local fork of mainnet. It should be possible by using the raw transaction, which was already signed on mainnet. – Peteris Sep 08 '20 at 11:17
  • 1
    You're right, if your two chains have the same chainId, then just sending the raw transaction should work. – clement Sep 08 '20 at 11:19
  • @clement Do you know how to reconstruct the raw transaction using JSON RPC data? – Peteris Sep 08 '20 at 11:22

1 Answers1

2

There is an undocumented eth_getRawTransactionByHash method now in geth nodes.

Get raw transaction from hash

After getting the raw transaction, it can be directly replayed using eth_sendRawTransaction as long as all the parameters are the same according to EIP-155 (https://eips.ethereum.org/EIPS/eip-155) (nonce, gasprice, startgas, to, value, data, chainid, 0, 0).

Peteris
  • 1,005
  • 7
  • 24