From 1259791d8d39ff418120b384de97ca294a0728ab Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Tue, 8 Oct 2024 13:22:59 -0600 Subject: [PATCH 01/13] Update to sequencer.go to remove `EnableEspressoSovereign` flag, and instead sequence based on hotshot liveness at l1 block height. --- execution/gethexec/sequencer.go | 49 ++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 96367e8aef..97fcbbd116 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + lightclient "github.com/EspressoSystems/espresso-sequencer-go/light-client" "math" "math/big" "runtime/debug" @@ -80,7 +81,8 @@ type SequencerConfig struct { expectedSurplusHardThreshold int // Espresso specific flags - EnableEspressoSovereign bool `koanf:"enable-espresso-sovereign"` + LightClientAddress string `koanf:"light-client-address"` + SwitchDelayThreshold uint64 `koanf:"switch-delay-threshold"` EspressoFinalityNodeConfig EspressoFinalityNodeConfig `koanf:"espresso-finality-node-config"` // Espresso Finality Node creates blocks with finalized hotshot transactions EnableEspressoFinalityNode bool `koanf:"enable-espresso-finality-node"` @@ -129,7 +131,6 @@ var DefaultSequencerConfig = SequencerConfig{ EnableProfiling: false, EnableEspressoFinalityNode: false, - EnableEspressoSovereign: false, } var TestSequencerConfig = SequencerConfig{ @@ -150,7 +151,6 @@ var TestSequencerConfig = SequencerConfig{ EnableProfiling: false, EnableEspressoFinalityNode: false, - EnableEspressoSovereign: false, } func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -172,7 +172,6 @@ func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { // Espresso specific flags f.Bool(prefix+".enable-espresso-finality-node", DefaultSequencerConfig.EnableEspressoFinalityNode, "enable espresso finality node") - f.Bool(prefix+".enable-espresso-sovereign", DefaultSequencerConfig.EnableEspressoSovereign, "enable sovereign sequencer mode for the Espresso integration") } type txQueueItem struct { @@ -341,6 +340,8 @@ type Sequencer struct { expectedSurplusMutex sync.RWMutex expectedSurplus int64 expectedSurplusUpdated bool + + lightClientReader *lightclient.LightClientReader } func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderReader, configFetcher SequencerConfigFetcher) (*Sequencer, error) { @@ -356,17 +357,26 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead } senderWhitelist[common.HexToAddress(address)] = struct{}{} } + + lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1Reader.Client()) + + if err != nil { + log.Error("Could not construct light client reader for sequencer. Failing.", "err", err) + return nil, err + } + s := &Sequencer{ - execEngine: execEngine, - txQueue: make(chan txQueueItem, config.QueueSize), - l1Reader: l1Reader, - config: configFetcher, - senderWhitelist: senderWhitelist, - nonceCache: newNonceCache(config.NonceCacheSize), - l1BlockNumber: 0, - l1Timestamp: 0, - pauseChan: nil, - onForwarderSet: make(chan struct{}, 1), + execEngine: execEngine, + txQueue: make(chan txQueueItem, config.QueueSize), + l1Reader: l1Reader, + config: configFetcher, + senderWhitelist: senderWhitelist, + nonceCache: newNonceCache(config.NonceCacheSize), + l1BlockNumber: 0, + l1Timestamp: 0, + pauseChan: nil, + onForwarderSet: make(chan struct{}, 1), + lightClientReader: lightClientReader, } s.nonceFailures = &nonceFailureCache{ containers.NewLruCacheWithOnEvict(config.NonceCacheSize, s.onNonceFailureEvict), @@ -938,10 +948,17 @@ func (s *Sequencer) createBlock(ctx context.Context) (returnValue bool) { block *types.Block err error ) + + shouldSequenceWithEspresso, err := s.lightClientReader.IsHotShotLiveAtHeight(l1Block, s.config().SwitchDelayThreshold) + + if err != nil { + log.Warn("An error occurred while attempting to determine if hotshot is live at l1 block, sequencing transactions without espresso", "l1Block", l1Block, "err", err) + shouldSequenceWithEspresso = false + } if config.EnableProfiling { - block, err = s.execEngine.SequenceTransactionsWithProfiling(header, txes, hooks, config.EnableEspressoSovereign) + block, err = s.execEngine.SequenceTransactionsWithProfiling(header, txes, hooks, shouldSequenceWithEspresso) } else { - block, err = s.execEngine.SequenceTransactions(header, txes, hooks, config.EnableEspressoSovereign) + block, err = s.execEngine.SequenceTransactions(header, txes, hooks, shouldSequenceWithEspresso) } elapsed := time.Since(start) blockCreationTimer.Update(elapsed) From 413324fff3bc3907f489355b8e2f487ee20a2dd8 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Tue, 8 Oct 2024 13:23:43 -0600 Subject: [PATCH 02/13] Update node.go to remove reference to `EnableEspressoSovereign` --- execution/gethexec/node.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index a0da6d6144..a570ee1fe0 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -186,11 +186,6 @@ func CreateExecutionNode( return nil, err } - // sovereign sequencer should not be configured with espresso finality node - if config.Sequencer.EnableEspressoFinalityNode && config.Sequencer.EnableEspressoSovereign { - return nil, errors.New("espresso finality node cannot be configured with espresso sovereign sequencer") - } - if config.Sequencer.EnableEspressoFinalityNode { espressoFinalityNode := NewEspressoFinalityNode(execEngine, seqConfigFetcher) txPublisher = espressoFinalityNode From 37335486ee077111e0627f6c59e8b120616a20f0 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Tue, 8 Oct 2024 13:45:45 -0600 Subject: [PATCH 03/13] update Espresso tests to reflect removed config variables, and add escape hatch test to e2e test. --- system_tests/espresso_e2e_test.go | 85 +++++++++++++++++++ system_tests/espresso_finality_node_test.go | 2 - .../espresso_sovereign_sequencer_test.go | 2 - 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/system_tests/espresso_e2e_test.go b/system_tests/espresso_e2e_test.go index 8ca372708e..8ef8e691bc 100644 --- a/system_tests/espresso_e2e_test.go +++ b/system_tests/espresso_e2e_test.go @@ -3,7 +3,11 @@ package arbtest import ( "context" "encoding/json" + lightclient "github.com/EspressoSystems/espresso-sequencer-go/light-client" + lightclientmock "github.com/EspressoSystems/espresso-sequencer-go/light-client-mock" + "github.com/ethereum/go-ethereum/common" "math/big" + "os" "os/exec" "testing" "time" @@ -22,6 +26,7 @@ var workingDir = "./espresso-e2e" var lightClientAddress = "0xb075b82c7a23e0994df4793422a1f03dbcf9136f" var hotShotUrl = "http://127.0.0.1:41000" +var delayThreshold = 10 var ( jitValidationPort = 54320 @@ -141,6 +146,17 @@ func waitForEspressoNode(t *testing.T, ctx context.Context) error { }) } +func waitForHotShotLiveness(t *testing.T, ctx context.Context, lightClientReader *lightclient.LightClientReader) error { + return waitForWith(t, ctx, 400*time.Second, 1*time.Second, func() bool { + log.Info("Waiting for HotShot Liveness") + live, err := lightClientReader.IsHotShotLive(10) + if err != nil { + return false + } + return live + }) +} + func waitForL1Node(t *testing.T, ctx context.Context) error { return waitFor(t, ctx, func() bool { if e := exec.Command( @@ -207,6 +223,15 @@ func TestEspressoE2E(t *testing.T) { }) Require(t, err) + //make light client reader + + lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) + Require(t, err) + //wait for hotshot liveness + + err = waitForHotShotLiveness(t, ctx, lightClientReader) + Require(t, err) + // Check if the tx is executed correctly err = checkTransferTxOnL2(t, ctx, l2Node, "User10", l2Info) Require(t, err) @@ -246,6 +271,66 @@ func TestEspressoE2E(t *testing.T) { return balance2.Cmp(transferAmount) >= 0 }) Require(t, err) + + // Pause l1 height and verify that the escape hatch is working + checkStaker := os.Getenv("E2E_SKIP_ESCAPE_HATCH_TEST") + if checkStaker == "" { + log.Info("Checking the escape hatch") + // Start to check the escape hatch + address := common.HexToAddress(lightClientAddress) + + txOpts := builder.L1Info.GetDefaultTransactOpts("Faucet", ctx) + + // Freeze the l1 height + err := lightclientmock.FreezeL1Height(t, builder.L1.Client, address, &txOpts) + log.Info("waiting for light client to report hotshot is down") + Require(t, err) + err = waitForWith(t, ctx, 10*time.Minute, 1*time.Second, func() bool { + isLive, err := lightclientmock.IsHotShotLive(t, builder.L1.Client, address, uint64(delayThreshold)) + if err != nil { + return false + } + return !isLive + }) + Require(t, err) + log.Info("light client has reported that hotshot is down") + // Wait for the switch to be totally finished + currMsg, err := builder.L2.ConsensusNode.TxStreamer.GetMessageCount() + Require(t, err) + log.Info("waiting for message count", "currMsg", currMsg) + var validatedMsg arbutil.MessageIndex + err = waitForWith(t, ctx, 6*time.Minute, 60*time.Second, func() bool { + validatedCnt := builder.L2.ConsensusNode.BlockValidator.Validated(t) + log.Info("Validation status", "validatedCnt", validatedCnt, "msgCnt", msgCnt) + if validatedCnt >= currMsg { + validatedMsg = validatedCnt + return true + } + return false + }) + Require(t, err) + err = checkTransferTxOnL2(t, ctx, l2Node, "User12", l2Info) + Require(t, err) + err = checkTransferTxOnL2(t, ctx, l2Node, "User13", l2Info) + Require(t, err) + + err = waitForWith(t, ctx, 3*time.Minute, 20*time.Second, func() bool { + validated := builder.L2.ConsensusNode.BlockValidator.Validated(t) + return validated >= validatedMsg + }) + Require(t, err) + + // Unfreeze the l1 height + err = lightclientmock.UnfreezeL1Height(t, builder.L1.Client, address, &txOpts) + Require(t, err) + + // Check if the validated count is increasing + err = waitForWith(t, ctx, 3*time.Minute, 20*time.Second, func() bool { + validated := builder.L2.ConsensusNode.BlockValidator.Validated(t) + return validated >= validatedMsg+10 + }) + Require(t, err) + } } func checkTransferTxOnL2( diff --git a/system_tests/espresso_finality_node_test.go b/system_tests/espresso_finality_node_test.go index ab8e3b1ac6..3b8d855b92 100644 --- a/system_tests/espresso_finality_node_test.go +++ b/system_tests/espresso_finality_node_test.go @@ -34,8 +34,6 @@ func createEspressoFinalityNode(t *testing.T, builder *NodeBuilder) (*TestClient execConfig.Sequencer.EspressoFinalityNodeConfig.StartBlock = 1 execConfig.Sequencer.EspressoFinalityNodeConfig.HotShotUrl = hotShotUrl - // disable sovereign sequencer - execConfig.Sequencer.EnableEspressoSovereign = false builder.nodeConfig.TransactionStreamer.SovereignSequencerEnabled = false return builder.Build2ndNode(t, &SecondNodeParams{ diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index e9527ee565..9473478bd6 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -41,8 +41,6 @@ func createL1AndL2Node(ctx context.Context, t *testing.T) (*NodeBuilder, func()) builder.nodeConfig.Sequencer = true builder.nodeConfig.Dangerous.NoSequencerCoordinator = true builder.execConfig.Sequencer.Enable = true - // using the sovereign sequencer - builder.execConfig.Sequencer.EnableEspressoSovereign = true // transaction stream config builder.nodeConfig.TransactionStreamer.SovereignSequencerEnabled = true From daa9cc8acdff9908c3b6863c4d80a0ad6ed41207 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Tue, 8 Oct 2024 13:51:20 -0600 Subject: [PATCH 04/13] Add wait for hotshot liveness in sovereign sequencer test to ensure sovereign sequencer is enabled. --- system_tests/espresso_sovereign_sequencer_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index 9473478bd6..fbc8d5c2a2 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -3,6 +3,8 @@ package arbtest import ( "context" "fmt" + lightclient "github.com/EspressoSystems/espresso-sequencer-go/light-client" + "github.com/ethereum/go-ethereum/common" "math/big" "testing" "time" @@ -77,6 +79,12 @@ func TestSovereignSequencer(t *testing.T) { err = waitForEspressoNode(t, ctx) Require(t, err) + // create light client reader + lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) + + // wait for hotshot liveness + err = waitForHotShotLiveness(t, ctx, lightClientReader) + err = checkTransferTxOnL2(t, ctx, builder.L2, "User14", builder.L2Info) Require(t, err) From 911b8e8c0b42daa12704cc4bfad71496e38a42d1 Mon Sep 17 00:00:00 2001 From: Mathis Antony Date: Wed, 9 Oct 2024 09:06:27 -0600 Subject: [PATCH 05/13] go fmt --- system_tests/espresso_e2e_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system_tests/espresso_e2e_test.go b/system_tests/espresso_e2e_test.go index 8ef8e691bc..9b9ce11fed 100644 --- a/system_tests/espresso_e2e_test.go +++ b/system_tests/espresso_e2e_test.go @@ -223,11 +223,11 @@ func TestEspressoE2E(t *testing.T) { }) Require(t, err) - //make light client reader + // make light client reader lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) Require(t, err) - //wait for hotshot liveness + // wait for hotshot liveness err = waitForHotShotLiveness(t, ctx, lightClientReader) Require(t, err) From 227de30740d85320a7c0a165b6df015b61df13b1 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Wed, 9 Oct 2024 16:36:05 -0600 Subject: [PATCH 06/13] Add comment to explain changes needed in replay binary when panics are no longer an issue. --- cmd/replay/main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/replay/main.go b/cmd/replay/main.go index 3d29d5f79e..637e4df18e 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -288,6 +288,14 @@ func main() { // Handle the various pre-conditions if the message is an Espresso message validatingAgainstEspresso := chainConfig.ArbitrumChainParams.EnableEspresso && arbos.IsEspressoMsg(message.Message) + + // Currently we don't check the hotshot liveness here as it introduces a panic if the wavmio call fails. + // When we can again panic in the STF, we should re-add this check. + // + // The following call will be used to check the liveness based on the l1 block height. + // isHotShotLive := wavmio.IsHotShotLive(message.Message.Header.BlockNumber) + // + // The following line should be changed to if validatingAgainstEspresso && isHotShotLive { if validatingAgainstEspresso { txs, jst, err := arbos.ParseEspressoMsg(message.Message) if err != nil { From 80f1aee15aedbef41c179642207764c5b92ab961 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Wed, 9 Oct 2024 16:36:28 -0600 Subject: [PATCH 07/13] Fix lint issues --- system_tests/espresso_e2e_test.go | 4 ++-- system_tests/espresso_sovereign_sequencer_test.go | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/system_tests/espresso_e2e_test.go b/system_tests/espresso_e2e_test.go index 8ef8e691bc..9b9ce11fed 100644 --- a/system_tests/espresso_e2e_test.go +++ b/system_tests/espresso_e2e_test.go @@ -223,11 +223,11 @@ func TestEspressoE2E(t *testing.T) { }) Require(t, err) - //make light client reader + // make light client reader lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) Require(t, err) - //wait for hotshot liveness + // wait for hotshot liveness err = waitForHotShotLiveness(t, ctx, lightClientReader) Require(t, err) diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index fbc8d5c2a2..4fa55d3778 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -82,9 +82,11 @@ func TestSovereignSequencer(t *testing.T) { // create light client reader lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) + Require(t, err) + // wait for hotshot liveness err = waitForHotShotLiveness(t, ctx, lightClientReader) - + Require(t, err) err = checkTransferTxOnL2(t, ctx, builder.L2, "User14", builder.L2Info) Require(t, err) From 1005627c71888e9272b4c4a313320021b9be2f63 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Wed, 9 Oct 2024 20:41:20 -0600 Subject: [PATCH 08/13] Modify construction of lightClientReader in sequencer.go to allow for nil `l1Reader` --- execution/gethexec/sequencer.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 97fcbbd116..e776b5019a 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -358,7 +358,14 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead senderWhitelist[common.HexToAddress(address)] = struct{}{} } - lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1Reader.Client()) + var ( + lightClientReader *lightclient.LightClientReader + err error + ) + + if l1Reader != nil { + lightClientReader, err = lightclient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1Reader.Client()) + } if err != nil { log.Error("Could not construct light client reader for sequencer. Failing.", "err", err) @@ -945,16 +952,23 @@ func (s *Sequencer) createBlock(ctx context.Context) (returnValue bool) { start := time.Now() var ( - block *types.Block - err error + block *types.Block + err error + shouldSequenceWithEspresso bool ) - shouldSequenceWithEspresso, err := s.lightClientReader.IsHotShotLiveAtHeight(l1Block, s.config().SwitchDelayThreshold) + // Initialize shouldSequenceWithEspresso to false and if we have a light client reader then give it a value based on hotshot liveness + // This is a side effect of the sequencer having the capability to run without an L1 reader. For the Espresso integration this is a necessary component of the sequencer. + // However, many tests use the case of having a nil l1 reader + if s.lightClientReader != nil { + shouldSequenceWithEspresso, err = s.lightClientReader.IsHotShotLiveAtHeight(l1Block, s.config().SwitchDelayThreshold) + } if err != nil { log.Warn("An error occurred while attempting to determine if hotshot is live at l1 block, sequencing transactions without espresso", "l1Block", l1Block, "err", err) shouldSequenceWithEspresso = false } + if config.EnableProfiling { block, err = s.execEngine.SequenceTransactionsWithProfiling(header, txes, hooks, shouldSequenceWithEspresso) } else { From 2cb6b6f13e8032fcb6451ac9a05cc4a94da9289d Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Thu, 10 Oct 2024 10:55:59 -0600 Subject: [PATCH 09/13] Update test configs to align with changes. --- system_tests/espresso_sovereign_sequencer_test.go | 2 ++ .../espresso_transaction_payload_signature_test.go | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index 4fa55d3778..cde315252c 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -41,8 +41,10 @@ func createL1AndL2Node(ctx context.Context, t *testing.T) (*NodeBuilder, func()) // sequencer config builder.nodeConfig.Sequencer = true + builder.nodeConfig.ParentChainReader.Enable = true // This flag is necessary to enable sequencing transactions with espresso behavior builder.nodeConfig.Dangerous.NoSequencerCoordinator = true builder.execConfig.Sequencer.Enable = true + builder.execConfig.Sequencer.LightClientAddress = lightClientAddress // transaction stream config builder.nodeConfig.TransactionStreamer.SovereignSequencerEnabled = true diff --git a/system_tests/espresso_transaction_payload_signature_test.go b/system_tests/espresso_transaction_payload_signature_test.go index 503222d94f..e9b5e6dc7f 100644 --- a/system_tests/espresso_transaction_payload_signature_test.go +++ b/system_tests/espresso_transaction_payload_signature_test.go @@ -4,6 +4,8 @@ import ( "context" "crypto/ecdsa" "fmt" + lightclient "github.com/EspressoSystems/espresso-sequencer-go/light-client" + "github.com/ethereum/go-ethereum/common" "testing" "github.com/ethereum/go-ethereum/crypto" @@ -35,6 +37,13 @@ func TestEspressoTransactionSignatureForSovereignSequencer(t *testing.T) { err = waitForEspressoNode(t, ctx) Require(t, err) + lightClientReader, err := lightclient.NewLightClientReader(common.HexToAddress(lightClientAddress), builder.L1.Client) + Require(t, err) + // wait for hotshot liveness + + err = waitForHotShotLiveness(t, ctx, lightClientReader) + Require(t, err) + err = checkTransferTxOnL2(t, ctx, l2Node, "User14", l2Info) Require(t, err) From 3d3cae3b3d2c048a100b4b508d8f94b0f4408f96 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Thu, 10 Oct 2024 16:14:34 -0600 Subject: [PATCH 10/13] Update comments according to feedback. --- cmd/replay/main.go | 7 ------- execution/gethexec/sequencer.go | 3 +++ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/replay/main.go b/cmd/replay/main.go index 637e4df18e..984337dd61 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -289,13 +289,6 @@ func main() { // Handle the various pre-conditions if the message is an Espresso message validatingAgainstEspresso := chainConfig.ArbitrumChainParams.EnableEspresso && arbos.IsEspressoMsg(message.Message) - // Currently we don't check the hotshot liveness here as it introduces a panic if the wavmio call fails. - // When we can again panic in the STF, we should re-add this check. - // - // The following call will be used to check the liveness based on the l1 block height. - // isHotShotLive := wavmio.IsHotShotLive(message.Message.Header.BlockNumber) - // - // The following line should be changed to if validatingAgainstEspresso && isHotShotLive { if validatingAgainstEspresso { txs, jst, err := arbos.ParseEspressoMsg(message.Message) if err != nil { diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index e776b5019a..46a32af884 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -358,6 +358,9 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead senderWhitelist[common.HexToAddress(address)] = struct{}{} } + // For the sovereign sequencer to have an escape hatch, we need to be able to read the state of the light client. + // To accomplish this, we introduce a requirement on the l1Reader/ParentChainReader to not be null. This is a soft + // requirement as the sequencer will still run if we don't have this reader, but it will not create espresso messages. var ( lightClientReader *lightclient.LightClientReader err error From 7f3b85b4b3bcae9fd21a1e6b122b439a199e21fa Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Fri, 11 Oct 2024 10:52:09 -0600 Subject: [PATCH 11/13] Revert removal of `EnableEspressoSovereign` --- execution/gethexec/sequencer.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 46a32af884..70e383b105 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -86,6 +86,7 @@ type SequencerConfig struct { EspressoFinalityNodeConfig EspressoFinalityNodeConfig `koanf:"espresso-finality-node-config"` // Espresso Finality Node creates blocks with finalized hotshot transactions EnableEspressoFinalityNode bool `koanf:"enable-espresso-finality-node"` + EnableEspressoSovereign bool `koanf:"enable-espresso-sovereign"` } func (c *SequencerConfig) Validate() error { @@ -131,6 +132,7 @@ var DefaultSequencerConfig = SequencerConfig{ EnableProfiling: false, EnableEspressoFinalityNode: false, + EnableEspressoSovereign: false, } var TestSequencerConfig = SequencerConfig{ @@ -151,6 +153,7 @@ var TestSequencerConfig = SequencerConfig{ EnableProfiling: false, EnableEspressoFinalityNode: false, + EnableEspressoSovereign: false, } func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -172,6 +175,7 @@ func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { // Espresso specific flags f.Bool(prefix+".enable-espresso-finality-node", DefaultSequencerConfig.EnableEspressoFinalityNode, "enable espresso finality node") + f.Bool(prefix+".enable-espresso-sovereign", DefaultSequencerConfig.EnableEspressoSovereign, "enable sovereign sequencer mode for the Espresso integration") } type txQueueItem struct { From f0b7b4f275444d256f467913bc2e3fea143ec433 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Fri, 11 Oct 2024 11:44:21 -0600 Subject: [PATCH 12/13] Add additional check to ensure that if EnableEspressoSovereign is on we can't construct a sequencer with a nil lightClientReader --- execution/gethexec/sequencer.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index 70e383b105..99ff89754a 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -370,13 +370,16 @@ func NewSequencer(execEngine *ExecutionEngine, l1Reader *headerreader.HeaderRead err error ) - if l1Reader != nil { - lightClientReader, err = lightclient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1Reader.Client()) + if l1Reader == nil && config.EnableEspressoSovereign { + return nil, fmt.Errorf("Cannot enable espresso sequencing mode in the sovereign sequencer with no l1 reader") } - if err != nil { - log.Error("Could not construct light client reader for sequencer. Failing.", "err", err) - return nil, err + if l1Reader != nil { + lightClientReader, err = lightclient.NewLightClientReader(common.HexToAddress(config.LightClientAddress), l1Reader.Client()) + if err != nil { + log.Error("Could not construct light client reader for sequencer. Failing.", "err", err) + return nil, err + } } s := &Sequencer{ From dcc965d5f9b70f73e3f4f4c607baeebb2008dac9 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Fri, 11 Oct 2024 11:53:59 -0600 Subject: [PATCH 13/13] Add `EnableEspressoSovereign` config flag to test configs. --- system_tests/espresso_sovereign_sequencer_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index cde315252c..0a209d6592 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -43,6 +43,7 @@ func createL1AndL2Node(ctx context.Context, t *testing.T) (*NodeBuilder, func()) builder.nodeConfig.Sequencer = true builder.nodeConfig.ParentChainReader.Enable = true // This flag is necessary to enable sequencing transactions with espresso behavior builder.nodeConfig.Dangerous.NoSequencerCoordinator = true + builder.execConfig.Sequencer.EnableEspressoSovereign = true builder.execConfig.Sequencer.Enable = true builder.execConfig.Sequencer.LightClientAddress = lightClientAddress