1

I'm trying to create two transactions with the same nonce and send those transactions to two different nodes. Such as:

const Web3 = require('web3');

const web3_1 = new Web3(rpcURL1); // node 1
const web3_2 = new Web3(rpcURL2); // node 2
const web3_3 = new Web3(rpcURL3); // node 3

// Let's call tx1
web3_2.eth.sendTransaction(
    {
        from: account0, to: account1, value: web3_1.utils.toWei("1", "ether"), nonce: 3
    }
);

// Let's call tx2
web3_3.eth.sendTransaction(
    {
        from: account0, to: account1, value: web3_1.utils.toWei("1", "ether"), nonce: 3
    }
);

I'm testing this on a private network with 3 nodes. All the nodes have each other as peers.

The error I'm getting when I run the code above: Error: Returned error: known transaction: [txHash]

According to web3.js documentation, sendTransaction method returns a callback. Since I'm not waiting for this callback to be resolved, I assume transactions would be fired simultaneously or at very close times.

My guess is that since I'm using a private network and there are only three nodes, transaction propagation between the nodes is pretty fast (my assumption might be wrong). That's why, even though the transactions are submitted at very close times, tx1 is propagated to node3 before tx2 reaches node3. I believe that would be the only way for node3 to know about tx1.

If you think that's the case, is there any way in Ethereum to control the transaction propagation process or slow down it?

If you think that's not the case, what would be your suggestion for me to create these double-spending transactions on different nodes?

2 Answers 2

1

"known transaction" means that both transaction are exactly the same. You might try changing value so they are different.

If all your nodes are running on the same lan and all of them are connected between them it is very likely they will propagate the transactions quickly. An quick and dirty way to test this is to keep the nodes isolated, for example by changing the p2p port so they can't talk between them.

When a node receives two pending transactions with the same nonce and similar gas price it will keep the first one and discard the other.

Enforced by the Ethereum consensus rules two transactions with the same nonce cannot be mined and form part of the same block chain.

Two nodes can mine the different transactions in two separated blocks creating a blockchain fork. Eventualy all the nodes will follow one of the forks, the one with the largest amount of work in case of PoW.

2
  • I changed the value field as you suggested and now I'm getting Error: Returned error: replacement transaction underpriced. My understanding is that, since I have two transactions with the same nonce, when one of them (e.g. tx1 on node1) is propagated to node2, it's trying to replace tx1 with tx2 on node2and failing since gas price of tx1 is not high enough. In this case, shouldn't node2 keep tx2 in its pending queue. I checked that and it was empty. Or does node2 just discard tx2?
    – flopoe
    Commented Oct 29, 2019 at 2:50
  • The message "replacement transaction underpriced" in node2 means it already have tx1. A node can't have two transactions with the same nonce it will select the first transaction arrived unless the second has at least a 10% increased gas price .
    – Ismael
    Commented Oct 29, 2019 at 3:53
0

In your case if you run the execution multiple times you'll get different results depending on which node receives and processes your transaction faster.

That being said, nodes are supposed to be prepared to reach consensus, which implies discarding those transactions that would produce a double spend, which is definitely positive.

If you think that's the case, is there any way in Ethereum to control the transaction propagation process or slow down it?

No, you cannot control what nodes are doing unless they are yours and you modify their source code, but it's not a practical approach since it's not feasible in production environments.

If you think that's not the case, what would be your suggestion for me to create these double-spending transactions on different nodes?

As I mentioned, you are not supposed to be able to create double-spending transactions. If you really want to, you'd have to modify the source code of your nodes so that in your testnet transactions are delayed, skipped, or simply nodes reach consensus over double-spending transactions.

Actually, something similar to what you are looking for happened recently in an Ethereum Classic 51% attack. Essentially you need modified nodes and >51% network capacity.

2
  • Assume that we bypassed the protection and we were able to send two double-spending transactions (tx1 and tx2) to two different nodes (node1 and node2). I think this wouldn't be impossible in mainnet/testnet since transaction propagation won't be super fast. What happens when tx1 is propagated to node2 in the future? Shouldn't node2 just reject it and keep tx2 since tx1 will be seem like a double-spending transaction to node2?
    – flopoe
    Commented Oct 29, 2019 at 3:11
  • If the node has already seen a transaction with that nonce it will reject the new arrived transaction, unless it has a higher fee, in which can it will discard the first one and pick up the new one. In any case that prevents the double spending.
    – Moliholy
    Commented Oct 29, 2019 at 7:26

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.