From baec7fc1ff8f2c9b75261b46af1c2be7b8756106 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 10:53:07 -0300 Subject: [PATCH 01/33] ExecutionClient.ResultAtPos returns PromiseInterface --- arbnode/inbox_test.go | 48 ++++++++++++++++++-- arbnode/transaction_streamer.go | 2 +- execution/gethexec/node.go | 5 +- execution/interface.go | 3 +- system_tests/bold_challenge_protocol_test.go | 4 +- system_tests/seqfeed_test.go | 2 +- 6 files changed, 52 insertions(+), 12 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 0c31008ff1..0fbdd37183 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -23,27 +23,65 @@ import ( "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/cmd/chaininfo" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/util/testhelpers" "github.com/offchainlabs/nitro/util/testhelpers/env" ) type execClientWrapper struct { - *gethexec.ExecutionEngine - t *testing.T + ExecutionEngine *gethexec.ExecutionEngine + t *testing.T } -func (w *execClientWrapper) Pause() { w.t.Error("not supported") } -func (w *execClientWrapper) Activate() { w.t.Error("not supported") } +func (w *execClientWrapper) Pause() { w.t.Error("not supported") } + +func (w *execClientWrapper) Activate() { w.t.Error("not supported") } + func (w *execClientWrapper) ForwardTo(url string) error { w.t.Error("not supported"); return nil } -func (w *execClientWrapper) Synced() bool { w.t.Error("not supported"); return false } + +func (w *execClientWrapper) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { + return w.ExecutionEngine.SequenceDelayedMessage(message, delayedSeqNum) +} + +func (w *execClientWrapper) NextDelayedMessageNumber() (uint64, error) { + return w.ExecutionEngine.NextDelayedMessageNumber() +} + +func (w *execClientWrapper) MarkFeedStart(to arbutil.MessageIndex) { + w.ExecutionEngine.MarkFeedStart(to) +} + +func (w *execClientWrapper) Synced() bool { w.t.Error("not supported"); return false } + func (w *execClientWrapper) FullSyncProgressMap() map[string]interface{} { w.t.Error("not supported") return nil } +func (w *execClientWrapper) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) (*execution.MessageResult, error) { + return w.ExecutionEngine.DigestMessage(num, msg, msgForPrefetch) +} + +func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*execution.MessageResult, error) { + return w.ExecutionEngine.Reorg(count, newMessages, oldMessages) +} + +func (w *execClientWrapper) HeadMessageNumber() (arbutil.MessageIndex, error) { + return w.ExecutionEngine.HeadMessageNumber() +} + +func (w *execClientWrapper) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { + return w.ExecutionEngine.HeadMessageNumberSync(t) +} + +func (w *execClientWrapper) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { + return containers.NewReadyPromise(w.ExecutionEngine.ResultAtPos(pos)) +} + func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*gethexec.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) { chainConfig := chaininfo.ArbitrumDevTestChainConfig() diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 1a961ebd3f..3c42c0ff48 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -1090,7 +1090,7 @@ func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execut } log.Info(FailedToGetMsgResultFromDB, "count", count) - msgResult, err := s.exec.ResultAtPos(pos) + msgResult, err := s.exec.ResultAtPos(pos).Await(context.Background()) if err != nil { return nil, err } diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 16e4948723..9c1f0ea7b2 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -29,6 +29,7 @@ import ( "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" + "github.com/offchainlabs/nitro/util/containers" "github.com/offchainlabs/nitro/util/dbutil" "github.com/offchainlabs/nitro/util/headerreader" ) @@ -406,8 +407,8 @@ func (n *ExecutionNode) NextDelayedMessageNumber() (uint64, error) { func (n *ExecutionNode) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { return n.ExecEngine.SequenceDelayedMessage(message, delayedSeqNum) } -func (n *ExecutionNode) ResultAtPos(pos arbutil.MessageIndex) (*execution.MessageResult, error) { - return n.ExecEngine.ResultAtPos(pos) +func (n *ExecutionNode) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { + return containers.NewReadyPromise(n.ExecEngine.ResultAtPos(pos)) } func (n *ExecutionNode) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { return n.ExecEngine.ArbOSVersionForMessageNumber(messageNum) diff --git a/execution/interface.go b/execution/interface.go index c0aa71c146..3413fd1c19 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -10,6 +10,7 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" + "github.com/offchainlabs/nitro/util/containers" ) type MessageResult struct { @@ -33,7 +34,7 @@ type ExecutionClient interface { Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*MessageResult, error) HeadMessageNumber() (arbutil.MessageIndex, error) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) - ResultAtPos(pos arbutil.MessageIndex) (*MessageResult, error) + ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] } // needed for validators / stakers diff --git a/system_tests/bold_challenge_protocol_test.go b/system_tests/bold_challenge_protocol_test.go index 777817bf3e..fe49999bdd 100644 --- a/system_tests/bold_challenge_protocol_test.go +++ b/system_tests/bold_challenge_protocol_test.go @@ -138,9 +138,9 @@ func testChallengeProtocolBOLD(t *testing.T, spawnerOpts ...server_arb.SpawnerOp ) defer l2nodeB.StopAndWait() - genesisA, err := l2nodeA.Execution.ResultAtPos(0) + genesisA, err := l2nodeA.Execution.ResultAtPos(0).Await(ctx) Require(t, err) - genesisB, err := l2nodeB.Execution.ResultAtPos(0) + genesisB, err := l2nodeB.Execution.ResultAtPos(0).Await(ctx) Require(t, err) if genesisA.BlockHash != genesisB.BlockHash { Fatal(t, "genesis blocks mismatch between nodes") diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index b757291561..43736540e2 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -166,7 +166,7 @@ func compareAllMsgResultsFromConsensusAndExecution( var lastResult *execution.MessageResult for msgCount := arbutil.MessageIndex(1); msgCount <= consensusMsgCount; msgCount++ { pos := msgCount - 1 - resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)) + resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)).Await(context.Background()) Require(t, err) resultConsensus, err := testClient.ConsensusNode.TxStreamer.ResultAtCount(msgCount) From 46da509a57b4270c84576ac414b0a0a302b9b5fa Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 10:56:36 -0300 Subject: [PATCH 02/33] ExecutionClient.DigestMessage returns PromiseInterface --- arbnode/inbox_test.go | 4 ++-- arbnode/transaction_streamer.go | 2 +- execution/gethexec/node.go | 4 ++-- execution/interface.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 0fbdd37183..7f58138224 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -62,8 +62,8 @@ func (w *execClientWrapper) FullSyncProgressMap() map[string]interface{} { return nil } -func (w *execClientWrapper) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) (*execution.MessageResult, error) { - return w.ExecutionEngine.DigestMessage(num, msg, msgForPrefetch) +func (w *execClientWrapper) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { + return containers.NewReadyPromise(w.ExecutionEngine.DigestMessage(num, msg, msgForPrefetch)) } func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*execution.MessageResult, error) { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 3c42c0ff48..5da500a06b 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -1177,7 +1177,7 @@ func (s *TransactionStreamer) ExecuteNextMsg(ctx context.Context) bool { } msgForPrefetch = msg } - msgResult, err := s.exec.DigestMessage(pos, &msgAndBlockHash.MessageWithMeta, msgForPrefetch) + msgResult, err := s.exec.DigestMessage(pos, &msgAndBlockHash.MessageWithMeta, msgForPrefetch).Await(ctx) if err != nil { logger := log.Warn if prevMessageCount < msgCount { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 9c1f0ea7b2..8c93f5ce7e 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -389,8 +389,8 @@ func (n *ExecutionNode) StopAndWait() { // } } -func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) (*execution.MessageResult, error) { - return n.ExecEngine.DigestMessage(num, msg, msgForPrefetch) +func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { + return containers.NewReadyPromise(n.ExecEngine.DigestMessage(num, msg, msgForPrefetch)) } func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*execution.MessageResult, error) { return n.ExecEngine.Reorg(count, newMessages, oldMessages) diff --git a/execution/interface.go b/execution/interface.go index 3413fd1c19..89bbb6a2e4 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -30,7 +30,7 @@ var ErrSequencerInsertLockTaken = errors.New("insert lock taken") // always needed type ExecutionClient interface { - DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) (*MessageResult, error) + DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*MessageResult] Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*MessageResult, error) HeadMessageNumber() (arbutil.MessageIndex, error) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) From f880b81c80f7ec410b2dfa86a2aae649ab560a1d Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 10:59:15 -0300 Subject: [PATCH 03/33] ExecutionClient.Reorg returns PromiseInterface --- arbnode/inbox_test.go | 4 ++-- arbnode/transaction_streamer.go | 2 +- execution/gethexec/node.go | 4 ++-- execution/interface.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 7f58138224..9005990961 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -66,8 +66,8 @@ func (w *execClientWrapper) DigestMessage(num arbutil.MessageIndex, msg *arbosty return containers.NewReadyPromise(w.ExecutionEngine.DigestMessage(num, msg, msgForPrefetch)) } -func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*execution.MessageResult, error) { - return w.ExecutionEngine.Reorg(count, newMessages, oldMessages) +func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[[]*execution.MessageResult] { + return containers.NewReadyPromise(w.ExecutionEngine.Reorg(count, newMessages, oldMessages)) } func (w *execClientWrapper) HeadMessageNumber() (arbutil.MessageIndex, error) { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 5da500a06b..b59635f504 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -353,7 +353,7 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde s.reorgMutex.Lock() defer s.reorgMutex.Unlock() - messagesResults, err := s.exec.Reorg(count, newMessages, oldMessages) + messagesResults, err := s.exec.Reorg(count, newMessages, oldMessages).Await(context.Background()) if err != nil { return err } diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 8c93f5ce7e..91772fd773 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -392,8 +392,8 @@ func (n *ExecutionNode) StopAndWait() { func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { return containers.NewReadyPromise(n.ExecEngine.DigestMessage(num, msg, msgForPrefetch)) } -func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*execution.MessageResult, error) { - return n.ExecEngine.Reorg(count, newMessages, oldMessages) +func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { + return containers.NewReadyPromise(n.ExecEngine.Reorg(count, newMessages, oldMessages)) } func (n *ExecutionNode) HeadMessageNumber() (arbutil.MessageIndex, error) { return n.ExecEngine.HeadMessageNumber() diff --git a/execution/interface.go b/execution/interface.go index 89bbb6a2e4..f869db8cb4 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -31,7 +31,7 @@ var ErrSequencerInsertLockTaken = errors.New("insert lock taken") // always needed type ExecutionClient interface { DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*MessageResult] - Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) ([]*MessageResult, error) + Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*MessageResult] HeadMessageNumber() (arbutil.MessageIndex, error) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] From 961453324fbe67dd335ec86b322a0f6a18606947 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 11:07:18 -0300 Subject: [PATCH 04/33] ExecutionClient.HeadMessageNumber returns PromiseInterface --- arbnode/inbox_test.go | 6 +++--- arbnode/transaction_streamer.go | 4 ++-- execution/gethexec/node.go | 4 ++-- execution/interface.go | 2 +- system_tests/seqfeed_test.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 9005990961..372a752b0b 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -66,12 +66,12 @@ func (w *execClientWrapper) DigestMessage(num arbutil.MessageIndex, msg *arbosty return containers.NewReadyPromise(w.ExecutionEngine.DigestMessage(num, msg, msgForPrefetch)) } -func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[[]*execution.MessageResult] { +func (w *execClientWrapper) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { return containers.NewReadyPromise(w.ExecutionEngine.Reorg(count, newMessages, oldMessages)) } -func (w *execClientWrapper) HeadMessageNumber() (arbutil.MessageIndex, error) { - return w.ExecutionEngine.HeadMessageNumber() +func (w *execClientWrapper) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { + return containers.NewReadyPromise(w.ExecutionEngine.HeadMessageNumber()) } func (w *execClientWrapper) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index b59635f504..6ce3dea173 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -497,7 +497,7 @@ func (s *TransactionStreamer) GetProcessedMessageCount() (arbutil.MessageIndex, if err != nil { return 0, err } - digestedHead, err := s.exec.HeadMessageNumber() + digestedHead, err := s.exec.HeadMessageNumber().Await(context.Background()) if err != nil { return 0, err } @@ -1154,7 +1154,7 @@ func (s *TransactionStreamer) ExecuteNextMsg(ctx context.Context) bool { return false } s.execLastMsgCount = msgCount - pos, err := s.exec.HeadMessageNumber() + pos, err := s.exec.HeadMessageNumber().Await(ctx) if err != nil { log.Error("feedOneMsg failed to get exec engine message count", "err", err) return false diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 91772fd773..343c8e39e1 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -395,8 +395,8 @@ func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes. func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { return containers.NewReadyPromise(n.ExecEngine.Reorg(count, newMessages, oldMessages)) } -func (n *ExecutionNode) HeadMessageNumber() (arbutil.MessageIndex, error) { - return n.ExecEngine.HeadMessageNumber() +func (n *ExecutionNode) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { + return containers.NewReadyPromise(n.ExecEngine.HeadMessageNumber()) } func (n *ExecutionNode) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { return n.ExecEngine.HeadMessageNumberSync(t) diff --git a/execution/interface.go b/execution/interface.go index f869db8cb4..4912b3a8ef 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -32,7 +32,7 @@ var ErrSequencerInsertLockTaken = errors.New("insert lock taken") type ExecutionClient interface { DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*MessageResult] Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*MessageResult] - HeadMessageNumber() (arbutil.MessageIndex, error) + HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] } diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index 43736540e2..ca894658e7 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -152,7 +152,7 @@ func compareAllMsgResultsFromConsensusAndExecution( testClient *TestClient, testScenario string, ) *execution.MessageResult { - execHeadMsgNum, err := testClient.ExecNode.HeadMessageNumber() + execHeadMsgNum, err := testClient.ExecNode.HeadMessageNumber().Await(context.Background()) Require(t, err) consensusMsgCount, err := testClient.ConsensusNode.TxStreamer.GetMessageCount() Require(t, err) From cf800b4c9e7ac41a65883fc21a393ccf453ee6a1 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 11:25:03 -0300 Subject: [PATCH 05/33] ExecutionClient.HeadMessageNumberSync returns PromiseInterface --- arbnode/inbox_test.go | 4 ++-- execution/gethexec/node.go | 4 ++-- execution/interface.go | 2 +- system_tests/reorg_resequencing_test.go | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 372a752b0b..e91d3fe3a1 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -74,8 +74,8 @@ func (w *execClientWrapper) HeadMessageNumber() containers.PromiseInterface[arbu return containers.NewReadyPromise(w.ExecutionEngine.HeadMessageNumber()) } -func (w *execClientWrapper) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { - return w.ExecutionEngine.HeadMessageNumberSync(t) +func (w *execClientWrapper) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { + return containers.NewReadyPromise(w.ExecutionEngine.HeadMessageNumberSync(t)) } func (w *execClientWrapper) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 343c8e39e1..24b67edfe0 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -398,8 +398,8 @@ func (n *ExecutionNode) Reorg(count arbutil.MessageIndex, newMessages []arbostyp func (n *ExecutionNode) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { return containers.NewReadyPromise(n.ExecEngine.HeadMessageNumber()) } -func (n *ExecutionNode) HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) { - return n.ExecEngine.HeadMessageNumberSync(t) +func (n *ExecutionNode) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { + return containers.NewReadyPromise(n.ExecEngine.HeadMessageNumberSync(t)) } func (n *ExecutionNode) NextDelayedMessageNumber() (uint64, error) { return n.ExecEngine.NextDelayedMessageNumber() diff --git a/execution/interface.go b/execution/interface.go index 4912b3a8ef..7f34d5b3d1 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -33,7 +33,7 @@ type ExecutionClient interface { DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*MessageResult] Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*MessageResult] HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] - HeadMessageNumberSync(t *testing.T) (arbutil.MessageIndex, error) + HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] } diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index 70ab63bec1..b802f8b4e8 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -65,7 +65,7 @@ func TestReorgResequencing(t *testing.T) { err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) Require(t, err) verifyBalances("after empty reorg") @@ -91,7 +91,7 @@ func TestReorgResequencing(t *testing.T) { }}) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") @@ -102,7 +102,7 @@ func TestReorgResequencing(t *testing.T) { err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) Require(t, err) verifyBalances("after second empty reorg") From 700de67b3086828b3c1cd3621ae4bfddcc07733e Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 11:34:54 -0300 Subject: [PATCH 06/33] Fixes context usage when awaiting promises returned by ExecutionClient --- arbnode/transaction_streamer.go | 6 +++--- system_tests/meaningless_reorg_test.go | 4 ++-- system_tests/seqfeed_test.go | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 6ce3dea173..c244297596 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -353,7 +353,7 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde s.reorgMutex.Lock() defer s.reorgMutex.Unlock() - messagesResults, err := s.exec.Reorg(count, newMessages, oldMessages).Await(context.Background()) + messagesResults, err := s.exec.Reorg(count, newMessages, oldMessages).Await(s.GetContext()) if err != nil { return err } @@ -497,7 +497,7 @@ func (s *TransactionStreamer) GetProcessedMessageCount() (arbutil.MessageIndex, if err != nil { return 0, err } - digestedHead, err := s.exec.HeadMessageNumber().Await(context.Background()) + digestedHead, err := s.exec.HeadMessageNumber().Await(s.GetContext()) if err != nil { return 0, err } @@ -1090,7 +1090,7 @@ func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execut } log.Info(FailedToGetMsgResultFromDB, "count", count) - msgResult, err := s.exec.ResultAtPos(pos).Await(context.Background()) + msgResult, err := s.exec.ResultAtPos(pos).Await(s.GetContext()) if err != nil { return nil, err } diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index 350b21a6cf..47cbcad3d7 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -63,7 +63,7 @@ func TestMeaninglessBatchReorg(t *testing.T) { builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) } - compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "before reorg") + compareAllMsgResultsFromConsensusAndExecution(t, ctx, builder.L2, "before reorg") parentBlock := builder.L1.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) err = builder.L1.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) @@ -108,5 +108,5 @@ func TestMeaninglessBatchReorg(t *testing.T) { Fatal(t, "L2 block hash changed") } - compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after reorg") + compareAllMsgResultsFromConsensusAndExecution(t, ctx, builder.L2, "after reorg") } diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index ca894658e7..31cf573123 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -149,6 +149,7 @@ func TestRelayedSequencerFeed(t *testing.T) { func compareAllMsgResultsFromConsensusAndExecution( t *testing.T, + ctx context.Context, testClient *TestClient, testScenario string, ) *execution.MessageResult { @@ -166,7 +167,7 @@ func compareAllMsgResultsFromConsensusAndExecution( var lastResult *execution.MessageResult for msgCount := arbutil.MessageIndex(1); msgCount <= consensusMsgCount; msgCount++ { pos := msgCount - 1 - resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)).Await(context.Background()) + resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)).Await(ctx) Require(t, err) resultConsensus, err := testClient.ConsensusNode.TxStreamer.ResultAtCount(msgCount) @@ -267,7 +268,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance:", l2balance) } - fraudResult := compareAllMsgResultsFromConsensusAndExecution(t, testClientB, "fraud") + fraudResult := compareAllMsgResultsFromConsensusAndExecution(t, ctx, testClientB, "fraud") // Send the real transaction to client A, will cause a reorg on nodeB err = l2clientA.SendTransaction(ctx, realTx) @@ -319,7 +320,7 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Consensus relied on execution database to return the result") } // Consensus should update message result stored in its database after a reorg - realResult := compareAllMsgResultsFromConsensusAndExecution(t, testClientB, "real") + realResult := compareAllMsgResultsFromConsensusAndExecution(t, ctx, testClientB, "real") // Checks that results changed if reflect.DeepEqual(fraudResult, realResult) { t.Fatal("realResult and fraudResult are equal") From 4e6c52f6dfd1e42e06eaf596ba63bfd2c62b497d Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 14:14:07 -0300 Subject: [PATCH 07/33] Fixes reorg_requesequencing_test --- system_tests/reorg_resequencing_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/system_tests/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index b802f8b4e8..42080222a2 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -65,11 +65,11 @@ func TestReorgResequencing(t *testing.T) { err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after empty reorg") - compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after empty reorg") + compareAllMsgResultsFromConsensusAndExecution(t, ctx, builder.L2, "after empty reorg") prevMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) @@ -91,20 +91,20 @@ func TestReorgResequencing(t *testing.T) { }}) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") verifyBalances("after reorg with new deposit") - compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after reorg with new deposit") + compareAllMsgResultsFromConsensusAndExecution(t, ctx, builder.L2, "after reorg with new deposit") err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) - _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t).Await(ctx) + _, err = builder.L2.ExecNode.ExecEngine.HeadMessageNumberSync(t) Require(t, err) verifyBalances("after second empty reorg") - compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after second empty reorg") + compareAllMsgResultsFromConsensusAndExecution(t, ctx, builder.L2, "after second empty reorg") } From f3d205116891297060dc5a33ed2303189ff4dc86 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 24 Dec 2024 15:02:00 -0300 Subject: [PATCH 08/33] Fixes context used for execution client in transaction_streamer --- arbnode/transaction_streamer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index c244297596..d8f01a25d0 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -497,7 +497,7 @@ func (s *TransactionStreamer) GetProcessedMessageCount() (arbutil.MessageIndex, if err != nil { return 0, err } - digestedHead, err := s.exec.HeadMessageNumber().Await(s.GetContext()) + digestedHead, err := s.exec.HeadMessageNumber().Await(context.Background()) if err != nil { return 0, err } @@ -1090,7 +1090,7 @@ func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execut } log.Info(FailedToGetMsgResultFromDB, "count", count) - msgResult, err := s.exec.ResultAtPos(pos).Await(s.GetContext()) + msgResult, err := s.exec.ResultAtPos(pos).Await(context.Background()) if err != nil { return nil, err } From 6146145179536a7a64888fa8426292fe75a7536e Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 26 Dec 2024 13:32:05 -0300 Subject: [PATCH 09/33] Moves MarkFeedStart to ExecutionClient --- arbnode/inbox_test.go | 8 ++++++-- arbnode/transaction_streamer.go | 2 +- execution/gethexec/node.go | 8 ++++++-- execution/interface.go | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index e91d3fe3a1..afa4db0123 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -51,8 +51,12 @@ func (w *execClientWrapper) NextDelayedMessageNumber() (uint64, error) { return w.ExecutionEngine.NextDelayedMessageNumber() } -func (w *execClientWrapper) MarkFeedStart(to arbutil.MessageIndex) { - w.ExecutionEngine.MarkFeedStart(to) +func (w *execClientWrapper) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { + markFeedStartWithReturn := func(to arbutil.MessageIndex) (struct{}, error) { + w.ExecutionEngine.MarkFeedStart(to) + return struct{}{}, nil + } + return containers.NewReadyPromise(markFeedStartWithReturn(to)) } func (w *execClientWrapper) Synced() bool { w.t.Error("not supported"); return false } diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index d8f01a25d0..ac82435115 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -674,7 +674,7 @@ func (s *TransactionStreamer) AddMessagesAndEndBatch(pos arbutil.MessageIndex, m if messagesAreConfirmed { // Trim confirmed messages from l1pricedataCache - s.exec.MarkFeedStart(pos + arbutil.MessageIndex(len(messages))) + s.exec.MarkFeedStart(pos + arbutil.MessageIndex(len(messages))).Await(s.GetContext()) s.reorgMutex.RLock() dups, _, _, err := s.countDuplicateMessages(pos, messagesWithBlockHash, nil) s.reorgMutex.RUnlock() diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 24b67edfe0..40fb8c2d13 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -316,8 +316,12 @@ func CreateExecutionNode( } -func (n *ExecutionNode) MarkFeedStart(to arbutil.MessageIndex) { - n.ExecEngine.MarkFeedStart(to) +func (n *ExecutionNode) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { + markFeedStartWithReturn := func(to arbutil.MessageIndex) (struct{}, error) { + n.ExecEngine.MarkFeedStart(to) + return struct{}{}, nil + } + return containers.NewReadyPromise(markFeedStartWithReturn(to)) } func (n *ExecutionNode) Initialize(ctx context.Context) error { diff --git a/execution/interface.go b/execution/interface.go index 7f34d5b3d1..314b1fdc42 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -35,6 +35,7 @@ type ExecutionClient interface { HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] + MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] } // needed for validators / stakers @@ -56,7 +57,6 @@ type ExecutionSequencer interface { ForwardTo(url string) error SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error NextDelayedMessageNumber() (uint64, error) - MarkFeedStart(to arbutil.MessageIndex) Synced() bool FullSyncProgressMap() map[string]interface{} } From 2d097736eb1f53d2447d959a16479fdc43c9c5e0 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 26 Dec 2024 14:23:40 -0300 Subject: [PATCH 10/33] NonFullExecutionClient --- arbnode/node.go | 25 +++--- execution/gethexec/node.go | 83 +++++++++++++++++++ system_tests/common_test.go | 30 ++++--- .../non_full_execution_client_test.go | 48 +++++++++++ 4 files changed, 165 insertions(+), 21 deletions(-) create mode 100644 system_tests/non_full_execution_client_test.go diff --git a/arbnode/node.go b/arbnode/node.go index d96c4001c4..c715e53f25 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -894,23 +894,26 @@ func CreateNode( } func (n *Node) Start(ctx context.Context) error { - execClient, ok := n.Execution.(*gethexec.ExecutionNode) - if !ok { - execClient = nil + executionNode, isExecutionNode := n.Execution.(*gethexec.ExecutionNode) + nonFullExecutionClient, isNonFullExecutionClient := n.Execution.(*gethexec.NonFullExecutionClient) + + var err error + if isExecutionNode { + err = executionNode.Initialize(ctx) + } else if isNonFullExecutionClient { + err = nonFullExecutionClient.Initialize(ctx) } - if execClient != nil { - err := execClient.Initialize(ctx) - if err != nil { - return fmt.Errorf("error initializing exec client: %w", err) - } + if err != nil { + return fmt.Errorf("error initializing exec client: %w", err) } + n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator) - err := n.Stack.Start() + err = n.Stack.Start() if err != nil { return fmt.Errorf("error starting geth stack: %w", err) } - if execClient != nil { - execClient.SetConsensusClient(n) + if isExecutionNode { + executionNode.SetConsensusClient(n) } err = n.Execution.Start(ctx) if err != nil { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 40fb8c2d13..fb689c73cc 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -472,3 +472,86 @@ func (n *ExecutionNode) Synced() bool { func (n *ExecutionNode) FullSyncProgressMap() map[string]interface{} { return n.SyncMonitor.FullSyncProgressMap() } + +// Used to check if only implementing ExecutionClient from FullExecutionClient interface is enough in some scenarios +type NonFullExecutionClient struct { + ExecutionNode *ExecutionNode +} + +// ExecutionClient interface implementation +func (n *NonFullExecutionClient) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { + return n.ExecutionNode.DigestMessage(num, msg, msgForPrefetch) +} +func (n *NonFullExecutionClient) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { + return n.ExecutionNode.Reorg(count, newMessages, oldMessages) +} +func (n *NonFullExecutionClient) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { + return n.ExecutionNode.HeadMessageNumber() +} +func (n *NonFullExecutionClient) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { + return n.ExecutionNode.HeadMessageNumberSync(t) +} +func (n *NonFullExecutionClient) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { + return n.ExecutionNode.ResultAtPos(pos) +} +func (n *NonFullExecutionClient) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { + return n.ExecutionNode.MarkFeedStart(to) +} + +// ExecutionRecorder interface implementation +func (n *NonFullExecutionClient) RecordBlockCreation( + ctx context.Context, + pos arbutil.MessageIndex, + msg *arbostypes.MessageWithMetadata, +) (*execution.RecordResult, error) { + panic("RecordBlockCreation not supported") +} +func (n *NonFullExecutionClient) MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) { + panic("MarkValid not supported") +} +func (n *NonFullExecutionClient) PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error { + panic("PrepareForRecord not supported") +} + +// ExecutionSequence interface implementation +func (n *NonFullExecutionClient) Pause() { + panic("Pause not supported") +} +func (n *NonFullExecutionClient) Activate() { + // panic("Activate not supported") +} +func (n *NonFullExecutionClient) ForwardTo(url string) error { + panic("ForwardTo not supported") +} +func (n *NonFullExecutionClient) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { + panic("SequenceDelayedMessage not supported") +} +func (n *NonFullExecutionClient) NextDelayedMessageNumber() (uint64, error) { + panic("NextDelayedMessageNumber not supported") +} +func (n *NonFullExecutionClient) Synced() bool { + panic("Synced not supported") +} +func (n *NonFullExecutionClient) FullSyncProgressMap() map[string]interface{} { + panic("FullSyncProgressMap not supported") +} + +// Other funcs from FullExecutionClient +// not thread safe +func (n *NonFullExecutionClient) Start(ctx context.Context) error { + return n.ExecutionNode.Start(ctx) +} +func (n *NonFullExecutionClient) StopAndWait() { + n.ExecutionNode.StopAndWait() +} +func (n *NonFullExecutionClient) Maintenance() error { + return n.ExecutionNode.Maintenance() +} +func (n *NonFullExecutionClient) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { + return n.ExecutionNode.ArbOSVersionForMessageNumber(messageNum) +} + +// Not part of FullExecutionClient interface, but needed to start the node +func (n *NonFullExecutionClient) Initialize(ctx context.Context) error { + return n.ExecutionNode.Initialize(ctx) +} diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 346a5feec4..f21b627ee9 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -92,13 +92,14 @@ import ( type info = *BlockchainTestInfo type SecondNodeParams struct { - nodeConfig *arbnode.Config - execConfig *gethexec.Config - stackConfig *node.Config - dasConfig *das.DataAvailabilityConfig - initData *statetransfer.ArbosInitializationInfo - addresses *chaininfo.RollupAddresses - wasmCacheTag uint32 + nodeConfig *arbnode.Config + execConfig *gethexec.Config + stackConfig *node.Config + dasConfig *das.DataAvailabilityConfig + initData *statetransfer.ArbosInitializationInfo + addresses *chaininfo.RollupAddresses + wasmCacheTag uint32 + nonFullExecutionClient bool } type TestClient struct { @@ -743,8 +744,10 @@ func build2ndNode( testClient := NewTestClient(ctx) testClient.Client, testClient.ConsensusNode = - Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag) - testClient.ExecNode = getExecNode(t, testClient.ConsensusNode) + Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag, params.nonFullExecutionClient) + if !params.nonFullExecutionClient { + testClient.ExecNode = getExecNode(t, testClient.ConsensusNode) + } testClient.cleanup = func() { testClient.ConsensusNode.StopAndWait() } return testClient, func() { testClient.cleanup() } } @@ -1508,6 +1511,7 @@ func Create2ndNodeWithConfig( addresses *chaininfo.RollupAddresses, initMessage *arbostypes.ParsedInitMessage, wasmCacheTag uint32, + nonFullExecutionClient bool, ) (*ethclient.Client, *arbnode.Node) { if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() @@ -1554,7 +1558,13 @@ func Create2ndNodeWithConfig( currentExec, err := gethexec.CreateExecutionNode(ctx, chainStack, chainDb, blockchain, parentChainClient, configFetcher) Require(t, err) - currentNode, err := arbnode.CreateNode(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + var currentNode *arbnode.Node + if nonFullExecutionClient { + currentNode, err = arbnode.CreateNode(ctx, chainStack, &gethexec.NonFullExecutionClient{currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + } else { + currentNode, err = arbnode.CreateNode(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + } + Require(t, err) err = currentNode.Start(ctx) diff --git a/system_tests/non_full_execution_client_test.go b/system_tests/non_full_execution_client_test.go new file mode 100644 index 0000000000..dc84e1df1c --- /dev/null +++ b/system_tests/non_full_execution_client_test.go @@ -0,0 +1,48 @@ +// Copyright 2021-2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +package arbtest + +import ( + "context" + "math/big" + "testing" + "time" + + "github.com/offchainlabs/nitro/arbnode" +) + +func TestNonFullExecutionClient(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + cleanup := builder.Build(t) + defer cleanup() + seqTestClient := builder.L2 + + // build replica node + replicaConfig := arbnode.ConfigDefaultL1NonSequencerTest() + replicaTestClient, replicaCleanup := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: replicaConfig, nonFullExecutionClient: true}) + defer replicaCleanup() + + // generates blocks + builder.L2Info.GenerateAccount("User2") + for i := 0; i < 3; i++ { + tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) + err := seqTestClient.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = seqTestClient.EnsureTxSucceeded(tx) + Require(t, err) + _, err = WaitForTx(ctx, replicaTestClient.Client, tx.Hash(), time.Second*15) + Require(t, err) + } + + replicaBalance, err := replicaTestClient.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + Require(t, err) + if replicaBalance.Cmp(big.NewInt(3e12)) != 0 { + t.Fatal("Unexpected balance:", replicaBalance) + } +} From df911864f195f160c2fd5fe33150e45989953e4e Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 26 Dec 2024 14:50:15 -0300 Subject: [PATCH 11/33] Renames NonFullExecutionClient to ExecutionClientImpl --- arbnode/node.go | 6 +-- execution/gethexec/node.go | 44 +++++++++---------- system_tests/common_test.go | 26 +++++------ ..._test.go => execution_client_impl_test.go} | 6 +-- 4 files changed, 40 insertions(+), 42 deletions(-) rename system_tests/{non_full_execution_client_test.go => execution_client_impl_test.go} (88%) diff --git a/arbnode/node.go b/arbnode/node.go index c715e53f25..4973ff5fb7 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -895,13 +895,13 @@ func CreateNode( func (n *Node) Start(ctx context.Context) error { executionNode, isExecutionNode := n.Execution.(*gethexec.ExecutionNode) - nonFullExecutionClient, isNonFullExecutionClient := n.Execution.(*gethexec.NonFullExecutionClient) + executionClientImpl, isExecutionClientImpl := n.Execution.(*gethexec.ExecutionClientImpl) var err error if isExecutionNode { err = executionNode.Initialize(ctx) - } else if isNonFullExecutionClient { - err = nonFullExecutionClient.Initialize(ctx) + } else if isExecutionClientImpl { + err = executionClientImpl.Initialize(ctx) } if err != nil { return fmt.Errorf("error initializing exec client: %w", err) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index fb689c73cc..bba30d20cc 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -474,84 +474,84 @@ func (n *ExecutionNode) FullSyncProgressMap() map[string]interface{} { } // Used to check if only implementing ExecutionClient from FullExecutionClient interface is enough in some scenarios -type NonFullExecutionClient struct { +type ExecutionClientImpl struct { ExecutionNode *ExecutionNode } // ExecutionClient interface implementation -func (n *NonFullExecutionClient) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { +func (n *ExecutionClientImpl) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { return n.ExecutionNode.DigestMessage(num, msg, msgForPrefetch) } -func (n *NonFullExecutionClient) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { +func (n *ExecutionClientImpl) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { return n.ExecutionNode.Reorg(count, newMessages, oldMessages) } -func (n *NonFullExecutionClient) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { +func (n *ExecutionClientImpl) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { return n.ExecutionNode.HeadMessageNumber() } -func (n *NonFullExecutionClient) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { +func (n *ExecutionClientImpl) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { return n.ExecutionNode.HeadMessageNumberSync(t) } -func (n *NonFullExecutionClient) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { +func (n *ExecutionClientImpl) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { return n.ExecutionNode.ResultAtPos(pos) } -func (n *NonFullExecutionClient) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { +func (n *ExecutionClientImpl) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { return n.ExecutionNode.MarkFeedStart(to) } // ExecutionRecorder interface implementation -func (n *NonFullExecutionClient) RecordBlockCreation( +func (n *ExecutionClientImpl) RecordBlockCreation( ctx context.Context, pos arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, ) (*execution.RecordResult, error) { panic("RecordBlockCreation not supported") } -func (n *NonFullExecutionClient) MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) { +func (n *ExecutionClientImpl) MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) { panic("MarkValid not supported") } -func (n *NonFullExecutionClient) PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error { +func (n *ExecutionClientImpl) PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error { panic("PrepareForRecord not supported") } // ExecutionSequence interface implementation -func (n *NonFullExecutionClient) Pause() { +func (n *ExecutionClientImpl) Pause() { panic("Pause not supported") } -func (n *NonFullExecutionClient) Activate() { +func (n *ExecutionClientImpl) Activate() { // panic("Activate not supported") } -func (n *NonFullExecutionClient) ForwardTo(url string) error { +func (n *ExecutionClientImpl) ForwardTo(url string) error { panic("ForwardTo not supported") } -func (n *NonFullExecutionClient) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { +func (n *ExecutionClientImpl) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { panic("SequenceDelayedMessage not supported") } -func (n *NonFullExecutionClient) NextDelayedMessageNumber() (uint64, error) { +func (n *ExecutionClientImpl) NextDelayedMessageNumber() (uint64, error) { panic("NextDelayedMessageNumber not supported") } -func (n *NonFullExecutionClient) Synced() bool { +func (n *ExecutionClientImpl) Synced() bool { panic("Synced not supported") } -func (n *NonFullExecutionClient) FullSyncProgressMap() map[string]interface{} { +func (n *ExecutionClientImpl) FullSyncProgressMap() map[string]interface{} { panic("FullSyncProgressMap not supported") } // Other funcs from FullExecutionClient // not thread safe -func (n *NonFullExecutionClient) Start(ctx context.Context) error { +func (n *ExecutionClientImpl) Start(ctx context.Context) error { return n.ExecutionNode.Start(ctx) } -func (n *NonFullExecutionClient) StopAndWait() { +func (n *ExecutionClientImpl) StopAndWait() { n.ExecutionNode.StopAndWait() } -func (n *NonFullExecutionClient) Maintenance() error { +func (n *ExecutionClientImpl) Maintenance() error { return n.ExecutionNode.Maintenance() } -func (n *NonFullExecutionClient) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { +func (n *ExecutionClientImpl) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { return n.ExecutionNode.ArbOSVersionForMessageNumber(messageNum) } // Not part of FullExecutionClient interface, but needed to start the node -func (n *NonFullExecutionClient) Initialize(ctx context.Context) error { +func (n *ExecutionClientImpl) Initialize(ctx context.Context) error { return n.ExecutionNode.Initialize(ctx) } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index f21b627ee9..515508012c 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -92,14 +92,14 @@ import ( type info = *BlockchainTestInfo type SecondNodeParams struct { - nodeConfig *arbnode.Config - execConfig *gethexec.Config - stackConfig *node.Config - dasConfig *das.DataAvailabilityConfig - initData *statetransfer.ArbosInitializationInfo - addresses *chaininfo.RollupAddresses - wasmCacheTag uint32 - nonFullExecutionClient bool + nodeConfig *arbnode.Config + execConfig *gethexec.Config + stackConfig *node.Config + dasConfig *das.DataAvailabilityConfig + initData *statetransfer.ArbosInitializationInfo + addresses *chaininfo.RollupAddresses + wasmCacheTag uint32 + useExecutionClientImplAsFullExecutionClient bool } type TestClient struct { @@ -744,8 +744,8 @@ func build2ndNode( testClient := NewTestClient(ctx) testClient.Client, testClient.ConsensusNode = - Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag, params.nonFullExecutionClient) - if !params.nonFullExecutionClient { + Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag, params.useExecutionClientImplAsFullExecutionClient) + if !params.useExecutionClientImplAsFullExecutionClient { testClient.ExecNode = getExecNode(t, testClient.ConsensusNode) } testClient.cleanup = func() { testClient.ConsensusNode.StopAndWait() } @@ -1511,7 +1511,7 @@ func Create2ndNodeWithConfig( addresses *chaininfo.RollupAddresses, initMessage *arbostypes.ParsedInitMessage, wasmCacheTag uint32, - nonFullExecutionClient bool, + useExecutionClientImplAsFullExecutionClient bool, ) (*ethclient.Client, *arbnode.Node) { if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() @@ -1559,8 +1559,8 @@ func Create2ndNodeWithConfig( Require(t, err) var currentNode *arbnode.Node - if nonFullExecutionClient { - currentNode, err = arbnode.CreateNode(ctx, chainStack, &gethexec.NonFullExecutionClient{currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + if useExecutionClientImplAsFullExecutionClient { + currentNode, err = arbnode.CreateNode(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } else { currentNode, err = arbnode.CreateNode(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } diff --git a/system_tests/non_full_execution_client_test.go b/system_tests/execution_client_impl_test.go similarity index 88% rename from system_tests/non_full_execution_client_test.go rename to system_tests/execution_client_impl_test.go index dc84e1df1c..11358a90d6 100644 --- a/system_tests/non_full_execution_client_test.go +++ b/system_tests/execution_client_impl_test.go @@ -12,7 +12,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" ) -func TestNonFullExecutionClient(t *testing.T) { +func TestExecutionClientImplAsFullExecutionClient(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) @@ -23,12 +23,10 @@ func TestNonFullExecutionClient(t *testing.T) { defer cleanup() seqTestClient := builder.L2 - // build replica node replicaConfig := arbnode.ConfigDefaultL1NonSequencerTest() - replicaTestClient, replicaCleanup := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: replicaConfig, nonFullExecutionClient: true}) + replicaTestClient, replicaCleanup := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: replicaConfig, useExecutionClientImplAsFullExecutionClient: true}) defer replicaCleanup() - // generates blocks builder.L2Info.GenerateAccount("User2") for i := 0; i < 3; i++ { tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, big.NewInt(1e12), nil) From d2e3841f0a559ab58d67703427d7c9925445bff9 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 26 Dec 2024 15:28:04 -0300 Subject: [PATCH 12/33] Fix lint issue --- arbnode/transaction_streamer.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index ac82435115..c4d2243d6a 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -674,7 +674,10 @@ func (s *TransactionStreamer) AddMessagesAndEndBatch(pos arbutil.MessageIndex, m if messagesAreConfirmed { // Trim confirmed messages from l1pricedataCache - s.exec.MarkFeedStart(pos + arbutil.MessageIndex(len(messages))).Await(s.GetContext()) + _, err := s.exec.MarkFeedStart(pos + arbutil.MessageIndex(len(messages))).Await(s.GetContext()) + if err != nil { + log.Warn("TransactionStreamer: failed to mark feed start", "pos", pos, "err", err) + } s.reorgMutex.RLock() dups, _, _, err := s.countDuplicateMessages(pos, messagesWithBlockHash, nil) s.reorgMutex.RUnlock() From 3d9b619db81758bde3436c87d347970b363ac48e Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 30 Dec 2024 10:11:11 -0300 Subject: [PATCH 13/33] Removes HeadMessageNumberSync from ExecutionClient --- execution/gethexec/node.go | 3 --- execution/interface.go | 2 -- 2 files changed, 5 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index bba30d20cc..49e9e6795d 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -488,9 +488,6 @@ func (n *ExecutionClientImpl) Reorg(count arbutil.MessageIndex, newMessages []ar func (n *ExecutionClientImpl) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { return n.ExecutionNode.HeadMessageNumber() } -func (n *ExecutionClientImpl) HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] { - return n.ExecutionNode.HeadMessageNumberSync(t) -} func (n *ExecutionClientImpl) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { return n.ExecutionNode.ResultAtPos(pos) } diff --git a/execution/interface.go b/execution/interface.go index 314b1fdc42..589b9eb32d 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -3,7 +3,6 @@ package execution import ( "context" "errors" - "testing" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" @@ -33,7 +32,6 @@ type ExecutionClient interface { DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*MessageResult] Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*MessageResult] HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] - HeadMessageNumberSync(t *testing.T) containers.PromiseInterface[arbutil.MessageIndex] ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] } From dd72cf639e5ddcf68c76eb04c70e4c4ea9b28d78 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 30 Dec 2024 15:46:45 -0300 Subject: [PATCH 14/33] Uses ExecutionClient instead of ExecutionSequencer in TransactionStreamer --- arbnode/transaction_streamer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index c4d2243d6a..024a32062f 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -44,7 +44,7 @@ type TransactionStreamer struct { stopwaiter.StopWaiter chainConfig *params.ChainConfig - exec execution.ExecutionSequencer + exec execution.ExecutionClient execLastMsgCount arbutil.MessageIndex validator *staker.BlockValidator @@ -98,7 +98,7 @@ func TransactionStreamerConfigAddOptions(prefix string, f *flag.FlagSet) { func NewTransactionStreamer( db ethdb.Database, chainConfig *params.ChainConfig, - exec execution.ExecutionSequencer, + exec execution.ExecutionClient, broadcastServer *broadcaster.Broadcaster, fatalErrChan chan<- error, config TransactionStreamerConfigFetcher, From 504060bb3dc51b90a29005a07a6eb8e00fc11c3e Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 30 Dec 2024 16:06:48 -0300 Subject: [PATCH 15/33] Moves Maintenance from FullExecutionClient to ExecutionClient --- arbnode/inbox_test.go | 4 ++++ execution/interface.go | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index afa4db0123..5a80a271b6 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -59,6 +59,10 @@ func (w *execClientWrapper) MarkFeedStart(to arbutil.MessageIndex) containers.Pr return containers.NewReadyPromise(markFeedStartWithReturn(to)) } +func (w *execClientWrapper) Maintenance() error { + return nil +} + func (w *execClientWrapper) Synced() bool { w.t.Error("not supported"); return false } func (w *execClientWrapper) FullSyncProgressMap() map[string]interface{} { diff --git a/execution/interface.go b/execution/interface.go index 589b9eb32d..3183946b4e 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -34,6 +34,8 @@ type ExecutionClient interface { HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] + + Maintenance() error } // needed for validators / stakers @@ -67,8 +69,6 @@ type FullExecutionClient interface { Start(ctx context.Context) error StopAndWait() - Maintenance() error - ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) } From 8147b2c8dab6d553b4d6d2b74055f240203cff3f Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 30 Dec 2024 16:14:49 -0300 Subject: [PATCH 16/33] Uses ExecutionClient instead of FullExecutionClient in MaintenanceRunner --- arbnode/maintenance.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/maintenance.go b/arbnode/maintenance.go index 5e4e56b577..e73cee5d4b 100644 --- a/arbnode/maintenance.go +++ b/arbnode/maintenance.go @@ -24,7 +24,7 @@ import ( type MaintenanceRunner struct { stopwaiter.StopWaiter - exec execution.FullExecutionClient + exec execution.ExecutionClient config MaintenanceConfigFetcher seqCoordinator *SeqCoordinator dbs []ethdb.Database @@ -87,7 +87,7 @@ var DefaultMaintenanceConfig = MaintenanceConfig{ type MaintenanceConfigFetcher func() *MaintenanceConfig -func NewMaintenanceRunner(config MaintenanceConfigFetcher, seqCoordinator *SeqCoordinator, dbs []ethdb.Database, exec execution.FullExecutionClient) (*MaintenanceRunner, error) { +func NewMaintenanceRunner(config MaintenanceConfigFetcher, seqCoordinator *SeqCoordinator, dbs []ethdb.Database, exec execution.ExecutionClient) (*MaintenanceRunner, error) { cfg := config() if err := cfg.Validate(); err != nil { return nil, fmt.Errorf("validating config: %w", err) From e03febc60df68540ffc11d0f115d54a18fcc5e56 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Mon, 30 Dec 2024 16:35:01 -0300 Subject: [PATCH 17/33] ExecutionClient.Maintenance returns promise --- arbnode/inbox_test.go | 4 ++-- arbnode/maintenance.go | 3 ++- execution/gethexec/node.go | 10 +++++++--- execution/interface.go | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 5a80a271b6..dc80cd20d9 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -59,8 +59,8 @@ func (w *execClientWrapper) MarkFeedStart(to arbutil.MessageIndex) containers.Pr return containers.NewReadyPromise(markFeedStartWithReturn(to)) } -func (w *execClientWrapper) Maintenance() error { - return nil +func (w *execClientWrapper) Maintenance() containers.PromiseInterface[struct{}] { + return containers.NewReadyPromise(struct{}{}, nil) } func (w *execClientWrapper) Synced() bool { w.t.Error("not supported"); return false } diff --git a/arbnode/maintenance.go b/arbnode/maintenance.go index e73cee5d4b..5968cec75d 100644 --- a/arbnode/maintenance.go +++ b/arbnode/maintenance.go @@ -183,7 +183,8 @@ func (mr *MaintenanceRunner) runMaintenance() { } expected++ go func() { - results <- mr.exec.Maintenance() + _, res := mr.exec.Maintenance().Await(mr.GetContext()) + results <- res }() for i := 0; i < expected; i++ { err := <-results diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 49e9e6795d..0a8bb6b67f 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -461,8 +461,12 @@ func (n *ExecutionNode) MessageIndexToBlockNumber(messageNum arbutil.MessageInde return n.ExecEngine.MessageIndexToBlockNumber(messageNum) } -func (n *ExecutionNode) Maintenance() error { - return n.ChainDB.Compact(nil, nil) +func (n *ExecutionNode) Maintenance() containers.PromiseInterface[struct{}] { + compactWithReturn := func() (struct{}, error) { + err := n.ChainDB.Compact(nil, nil) + return struct{}{}, err + } + return containers.NewReadyPromise(compactWithReturn()) } func (n *ExecutionNode) Synced() bool { @@ -541,7 +545,7 @@ func (n *ExecutionClientImpl) Start(ctx context.Context) error { func (n *ExecutionClientImpl) StopAndWait() { n.ExecutionNode.StopAndWait() } -func (n *ExecutionClientImpl) Maintenance() error { +func (n *ExecutionClientImpl) Maintenance() containers.PromiseInterface[struct{}] { return n.ExecutionNode.Maintenance() } func (n *ExecutionClientImpl) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { diff --git a/execution/interface.go b/execution/interface.go index 3183946b4e..e21220a514 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -35,7 +35,7 @@ type ExecutionClient interface { ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*MessageResult] MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] - Maintenance() error + Maintenance() containers.PromiseInterface[struct{}] } // needed for validators / stakers From 962c3a094a05ecb71c1cc6ee4874150eb1aa5008 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 31 Dec 2024 20:47:58 -0300 Subject: [PATCH 18/33] Refactor CreateNode --- arbnode/node.go | 532 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 404 insertions(+), 128 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 4973ff5fb7..622167000d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -262,6 +262,7 @@ type Node struct { ArbDB ethdb.Database Stack *node.Node Execution execution.FullExecutionClient + ExecutionClient execution.ExecutionClient L1Reader *headerreader.HeaderReader TxStreamer *TransactionStreamer DeployInfo *chaininfo.RollupAddresses @@ -410,44 +411,30 @@ func StakerDataposter( }) } -func createNodeImpl( - ctx context.Context, - stack *node.Node, - exec execution.FullExecutionClient, - arbDb ethdb.Database, - configFetcher ConfigFetcher, - l2Config *params.ChainConfig, - l1client *ethclient.Client, - deployInfo *chaininfo.RollupAddresses, - txOptsValidator *bind.TransactOpts, - txOptsBatchPoster *bind.TransactOpts, - dataSigner signature.DataSignerFunc, - fatalErrChan chan error, - parentChainID *big.Int, - blobReader daprovider.BlobReader, -) (*Node, error) { - config := configFetcher.Get() - - err := checkArbDbSchemaVersion(arbDb) - if err != nil { - return nil, err - } - - l2ChainId := l2Config.ChainID.Uint64() - +func getSyncMonitor(configFetcher ConfigFetcher) *SyncMonitor { syncConfigFetcher := func() *SyncMonitorConfig { return &configFetcher.Get().SyncMonitor } - syncMonitor := NewSyncMonitor(syncConfigFetcher) + return NewSyncMonitor(syncConfigFetcher) +} + +func getL1Reader(ctx context.Context, configFetcher ConfigFetcher, l1client *ethclient.Client) (*headerreader.HeaderReader, error) { + config := configFetcher.Get() var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + var err error l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys) if err != nil { return nil, err } } + return l1Reader, nil +} + +func getBroadcastServer(configFetcher ConfigFetcher, dataSigner signature.DataSignerFunc, l2ChainId uint64, fatalErrChan chan error) (*broadcaster.Broadcaster, error) { + config := configFetcher.Get() var broadcastServer *broadcaster.Broadcaster if config.Feed.Output.Enable { @@ -460,13 +447,10 @@ func createNodeImpl( } broadcastServer = broadcaster.NewBroadcaster(func() *wsbroadcastserver.BroadcasterConfig { return &configFetcher.Get().Feed.Output }, l2ChainId, fatalErrChan, maybeDataSigner) } + return broadcastServer, nil +} - transactionStreamerConfigFetcher := func() *TransactionStreamerConfig { return &configFetcher.Get().TransactionStreamer } - txStreamer, err := NewTransactionStreamer(arbDb, l2Config, exec, broadcastServer, fatalErrChan, transactionStreamerConfigFetcher, &configFetcher.Get().SnapSyncTest) - if err != nil { - return nil, err - } - var coordinator *SeqCoordinator +func getBPVerifier(deployInfo *chaininfo.RollupAddresses, l1client *ethclient.Client) (*contracts.AddressVerifier, error) { var bpVerifier *contracts.AddressVerifier if deployInfo != nil && l1client != nil { sequencerInboxAddr := deployInfo.SequencerInbox @@ -477,20 +461,31 @@ func createNodeImpl( } bpVerifier = contracts.NewAddressVerifier(seqInboxCaller) } + return bpVerifier, nil +} - if config.SeqCoordinator.Enable { - coordinator, err = NewSeqCoordinator(dataSigner, bpVerifier, txStreamer, exec, syncMonitor, config.SeqCoordinator) - if err != nil { - return nil, err - } - } else if config.Sequencer && !config.Dangerous.NoSequencerCoordinator { - return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-sequencer-coordinator set") - } +func getMaintenanceRunner( + arbDb ethdb.Database, + configFetcher ConfigFetcher, + coordinator *SeqCoordinator, + exec execution.ExecutionClient, +) (*MaintenanceRunner, error) { dbs := []ethdb.Database{arbDb} maintenanceRunner, err := NewMaintenanceRunner(func() *MaintenanceConfig { return &configFetcher.Get().Maintenance }, coordinator, dbs, exec) if err != nil { return nil, err } + return maintenanceRunner, nil +} + +func getBroadcastClients( + configFetcher ConfigFetcher, + txStreamer *TransactionStreamer, + l2ChainId uint64, + bpVerifier *contracts.AddressVerifier, + fatalErrChan chan error, +) (*broadcastclients.BroadcastClients, error) { + config := configFetcher.Get() var broadcastClients *broadcastclients.BroadcastClients if config.Feed.Input.Enable() { @@ -512,62 +507,56 @@ func createNodeImpl( return nil, err } } + return broadcastClients, nil +} - if !config.ParentChainReader.Enable { - return &Node{ - ArbDB: arbDb, - Stack: stack, - Execution: exec, - L1Reader: nil, - TxStreamer: txStreamer, - DeployInfo: nil, - BlobReader: blobReader, - InboxReader: nil, - InboxTracker: nil, - DelayedSequencer: nil, - BatchPoster: nil, - MessagePruner: nil, - BlockValidator: nil, - StatelessBlockValidator: nil, - Staker: nil, - BroadcastServer: broadcastServer, - BroadcastClients: broadcastClients, - SeqCoordinator: coordinator, - MaintenanceRunner: maintenanceRunner, - DASLifecycleManager: nil, - SyncMonitor: syncMonitor, - configFetcher: configFetcher, - ctx: ctx, - }, nil - } - +func getDelayedBridgeAndSequencerInbox( + deployInfo *chaininfo.RollupAddresses, + l1client *ethclient.Client, +) (*DelayedBridge, *SequencerInbox, error) { if deployInfo == nil { - return nil, errors.New("deployinfo is nil") + return nil, nil, errors.New("deployinfo is nil") } delayedBridge, err := NewDelayedBridge(l1client, deployInfo.Bridge, deployInfo.DeployedAt) if err != nil { - return nil, err + return nil, nil, err } // #nosec G115 sequencerInbox, err := NewSequencerInbox(l1client, deployInfo.SequencerInbox, int64(deployInfo.DeployedAt)) if err != nil { - return nil, err + return nil, nil, err } + return delayedBridge, sequencerInbox, nil +} + +func getDAS( + ctx context.Context, + configFetcher ConfigFetcher, + l2Config *params.ChainConfig, + txStreamer *TransactionStreamer, + blobReader daprovider.BlobReader, + l1Reader *headerreader.HeaderReader, + deployInfo *chaininfo.RollupAddresses, + dataSigner signature.DataSignerFunc, + l1client *ethclient.Client, +) (das.DataAvailabilityServiceWriter, *das.LifecycleManager, []daprovider.Reader, error) { + config := configFetcher.Get() var daWriter das.DataAvailabilityServiceWriter var daReader das.DataAvailabilityServiceReader var dasLifecycleManager *das.LifecycleManager var dasKeysetFetcher *das.KeysetFetcher if config.DataAvailability.Enable { + var err error if config.BatchPoster.Enable { daWriter, daReader, dasKeysetFetcher, dasLifecycleManager, err = das.CreateBatchPosterDAS(ctx, &config.DataAvailability, dataSigner, l1client, deployInfo.SequencerInbox) if err != nil { - return nil, err + return nil, nil, nil, err } } else { daReader, dasKeysetFetcher, dasLifecycleManager, err = das.CreateDAReaderForNode(ctx, &config.DataAvailability, l1Reader, &deployInfo.SequencerInbox) if err != nil { - return nil, err + return nil, nil, nil, err } } @@ -580,12 +569,12 @@ func createNodeImpl( daReader = das.NewReaderPanicWrapper(daReader) } } else if l2Config.ArbitrumChainParams.DataAvailabilityCommittee { - return nil, errors.New("a data availability service is required for this chain, but it was not configured") + return nil, nil, nil, errors.New("a data availability service is required for this chain, but it was not configured") } // We support a nil txStreamer for the pruning code if txStreamer != nil && txStreamer.chainConfig.ArbitrumChainParams.DataAvailabilityCommittee && daReader == nil { - return nil, errors.New("data availability service required but unconfigured") + return nil, nil, nil, errors.New("data availability service required but unconfigured") } var dapReaders []daprovider.Reader if daReader != nil { @@ -594,9 +583,26 @@ func createNodeImpl( if blobReader != nil { dapReaders = append(dapReaders, daprovider.NewReaderForBlobReader(blobReader)) } + + return daWriter, dasLifecycleManager, dapReaders, nil +} + +func getInboxTrackerAndReader( + arbDb ethdb.Database, + txStreamer *TransactionStreamer, + dapReaders []daprovider.Reader, + configFetcher ConfigFetcher, + l1client *ethclient.Client, + l1Reader *headerreader.HeaderReader, + deployInfo *chaininfo.RollupAddresses, + delayedBridge *DelayedBridge, + sequencerInbox *SequencerInbox, +) (*InboxTracker, *InboxReader, error) { + config := configFetcher.Get() + inboxTracker, err := NewInboxTracker(arbDb, txStreamer, dapReaders, config.SnapSyncTest) if err != nil { - return nil, err + return nil, nil, err } firstMessageBlock := new(big.Int).SetUint64(deployInfo.DeployedAt) if config.SnapSyncTest.Enabled { @@ -622,33 +628,23 @@ func createNodeImpl( } inboxReader, err := NewInboxReader(inboxTracker, l1client, l1Reader, firstMessageBlock, delayedBridge, sequencerInbox, func() *InboxReaderConfig { return &configFetcher.Get().InboxReader }) if err != nil { - return nil, err + return nil, nil, err } txStreamer.SetInboxReaders(inboxReader, delayedBridge) - var statelessBlockValidator *staker.StatelessBlockValidator - if config.BlockValidator.RedisValidationClientConfig.Enabled() || config.BlockValidator.ValidationServerConfigs[0].URL != "" { - statelessBlockValidator, err = staker.NewStatelessBlockValidator( - inboxReader, - inboxTracker, - txStreamer, - exec, - rawdb.NewTable(arbDb, storage.BlockValidatorPrefix), - dapReaders, - func() *staker.BlockValidatorConfig { return &configFetcher.Get().BlockValidator }, - stack, - ) - } else { - err = errors.New("no validator url specified") - } - if err != nil { - if config.ValidatorRequired() || config.Staker.Enable { - return nil, fmt.Errorf("%w: failed to init block validator", err) - } - log.Warn("validation not supported", "err", err) - statelessBlockValidator = nil - } + return inboxTracker, inboxReader, nil +} + +func getBlockValidator( + configFetcher ConfigFetcher, + statelessBlockValidator *staker.StatelessBlockValidator, + inboxTracker *InboxTracker, + txStreamer *TransactionStreamer, + fatalErrChan chan error, +) (*staker.BlockValidator, error) { + config := configFetcher.Get() + var err error var blockValidator *staker.BlockValidator if config.ValidatorRequired() { blockValidator, err = staker.NewBlockValidator( @@ -662,6 +658,27 @@ func createNodeImpl( return nil, err } } + return blockValidator, err +} + +func getStaker( + ctx context.Context, + configFetcher ConfigFetcher, + arbDb ethdb.Database, + l1Reader *headerreader.HeaderReader, + txOptsValidator *bind.TransactOpts, + syncMonitor *SyncMonitor, + parentChainID *big.Int, + l1client *ethclient.Client, + deployInfo *chaininfo.RollupAddresses, + txStreamer *TransactionStreamer, + inboxTracker *InboxTracker, + stack *node.Node, + fatalErrChan chan error, + statelessBlockValidator *staker.StatelessBlockValidator, + blockValidator *staker.BlockValidator, +) (*multiprotocolstaker.MultiProtocolStaker, *MessagePruner, common.Address, error) { + config := configFetcher.Get() var stakerObj *multiprotocolstaker.MultiProtocolStaker var messagePruner *MessagePruner @@ -678,7 +695,7 @@ func createNodeImpl( parentChainID, ) if err != nil { - return nil, err + return nil, nil, common.Address{}, err } getExtraGas := func() uint64 { return configFetcher.Get().Staker.ExtraGas } // TODO: factor this out into separate helper, and split rest of node @@ -690,7 +707,7 @@ func createNodeImpl( if len(config.Staker.ContractWalletAddress) > 0 { if !common.IsHexAddress(config.Staker.ContractWalletAddress) { log.Error("invalid validator smart contract wallet", "addr", config.Staker.ContractWalletAddress) - return nil, errors.New("invalid validator smart contract wallet address") + return nil, nil, common.Address{}, errors.New("invalid validator smart contract wallet address") } tmpAddress := common.HexToAddress(config.Staker.ContractWalletAddress) existingWalletAddress = &tmpAddress @@ -698,15 +715,15 @@ func createNodeImpl( // #nosec G115 wallet, err = validatorwallet.NewContract(dp, existingWalletAddress, deployInfo.ValidatorWalletCreator, deployInfo.Rollup, l1Reader, txOptsValidator, int64(deployInfo.DeployedAt), func(common.Address) {}, getExtraGas) if err != nil { - return nil, err + return nil, nil, common.Address{}, err } } else { if len(config.Staker.ContractWalletAddress) > 0 { - return nil, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") + return nil, nil, common.Address{}, errors.New("validator contract wallet specified but flag to use a smart contract wallet was not specified") } wallet, err = validatorwallet.NewEOA(dp, deployInfo.Rollup, l1client, getExtraGas) if err != nil { - return nil, err + return nil, nil, common.Address{}, err } } } @@ -719,18 +736,116 @@ func createNodeImpl( stakerObj, err = multiprotocolstaker.NewMultiProtocolStaker(stack, l1Reader, wallet, bind.CallOpts{}, func() *legacystaker.L1ValidatorConfig { return &configFetcher.Get().Staker }, &configFetcher.Get().Bold, blockValidator, statelessBlockValidator, nil, deployInfo.StakeToken, confirmedNotifiers, deployInfo.ValidatorUtils, deployInfo.Bridge, fatalErrChan) if err != nil { - return nil, err + return nil, nil, common.Address{}, err } if err := wallet.Initialize(ctx); err != nil { - return nil, err + return nil, nil, common.Address{}, err } if dp != nil { stakerAddr = dp.Sender() } } + return stakerObj, messagePruner, stakerAddr, nil +} + +func getTransactionStreamer( + arbDb ethdb.Database, + l2Config *params.ChainConfig, + exec execution.ExecutionClient, + broadcastServer *broadcaster.Broadcaster, + configFetcher ConfigFetcher, + fatalErrChan chan error, +) (*TransactionStreamer, error) { + transactionStreamerConfigFetcher := func() *TransactionStreamerConfig { return &configFetcher.Get().TransactionStreamer } + txStreamer, err := NewTransactionStreamer(arbDb, l2Config, exec, broadcastServer, fatalErrChan, transactionStreamerConfigFetcher, &configFetcher.Get().SnapSyncTest) + if err != nil { + return nil, err + } + return txStreamer, nil +} + +func getSeqCoordinator( + configFetcher ConfigFetcher, + dataSigner signature.DataSignerFunc, + bpVerifier *contracts.AddressVerifier, + txStreamer *TransactionStreamer, + syncMonitor *SyncMonitor, + exec execution.ExecutionSequencer, +) (*SeqCoordinator, error) { + config := configFetcher.Get() + + var coordinator *SeqCoordinator + if config.SeqCoordinator.Enable { + var err error + coordinator, err = NewSeqCoordinator(dataSigner, bpVerifier, txStreamer, exec, syncMonitor, config.SeqCoordinator) + if err != nil { + return nil, err + } + } else if config.Sequencer && !config.Dangerous.NoSequencerCoordinator { + return nil, errors.New("sequencer must be enabled with coordinator, unless dangerous.no-sequencer-coordinator set") + } + return coordinator, nil +} + +func getStatelessBlockValidator( + configFetcher ConfigFetcher, + inboxReader *InboxReader, + inboxTracker *InboxTracker, + txStreamer *TransactionStreamer, + exec execution.FullExecutionClient, + arbDb ethdb.Database, + dapReaders []daprovider.Reader, + stack *node.Node, +) (*staker.StatelessBlockValidator, error) { + config := configFetcher.Get() + + var err error + var statelessBlockValidator *staker.StatelessBlockValidator + if config.BlockValidator.RedisValidationClientConfig.Enabled() || config.BlockValidator.ValidationServerConfigs[0].URL != "" { + statelessBlockValidator, err = staker.NewStatelessBlockValidator( + inboxReader, + inboxTracker, + txStreamer, + exec, + rawdb.NewTable(arbDb, storage.BlockValidatorPrefix), + dapReaders, + func() *staker.BlockValidatorConfig { return &configFetcher.Get().BlockValidator }, + stack, + ) + } else { + err = errors.New("no validator url specified") + } + if err != nil { + if config.ValidatorRequired() || config.Staker.Enable { + return nil, fmt.Errorf("%w: failed to init block validator", err) + } + log.Warn("validation not supported", "err", err) + statelessBlockValidator = nil + } + + return statelessBlockValidator, nil +} + +func getBatchPoster( + ctx context.Context, + configFetcher ConfigFetcher, + txOptsBatchPoster *bind.TransactOpts, + daWriter das.DataAvailabilityServiceWriter, + l1Reader *headerreader.HeaderReader, + inboxTracker *InboxTracker, + txStreamer *TransactionStreamer, + exec execution.FullExecutionClient, + arbDb ethdb.Database, + syncMonitor *SyncMonitor, + deployInfo *chaininfo.RollupAddresses, + parentChainID *big.Int, + dapReaders []daprovider.Reader, + stakerAddr common.Address, +) (*BatchPoster, error) { + config := configFetcher.Get() + var batchPoster *BatchPoster - var delayedSequencer *DelayedSequencer if config.BatchPoster.Enable { if txOptsBatchPoster == nil && config.BatchPoster.DataPoster.ExternalSigner.URL == "" { return nil, errors.New("batchposter, but no TxOpts") @@ -739,6 +854,7 @@ func createNodeImpl( if daWriter != nil { dapWriter = daprovider.NewWriterForDAS(daWriter) } + var err error batchPoster, err = NewBatchPoster(ctx, &BatchPosterOpts{ DataPosterDB: rawdb.NewTable(arbDb, storage.BatchPosterPrefix), L1Reader: l1Reader, @@ -763,8 +879,165 @@ func createNodeImpl( } } + return batchPoster, nil +} + +func getDelayedSequencer( + l1Reader *headerreader.HeaderReader, + inboxReader *InboxReader, + exec execution.FullExecutionClient, + configFetcher ConfigFetcher, + coordinator *SeqCoordinator, +) (*DelayedSequencer, error) { // always create DelayedSequencer, it won't do anything if it is disabled - delayedSequencer, err = NewDelayedSequencer(l1Reader, inboxReader, exec, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) + delayedSequencer, err := NewDelayedSequencer(l1Reader, inboxReader, exec, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) + if err != nil { + return nil, err + } + return delayedSequencer, nil +} + +func getNodeParentChainReaderDisabled( + ctx context.Context, + arbDb ethdb.Database, + stack *node.Node, + exec execution.FullExecutionClient, + txStreamer *TransactionStreamer, + blobReader daprovider.BlobReader, + broadcastServer *broadcaster.Broadcaster, + broadcastClients *broadcastclients.BroadcastClients, + coordinator *SeqCoordinator, + maintenanceRunner *MaintenanceRunner, + syncMonitor *SyncMonitor, + configFetcher ConfigFetcher, +) *Node { + return &Node{ + ArbDB: arbDb, + Stack: stack, + Execution: exec, + L1Reader: nil, + TxStreamer: txStreamer, + DeployInfo: nil, + BlobReader: blobReader, + InboxReader: nil, + InboxTracker: nil, + DelayedSequencer: nil, + BatchPoster: nil, + MessagePruner: nil, + BlockValidator: nil, + StatelessBlockValidator: nil, + Staker: nil, + BroadcastServer: broadcastServer, + BroadcastClients: broadcastClients, + SeqCoordinator: coordinator, + MaintenanceRunner: maintenanceRunner, + DASLifecycleManager: nil, + SyncMonitor: syncMonitor, + configFetcher: configFetcher, + ctx: ctx, + } +} + +func createNodeImpl( + ctx context.Context, + stack *node.Node, + exec execution.FullExecutionClient, + arbDb ethdb.Database, + configFetcher ConfigFetcher, + l2Config *params.ChainConfig, + l1client *ethclient.Client, + deployInfo *chaininfo.RollupAddresses, + txOptsValidator *bind.TransactOpts, + txOptsBatchPoster *bind.TransactOpts, + dataSigner signature.DataSignerFunc, + fatalErrChan chan error, + parentChainID *big.Int, + blobReader daprovider.BlobReader, +) (*Node, error) { + config := configFetcher.Get() + + err := checkArbDbSchemaVersion(arbDb) + if err != nil { + return nil, err + } + + syncMonitor := getSyncMonitor(configFetcher) + + l1Reader, err := getL1Reader(ctx, configFetcher, l1client) + if err != nil { + return nil, err + } + + broadcastServer, err := getBroadcastServer(configFetcher, dataSigner, l2Config.ChainID.Uint64(), fatalErrChan) + if err != nil { + return nil, err + } + + txStreamer, err := getTransactionStreamer(arbDb, l2Config, exec, broadcastServer, configFetcher, fatalErrChan) + if err != nil { + return nil, err + } + + bpVerifier, err := getBPVerifier(deployInfo, l1client) + if err != nil { + return nil, err + } + + coordinator, err := getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, exec) + if err != nil { + return nil, err + } + + maintenanceRunner, err := getMaintenanceRunner(arbDb, configFetcher, coordinator, exec) + if err != nil { + return nil, err + } + + broadcastClients, err := getBroadcastClients(configFetcher, txStreamer, l2Config.ChainID.Uint64(), bpVerifier, fatalErrChan) + if err != nil { + return nil, err + } + + if !config.ParentChainReader.Enable { + return getNodeParentChainReaderDisabled(ctx, arbDb, stack, exec, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil + } + + delayedBridge, sequencerInbox, err := getDelayedBridgeAndSequencerInbox(deployInfo, l1client) + if err != nil { + return nil, err + } + + daWriter, dasLifecycleManager, dapReaders, err := getDAS(ctx, configFetcher, l2Config, txStreamer, blobReader, l1Reader, deployInfo, dataSigner, l1client) + if err != nil { + return nil, err + } + + inboxTracker, inboxReader, err := getInboxTrackerAndReader(arbDb, txStreamer, dapReaders, configFetcher, l1client, l1Reader, deployInfo, delayedBridge, sequencerInbox) + if err != nil { + return nil, err + } + + statelessBlockValidator, err := getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, exec, arbDb, dapReaders, stack) + if err != nil { + return nil, err + } + + blockValidator, err := getBlockValidator(configFetcher, statelessBlockValidator, inboxTracker, txStreamer, fatalErrChan) + if err != nil { + return nil, err + } + + stakerObj, messagePruner, stakerAddr, err := getStaker(ctx, configFetcher, arbDb, l1Reader, txOptsValidator, syncMonitor, parentChainID, l1client, deployInfo, txStreamer, inboxTracker, stack, fatalErrChan, statelessBlockValidator, blockValidator) + if err != nil { + return nil, err + } + + batchPoster, err := getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, exec, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) + if err != nil { + return nil, err + } + + delayedSequencer, err := getDelayedSequencer(l1Reader, inboxReader, exec, configFetcher, coordinator) if err != nil { return nil, err } @@ -848,26 +1121,7 @@ func (n *Node) OnConfigReload(_ *Config, _ *Config) error { return nil } -func CreateNode( - ctx context.Context, - stack *node.Node, - exec execution.FullExecutionClient, - arbDb ethdb.Database, - configFetcher ConfigFetcher, - l2Config *params.ChainConfig, - l1client *ethclient.Client, - deployInfo *chaininfo.RollupAddresses, - txOptsValidator *bind.TransactOpts, - txOptsBatchPoster *bind.TransactOpts, - dataSigner signature.DataSignerFunc, - fatalErrChan chan error, - parentChainID *big.Int, - blobReader daprovider.BlobReader, -) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) - if err != nil { - return nil, err - } +func registerAPIs(currentNode *Node, stack *node.Node) { var apis []rpc.API if currentNode.BlockValidator != nil { apis = append(apis, rpc.API{ @@ -889,7 +1143,29 @@ func CreateNode( } stack.RegisterAPIs(apis) +} +func CreateNode( + ctx context.Context, + stack *node.Node, + exec execution.FullExecutionClient, + arbDb ethdb.Database, + configFetcher ConfigFetcher, + l2Config *params.ChainConfig, + l1client *ethclient.Client, + deployInfo *chaininfo.RollupAddresses, + txOptsValidator *bind.TransactOpts, + txOptsBatchPoster *bind.TransactOpts, + dataSigner signature.DataSignerFunc, + fatalErrChan chan error, + parentChainID *big.Int, + blobReader daprovider.BlobReader, +) (*Node, error) { + currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + if err != nil { + return nil, err + } + registerAPIs(currentNode, stack) return currentNode, nil } From 316e9e90c309d4a45ed3cc3d9a8082d8d6bb58f9 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 31 Dec 2024 20:53:20 -0300 Subject: [PATCH 19/33] Renames CreateNode to CreateNodeFullExecutionClient --- arbnode/node.go | 51 +++++++++++++++++++++++-------------- cmd/nitro/nitro.go | 2 +- system_tests/common_test.go | 10 ++++---- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 622167000d..4371e4c137 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -941,7 +941,8 @@ func getNodeParentChainReaderDisabled( func createNodeImpl( ctx context.Context, stack *node.Node, - exec execution.FullExecutionClient, + fullExecutionClient execution.FullExecutionClient, + executionClient execution.ExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -973,7 +974,7 @@ func createNodeImpl( return nil, err } - txStreamer, err := getTransactionStreamer(arbDb, l2Config, exec, broadcastServer, configFetcher, fatalErrChan) + txStreamer, err := getTransactionStreamer(arbDb, l2Config, executionClient, broadcastServer, configFetcher, fatalErrChan) if err != nil { return nil, err } @@ -983,12 +984,15 @@ func createNodeImpl( return nil, err } - coordinator, err := getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, exec) - if err != nil { - return nil, err + var coordinator *SeqCoordinator + if fullExecutionClient != nil { + coordinator, err = getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, fullExecutionClient) + if err != nil { + return nil, err + } } - maintenanceRunner, err := getMaintenanceRunner(arbDb, configFetcher, coordinator, exec) + maintenanceRunner, err := getMaintenanceRunner(arbDb, configFetcher, coordinator, executionClient) if err != nil { return nil, err } @@ -999,7 +1003,7 @@ func createNodeImpl( } if !config.ParentChainReader.Enable { - return getNodeParentChainReaderDisabled(ctx, arbDb, stack, exec, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil + return getNodeParentChainReaderDisabled(ctx, arbDb, stack, fullExecutionClient, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil } delayedBridge, sequencerInbox, err := getDelayedBridgeAndSequencerInbox(deployInfo, l1client) @@ -1017,9 +1021,12 @@ func createNodeImpl( return nil, err } - statelessBlockValidator, err := getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, exec, arbDb, dapReaders, stack) - if err != nil { - return nil, err + var statelessBlockValidator *staker.StatelessBlockValidator + if fullExecutionClient != nil { + statelessBlockValidator, err = getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, fullExecutionClient, arbDb, dapReaders, stack) + if err != nil { + return nil, err + } } blockValidator, err := getBlockValidator(configFetcher, statelessBlockValidator, inboxTracker, txStreamer, fatalErrChan) @@ -1032,20 +1039,26 @@ func createNodeImpl( return nil, err } - batchPoster, err := getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, exec, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) - if err != nil { - return nil, err + var batchPoster *BatchPoster + if fullExecutionClient != nil { + batchPoster, err = getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, fullExecutionClient, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) + if err != nil { + return nil, err + } } - delayedSequencer, err := getDelayedSequencer(l1Reader, inboxReader, exec, configFetcher, coordinator) - if err != nil { - return nil, err + var delayedSequencer *DelayedSequencer + if fullExecutionClient != nil { + delayedSequencer, err = getDelayedSequencer(l1Reader, inboxReader, fullExecutionClient, configFetcher, coordinator) + if err != nil { + return nil, err + } } return &Node{ ArbDB: arbDb, Stack: stack, - Execution: exec, + Execution: fullExecutionClient, L1Reader: l1Reader, TxStreamer: txStreamer, DeployInfo: deployInfo, @@ -1145,7 +1158,7 @@ func registerAPIs(currentNode *Node, stack *node.Node) { stack.RegisterAPIs(apis) } -func CreateNode( +func CreateNodeFullExecutionClient( ctx context.Context, stack *node.Node, exec execution.FullExecutionClient, @@ -1161,7 +1174,7 @@ func CreateNode( parentChainID *big.Int, blobReader daprovider.BlobReader, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + currentNode, err := createNodeImpl(ctx, stack, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) if err != nil { return nil, err } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index e4e1b79353..36edd07f0f 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -534,7 +534,7 @@ func mainImpl() int { return 1 } - currentNode, err := arbnode.CreateNode( + currentNode, err := arbnode.CreateNodeFullExecutionClient( ctx, stack, execNode, diff --git a/system_tests/common_test.go b/system_tests/common_test.go index 515508012c..d57728ee64 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -503,7 +503,7 @@ func buildOnParentChain( Require(t, err) fatalErrChan := make(chan error, 10) - chainTestClient.ConsensusNode, err = arbnode.CreateNode( + chainTestClient.ConsensusNode, err = arbnode.CreateNodeFullExecutionClient( ctx, chainTestClient.Stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainTestClient.Client, addresses, validatorTxOptsPtr, sequencerTxOptsPtr, dataSigner, fatalErrChan, parentChainId, nil) Require(t, err) @@ -625,7 +625,7 @@ func (b *NodeBuilder) BuildL2(t *testing.T) func() { Require(t, err) fatalErrChan := make(chan error, 10) - b.L2.ConsensusNode, err = arbnode.CreateNode( + b.L2.ConsensusNode, err = arbnode.CreateNodeFullExecutionClient( b.ctx, b.L2.Stack, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, fatalErrChan, big.NewInt(1337), nil) Require(t, err) @@ -674,7 +674,7 @@ func (b *NodeBuilder) RestartL2Node(t *testing.T) { Require(t, err) feedErrChan := make(chan error, 10) - currentNode, err := arbnode.CreateNode(b.ctx, stack, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, big.NewInt(1337), nil) + currentNode, err := arbnode.CreateNodeFullExecutionClient(b.ctx, stack, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, big.NewInt(1337), nil) Require(t, err) Require(t, currentNode.Start(b.ctx)) @@ -1560,9 +1560,9 @@ func Create2ndNodeWithConfig( var currentNode *arbnode.Node if useExecutionClientImplAsFullExecutionClient { - currentNode, err = arbnode.CreateNode(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } else { - currentNode, err = arbnode.CreateNode(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } Require(t, err) From ff3d3d7a11aba4cc86ad28e4865d82bd5b357783 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 31 Dec 2024 21:01:47 -0300 Subject: [PATCH 20/33] Uses more specific execution interfaces in createNodeImpl --- arbnode/node.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 4371e4c137..c585a4f292 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -793,7 +793,7 @@ func getStatelessBlockValidator( inboxReader *InboxReader, inboxTracker *InboxTracker, txStreamer *TransactionStreamer, - exec execution.FullExecutionClient, + exec execution.ExecutionRecorder, arbDb ethdb.Database, dapReaders []daprovider.Reader, stack *node.Node, @@ -885,7 +885,7 @@ func getBatchPoster( func getDelayedSequencer( l1Reader *headerreader.HeaderReader, inboxReader *InboxReader, - exec execution.FullExecutionClient, + exec execution.ExecutionSequencer, configFetcher ConfigFetcher, coordinator *SeqCoordinator, ) (*DelayedSequencer, error) { @@ -941,8 +941,10 @@ func getNodeParentChainReaderDisabled( func createNodeImpl( ctx context.Context, stack *node.Node, - fullExecutionClient execution.FullExecutionClient, executionClient execution.ExecutionClient, + executionSequencer execution.ExecutionSequencer, + executionRecorder execution.ExecutionRecorder, + fullExecutionClient execution.FullExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -985,8 +987,8 @@ func createNodeImpl( } var coordinator *SeqCoordinator - if fullExecutionClient != nil { - coordinator, err = getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, fullExecutionClient) + if executionSequencer != nil { + coordinator, err = getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, executionSequencer) if err != nil { return nil, err } @@ -1022,8 +1024,8 @@ func createNodeImpl( } var statelessBlockValidator *staker.StatelessBlockValidator - if fullExecutionClient != nil { - statelessBlockValidator, err = getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, fullExecutionClient, arbDb, dapReaders, stack) + if executionRecorder != nil { + statelessBlockValidator, err = getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, executionRecorder, arbDb, dapReaders, stack) if err != nil { return nil, err } @@ -1048,8 +1050,8 @@ func createNodeImpl( } var delayedSequencer *DelayedSequencer - if fullExecutionClient != nil { - delayedSequencer, err = getDelayedSequencer(l1Reader, inboxReader, fullExecutionClient, configFetcher, coordinator) + if executionSequencer != nil { + delayedSequencer, err = getDelayedSequencer(l1Reader, inboxReader, executionSequencer, configFetcher, coordinator) if err != nil { return nil, err } @@ -1174,7 +1176,7 @@ func CreateNodeFullExecutionClient( parentChainID *big.Int, blobReader daprovider.BlobReader, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + currentNode, err := createNodeImpl(ctx, stack, exec, exec, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) if err != nil { return nil, err } From 621d9457df852edd433af4e1e9f3ba274fb84c1d Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 31 Dec 2024 21:08:17 -0300 Subject: [PATCH 21/33] ExecutionBatchPoster --- arbnode/batch_poster.go | 4 ++-- arbnode/node.go | 9 +++++---- execution/interface.go | 8 ++++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 70c5952042..3adedb4ac1 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -97,7 +97,7 @@ type BatchPoster struct { l1Reader *headerreader.HeaderReader inbox *InboxTracker streamer *TransactionStreamer - arbOSVersionGetter execution.FullExecutionClient + arbOSVersionGetter execution.ExecutionBatchPoster config BatchPosterConfigFetcher seqInbox *bridgegen.SequencerInbox syncMonitor *SyncMonitor @@ -307,7 +307,7 @@ type BatchPosterOpts struct { L1Reader *headerreader.HeaderReader Inbox *InboxTracker Streamer *TransactionStreamer - VersionGetter execution.FullExecutionClient + VersionGetter execution.ExecutionBatchPoster SyncMonitor *SyncMonitor Config BatchPosterConfigFetcher DeployInfo *chaininfo.RollupAddresses diff --git a/arbnode/node.go b/arbnode/node.go index c585a4f292..c0e9eea5fa 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -835,7 +835,7 @@ func getBatchPoster( l1Reader *headerreader.HeaderReader, inboxTracker *InboxTracker, txStreamer *TransactionStreamer, - exec execution.FullExecutionClient, + exec execution.ExecutionBatchPoster, arbDb ethdb.Database, syncMonitor *SyncMonitor, deployInfo *chaininfo.RollupAddresses, @@ -944,6 +944,7 @@ func createNodeImpl( executionClient execution.ExecutionClient, executionSequencer execution.ExecutionSequencer, executionRecorder execution.ExecutionRecorder, + executionBatchPoster execution.ExecutionBatchPoster, fullExecutionClient execution.FullExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, @@ -1042,8 +1043,8 @@ func createNodeImpl( } var batchPoster *BatchPoster - if fullExecutionClient != nil { - batchPoster, err = getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, fullExecutionClient, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) + if executionBatchPoster != nil { + batchPoster, err = getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, executionBatchPoster, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) if err != nil { return nil, err } @@ -1176,7 +1177,7 @@ func CreateNodeFullExecutionClient( parentChainID *big.Int, blobReader daprovider.BlobReader, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, exec, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + currentNode, err := createNodeImpl(ctx, stack, exec, exec, exec, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) if err != nil { return nil, err } diff --git a/execution/interface.go b/execution/interface.go index e21220a514..669ef68c3f 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -61,15 +61,19 @@ type ExecutionSequencer interface { FullSyncProgressMap() map[string]interface{} } +// needed for batch poster +type ExecutionBatchPoster interface { + ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) +} + type FullExecutionClient interface { ExecutionClient ExecutionRecorder ExecutionSequencer + ExecutionBatchPoster Start(ctx context.Context) error StopAndWait() - - ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) } // not implemented in execution, used as input From b4bd1fc45a3f6169bf6dd28dfd8317ecc4170b26 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Tue, 31 Dec 2024 21:29:08 -0300 Subject: [PATCH 22/33] Get rid of FullExecutionClient --- arbnode/node.go | 33 ++++++++++++++++------------ cmd/nitro/nitro.go | 3 +++ execution/interface.go | 13 +++-------- system_tests/block_validator_test.go | 2 +- system_tests/common_test.go | 12 +++++----- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index c0e9eea5fa..73da3869de 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -261,8 +261,8 @@ func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { type Node struct { ArbDB ethdb.Database Stack *node.Node - Execution execution.FullExecutionClient ExecutionClient execution.ExecutionClient + ExecutionSequencer execution.ExecutionSequencer L1Reader *headerreader.HeaderReader TxStreamer *TransactionStreamer DeployInfo *chaininfo.RollupAddresses @@ -901,7 +901,8 @@ func getNodeParentChainReaderDisabled( ctx context.Context, arbDb ethdb.Database, stack *node.Node, - exec execution.FullExecutionClient, + executionClient execution.ExecutionClient, + executionSequencer execution.ExecutionSequencer, txStreamer *TransactionStreamer, blobReader daprovider.BlobReader, broadcastServer *broadcaster.Broadcaster, @@ -914,7 +915,8 @@ func getNodeParentChainReaderDisabled( return &Node{ ArbDB: arbDb, Stack: stack, - Execution: exec, + ExecutionClient: executionClient, + ExecutionSequencer: executionSequencer, L1Reader: nil, TxStreamer: txStreamer, DeployInfo: nil, @@ -945,7 +947,6 @@ func createNodeImpl( executionSequencer execution.ExecutionSequencer, executionRecorder execution.ExecutionRecorder, executionBatchPoster execution.ExecutionBatchPoster, - fullExecutionClient execution.FullExecutionClient, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -1006,7 +1007,7 @@ func createNodeImpl( } if !config.ParentChainReader.Enable { - return getNodeParentChainReaderDisabled(ctx, arbDb, stack, fullExecutionClient, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil + return getNodeParentChainReaderDisabled(ctx, arbDb, stack, executionClient, executionSequencer, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil } delayedBridge, sequencerInbox, err := getDelayedBridgeAndSequencerInbox(deployInfo, l1client) @@ -1061,7 +1062,8 @@ func createNodeImpl( return &Node{ ArbDB: arbDb, Stack: stack, - Execution: fullExecutionClient, + ExecutionClient: executionClient, + ExecutionSequencer: executionSequencer, L1Reader: l1Reader, TxStreamer: txStreamer, DeployInfo: deployInfo, @@ -1164,7 +1166,10 @@ func registerAPIs(currentNode *Node, stack *node.Node) { func CreateNodeFullExecutionClient( ctx context.Context, stack *node.Node, - exec execution.FullExecutionClient, + executionClient execution.ExecutionClient, + executionSequencer execution.ExecutionSequencer, + executionRecorder execution.ExecutionRecorder, + executionBatchPoster execution.ExecutionBatchPoster, arbDb ethdb.Database, configFetcher ConfigFetcher, l2Config *params.ChainConfig, @@ -1177,7 +1182,7 @@ func CreateNodeFullExecutionClient( parentChainID *big.Int, blobReader daprovider.BlobReader, ) (*Node, error) { - currentNode, err := createNodeImpl(ctx, stack, exec, exec, exec, exec, exec, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + currentNode, err := createNodeImpl(ctx, stack, executionClient, executionSequencer, executionRecorder, executionBatchPoster, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) if err != nil { return nil, err } @@ -1186,8 +1191,8 @@ func CreateNodeFullExecutionClient( } func (n *Node) Start(ctx context.Context) error { - executionNode, isExecutionNode := n.Execution.(*gethexec.ExecutionNode) - executionClientImpl, isExecutionClientImpl := n.Execution.(*gethexec.ExecutionClientImpl) + executionNode, isExecutionNode := n.ExecutionClient.(*gethexec.ExecutionNode) + executionClientImpl, isExecutionClientImpl := n.ExecutionClient.(*gethexec.ExecutionClientImpl) var err error if isExecutionNode { @@ -1207,7 +1212,7 @@ func (n *Node) Start(ctx context.Context) error { if isExecutionNode { executionNode.SetConsensusClient(n) } - err = n.Execution.Start(ctx) + err = n.ExecutionClient.Start(ctx) if err != nil { return fmt.Errorf("error starting exec client: %w", err) } @@ -1257,7 +1262,7 @@ func (n *Node) Start(ctx context.Context) error { if n.SeqCoordinator != nil { n.SeqCoordinator.Start(ctx) } else { - n.Execution.Activate() + n.ExecutionSequencer.Activate() } if n.MaintenanceRunner != nil { n.MaintenanceRunner.Start(ctx) @@ -1377,8 +1382,8 @@ func (n *Node) StopAndWait() { if n.DASLifecycleManager != nil { n.DASLifecycleManager.StopAndWaitUntil(2 * time.Second) } - if n.Execution != nil { - n.Execution.StopAndWait() + if n.ExecutionClient != nil { + n.ExecutionClient.StopAndWait() } if err := n.Stack.Close(); err != nil { log.Error("error on stack close", "err", err) diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 36edd07f0f..03cc811e16 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -538,6 +538,9 @@ func mainImpl() int { ctx, stack, execNode, + execNode, + execNode, + execNode, arbDb, &NodeConfigFetcher{liveNodeConfig}, l2BlockChain.Config(), diff --git a/execution/interface.go b/execution/interface.go index 669ef68c3f..51de32a685 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -36,6 +36,9 @@ type ExecutionClient interface { MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] Maintenance() containers.PromiseInterface[struct{}] + + Start(ctx context.Context) error + StopAndWait() } // needed for validators / stakers @@ -66,16 +69,6 @@ type ExecutionBatchPoster interface { ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) } -type FullExecutionClient interface { - ExecutionClient - ExecutionRecorder - ExecutionSequencer - ExecutionBatchPoster - - Start(ctx context.Context) error - StopAndWait() -} - // not implemented in execution, used as input // BatchFetcher is required for any execution node type BatchFetcher interface { diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index d6ae4973ac..7dd2d50daf 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -247,7 +247,7 @@ func testBlockValidatorSimple(t *testing.T, opts Options) { if !testClientB.ConsensusNode.BlockValidator.WaitForPos(t, ctx, arbutil.MessageIndex(lastBlock.NumberU64()), timeout) { Fatal(t, "did not validate all blocks") } - gethExec, ok := testClientB.ConsensusNode.Execution.(*gethexec.ExecutionNode) + gethExec, ok := testClientB.ConsensusNode.ExecutionClient.(*gethexec.ExecutionNode) if !ok { t.Fail() } diff --git a/system_tests/common_test.go b/system_tests/common_test.go index d57728ee64..e019a59935 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -504,7 +504,7 @@ func buildOnParentChain( fatalErrChan := make(chan error, 10) chainTestClient.ConsensusNode, err = arbnode.CreateNodeFullExecutionClient( - ctx, chainTestClient.Stack, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainTestClient.Client, + ctx, chainTestClient.Stack, execNode, execNode, execNode, execNode, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainTestClient.Client, addresses, validatorTxOptsPtr, sequencerTxOptsPtr, dataSigner, fatalErrChan, parentChainId, nil) Require(t, err) @@ -626,7 +626,7 @@ func (b *NodeBuilder) BuildL2(t *testing.T) func() { fatalErrChan := make(chan error, 10) b.L2.ConsensusNode, err = arbnode.CreateNodeFullExecutionClient( - b.ctx, b.L2.Stack, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), + b.ctx, b.L2.Stack, execNode, execNode, execNode, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, fatalErrChan, big.NewInt(1337), nil) Require(t, err) @@ -674,7 +674,7 @@ func (b *NodeBuilder) RestartL2Node(t *testing.T) { Require(t, err) feedErrChan := make(chan error, 10) - currentNode, err := arbnode.CreateNodeFullExecutionClient(b.ctx, stack, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, big.NewInt(1337), nil) + currentNode, err := arbnode.CreateNodeFullExecutionClient(b.ctx, stack, execNode, execNode, execNode, execNode, arbDb, NewFetcherFromConfig(b.nodeConfig), blockchain.Config(), nil, nil, nil, nil, nil, feedErrChan, big.NewInt(1337), nil) Require(t, err) Require(t, currentNode.Start(b.ctx)) @@ -1560,9 +1560,9 @@ func Create2ndNodeWithConfig( var currentNode *arbnode.Node if useExecutionClientImplAsFullExecutionClient { - currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } else { - currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, currentExec, currentExec, currentExec, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } Require(t, err) @@ -1816,7 +1816,7 @@ func TestMain(m *testing.M) { func getExecNode(t *testing.T, node *arbnode.Node) *gethexec.ExecutionNode { t.Helper() - gethExec, ok := node.Execution.(*gethexec.ExecutionNode) + gethExec, ok := node.ExecutionClient.(*gethexec.ExecutionNode) if !ok { t.Fatal("failed to get exec node from arbnode") } From db2c8dcbeb947919f2a8c4bef44a874e80739bab Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:23:17 -0300 Subject: [PATCH 23/33] Checks execution clients in CreateNodeFullExecutionClient --- arbnode/node.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arbnode/node.go b/arbnode/node.go index 73da3869de..c6fab01d9b 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -1182,6 +1182,9 @@ func CreateNodeFullExecutionClient( parentChainID *big.Int, blobReader daprovider.BlobReader, ) (*Node, error) { + if (executionClient == nil) || (executionSequencer == nil) || (executionRecorder == nil) || (executionBatchPoster == nil) { + return nil, errors.New("execution client, sequencer, recorder, and batch poster must be non-nil") + } currentNode, err := createNodeImpl(ctx, stack, executionClient, executionSequencer, executionRecorder, executionBatchPoster, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) if err != nil { return nil, err From 5ff9d782cecd5debf106ac57efdc8686992aa965 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:30:49 -0300 Subject: [PATCH 24/33] Moves execution clients nil check to get funcs --- arbnode/node.go | 54 ++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index c6fab01d9b..8d49ba0a7d 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -777,6 +777,10 @@ func getSeqCoordinator( var coordinator *SeqCoordinator if config.SeqCoordinator.Enable { + if exec == nil { + return nil, errors.New("sequencer coordinator requires an execution sequencer") + } + var err error coordinator, err = NewSeqCoordinator(dataSigner, bpVerifier, txStreamer, exec, syncMonitor, config.SeqCoordinator) if err != nil { @@ -803,6 +807,10 @@ func getStatelessBlockValidator( var err error var statelessBlockValidator *staker.StatelessBlockValidator if config.BlockValidator.RedisValidationClientConfig.Enabled() || config.BlockValidator.ValidationServerConfigs[0].URL != "" { + if exec == nil { + return nil, errors.New("stateless block validator requires an execution recorder") + } + statelessBlockValidator, err = staker.NewStatelessBlockValidator( inboxReader, inboxTracker, @@ -847,6 +855,10 @@ func getBatchPoster( var batchPoster *BatchPoster if config.BatchPoster.Enable { + if exec == nil { + return nil, errors.New("batch poster requires an execution batch poster") + } + if txOptsBatchPoster == nil && config.BatchPoster.DataPoster.ExternalSigner.URL == "" { return nil, errors.New("batchposter, but no TxOpts") } @@ -889,7 +901,11 @@ func getDelayedSequencer( configFetcher ConfigFetcher, coordinator *SeqCoordinator, ) (*DelayedSequencer, error) { - // always create DelayedSequencer, it won't do anything if it is disabled + if exec == nil { + return nil, nil + } + + // always create DelayedSequencer if exec is non nil, it won't do anything if it is disabled delayedSequencer, err := NewDelayedSequencer(l1Reader, inboxReader, exec, coordinator, func() *DelayedSequencerConfig { return &configFetcher.Get().DelayedSequencer }) if err != nil { return nil, err @@ -988,12 +1004,9 @@ func createNodeImpl( return nil, err } - var coordinator *SeqCoordinator - if executionSequencer != nil { - coordinator, err = getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, executionSequencer) - if err != nil { - return nil, err - } + coordinator, err := getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, executionSequencer) + if err != nil { + return nil, err } maintenanceRunner, err := getMaintenanceRunner(arbDb, configFetcher, coordinator, executionClient) @@ -1025,12 +1038,9 @@ func createNodeImpl( return nil, err } - var statelessBlockValidator *staker.StatelessBlockValidator - if executionRecorder != nil { - statelessBlockValidator, err = getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, executionRecorder, arbDb, dapReaders, stack) - if err != nil { - return nil, err - } + statelessBlockValidator, err := getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, executionRecorder, arbDb, dapReaders, stack) + if err != nil { + return nil, err } blockValidator, err := getBlockValidator(configFetcher, statelessBlockValidator, inboxTracker, txStreamer, fatalErrChan) @@ -1043,20 +1053,14 @@ func createNodeImpl( return nil, err } - var batchPoster *BatchPoster - if executionBatchPoster != nil { - batchPoster, err = getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, executionBatchPoster, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) - if err != nil { - return nil, err - } + batchPoster, err := getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, executionBatchPoster, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) + if err != nil { + return nil, err } - var delayedSequencer *DelayedSequencer - if executionSequencer != nil { - delayedSequencer, err = getDelayedSequencer(l1Reader, inboxReader, executionSequencer, configFetcher, coordinator) - if err != nil { - return nil, err - } + delayedSequencer, err := getDelayedSequencer(l1Reader, inboxReader, executionSequencer, configFetcher, coordinator) + if err != nil { + return nil, err } return &Node{ From db9c5c4f7e384a64a3bd69803110175911572bba Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:36:28 -0300 Subject: [PATCH 25/33] Pass config to get functions --- arbnode/node.go | 54 ++++++++++++++++++------------------------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 8d49ba0a7d..48d703e034 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -418,9 +418,7 @@ func getSyncMonitor(configFetcher ConfigFetcher) *SyncMonitor { return NewSyncMonitor(syncConfigFetcher) } -func getL1Reader(ctx context.Context, configFetcher ConfigFetcher, l1client *ethclient.Client) (*headerreader.HeaderReader, error) { - config := configFetcher.Get() - +func getL1Reader(ctx context.Context, config *Config, configFetcher ConfigFetcher, l1client *ethclient.Client) (*headerreader.HeaderReader, error) { var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) @@ -433,9 +431,7 @@ func getL1Reader(ctx context.Context, configFetcher ConfigFetcher, l1client *eth return l1Reader, nil } -func getBroadcastServer(configFetcher ConfigFetcher, dataSigner signature.DataSignerFunc, l2ChainId uint64, fatalErrChan chan error) (*broadcaster.Broadcaster, error) { - config := configFetcher.Get() - +func getBroadcastServer(config *Config, configFetcher ConfigFetcher, dataSigner signature.DataSignerFunc, l2ChainId uint64, fatalErrChan chan error) (*broadcaster.Broadcaster, error) { var broadcastServer *broadcaster.Broadcaster if config.Feed.Output.Enable { var maybeDataSigner signature.DataSignerFunc @@ -479,14 +475,13 @@ func getMaintenanceRunner( } func getBroadcastClients( + config *Config, configFetcher ConfigFetcher, txStreamer *TransactionStreamer, l2ChainId uint64, bpVerifier *contracts.AddressVerifier, fatalErrChan chan error, ) (*broadcastclients.BroadcastClients, error) { - config := configFetcher.Get() - var broadcastClients *broadcastclients.BroadcastClients if config.Feed.Input.Enable() { currentMessageCount, err := txStreamer.GetMessageCount() @@ -531,7 +526,7 @@ func getDelayedBridgeAndSequencerInbox( func getDAS( ctx context.Context, - configFetcher ConfigFetcher, + config *Config, l2Config *params.ChainConfig, txStreamer *TransactionStreamer, blobReader daprovider.BlobReader, @@ -540,8 +535,6 @@ func getDAS( dataSigner signature.DataSignerFunc, l1client *ethclient.Client, ) (das.DataAvailabilityServiceWriter, *das.LifecycleManager, []daprovider.Reader, error) { - config := configFetcher.Get() - var daWriter das.DataAvailabilityServiceWriter var daReader das.DataAvailabilityServiceReader var dasLifecycleManager *das.LifecycleManager @@ -591,6 +584,7 @@ func getInboxTrackerAndReader( arbDb ethdb.Database, txStreamer *TransactionStreamer, dapReaders []daprovider.Reader, + config *Config, configFetcher ConfigFetcher, l1client *ethclient.Client, l1Reader *headerreader.HeaderReader, @@ -598,8 +592,6 @@ func getInboxTrackerAndReader( delayedBridge *DelayedBridge, sequencerInbox *SequencerInbox, ) (*InboxTracker, *InboxReader, error) { - config := configFetcher.Get() - inboxTracker, err := NewInboxTracker(arbDb, txStreamer, dapReaders, config.SnapSyncTest) if err != nil { return nil, nil, err @@ -636,14 +628,13 @@ func getInboxTrackerAndReader( } func getBlockValidator( + config *Config, configFetcher ConfigFetcher, statelessBlockValidator *staker.StatelessBlockValidator, inboxTracker *InboxTracker, txStreamer *TransactionStreamer, fatalErrChan chan error, ) (*staker.BlockValidator, error) { - config := configFetcher.Get() - var err error var blockValidator *staker.BlockValidator if config.ValidatorRequired() { @@ -663,6 +654,7 @@ func getBlockValidator( func getStaker( ctx context.Context, + config *Config, configFetcher ConfigFetcher, arbDb ethdb.Database, l1Reader *headerreader.HeaderReader, @@ -678,8 +670,6 @@ func getStaker( statelessBlockValidator *staker.StatelessBlockValidator, blockValidator *staker.BlockValidator, ) (*multiprotocolstaker.MultiProtocolStaker, *MessagePruner, common.Address, error) { - config := configFetcher.Get() - var stakerObj *multiprotocolstaker.MultiProtocolStaker var messagePruner *MessagePruner var stakerAddr common.Address @@ -766,15 +756,13 @@ func getTransactionStreamer( } func getSeqCoordinator( - configFetcher ConfigFetcher, + config *Config, dataSigner signature.DataSignerFunc, bpVerifier *contracts.AddressVerifier, txStreamer *TransactionStreamer, syncMonitor *SyncMonitor, exec execution.ExecutionSequencer, ) (*SeqCoordinator, error) { - config := configFetcher.Get() - var coordinator *SeqCoordinator if config.SeqCoordinator.Enable { if exec == nil { @@ -793,6 +781,7 @@ func getSeqCoordinator( } func getStatelessBlockValidator( + config *Config, configFetcher ConfigFetcher, inboxReader *InboxReader, inboxTracker *InboxTracker, @@ -802,8 +791,6 @@ func getStatelessBlockValidator( dapReaders []daprovider.Reader, stack *node.Node, ) (*staker.StatelessBlockValidator, error) { - config := configFetcher.Get() - var err error var statelessBlockValidator *staker.StatelessBlockValidator if config.BlockValidator.RedisValidationClientConfig.Enabled() || config.BlockValidator.ValidationServerConfigs[0].URL != "" { @@ -837,6 +824,7 @@ func getStatelessBlockValidator( func getBatchPoster( ctx context.Context, + config *Config, configFetcher ConfigFetcher, txOptsBatchPoster *bind.TransactOpts, daWriter das.DataAvailabilityServiceWriter, @@ -851,8 +839,6 @@ func getBatchPoster( dapReaders []daprovider.Reader, stakerAddr common.Address, ) (*BatchPoster, error) { - config := configFetcher.Get() - var batchPoster *BatchPoster if config.BatchPoster.Enable { if exec == nil { @@ -984,12 +970,12 @@ func createNodeImpl( syncMonitor := getSyncMonitor(configFetcher) - l1Reader, err := getL1Reader(ctx, configFetcher, l1client) + l1Reader, err := getL1Reader(ctx, config, configFetcher, l1client) if err != nil { return nil, err } - broadcastServer, err := getBroadcastServer(configFetcher, dataSigner, l2Config.ChainID.Uint64(), fatalErrChan) + broadcastServer, err := getBroadcastServer(config, configFetcher, dataSigner, l2Config.ChainID.Uint64(), fatalErrChan) if err != nil { return nil, err } @@ -1004,7 +990,7 @@ func createNodeImpl( return nil, err } - coordinator, err := getSeqCoordinator(configFetcher, dataSigner, bpVerifier, txStreamer, syncMonitor, executionSequencer) + coordinator, err := getSeqCoordinator(config, dataSigner, bpVerifier, txStreamer, syncMonitor, executionSequencer) if err != nil { return nil, err } @@ -1014,7 +1000,7 @@ func createNodeImpl( return nil, err } - broadcastClients, err := getBroadcastClients(configFetcher, txStreamer, l2Config.ChainID.Uint64(), bpVerifier, fatalErrChan) + broadcastClients, err := getBroadcastClients(config, configFetcher, txStreamer, l2Config.ChainID.Uint64(), bpVerifier, fatalErrChan) if err != nil { return nil, err } @@ -1028,32 +1014,32 @@ func createNodeImpl( return nil, err } - daWriter, dasLifecycleManager, dapReaders, err := getDAS(ctx, configFetcher, l2Config, txStreamer, blobReader, l1Reader, deployInfo, dataSigner, l1client) + daWriter, dasLifecycleManager, dapReaders, err := getDAS(ctx, config, l2Config, txStreamer, blobReader, l1Reader, deployInfo, dataSigner, l1client) if err != nil { return nil, err } - inboxTracker, inboxReader, err := getInboxTrackerAndReader(arbDb, txStreamer, dapReaders, configFetcher, l1client, l1Reader, deployInfo, delayedBridge, sequencerInbox) + inboxTracker, inboxReader, err := getInboxTrackerAndReader(arbDb, txStreamer, dapReaders, config, configFetcher, l1client, l1Reader, deployInfo, delayedBridge, sequencerInbox) if err != nil { return nil, err } - statelessBlockValidator, err := getStatelessBlockValidator(configFetcher, inboxReader, inboxTracker, txStreamer, executionRecorder, arbDb, dapReaders, stack) + statelessBlockValidator, err := getStatelessBlockValidator(config, configFetcher, inboxReader, inboxTracker, txStreamer, executionRecorder, arbDb, dapReaders, stack) if err != nil { return nil, err } - blockValidator, err := getBlockValidator(configFetcher, statelessBlockValidator, inboxTracker, txStreamer, fatalErrChan) + blockValidator, err := getBlockValidator(config, configFetcher, statelessBlockValidator, inboxTracker, txStreamer, fatalErrChan) if err != nil { return nil, err } - stakerObj, messagePruner, stakerAddr, err := getStaker(ctx, configFetcher, arbDb, l1Reader, txOptsValidator, syncMonitor, parentChainID, l1client, deployInfo, txStreamer, inboxTracker, stack, fatalErrChan, statelessBlockValidator, blockValidator) + stakerObj, messagePruner, stakerAddr, err := getStaker(ctx, config, configFetcher, arbDb, l1Reader, txOptsValidator, syncMonitor, parentChainID, l1client, deployInfo, txStreamer, inboxTracker, stack, fatalErrChan, statelessBlockValidator, blockValidator) if err != nil { return nil, err } - batchPoster, err := getBatchPoster(ctx, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, executionBatchPoster, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) + batchPoster, err := getBatchPoster(ctx, config, configFetcher, txOptsBatchPoster, daWriter, l1Reader, inboxTracker, txStreamer, executionBatchPoster, arbDb, syncMonitor, deployInfo, parentChainID, dapReaders, stakerAddr) if err != nil { return nil, err } From c7efe2438a8dca076d66ef387f6272ee7ab9f487 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:37:39 -0300 Subject: [PATCH 26/33] Split arguments of get functions in multiple lines --- arbnode/node.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index 48d703e034..34c74a0f5c 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -418,7 +418,12 @@ func getSyncMonitor(configFetcher ConfigFetcher) *SyncMonitor { return NewSyncMonitor(syncConfigFetcher) } -func getL1Reader(ctx context.Context, config *Config, configFetcher ConfigFetcher, l1client *ethclient.Client) (*headerreader.HeaderReader, error) { +func getL1Reader( + ctx context.Context, + config *Config, + configFetcher ConfigFetcher, + l1client *ethclient.Client, +) (*headerreader.HeaderReader, error) { var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) @@ -431,7 +436,13 @@ func getL1Reader(ctx context.Context, config *Config, configFetcher ConfigFetche return l1Reader, nil } -func getBroadcastServer(config *Config, configFetcher ConfigFetcher, dataSigner signature.DataSignerFunc, l2ChainId uint64, fatalErrChan chan error) (*broadcaster.Broadcaster, error) { +func getBroadcastServer( + config *Config, + configFetcher ConfigFetcher, + dataSigner signature.DataSignerFunc, + l2ChainId uint64, + fatalErrChan chan error, +) (*broadcaster.Broadcaster, error) { var broadcastServer *broadcaster.Broadcaster if config.Feed.Output.Enable { var maybeDataSigner signature.DataSignerFunc @@ -446,7 +457,10 @@ func getBroadcastServer(config *Config, configFetcher ConfigFetcher, dataSigner return broadcastServer, nil } -func getBPVerifier(deployInfo *chaininfo.RollupAddresses, l1client *ethclient.Client) (*contracts.AddressVerifier, error) { +func getBPVerifier( + deployInfo *chaininfo.RollupAddresses, + l1client *ethclient.Client, +) (*contracts.AddressVerifier, error) { var bpVerifier *contracts.AddressVerifier if deployInfo != nil && l1client != nil { sequencerInboxAddr := deployInfo.SequencerInbox From 7cbae4498334ad12669aa052d2293b51fe1855db Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:55:09 -0300 Subject: [PATCH 27/33] Get rid of ExecutionClientImpl --- arbnode/node.go | 52 ++++++++---- execution/gethexec/node.go | 80 ------------------- system_tests/common_test.go | 28 +++---- ..._test.go => execution_client_only_test.go} | 12 +-- 4 files changed, 57 insertions(+), 115 deletions(-) rename system_tests/{execution_client_impl_test.go => execution_client_only_test.go} (61%) diff --git a/arbnode/node.go b/arbnode/node.go index 34c74a0f5c..2856968e26 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -1167,6 +1167,33 @@ func registerAPIs(currentNode *Node, stack *node.Node) { stack.RegisterAPIs(apis) } +func CreateNodeExecutionClient( + ctx context.Context, + stack *node.Node, + executionClient execution.ExecutionClient, + arbDb ethdb.Database, + configFetcher ConfigFetcher, + l2Config *params.ChainConfig, + l1client *ethclient.Client, + deployInfo *chaininfo.RollupAddresses, + txOptsValidator *bind.TransactOpts, + txOptsBatchPoster *bind.TransactOpts, + dataSigner signature.DataSignerFunc, + fatalErrChan chan error, + parentChainID *big.Int, + blobReader daprovider.BlobReader, +) (*Node, error) { + if executionClient == nil { + return nil, errors.New("execution client must be non-nil") + } + currentNode, err := createNodeImpl(ctx, stack, executionClient, nil, nil, nil, arbDb, configFetcher, l2Config, l1client, deployInfo, txOptsValidator, txOptsBatchPoster, dataSigner, fatalErrChan, parentChainID, blobReader) + if err != nil { + return nil, err + } + registerAPIs(currentNode, stack) + return currentNode, nil +} + func CreateNodeFullExecutionClient( ctx context.Context, stack *node.Node, @@ -1198,26 +1225,23 @@ func CreateNodeFullExecutionClient( } func (n *Node) Start(ctx context.Context) error { - executionNode, isExecutionNode := n.ExecutionClient.(*gethexec.ExecutionNode) - executionClientImpl, isExecutionClientImpl := n.ExecutionClient.(*gethexec.ExecutionClientImpl) - - var err error - if isExecutionNode { - err = executionNode.Initialize(ctx) - } else if isExecutionClientImpl { - err = executionClientImpl.Initialize(ctx) + execClient, ok := n.ExecutionClient.(*gethexec.ExecutionNode) + if !ok { + execClient = nil } - if err != nil { - return fmt.Errorf("error initializing exec client: %w", err) + if execClient != nil { + err := execClient.Initialize(ctx) + if err != nil { + return fmt.Errorf("error initializing exec client: %w", err) + } } - n.SyncMonitor.Initialize(n.InboxReader, n.TxStreamer, n.SeqCoordinator) - err = n.Stack.Start() + err := n.Stack.Start() if err != nil { return fmt.Errorf("error starting geth stack: %w", err) } - if isExecutionNode { - executionNode.SetConsensusClient(n) + if execClient != nil { + execClient.SetConsensusClient(n) } err = n.ExecutionClient.Start(ctx) if err != nil { diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 0a8bb6b67f..5b78a73c73 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -476,83 +476,3 @@ func (n *ExecutionNode) Synced() bool { func (n *ExecutionNode) FullSyncProgressMap() map[string]interface{} { return n.SyncMonitor.FullSyncProgressMap() } - -// Used to check if only implementing ExecutionClient from FullExecutionClient interface is enough in some scenarios -type ExecutionClientImpl struct { - ExecutionNode *ExecutionNode -} - -// ExecutionClient interface implementation -func (n *ExecutionClientImpl) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { - return n.ExecutionNode.DigestMessage(num, msg, msgForPrefetch) -} -func (n *ExecutionClientImpl) Reorg(count arbutil.MessageIndex, newMessages []arbostypes.MessageWithMetadataAndBlockHash, oldMessages []*arbostypes.MessageWithMetadata) containers.PromiseInterface[[]*execution.MessageResult] { - return n.ExecutionNode.Reorg(count, newMessages, oldMessages) -} -func (n *ExecutionClientImpl) HeadMessageNumber() containers.PromiseInterface[arbutil.MessageIndex] { - return n.ExecutionNode.HeadMessageNumber() -} -func (n *ExecutionClientImpl) ResultAtPos(pos arbutil.MessageIndex) containers.PromiseInterface[*execution.MessageResult] { - return n.ExecutionNode.ResultAtPos(pos) -} -func (n *ExecutionClientImpl) MarkFeedStart(to arbutil.MessageIndex) containers.PromiseInterface[struct{}] { - return n.ExecutionNode.MarkFeedStart(to) -} - -// ExecutionRecorder interface implementation -func (n *ExecutionClientImpl) RecordBlockCreation( - ctx context.Context, - pos arbutil.MessageIndex, - msg *arbostypes.MessageWithMetadata, -) (*execution.RecordResult, error) { - panic("RecordBlockCreation not supported") -} -func (n *ExecutionClientImpl) MarkValid(pos arbutil.MessageIndex, resultHash common.Hash) { - panic("MarkValid not supported") -} -func (n *ExecutionClientImpl) PrepareForRecord(ctx context.Context, start, end arbutil.MessageIndex) error { - panic("PrepareForRecord not supported") -} - -// ExecutionSequence interface implementation -func (n *ExecutionClientImpl) Pause() { - panic("Pause not supported") -} -func (n *ExecutionClientImpl) Activate() { - // panic("Activate not supported") -} -func (n *ExecutionClientImpl) ForwardTo(url string) error { - panic("ForwardTo not supported") -} -func (n *ExecutionClientImpl) SequenceDelayedMessage(message *arbostypes.L1IncomingMessage, delayedSeqNum uint64) error { - panic("SequenceDelayedMessage not supported") -} -func (n *ExecutionClientImpl) NextDelayedMessageNumber() (uint64, error) { - panic("NextDelayedMessageNumber not supported") -} -func (n *ExecutionClientImpl) Synced() bool { - panic("Synced not supported") -} -func (n *ExecutionClientImpl) FullSyncProgressMap() map[string]interface{} { - panic("FullSyncProgressMap not supported") -} - -// Other funcs from FullExecutionClient -// not thread safe -func (n *ExecutionClientImpl) Start(ctx context.Context) error { - return n.ExecutionNode.Start(ctx) -} -func (n *ExecutionClientImpl) StopAndWait() { - n.ExecutionNode.StopAndWait() -} -func (n *ExecutionClientImpl) Maintenance() containers.PromiseInterface[struct{}] { - return n.ExecutionNode.Maintenance() -} -func (n *ExecutionClientImpl) ArbOSVersionForMessageNumber(messageNum arbutil.MessageIndex) (uint64, error) { - return n.ExecutionNode.ArbOSVersionForMessageNumber(messageNum) -} - -// Not part of FullExecutionClient interface, but needed to start the node -func (n *ExecutionClientImpl) Initialize(ctx context.Context) error { - return n.ExecutionNode.Initialize(ctx) -} diff --git a/system_tests/common_test.go b/system_tests/common_test.go index e019a59935..473e03450d 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -92,14 +92,14 @@ import ( type info = *BlockchainTestInfo type SecondNodeParams struct { - nodeConfig *arbnode.Config - execConfig *gethexec.Config - stackConfig *node.Config - dasConfig *das.DataAvailabilityConfig - initData *statetransfer.ArbosInitializationInfo - addresses *chaininfo.RollupAddresses - wasmCacheTag uint32 - useExecutionClientImplAsFullExecutionClient bool + nodeConfig *arbnode.Config + execConfig *gethexec.Config + stackConfig *node.Config + dasConfig *das.DataAvailabilityConfig + initData *statetransfer.ArbosInitializationInfo + addresses *chaininfo.RollupAddresses + wasmCacheTag uint32 + useExecutionClientOnly bool } type TestClient struct { @@ -744,10 +744,8 @@ func build2ndNode( testClient := NewTestClient(ctx) testClient.Client, testClient.ConsensusNode = - Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag, params.useExecutionClientImplAsFullExecutionClient) - if !params.useExecutionClientImplAsFullExecutionClient { - testClient.ExecNode = getExecNode(t, testClient.ConsensusNode) - } + Create2ndNodeWithConfig(t, ctx, firstNodeTestClient.ConsensusNode, parentChainTestClient.Stack, parentChainInfo, params.initData, params.nodeConfig, params.execConfig, params.stackConfig, valnodeConfig, params.addresses, initMessage, params.wasmCacheTag, params.useExecutionClientOnly) + testClient.ExecNode = getExecNode(t, testClient.ConsensusNode) testClient.cleanup = func() { testClient.ConsensusNode.StopAndWait() } return testClient, func() { testClient.cleanup() } } @@ -1511,7 +1509,7 @@ func Create2ndNodeWithConfig( addresses *chaininfo.RollupAddresses, initMessage *arbostypes.ParsedInitMessage, wasmCacheTag uint32, - useExecutionClientImplAsFullExecutionClient bool, + useExecutionClientOnly bool, ) (*ethclient.Client, *arbnode.Node) { if nodeConfig == nil { nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() @@ -1559,8 +1557,8 @@ func Create2ndNodeWithConfig( Require(t, err) var currentNode *arbnode.Node - if useExecutionClientImplAsFullExecutionClient { - currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, &gethexec.ExecutionClientImpl{ExecutionNode: currentExec}, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) + if useExecutionClientOnly { + currentNode, err = arbnode.CreateNodeExecutionClient(ctx, chainStack, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } else { currentNode, err = arbnode.CreateNodeFullExecutionClient(ctx, chainStack, currentExec, currentExec, currentExec, currentExec, arbDb, NewFetcherFromConfig(nodeConfig), blockchain.Config(), parentChainClient, addresses, &validatorTxOpts, &sequencerTxOpts, dataSigner, feedErrChan, big.NewInt(1337), nil) } diff --git a/system_tests/execution_client_impl_test.go b/system_tests/execution_client_only_test.go similarity index 61% rename from system_tests/execution_client_impl_test.go rename to system_tests/execution_client_only_test.go index 11358a90d6..22c76b868f 100644 --- a/system_tests/execution_client_impl_test.go +++ b/system_tests/execution_client_only_test.go @@ -12,7 +12,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" ) -func TestExecutionClientImplAsFullExecutionClient(t *testing.T) { +func TestExecutionClientOnly(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) @@ -23,9 +23,9 @@ func TestExecutionClientImplAsFullExecutionClient(t *testing.T) { defer cleanup() seqTestClient := builder.L2 - replicaConfig := arbnode.ConfigDefaultL1NonSequencerTest() - replicaTestClient, replicaCleanup := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: replicaConfig, useExecutionClientImplAsFullExecutionClient: true}) - defer replicaCleanup() + replicaExecutionClientOnlyConfig := arbnode.ConfigDefaultL1NonSequencerTest() + replicaExecutionClientOnlyTestClient, replicaExecutionClientOnlyCleanup := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: replicaExecutionClientOnlyConfig, useExecutionClientOnly: true}) + defer replicaExecutionClientOnlyCleanup() builder.L2Info.GenerateAccount("User2") for i := 0; i < 3; i++ { @@ -34,11 +34,11 @@ func TestExecutionClientImplAsFullExecutionClient(t *testing.T) { Require(t, err) _, err = seqTestClient.EnsureTxSucceeded(tx) Require(t, err) - _, err = WaitForTx(ctx, replicaTestClient.Client, tx.Hash(), time.Second*15) + _, err = WaitForTx(ctx, replicaExecutionClientOnlyTestClient.Client, tx.Hash(), time.Second*15) Require(t, err) } - replicaBalance, err := replicaTestClient.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) + replicaBalance, err := replicaExecutionClientOnlyTestClient.Client.BalanceAt(ctx, builder.L2Info.GetAddress("User2"), nil) Require(t, err) if replicaBalance.Cmp(big.NewInt(3e12)) != 0 { t.Fatal("Unexpected balance:", replicaBalance) From 70a1743ffbefc7251c564bfe73a2721f9c5b4026 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 19:57:23 -0300 Subject: [PATCH 28/33] Fixes inbox_test --- arbnode/inbox_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index dc80cd20d9..0c8f00a3d4 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -90,6 +90,14 @@ func (w *execClientWrapper) ResultAtPos(pos arbutil.MessageIndex) containers.Pro return containers.NewReadyPromise(w.ExecutionEngine.ResultAtPos(pos)) } +func (w *execClientWrapper) Start(ctx context.Context) error { + return nil +} + +func (w *execClientWrapper) StopAndWait() { + return +} + func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*gethexec.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) { chainConfig := chaininfo.ArbitrumDevTestChainConfig() From 375bd8d09f520181c7880a869fea20478700d6fc Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 20:02:01 -0300 Subject: [PATCH 29/33] Fixes Node.Start nil reference --- arbnode/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/node.go b/arbnode/node.go index 2856968e26..b5742524c9 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -1292,7 +1292,7 @@ func (n *Node) Start(ctx context.Context) error { } if n.SeqCoordinator != nil { n.SeqCoordinator.Start(ctx) - } else { + } else if n.ExecutionSequencer != nil { n.ExecutionSequencer.Activate() } if n.MaintenanceRunner != nil { From 483c082d2eae839c4a55061264d1972c2acc62e4 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Thu, 2 Jan 2025 21:01:28 -0300 Subject: [PATCH 30/33] ExecutionClient.Start and ExecutionClient.StopAndWait return promises --- arbnode/inbox_test.go | 8 ++++---- arbnode/node.go | 7 +++++-- execution/gethexec/node.go | 14 ++++++++------ execution/interface.go | 4 ++-- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index 0c8f00a3d4..2207e47b4e 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -90,12 +90,12 @@ func (w *execClientWrapper) ResultAtPos(pos arbutil.MessageIndex) containers.Pro return containers.NewReadyPromise(w.ExecutionEngine.ResultAtPos(pos)) } -func (w *execClientWrapper) Start(ctx context.Context) error { - return nil +func (w *execClientWrapper) Start(ctx context.Context) containers.PromiseInterface[struct{}] { + return containers.NewReadyPromise(struct{}{}, nil) } -func (w *execClientWrapper) StopAndWait() { - return +func (w *execClientWrapper) StopAndWait() containers.PromiseInterface[struct{}] { + return containers.NewReadyPromise(struct{}{}, nil) } func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (*gethexec.ExecutionEngine, *TransactionStreamer, ethdb.Database, *core.BlockChain) { diff --git a/arbnode/node.go b/arbnode/node.go index b5742524c9..a0f8f02e6c 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -1243,7 +1243,7 @@ func (n *Node) Start(ctx context.Context) error { if execClient != nil { execClient.SetConsensusClient(n) } - err = n.ExecutionClient.Start(ctx) + _, err = n.ExecutionClient.Start(ctx).Await(ctx) if err != nil { return fmt.Errorf("error starting exec client: %w", err) } @@ -1414,7 +1414,10 @@ func (n *Node) StopAndWait() { n.DASLifecycleManager.StopAndWaitUntil(2 * time.Second) } if n.ExecutionClient != nil { - n.ExecutionClient.StopAndWait() + _, err := n.ExecutionClient.StopAndWait().Await(n.ctx) + if err != nil { + log.Error("error stopping execution client", "err", err) + } } if err := n.Stack.Close(); err != nil { log.Error("error on stack close", "err", err) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 5b78a73c73..9ee0bcc896 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -347,9 +347,9 @@ func (n *ExecutionNode) Initialize(ctx context.Context) error { } // not thread safe -func (n *ExecutionNode) Start(ctx context.Context) error { +func (n *ExecutionNode) Start(ctx context.Context) containers.PromiseInterface[struct{}] { if n.started.Swap(true) { - return errors.New("already started") + return containers.NewReadyPromise(struct{}{}, errors.New("already started")) } // TODO after separation // err := n.Stack.Start() @@ -359,17 +359,17 @@ func (n *ExecutionNode) Start(ctx context.Context) error { n.ExecEngine.Start(ctx) err := n.TxPublisher.Start(ctx) if err != nil { - return fmt.Errorf("error starting transaction puiblisher: %w", err) + return containers.NewReadyPromise(struct{}{}, fmt.Errorf("error starting transaction puiblisher: %w", err)) } if n.ParentChainReader != nil { n.ParentChainReader.Start(ctx) } - return nil + return containers.NewReadyPromise(struct{}{}, nil) } -func (n *ExecutionNode) StopAndWait() { +func (n *ExecutionNode) StopAndWait() containers.PromiseInterface[struct{}] { if !n.started.Load() { - return + return containers.NewReadyPromise(struct{}{}, nil) } // TODO after separation // n.Stack.StopRPC() // does nothing if not running @@ -391,6 +391,8 @@ func (n *ExecutionNode) StopAndWait() { // if err := n.Stack.Close(); err != nil { // log.Error("error on stak close", "err", err) // } + + return containers.NewReadyPromise(struct{}{}, nil) } func (n *ExecutionNode) DigestMessage(num arbutil.MessageIndex, msg *arbostypes.MessageWithMetadata, msgForPrefetch *arbostypes.MessageWithMetadata) containers.PromiseInterface[*execution.MessageResult] { diff --git a/execution/interface.go b/execution/interface.go index 51de32a685..dcf6fec72a 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -37,8 +37,8 @@ type ExecutionClient interface { Maintenance() containers.PromiseInterface[struct{}] - Start(ctx context.Context) error - StopAndWait() + Start(ctx context.Context) containers.PromiseInterface[struct{}] + StopAndWait() containers.PromiseInterface[struct{}] } // needed for validators / stakers From f5034ab712fec49498f4fee4af5370abc0df09cd Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Fri, 3 Jan 2025 10:34:55 -0300 Subject: [PATCH 31/33] Fixes challengetests --- arbnode/node.go | 6 +++++- system_tests/bold_challenge_protocol_test.go | 20 ++++++++++---------- system_tests/bold_state_provider_test.go | 2 +- system_tests/overflow_assertions_test.go | 4 ++-- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index a0f8f02e6c..adc5c81a2f 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -263,6 +263,7 @@ type Node struct { Stack *node.Node ExecutionClient execution.ExecutionClient ExecutionSequencer execution.ExecutionSequencer + ExecutionRecorder execution.ExecutionRecorder L1Reader *headerreader.HeaderReader TxStreamer *TransactionStreamer DeployInfo *chaininfo.RollupAddresses @@ -919,6 +920,7 @@ func getNodeParentChainReaderDisabled( stack *node.Node, executionClient execution.ExecutionClient, executionSequencer execution.ExecutionSequencer, + executionRecorder execution.ExecutionRecorder, txStreamer *TransactionStreamer, blobReader daprovider.BlobReader, broadcastServer *broadcaster.Broadcaster, @@ -933,6 +935,7 @@ func getNodeParentChainReaderDisabled( Stack: stack, ExecutionClient: executionClient, ExecutionSequencer: executionSequencer, + ExecutionRecorder: executionRecorder, L1Reader: nil, TxStreamer: txStreamer, DeployInfo: nil, @@ -1020,7 +1023,7 @@ func createNodeImpl( } if !config.ParentChainReader.Enable { - return getNodeParentChainReaderDisabled(ctx, arbDb, stack, executionClient, executionSequencer, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil + return getNodeParentChainReaderDisabled(ctx, arbDb, stack, executionClient, executionSequencer, executionRecorder, txStreamer, blobReader, broadcastServer, broadcastClients, coordinator, maintenanceRunner, syncMonitor, configFetcher), nil } delayedBridge, sequencerInbox, err := getDelayedBridgeAndSequencerInbox(deployInfo, l1client) @@ -1068,6 +1071,7 @@ func createNodeImpl( Stack: stack, ExecutionClient: executionClient, ExecutionSequencer: executionSequencer, + ExecutionRecorder: executionRecorder, L1Reader: l1Reader, TxStreamer: txStreamer, DeployInfo: deployInfo, diff --git a/system_tests/bold_challenge_protocol_test.go b/system_tests/bold_challenge_protocol_test.go index fe49999bdd..9a8bdec4a4 100644 --- a/system_tests/bold_challenge_protocol_test.go +++ b/system_tests/bold_challenge_protocol_test.go @@ -138,9 +138,9 @@ func testChallengeProtocolBOLD(t *testing.T, spawnerOpts ...server_arb.SpawnerOp ) defer l2nodeB.StopAndWait() - genesisA, err := l2nodeA.Execution.ResultAtPos(0).Await(ctx) + genesisA, err := l2nodeA.ExecutionClient.ResultAtPos(0).Await(ctx) Require(t, err) - genesisB, err := l2nodeB.Execution.ResultAtPos(0).Await(ctx) + genesisB, err := l2nodeB.ExecutionClient.ResultAtPos(0).Await(ctx) Require(t, err) if genesisA.BlockHash != genesisB.BlockHash { Fatal(t, "genesis blocks mismatch between nodes") @@ -160,7 +160,7 @@ func testChallengeProtocolBOLD(t *testing.T, spawnerOpts ...server_arb.SpawnerOp l2nodeA.InboxReader, l2nodeA.InboxTracker, l2nodeA.TxStreamer, - l2nodeA.Execution, + l2nodeA.ExecutionRecorder, l2nodeA.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), @@ -175,7 +175,7 @@ func testChallengeProtocolBOLD(t *testing.T, spawnerOpts ...server_arb.SpawnerOp l2nodeB.InboxReader, l2nodeB.InboxTracker, l2nodeB.TxStreamer, - l2nodeB.Execution, + l2nodeB.ExecutionRecorder, l2nodeB.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), @@ -331,11 +331,11 @@ func testChallengeProtocolBOLD(t *testing.T, spawnerOpts ...server_arb.SpawnerOp t.Logf("Node B batch count %d, msgs %d", bcB, msgB) // Wait for both nodes' chains to catch up. - nodeAExec, ok := l2nodeA.Execution.(*gethexec.ExecutionNode) + nodeAExec, ok := l2nodeA.ExecutionClient.(*gethexec.ExecutionNode) if !ok { Fatal(t, "not geth execution node") } - nodeBExec, ok := l2nodeB.Execution.(*gethexec.ExecutionNode) + nodeBExec, ok := l2nodeB.ExecutionClient.(*gethexec.ExecutionNode) if !ok { Fatal(t, "not geth execution node") } @@ -616,8 +616,8 @@ func createTestNodeOnL1ForBoldProtocol( parentChainId, err := l1client.ChainID(ctx) Require(t, err) - currentNode, err = arbnode.CreateNode( - ctx, l2stack, execNode, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, + currentNode, err = arbnode.CreateNodeFullExecutionClient( + ctx, l2stack, execNode, execNode, execNode, execNode, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, addresses, sequencerTxOptsPtr, sequencerTxOptsPtr, dataSigner, fatalErrChan, parentChainId, nil, // Blob reader. ) @@ -777,7 +777,7 @@ func create2ndNodeWithConfigForBoldProtocol( fatalErrChan := make(chan error, 10) l1rpcClient := l1stack.Attach() l1client := ethclient.NewClient(l1rpcClient) - firstExec, ok := first.Execution.(*gethexec.ExecutionNode) + firstExec, ok := first.ExecutionClient.(*gethexec.ExecutionNode) if !ok { Fatal(t, "not geth execution node") } @@ -826,7 +826,7 @@ func create2ndNodeWithConfigForBoldProtocol( Require(t, err) l1ChainId, err := l1client.ChainID(ctx) Require(t, err) - l2node, err := arbnode.CreateNode(ctx, l2stack, execNode, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, addresses, &txOpts, &txOpts, dataSigner, fatalErrChan, l1ChainId, nil /* blob reader */) + l2node, err := arbnode.CreateNodeFullExecutionClient(ctx, l2stack, execNode, execNode, execNode, execNode, l2arbDb, NewFetcherFromConfig(nodeConfig), l2blockchain.Config(), l1client, addresses, &txOpts, &txOpts, dataSigner, fatalErrChan, l1ChainId, nil /* blob reader */) Require(t, err) l2client := ClientForStack(t, l2stack) diff --git a/system_tests/bold_state_provider_test.go b/system_tests/bold_state_provider_test.go index 0ecce5ba64..cd137ea5b2 100644 --- a/system_tests/bold_state_provider_test.go +++ b/system_tests/bold_state_provider_test.go @@ -380,7 +380,7 @@ func setupBoldStateProvider(t *testing.T, ctx context.Context, blockChallengeHei l2node.InboxReader, l2node.InboxTracker, l2node.TxStreamer, - l2node.Execution, + l2node.ExecutionRecorder, l2node.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), diff --git a/system_tests/overflow_assertions_test.go b/system_tests/overflow_assertions_test.go index c024a43070..6bc7faa9ca 100644 --- a/system_tests/overflow_assertions_test.go +++ b/system_tests/overflow_assertions_test.go @@ -94,7 +94,7 @@ func TestOverflowAssertions(t *testing.T) { l2node.InboxReader, l2node.InboxTracker, l2node.TxStreamer, - l2node.Execution, + l2node.ExecutionRecorder, l2node.ArbDB, nil, StaticFetcherFrom(t, &blockValidatorConfig), @@ -173,7 +173,7 @@ func TestOverflowAssertions(t *testing.T) { t.Logf("Node batch count %d, msgs %d", bc, msgs) // Wait for the node to catch up. - nodeExec, ok := l2node.Execution.(*gethexec.ExecutionNode) + nodeExec, ok := l2node.ExecutionClient.(*gethexec.ExecutionNode) if !ok { Fatal(t, "not geth execution node") } From da6022ac473bca38de20f1dbdbbb6f29c3386494 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Fri, 3 Jan 2025 11:19:28 -0300 Subject: [PATCH 32/33] Fixes snap sync test procedure when creating arb node --- arbnode/node.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/arbnode/node.go b/arbnode/node.go index adc5c81a2f..22d0142269 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -596,6 +596,8 @@ func getDAS( } func getInboxTrackerAndReader( + ctx context.Context, + exec execution.ExecutionSequencer, arbDb ethdb.Database, txStreamer *TransactionStreamer, dapReaders []daprovider.Reader, @@ -613,10 +615,14 @@ func getInboxTrackerAndReader( } firstMessageBlock := new(big.Int).SetUint64(deployInfo.DeployedAt) if config.SnapSyncTest.Enabled { + if exec == nil { + return nil, nil, errors.New("snap sync test requires an execution sequencer") + } + batchCount := config.SnapSyncTest.BatchCount delayedMessageNumber, err := exec.NextDelayedMessageNumber() if err != nil { - return nil, err + return nil, nil, err } if batchCount > delayedMessageNumber { batchCount = delayedMessageNumber @@ -629,7 +635,7 @@ func getInboxTrackerAndReader( } block, err := FindBlockContainingBatchCount(ctx, deployInfo.Bridge, l1client, config.SnapSyncTest.ParentChainAssertionBlock, batchCount) if err != nil { - return nil, err + return nil, nil, err } firstMessageBlock.SetUint64(block) } @@ -1036,7 +1042,7 @@ func createNodeImpl( return nil, err } - inboxTracker, inboxReader, err := getInboxTrackerAndReader(arbDb, txStreamer, dapReaders, config, configFetcher, l1client, l1Reader, deployInfo, delayedBridge, sequencerInbox) + inboxTracker, inboxReader, err := getInboxTrackerAndReader(ctx, executionSequencer, arbDb, txStreamer, dapReaders, config, configFetcher, l1client, l1Reader, deployInfo, delayedBridge, sequencerInbox) if err != nil { return nil, err } From 53701a76c4080b1259d0dc2e0aedc2539036a4b1 Mon Sep 17 00:00:00 2001 From: Diego Ximenes Date: Wed, 15 Jan 2025 16:00:44 -0300 Subject: [PATCH 33/33] Avoids using context.Background() in transaction streamer --- arbnode/transaction_streamer.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 024a32062f..d845bcd477 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -497,7 +497,7 @@ func (s *TransactionStreamer) GetProcessedMessageCount() (arbutil.MessageIndex, if err != nil { return 0, err } - digestedHead, err := s.exec.HeadMessageNumber().Await(context.Background()) + digestedHead, err := s.exec.HeadMessageNumber().Await(s.GetContext()) if err != nil { return 0, err } @@ -1093,7 +1093,11 @@ func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execut } log.Info(FailedToGetMsgResultFromDB, "count", count) - msgResult, err := s.exec.ResultAtPos(pos).Await(context.Background()) + ctx := context.Background() + if s.Started() { + ctx = s.GetContext() + } + msgResult, err := s.exec.ResultAtPos(pos).Await(ctx) if err != nil { return nil, err }