From 5b4d5cab60e449fdb6c00c39eaa2ab2a1c92d862 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Mon, 11 Nov 2024 15:52:16 -0500 Subject: [PATCH 1/5] Add espresso proof validation to batch poster Adds calls to the espresso validation code to the batch poster to validate the namespace proof and merkle proof in a TEE --- arbnode/batch_poster.go | 24 ++++++++++++++++--- .../espresso_sovereign_sequencer_test.go | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 1cf7bc6edc..0d51dacebb 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -8,6 +8,7 @@ import ( "context" "encoding/binary" "encoding/hex" + "encoding/json" "errors" "fmt" "math" @@ -36,6 +37,7 @@ import ( hotshotClient "github.com/EspressoSystems/espresso-sequencer-go/client" lightclient "github.com/EspressoSystems/espresso-sequencer-go/light-client" + "github.com/offchainlabs/nitro/espressocrypto" "github.com/offchainlabs/nitro/arbnode/dataposter" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" @@ -540,7 +542,7 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( ctx context.Context, msg *arbostypes.MessageWithMetadata, ) error { - + // TODO Add escape hatch check after checking arbitrum chain params for enable espresso. if arbos.IsEspressoMsg(msg.Message) { arbOSConfig, err := b.arbOSVersionGetter.GetArbOSConfigAtHeight(0) if err != nil { @@ -593,8 +595,24 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( } var newMsg arbostypes.L1IncomingMessage jst.BlockMerkleJustification = &arbostypes.BlockMerkleJustification{BlockMerkleProof: &proof, BlockMerkleComm: nextHeader.BlockMerkleTreeRoot} - - if arbos.IsEspressoSovereignMsg(msg.Message) { + + log.Info("About to validate merkle and namespace proofs") + + //Validate espresso proofs. + json_header, err := json.Marshal(jst.Header) + if err != nil{ + return fmt.Errorf("Failed to Marshal the jst Header") + } + + valid_proof := espressocrypto.VerifyMerkleProof(proof.Proof, json_header, *jst.BlockMerkleJustification.BlockMerkleComm, snapshot.Root) + valid_namespace := espressocrypto.VerifyNamespace(arbOSConfig.ChainID.Uint64(), *jst.Proof, *jst.Header.PayloadCommitment, *jst.Header.NsTable, txs, *jst.VidCommon) + if !(valid_proof && valid_namespace){ + return fmt.Errorf("Cannot add Espresso block merkle proof as it is not valid") + } + + log.Info("Espresso proofs have been validated!") + + if arbos.IsEspressoSovereignMsg(msg.Message) { // Passing an empty byte slice as payloadSignature because txs[0] already contains the payloadSignature here newMsg, err = arbos.MessageFromEspressoSovereignTx(txs[0], jst, []byte{}, msg.Message.Header) if err != nil { diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index 04b7ee529d..6e1bb41666 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -48,6 +48,7 @@ func createL1AndL2Node(ctx context.Context, t *testing.T) (*NodeBuilder, func()) builder.execConfig.Sequencer.EnableEspressoSovereign = true builder.execConfig.Sequencer.Enable = true builder.execConfig.Sequencer.LightClientAddress = lightClientAddress + builder.execConfig.Sequencer.SwitchDelayThreshold = 5 builder.execConfig.Caching.StateScheme = "hash" builder.execConfig.Caching.Archive = true From c5249dfd3d7e2eafd132200ac8cdbf3097ad69c4 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Mon, 11 Nov 2024 16:01:17 -0500 Subject: [PATCH 2/5] result of make fmt --- arbnode/batch_poster.go | 38 +++++++++---------- .../espresso_sovereign_sequencer_test.go | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 0d51dacebb..96a0422eba 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -542,7 +542,7 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( ctx context.Context, msg *arbostypes.MessageWithMetadata, ) error { - // TODO Add escape hatch check after checking arbitrum chain params for enable espresso. + // TODO Add escape hatch check after checking arbitrum chain params for enable espresso. if arbos.IsEspressoMsg(msg.Message) { arbOSConfig, err := b.arbOSVersionGetter.GetArbOSConfigAtHeight(0) if err != nil { @@ -595,24 +595,24 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( } var newMsg arbostypes.L1IncomingMessage jst.BlockMerkleJustification = &arbostypes.BlockMerkleJustification{BlockMerkleProof: &proof, BlockMerkleComm: nextHeader.BlockMerkleTreeRoot} - - log.Info("About to validate merkle and namespace proofs") - - //Validate espresso proofs. - json_header, err := json.Marshal(jst.Header) - if err != nil{ - return fmt.Errorf("Failed to Marshal the jst Header") - } - - valid_proof := espressocrypto.VerifyMerkleProof(proof.Proof, json_header, *jst.BlockMerkleJustification.BlockMerkleComm, snapshot.Root) - valid_namespace := espressocrypto.VerifyNamespace(arbOSConfig.ChainID.Uint64(), *jst.Proof, *jst.Header.PayloadCommitment, *jst.Header.NsTable, txs, *jst.VidCommon) - if !(valid_proof && valid_namespace){ - return fmt.Errorf("Cannot add Espresso block merkle proof as it is not valid") - } - - log.Info("Espresso proofs have been validated!") - - if arbos.IsEspressoSovereignMsg(msg.Message) { + + log.Info("About to validate merkle and namespace proofs") + + //Validate espresso proofs. + json_header, err := json.Marshal(jst.Header) + if err != nil { + return fmt.Errorf("Failed to Marshal the jst Header") + } + + valid_proof := espressocrypto.VerifyMerkleProof(proof.Proof, json_header, *jst.BlockMerkleJustification.BlockMerkleComm, snapshot.Root) + valid_namespace := espressocrypto.VerifyNamespace(arbOSConfig.ChainID.Uint64(), *jst.Proof, *jst.Header.PayloadCommitment, *jst.Header.NsTable, txs, *jst.VidCommon) + if !(valid_proof && valid_namespace) { + return fmt.Errorf("Cannot add Espresso block merkle proof as it is not valid") + } + + log.Info("Espresso proofs have been validated!") + + if arbos.IsEspressoSovereignMsg(msg.Message) { // Passing an empty byte slice as payloadSignature because txs[0] already contains the payloadSignature here newMsg, err = arbos.MessageFromEspressoSovereignTx(txs[0], jst, []byte{}, msg.Message.Header) if err != nil { diff --git a/system_tests/espresso_sovereign_sequencer_test.go b/system_tests/espresso_sovereign_sequencer_test.go index 6e1bb41666..19e0a09e6a 100644 --- a/system_tests/espresso_sovereign_sequencer_test.go +++ b/system_tests/espresso_sovereign_sequencer_test.go @@ -48,7 +48,7 @@ func createL1AndL2Node(ctx context.Context, t *testing.T) (*NodeBuilder, func()) builder.execConfig.Sequencer.EnableEspressoSovereign = true builder.execConfig.Sequencer.Enable = true builder.execConfig.Sequencer.LightClientAddress = lightClientAddress - builder.execConfig.Sequencer.SwitchDelayThreshold = 5 + builder.execConfig.Sequencer.SwitchDelayThreshold = 5 builder.execConfig.Caching.StateScheme = "hash" builder.execConfig.Caching.Archive = true From f929d2a1b63f7b68aa43a641e158393996725fae Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Mon, 11 Nov 2024 17:30:59 -0500 Subject: [PATCH 3/5] Fix lint errors --- arbnode/batch_poster.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 96a0422eba..00da185c5e 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -598,7 +598,7 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( log.Info("About to validate merkle and namespace proofs") - //Validate espresso proofs. + // Validate espresso proofs. json_header, err := json.Marshal(jst.Header) if err != nil { return fmt.Errorf("Failed to Marshal the jst Header") From 228be2eb2ffe85d63d2386d736dc1babeeec1194 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Mon, 11 Nov 2024 19:27:19 -0500 Subject: [PATCH 4/5] Add better logging --- arbnode/batch_poster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 00da185c5e..02bc76ba70 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -596,7 +596,7 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( var newMsg arbostypes.L1IncomingMessage jst.BlockMerkleJustification = &arbostypes.BlockMerkleJustification{BlockMerkleProof: &proof, BlockMerkleComm: nextHeader.BlockMerkleTreeRoot} - log.Info("About to validate merkle and namespace proofs") + log.Info("About to validate merkle and namespace proofs for msg count with batch relevant to l1 height", "msg count", b.building.msgCount, "l1 height", msg.Message.Header.BlockNumber) // Validate espresso proofs. json_header, err := json.Marshal(jst.Header) @@ -610,7 +610,7 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( return fmt.Errorf("Cannot add Espresso block merkle proof as it is not valid") } - log.Info("Espresso proofs have been validated!") + log.Info("Espresso proofs have been validated!", "msg count", b.building.msgCount, "l1 height", msg.Message.Header.BlockNumber) if arbos.IsEspressoSovereignMsg(msg.Message) { // Passing an empty byte slice as payloadSignature because txs[0] already contains the payloadSignature here From d560a41ccb6b168dc7c54918917f388182f60ac3 Mon Sep 17 00:00:00 2001 From: Zach Showalter Date: Tue, 12 Nov 2024 11:27:43 -0500 Subject: [PATCH 5/5] Fix batch poster after merge of upstream/integration --- arbnode/batch_poster.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index d06d26a706..0b0bd77199 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -610,10 +610,9 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( } else { newMsg, err = arbos.MessageFromEspresso(msg.Message.Header, txs, jst) if err != nil { - return fmt.Errorf("error fetching the block merkle proof for validated height %v and leaf height %v. Request failed with error %w", snapshot.Height, jst.Header.Height, err) + return fmt.Errorf("error fetching the block merkle proof for validated height %v and leaf height %v. Request failed with error %w", snapshot.Height, jst.Header.Header.GetBlockHeight(), err) } - var newMsg arbostypes.L1IncomingMessage - jst.BlockMerkleJustification = &arbostypes.BlockMerkleJustification{BlockMerkleProof: &proof, BlockMerkleComm: nextHeader.BlockMerkleTreeRoot} + jst.BlockMerkleJustification = &arbostypes.BlockMerkleJustification{BlockMerkleProof: &proof, BlockMerkleComm: nextHeader.Header.GetBlockMerkleTreeRoot()} log.Info("About to validate merkle and namespace proofs for msg count with batch relevant to l1 height", "msg count", b.building.msgCount, "l1 height", msg.Message.Header.BlockNumber) @@ -624,12 +623,12 @@ func (b *BatchPoster) addEspressoBlockMerkleProof( } valid_proof := espressocrypto.VerifyMerkleProof(proof.Proof, json_header, *jst.BlockMerkleJustification.BlockMerkleComm, snapshot.Root) - valid_namespace := espressocrypto.VerifyNamespace(arbOSConfig.ChainID.Uint64(), *jst.Proof, *jst.Header.PayloadCommitment, *jst.Header.NsTable, txs, *jst.VidCommon) + valid_namespace := espressocrypto.VerifyNamespace(arbOSConfig.ChainID.Uint64(), *jst.Proof, *jst.Header.Header.GetPayloadCommitment(), *jst.Header.Header.GetNsTable(), txs, *jst.VidCommon) if !(valid_proof && valid_namespace) { return fmt.Errorf("Cannot add Espresso block merkle proof as it is not valid") } - log.Info("Espresso proofs have been validated!", "msg count", b.building.msgCount, "l1 height", msg.Message.Header.BlockNumber) + log.Info("Espresso proofs have been validated!", "msg count", b.building.msgCount, "l1 height", msg.Message.Header.BlockNumber) if arbos.IsEspressoSovereignMsg(msg.Message) { // Passing an empty byte slice as payloadSignature because txs[0] already contains the payloadSignature here