From b27e0b8eaea09761d6460d46c2577d1ce1b60402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Fri, 14 Apr 2023 11:52:27 +0900 Subject: [PATCH 1/9] add L1 message validation --- consensus/errors.go | 6 +++++ core/block_validator.go | 59 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/consensus/errors.go b/consensus/errors.go index a3c8f737f08..89e567513ec 100644 --- a/consensus/errors.go +++ b/consensus/errors.go @@ -37,4 +37,10 @@ var ( // ErrInvalidTxCount is returned if a block contains too many transactions. ErrInvalidTxCount = errors.New("invalid transaction count") + + // TODO + ErrInvalidL1MessageOrder = errors.New("TODO") + + // TODO + ErrUnknownL1Message = errors.New("TODO") ) diff --git a/core/block_validator.go b/core/block_validator.go index 01786e02ce4..c8b0e7a65d0 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -20,6 +20,7 @@ import ( "fmt" "github.com/scroll-tech/go-ethereum/consensus" + "github.com/scroll-tech/go-ethereum/core/rawdb" "github.com/scroll-tech/go-ethereum/core/state" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/params" @@ -74,6 +75,64 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { } return consensus.ErrPrunedAncestor } + + return v.ValidateL1Messages(block) +} + +// ValidateL1Messages +// check conditions: +// - block contains correct L1 messages in correct order +// - L1 messages are in a contiguous block at the front +func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { + previousEnqueueIndex := rawdb.ReadLastL1MessageInL2Block(v.bc.db, block.ParentHash()) + if previousEnqueueIndex == nil { + // TODO: handle case where we don't have this after snapshot sync + return consensus.ErrUnknownAncestor + } + + enqueueIndex := *previousEnqueueIndex + numL1Txs := uint64(0) + L1SectionOver := false + it := rawdb.IterateL1MessagesFrom(v.bc.db, enqueueIndex) + + // count and check contiguous + for _, tx := range block.Transactions() { + if !tx.IsL1MessageTx() { + L1SectionOver = true + continue + } + + numL1Txs += 1 + enqueueIndex += 1 + + if L1SectionOver { + return consensus.ErrInvalidL1MessageOrder + } + + // wrong nonce + if tx.Nonce() != enqueueIndex { + return consensus.ErrInvalidL1MessageOrder + } + + if exists := it.Next(); !exists { + // TODO + } + + // sanity check + if it.EnqueueIndex() != enqueueIndex { + // TODO + } + + msg := it.L1Message() + + if tx.Hash() != types.NewTx(&msg).Hash() { + return consensus.ErrUnknownL1Message + } + } + + // write to db + rawdb.WriteLastL1MessageInL2Block(v.bc.db, block.Hash(), enqueueIndex) + return nil } From 379a8c43029e9210fb9c812518b06f7d411cb0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 15 Apr 2023 19:59:39 +0900 Subject: [PATCH 2/9] add comments and better error handling --- consensus/errors.go | 14 ++++++---- core/block_validator.go | 58 ++++++++++++++++++++++----------------- core/types/transaction.go | 9 ++++++ 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/consensus/errors.go b/consensus/errors.go index 89e567513ec..1c502db1e24 100644 --- a/consensus/errors.go +++ b/consensus/errors.go @@ -38,9 +38,13 @@ var ( // ErrInvalidTxCount is returned if a block contains too many transactions. ErrInvalidTxCount = errors.New("invalid transaction count") - // TODO - ErrInvalidL1MessageOrder = errors.New("TODO") - - // TODO - ErrUnknownL1Message = errors.New("TODO") + // ErrInvalidL1MessageOrder is returned if a block contains L1 messages in the wrong + // order. Possible scenarios are: (1) L1 messages do not follow their QueueIndex order, + // (2) the block skipped once or more L1 message, (3) L1 messages are not included in + // a contiguous block at the front of the block. + ErrInvalidL1MessageOrder = errors.New("invalid L1 message order") + + // ErrUnknownL1Message is returned if a block contains an L1 message that does not + // match the corresponding message in the node's local database. + ErrUnknownL1Message = errors.New("unknown L1 message") ) diff --git a/core/block_validator.go b/core/block_validator.go index c8b0e7a65d0..c5d0acea6fc 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -75,63 +75,71 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { } return consensus.ErrPrunedAncestor } - return v.ValidateL1Messages(block) } -// ValidateL1Messages -// check conditions: -// - block contains correct L1 messages in correct order -// - L1 messages are in a contiguous block at the front +// ValidateL1Messages validates L1 messages contained in a block. +// We check the following conditions: +// - L1 messages are in a contiguous block at the front of the block. +// - The first L1 message's QueueIndex is right after the last L1 message included in the chain. +// - L1 messages follow the QueueIndex order. No L1 message is skipped. +// - The L1 messages included in the block match the node's view of the L1 ledger. func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { - previousEnqueueIndex := rawdb.ReadLastL1MessageInL2Block(v.bc.db, block.ParentHash()) - if previousEnqueueIndex == nil { + var queueIndex uint64 + + if block.NumberU64() != 1 { + queueIndex = 0 + } else { + // all blocks should have previousQueueIndex in the database except for genesis // TODO: handle case where we don't have this after snapshot sync - return consensus.ErrUnknownAncestor + previousQueueIndex := rawdb.ReadLastL1MessageInL2Block(v.bc.db, block.ParentHash()) + if previousQueueIndex == nil { + // TODO: make sure we correctly re-process block after ErrUnknownAncestor + return consensus.ErrUnknownAncestor + } else { + queueIndex = *previousQueueIndex + } } - enqueueIndex := *previousEnqueueIndex - numL1Txs := uint64(0) L1SectionOver := false - it := rawdb.IterateL1MessagesFrom(v.bc.db, enqueueIndex) + it := rawdb.IterateL1MessagesFrom(v.bc.db, queueIndex) - // count and check contiguous for _, tx := range block.Transactions() { if !tx.IsL1MessageTx() { L1SectionOver = true continue } - numL1Txs += 1 - enqueueIndex += 1 - + // check that L1 messages are before L2 transactions if L1SectionOver { return consensus.ErrInvalidL1MessageOrder } - // wrong nonce - if tx.Nonce() != enqueueIndex { + queueIndex += 1 + + // check queue index + if tx.AsL1MessageTx().QueueIndex != queueIndex { return consensus.ErrInvalidL1MessageOrder } if exists := it.Next(); !exists { - // TODO - } - - // sanity check - if it.EnqueueIndex() != enqueueIndex { - // TODO + // TODO: make sure we correctly re-process block after ErrUnknownAncestor + return consensus.ErrUnknownAncestor } + // check that the L1 message in the block is the same that we collected from L1 msg := it.L1Message() + expectedHash := types.NewTx(&msg).Hash() - if tx.Hash() != types.NewTx(&msg).Hash() { + if tx.Hash() != expectedHash { return consensus.ErrUnknownL1Message } } // write to db - rawdb.WriteLastL1MessageInL2Block(v.bc.db, block.Hash(), enqueueIndex) + // TODO: ValidateL1Messages should not have side effects, consider + // moving this elsewhere. + rawdb.WriteLastL1MessageInL2Block(v.bc.db, block.Hash(), queueIndex) return nil } diff --git a/core/types/transaction.go b/core/types/transaction.go index 1993cb2a119..153efe6720d 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -296,6 +296,15 @@ func (tx *Transaction) IsL1MessageTx() bool { return tx.Type() == L1MessageTxType } +// AsL1MessageTx casts the tx into an L1 cross-domain tx. +func (tx *Transaction) AsL1MessageTx() *L1MessageTx { + if tx.Type() != L1MessageTxType { + return nil + } + + return tx.inner.(*L1MessageTx) +} + // Cost returns gas * gasPrice + value. func (tx *Transaction) Cost() *big.Int { total := new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())) From b6ccd27d89a950c913b5669866809e895f204827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Sat, 15 Apr 2023 20:10:41 +0900 Subject: [PATCH 3/9] handle leveldb not found error --- core/rawdb/accessors_l1_message.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/rawdb/accessors_l1_message.go b/core/rawdb/accessors_l1_message.go index 3ed6c7c9c1d..2bfbb2b820e 100644 --- a/core/rawdb/accessors_l1_message.go +++ b/core/rawdb/accessors_l1_message.go @@ -12,6 +12,8 @@ import ( "github.com/scroll-tech/go-ethereum/rlp" ) +const ErrNotFound = "leveldb: not found" + // WriteSyncedL1BlockNumber writes the highest synced L1 block number to the database. func WriteSyncedL1BlockNumber(db ethdb.KeyValueWriter, L1BlockNumber uint64) { value := big.NewInt(0).SetUint64(L1BlockNumber).Bytes() @@ -24,6 +26,9 @@ func WriteSyncedL1BlockNumber(db ethdb.KeyValueWriter, L1BlockNumber uint64) { // ReadSyncedL1BlockNumber retrieves the highest synced L1 block number. func ReadSyncedL1BlockNumber(db ethdb.Reader) *uint64 { data, err := db.Get(syncedL1BlockNumberKey) + if err != nil && err.Error() == ErrNotFound { + return nil + } if err != nil { log.Crit("Failed to read synced L1 block number from database", "err", err) } @@ -71,6 +76,9 @@ func WriteL1MessagesBatch(db ethdb.Batcher, l1Msgs []types.L1MessageTx) { // ReadL1MessageRLP retrieves an L1 message in its raw RLP database encoding. func ReadL1MessageRLP(db ethdb.Reader, enqueueIndex uint64) rlp.RawValue { data, err := db.Get(L1MessageKey(enqueueIndex)) + if err != nil && err.Error() == ErrNotFound { + return nil + } if err != nil { log.Crit("Failed to load L1 message", "enqueueIndex", enqueueIndex, "err", err) } @@ -190,6 +198,9 @@ func WriteLastL1MessageInL2Block(db ethdb.KeyValueWriter, l2BlockHash common.Has // The caller must add special handling for the L2 genesis block. func ReadLastL1MessageInL2Block(db ethdb.Reader, l2BlockHash common.Hash) *uint64 { data, err := db.Get(LastL1MessageInL2BlockKey(l2BlockHash)) + if err != nil && err.Error() == ErrNotFound { + return nil + } if err != nil { log.Crit("Failed to read last L1 message in L2 block from database", "l2BlockHash", l2BlockHash, "err", err) } From c2b985d3fc64397a4e039229c67d8ce463138610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Apr 2023 17:14:40 +0200 Subject: [PATCH 4/9] update incorrect condition for genesis block --- core/block_validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/block_validator.go b/core/block_validator.go index c5d0acea6fc..28f7d62b913 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -87,7 +87,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { var queueIndex uint64 - if block.NumberU64() != 1 { + if block.NumberU64() <= 1 { queueIndex = 0 } else { // all blocks should have previousQueueIndex in the database except for genesis From 1a4db58be643707774f6deb9f206c45504235f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Apr 2023 17:23:15 +0200 Subject: [PATCH 5/9] typo --- consensus/errors.go | 2 +- core/block_validator.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/consensus/errors.go b/consensus/errors.go index 1c502db1e24..82c3b26b526 100644 --- a/consensus/errors.go +++ b/consensus/errors.go @@ -40,7 +40,7 @@ var ( // ErrInvalidL1MessageOrder is returned if a block contains L1 messages in the wrong // order. Possible scenarios are: (1) L1 messages do not follow their QueueIndex order, - // (2) the block skipped once or more L1 message, (3) L1 messages are not included in + // (2) the block skipped one or more L1 messages, (3) L1 messages are not included in // a contiguous block at the front of the block. ErrInvalidL1MessageOrder = errors.New("invalid L1 message order") diff --git a/core/block_validator.go b/core/block_validator.go index 28f7d62b913..351a1bb5042 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -80,7 +80,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // ValidateL1Messages validates L1 messages contained in a block. // We check the following conditions: -// - L1 messages are in a contiguous block at the front of the block. +// - L1 messages are in a contiguous section at the front of the block. // - The first L1 message's QueueIndex is right after the last L1 message included in the chain. // - L1 messages follow the QueueIndex order. No L1 message is skipped. // - The L1 messages included in the block match the node's view of the L1 ledger. From 40cddfb308b684217cd25ae267ccc6443f4c7947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Apr 2023 17:36:54 +0200 Subject: [PATCH 6/9] change inclusion index logic --- core/block_validator.go | 25 ++++++++----------------- core/rawdb/accessors_l1_message.go | 20 ++++++++++---------- core/rawdb/accessors_l1_message_test.go | 4 ++-- core/rawdb/database.go | 2 +- core/rawdb/schema.go | 12 ++++++------ eth/backend.go | 1 + 6 files changed, 28 insertions(+), 36 deletions(-) diff --git a/core/block_validator.go b/core/block_validator.go index 351a1bb5042..61b520bb58c 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -85,21 +85,12 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // - L1 messages follow the QueueIndex order. No L1 message is skipped. // - The L1 messages included in the block match the node's view of the L1 ledger. func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { - var queueIndex uint64 - - if block.NumberU64() <= 1 { - queueIndex = 0 - } else { - // all blocks should have previousQueueIndex in the database except for genesis - // TODO: handle case where we don't have this after snapshot sync - previousQueueIndex := rawdb.ReadLastL1MessageInL2Block(v.bc.db, block.ParentHash()) - if previousQueueIndex == nil { - // TODO: make sure we correctly re-process block after ErrUnknownAncestor - return consensus.ErrUnknownAncestor - } else { - queueIndex = *previousQueueIndex - } + nextQueueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(v.bc.db, block.ParentHash()) + if nextQueueIndex == nil { + // TODO: make sure we correctly re-process block after ErrUnknownAncestor + return consensus.ErrUnknownAncestor } + queueIndex := *nextQueueIndex L1SectionOver := false it := rawdb.IterateL1MessagesFrom(v.bc.db, queueIndex) @@ -115,13 +106,13 @@ func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { return consensus.ErrInvalidL1MessageOrder } - queueIndex += 1 - // check queue index if tx.AsL1MessageTx().QueueIndex != queueIndex { return consensus.ErrInvalidL1MessageOrder } + queueIndex += 1 + if exists := it.Next(); !exists { // TODO: make sure we correctly re-process block after ErrUnknownAncestor return consensus.ErrUnknownAncestor @@ -139,7 +130,7 @@ func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { // write to db // TODO: ValidateL1Messages should not have side effects, consider // moving this elsewhere. - rawdb.WriteLastL1MessageInL2Block(v.bc.db, block.Hash(), queueIndex) + rawdb.WriteFirstQueueIndexNotInL2Block(v.bc.db, block.Hash(), queueIndex) return nil } diff --git a/core/rawdb/accessors_l1_message.go b/core/rawdb/accessors_l1_message.go index 014079cc037..6844eeeb542 100644 --- a/core/rawdb/accessors_l1_message.go +++ b/core/rawdb/accessors_l1_message.go @@ -190,20 +190,20 @@ func ReadL1MessagesInRange(db ethdb.Iteratee, firstEnqueueIndex, lastEnqueueInde return msgs } -// WriteLastL1MessageInL2Block writes the enqueue index of the last message included in the -// ledger up to and including the provided L2 block. The L2 block is identified by its block -// hash. If the L2 block contains zero L1 messages, this value MUST equal its parent's value. -func WriteLastL1MessageInL2Block(db ethdb.KeyValueWriter, l2BlockHash common.Hash, enqueueIndex uint64) { - if err := db.Put(LastL1MessageInL2BlockKey(l2BlockHash), encodeEnqueueIndex(enqueueIndex)); err != nil { +// WriteFirstQueueIndexNotInL2Block writes the queue index of the first message +// that is NOT included in the ledger up to and including the provided L2 block. +// The L2 block is identified by its block hash. If the L2 block contains zero +// L1 messages, this value MUST equal its parent's value. +func WriteFirstQueueIndexNotInL2Block(db ethdb.KeyValueWriter, l2BlockHash common.Hash, enqueueIndex uint64) { + if err := db.Put(FirstQueueIndexNotInL2BlockKey(l2BlockHash), encodeEnqueueIndex(enqueueIndex)); err != nil { log.Crit("Failed to store last L1 message in L2 block", "l2BlockHash", l2BlockHash, "err", err) } } -// ReadLastL1MessageInL2Block retrieves the enqueue index of the last message -// included in the ledger up to and including the provided L2 block. -// The caller must add special handling for the L2 genesis block. -func ReadLastL1MessageInL2Block(db ethdb.Reader, l2BlockHash common.Hash) *uint64 { - data, err := db.Get(LastL1MessageInL2BlockKey(l2BlockHash)) +// ReadFirstQueueIndexNotInL2Block retrieves the queue index of the first message +// that is NOT included in the ledger up to and including the provided L2 block. +func ReadFirstQueueIndexNotInL2Block(db ethdb.Reader, l2BlockHash common.Hash) *uint64 { + data, err := db.Get(FirstQueueIndexNotInL2BlockKey(l2BlockHash)) if err != nil && isNotFoundErr(err) { return nil } diff --git a/core/rawdb/accessors_l1_message_test.go b/core/rawdb/accessors_l1_message_test.go index eb97a69f42b..d80725ea349 100644 --- a/core/rawdb/accessors_l1_message_test.go +++ b/core/rawdb/accessors_l1_message_test.go @@ -118,8 +118,8 @@ func TestReadWriteLastL1MessageInL2Block(t *testing.T) { db := NewMemoryDatabase() for _, num := range inputs { l2BlockHash := common.Hash{byte(num)} - WriteLastL1MessageInL2Block(db, l2BlockHash, num) - got := ReadLastL1MessageInL2Block(db, l2BlockHash) + WriteFirstQueueIndexNotInL2Block(db, l2BlockHash, num) + got := ReadFirstQueueIndexNotInL2Block(db, l2BlockHash) if got == nil || *got != num { t.Fatal("Enqueue index mismatch", "expected", num, "got", got) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 63fcfb66ce6..6d48143ea78 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -386,7 +386,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { cliqueSnaps.Add(size) case bytes.HasPrefix(key, L1MessagePrefix) && len(key) == len(L1MessagePrefix)+8: l1Messages.Add(size) - case bytes.HasPrefix(key, LastL1MessageInL2BlockPrefix) && len(key) == len(LastL1MessageInL2BlockPrefix)+common.HashLength: + case bytes.HasPrefix(key, FirstQueueIndexNotInL2BlockPrefix) && len(key) == len(FirstQueueIndexNotInL2BlockPrefix)+common.HashLength: lastL1Message.Add(size) case bytes.HasPrefix(key, []byte("cht-")) || bytes.HasPrefix(key, []byte("chtIndexV2-")) || diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index 30dbb9a8b44..52e62038e06 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -100,9 +100,9 @@ var ( preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) // Scroll L1 message store - syncedL1BlockNumberKey = []byte("LastSyncedL1BlockNumber") - L1MessagePrefix = []byte("l1") // L1MessagePrefix + enqueueIndex (uint64 big endian) -> L1MessageTx - LastL1MessageInL2BlockPrefix = []byte("l1b") // LastL1MessageInL2BlockPrefix + L2 block hash -> enqueue index + syncedL1BlockNumberKey = []byte("LastSyncedL1BlockNumber") + L1MessagePrefix = []byte("l1") // L1MessagePrefix + enqueueIndex (uint64 big endian) -> L1MessageTx + FirstQueueIndexNotInL2BlockPrefix = []byte("q") // FirstQueueIndexNotInL2BlockPrefix + L2 block hash -> enqueue index ) const ( @@ -248,7 +248,7 @@ func L1MessageKey(enqueueIndex uint64) []byte { return append(L1MessagePrefix, encodeEnqueueIndex(enqueueIndex)...) } -// LastL1MessageInL2BlockKey = LastL1MessageInL2BlockPrefix + L2 block hash -func LastL1MessageInL2BlockKey(l2BlockHash common.Hash) []byte { - return append(LastL1MessageInL2BlockPrefix, l2BlockHash.Bytes()...) +// FirstQueueIndexNotInL2BlockKey = FirstQueueIndexNotInL2BlockPrefix + L2 block hash +func FirstQueueIndexNotInL2BlockKey(l2BlockHash common.Hash) []byte { + return append(FirstQueueIndexNotInL2BlockPrefix, l2BlockHash.Bytes()...) } diff --git a/eth/backend.go b/eth/backend.go index 4b6612b9437..443a46b7056 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -138,6 +138,7 @@ func New(stack *node.Node, config *ethconfig.Config, l1Client sync_service.EthCl if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } + rawdb.WriteFirstQueueIndexNotInL2Block(chainDb, genesisHash, 0) log.Info("Initialised chain configuration", "config", chainConfig) if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil { From 1280b8f74ecf738830339a9adaad651f0a52d308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Apr 2023 17:38:48 +0200 Subject: [PATCH 7/9] disable L1 message check for legacy tests --- core/block_validator.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/block_validator.go b/core/block_validator.go index 61b520bb58c..9698e85c69c 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -85,6 +85,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // - L1 messages follow the QueueIndex order. No L1 message is skipped. // - The L1 messages included in the block match the node's view of the L1 ledger. func (v *BlockValidator) ValidateL1Messages(block *types.Block) error { + if v.config.L1Config == nil || v.config.L1Config.NumL1MessagesPerBlock == 0 { + return nil + } + nextQueueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(v.bc.db, block.ParentHash()) if nextQueueIndex == nil { // TODO: make sure we correctly re-process block after ErrUnknownAncestor From 88a4dc531e4b017db30ee85dc789c4cc9b4c72ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Wed, 26 Apr 2023 18:06:32 +0200 Subject: [PATCH 8/9] set NumL1MessagesPerBlock to 0 in tests --- params/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/config.go b/params/config.go index 15030408c3a..e19d647a18a 100644 --- a/params/config.go +++ b/params/config.go @@ -258,19 +258,19 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, nil, true, true, nil, true, &L1Config{5, nil, 20}} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, nil, true, true, nil, true, &L1Config{5, nil, 0}} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, false, nil, true, true, nil, true, &L1Config{5, nil, 20}} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, false, nil, true, true, nil, true, &L1Config{5, nil, 0}} - TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, &common.Address{123}, true, true, nil, true, &L1Config{5, nil, 20}} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, &common.Address{123}, true, true, nil, true, &L1Config{5, nil, 0}} TestRules = TestChainConfig.Rules(new(big.Int)) - TestNoL1feeChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, &common.Address{123}, true, true, nil, false, &L1Config{5, nil, 20}} + TestNoL1feeChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, false, &common.Address{123}, true, true, nil, false, &L1Config{5, nil, 0}} ) // TrustedCheckpoint represents a set of post-processed trie roots (CHT and From 03ba24faf265627693551cdc227c4c317dc5a06f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Garamv=C3=B6lgyi?= Date: Thu, 27 Apr 2023 10:29:56 +0200 Subject: [PATCH 9/9] update default genesis config --- params/config.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/params/config.go b/params/config.go index a77f6d59471..a4c42cc406b 100644 --- a/params/config.go +++ b/params/config.go @@ -255,8 +255,9 @@ var ( } // ScrollAlphaChainConfig contains the chain parameters to run a node on the Scroll Alpha test network. - ScrollFeeVaultAddress = common.HexToAddress("0x5300000000000000000000000000000000000005") - ScrollMaxTxPerBlock = 44 + ScrollFeeVaultAddress = common.HexToAddress("0x5300000000000000000000000000000000000005") + ScrollL1MessageQueueAddress = common.HexToAddress("0x79DB48002Aa861C8cb189cabc21c6B1468BC83BB") + ScrollMaxTxPerBlock = 44 ScrollAlphaChainConfig = &ChainConfig{ ChainID: big.NewInt(534353), @@ -284,6 +285,11 @@ var ( FeeVaultAddress: &ScrollFeeVaultAddress, EnableEIP2718: false, EnableEIP1559: false, + L1Config: &L1Config{ + L1ChainId: 5, + L1MessageQueueAddress: &ScrollL1MessageQueueAddress, + NumL1MessagesPerBlock: 0, + }, }, }