diff --git a/clients/op-erigon/entrypoint.sh b/clients/op-erigon/entrypoint.sh index 72026ea8f6..c701cd03b9 100644 --- a/clients/op-erigon/entrypoint.sh +++ b/clients/op-erigon/entrypoint.sh @@ -34,6 +34,11 @@ sleep 1 # We check for env variables that may not be bound so we need to disable `set -u` for this section. EXTRA_FLAGS="" set +u +if [ "$HIVE_OP_EXEC_DISABLE_TX_GOSSIP" != "" ]; then + EXTRA_FLAGS="$EXTRA_FLAGS --rollup.disabletxpoolgossip=$HIVE_OP_EXEC_DISABLE_TX_GOSSIP" +else + EXTRA_FLAGS="$EXTRA_FLAGS --rollup.disabletxpoolgossip=true" +fi if [ "$HIVE_OP_GETH_SEQUENCER_HTTP" != "" ]; then EXTRA_FLAGS="$EXTRA_FLAGS --rollup.sequencerhttp $HIVE_OP_GETH_SEQUENCER_HTTP" fi diff --git a/simulators/optimism/p2p/main.go b/simulators/optimism/p2p/main.go index 8eb526e319..0cee942f1b 100644 --- a/simulators/optimism/p2p/main.go +++ b/simulators/optimism/p2p/main.go @@ -43,7 +43,11 @@ func main() { Description: `This test verifies that tx gossiping works`, Run: func(t *hivesim.T) { txGossipingTest(t) }, }) - + suite.Add(&hivesim.TestSpec{ + Name: "tx gossip disabling", + Description: `This test verifies that tx gossip disabling works`, + Run: func(t *hivesim.T) { txGossipingDisableTest(t) }, + }) sim := hivesim.New() hivesim.MustRunSuite(sim, suite) } @@ -59,11 +63,11 @@ func txGossipingTest(t *hivesim.T) { d.AddEth1() d.WaitUpEth1(0, time.Second*10) - d.AddOpL2() + d.AddOpL2(hivesim.Params{"HIVE_OP_EXEC_DISABLE_TX_GOSSIP": "false"}) d.AddOpNode(0, 0, false) seqNode := d.GetOpL2Engine(0) - d.AddOpL2() + d.AddOpL2(hivesim.Params{"HIVE_OP_EXEC_DISABLE_TX_GOSSIP": "false"}) d.AddOpNode(0, 1, false) verifNode := d.GetOpL2Engine(1) verifClient := verifNode.EthClient() @@ -118,6 +122,108 @@ func txGossipingTest(t *hivesim.T) { t.Log("found gossiped transaction on sequencer") } +// txGossipingDisableTest verifies that a transaction submitted to a replica execution client +// with tx gossiping disabled does not show up on the sequencer tx pool. After that, submit +// transaction to sequencer which tx gossip enabled, and test tx does not show up at replica. +func txGossipingDisableTest(t *hivesim.T) { + d := optimism.NewDevnet(t) + sender := d.L2Vault.GenerateKey() + receiver := d.L2Vault.GenerateKey() + + d.InitChain(30, 4, 30, core.GenesisAlloc{sender: {Balance: big.NewInt(params.Ether)}}) + d.AddEth1() + d.WaitUpEth1(0, time.Second*10) + + d.AddOpL2(hivesim.Params{"HIVE_OP_EXEC_DISABLE_TX_GOSSIP": "false"}) + d.AddOpNode(0, 0, false) + + seqNode := d.GetOpL2Engine(0) + seqClient := seqNode.EthClient() + + d.AddOpL2(hivesim.Params{"HIVE_OP_EXEC_DISABLE_TX_GOSSIP": "true"}) + d.AddOpNode(0, 1, false) + verifNode := d.GetOpL2Engine(1) + verifClient := verifNode.EthClient() + + var wg sync.WaitGroup + wg.Add(2) + + go func() { + d.WaitUpOpL2Engine(0, time.Second*10) + wg.Done() + }() + go func() { + d.WaitUpOpL2Engine(1, time.Second*10) + wg.Done() + }() + + t.Log("waiting for nodes to come up") + wg.Wait() + + t.Logf("peering execution clients %s with %s", seqNode.IP.String(), verifNode.IP.String()) + seqNodeExtended := &optimism.OpL2EngineExtended{OpL2Engine: seqNode} + verifNodeExtended := &optimism.OpL2EngineExtended{OpL2Engine: verifNode} + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + require.NoError(t, seqNodeExtended.ConnectPeer(ctx, verifNodeExtended)) + + nonce := uint64(0) + baseTx := types.NewTx(&types.DynamicFeeTx{ + ChainID: optimism.L2ChainIDBig, + Nonce: nonce, + To: &receiver, + Gas: 75000, + GasTipCap: big.NewInt(10 * params.GWei), + GasFeeCap: big.NewInt(20 * params.GWei), + Value: big.NewInt(0.0001 * params.Ether), + }) + + tx, err := d.L2Vault.SignTransaction(sender, baseTx) + require.Nil(t, err) + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + require.NoError(t, verifClient.SendTransaction(ctx, tx)) + t.Log("sent tx to verifier. Give some time to check tx gossiping is disabled") + + <-time.After(10 * time.Second) + + ctx, cancel = context.WithTimeout(context.Background(), 180*time.Second) + defer cancel() + found, _ := optimism.WaitPendingTransactionFromTxPool(ctx, seqNodeExtended, sender, tx) + if found { + t.Fatal("transaction gossiped") + } + t.Log("transaction not gossiped on sequencer") + + nonce += 1 + baseTx2 := types.NewTx(&types.DynamicFeeTx{ + ChainID: optimism.L2ChainIDBig, + Nonce: nonce, + To: &receiver, + Gas: 75000, + GasTipCap: big.NewInt(10 * params.GWei), + GasFeeCap: big.NewInt(20 * params.GWei), + Value: big.NewInt(0.0001 * params.Ether), + }) + + tx2, err := d.L2Vault.SignTransaction(sender, baseTx2) + require.Nil(t, err) + ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + require.NoError(t, seqClient.SendTransaction(ctx, tx2)) + t.Log("sent tx to sequencer. Give some time to check tx gossiping is disabled") + + <-time.After(10 * time.Second) + + ctx, cancel = context.WithTimeout(context.Background(), 180*time.Second) + defer cancel() + found2, _ := optimism.WaitPendingTransactionFromTxPool(ctx, verifNodeExtended, sender, tx2) + if found2 { + t.Fatal("transaction gossiped") + } + t.Log("transaction not gossiped on validator") +} + // txForwardingTest verifies that a transaction submitted to a replica with tx forwarding enabled shows up on the sequencer. // TODO: The transaction shows up with `getTransaction`, but it remains pending and is not mined for some reason. // This is weird, but fine because it still shows that the transaction is received by the sequencer.