Skip to content

Commit 983d630

Browse files
ThegaramNazariiDenhamaxwolfficemelon0xmountaintop
authored
feat: Sync and relay L1 messages (#350)
* add l1 config in genesis config (#249) * add l1 config in genesis config * fix lint * Update params/config.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * extend node configuration (#251) * extend node configuration * use block number instead of hash * accept safe, finalized and numbers for L1Confirmations * fix typos --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * Fix/improve node config parsing (#260) * raise error on failed parsing * default value * add l1-message-type, transaction methods (#252) * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * txpool l1 check, pointer change, marhsal test * draft: start implementing l1message gas behavior * draft: start implementing l1message gas behavior * change to gas usage * error comment typo Co-authored-by: Haichen Shen <shenhaichen@gmail.com> * goimports * update nonce, add hash test (fails), marshal test * goimports * target addr cant be nil * change call msg * comment out test * lint --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> Co-authored-by: Haichen Shen <shenhaichen@gmail.com> * Add L1 message database (#255) * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * add L1 message store to rawdb * remove comments * rename to l1_message * rename variables and add comments * write l1 msgs in a batch * add more comments * update tests * allow batched and non-batched writes * rename to accessors_l1_message * handle error * add range check * fix tests * update comments * nit * support blocks with 0 l1 messages --------- Co-authored-by: Max Wolff <maxcwolff@gmail.com> Co-authored-by: Max Wolff <max@scroll.io> * Fix L1Message Deep Copy, Complete Bridge Tx Hash test (#269) * deep copy value field, add tx hash test comment * typo * Rename nonce to queueindex, increment sender nonce on L1 message execution (#271) * change nonce to queueindex, increment nonce on L1 message * fix db acccessors * Update core/types/transaction_marshalling.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * Fix db inspect command (#276) fix db inspect command * Add l1 sync service (#256) * extend node configuration * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * use block number instead of hash * accept safe, finalized and numbers for L1Confirmations * add L1 message store to rawdb * remove comments * fix typos * add L1 message sync service * use l1 contract address and chain ID * use L1DeploymentBlock * add confirmation config * move bridge client to separate file * use uint64 block number * fix bigint comparison * rename constants * add more logs * rename to l1_message * rename variables and add comments * write l1 msgs in a batch * add more comments * update tests * allow batched and non-batched writes * rename to accessors_l1_message * handle error * check if config is provided * improve sync service DB batched writes * add range check * fix tests * update comments * nit * fix flush range and improve comments * solve circular dependency * update stress tests * initialize l1 client for geth * start sync service * add more comments * check nil correctly * address comments * fix merge * fix genesis l1config deserialization * add sync progress logs * initial sync * handle leveldb not found error * use errors.Is * address comments * update DefaultPollInterval --------- Co-authored-by: Nazarii Denha <dengaaa2002@gmail.com> Co-authored-by: Max Wolff <maxcwolff@gmail.com> Co-authored-by: Max Wolff <max@scroll.io> * Add L1 message validation (#272) * add L1 message validation * add comments and better error handling * handle leveldb not found error * update incorrect condition for genesis block * typo * change inclusion index logic * disable L1 message check for legacy tests * set NumL1MessagesPerBlock to 0 in tests * update default genesis config * Add L1 msg validation tests (#303) add L1 msg validation tests * Update miner include l1 messages (#265) * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * add L1 message store to rawdb * add L1 message sync service * remove comments * use l1 contract address and chain ID * extend node configuration * use block number instead of hash * accept safe, finalized and numbers for L1Confirmations * fix typos * use L1DeploymentBlock * add confirmation config * move bridge client to separate file * use uint64 block number * fix bigint comparison * rename constants * add more logs * Fix/improve node config parsing (#260) * raise error on failed parsing * default value * rename to l1_message * rename variables and add comments * write l1 msgs in a batch * add more comments * update tests * allow batched and non-batched writes * rename to accessors_l1_message * handle error * check if config is provided * improve sync service DB batched writes * include l1 messages in blocks: part 1 * add l1-message-type, transaction methods (#252) * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * txpool l1 check, pointer change, marhsal test * draft: start implementing l1message gas behavior * draft: start implementing l1message gas behavior * change to gas usage * error comment typo Co-authored-by: Haichen Shen <shenhaichen@gmail.com> * goimports * update nonce, add hash test (fails), marshal test * goimports * target addr cant be nil * change call msg * comment out test * lint --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> Co-authored-by: Haichen Shen <shenhaichen@gmail.com> * Add L1 message database (#255) * add l1-message-type, transaction methods * goimports * Update core/types/transaction.go Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * add L1 message store to rawdb * remove comments * rename to l1_message * rename variables and add comments * write l1 msgs in a batch * add more comments * update tests * allow batched and non-batched writes * rename to accessors_l1_message * handle error * add range check * fix tests * update comments * nit * support blocks with 0 l1 messages --------- Co-authored-by: Max Wolff <maxcwolff@gmail.com> Co-authored-by: Max Wolff <max@scroll.io> * build(docker): auto docker push when pushing git tags (#258) * build(docker): update docker trigger tag prefix (#259) * Fix L1Message Deep Copy, Complete Bridge Tx Hash test (#269) * deep copy value field, add tx hash test comment * typo * commitl1messages * lint * Revert "add L1 message sync service" This reverts commit 5305e8a. * Revert "move bridge client to separate file" This reverts commit 0b220be. * update branch * use commitMessages for l1Txs * little fix * fix config * fix test * comment fixes * fix * fix config check --------- Co-authored-by: Max Wolff <maxcwolff@gmail.com> Co-authored-by: Max Wolff <max@scroll.io> Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> Co-authored-by: Péter Garamvölgyi <peter@scroll.io> Co-authored-by: Haichen Shen <shenhaichen@gmail.com> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> * Add ErrUnknownAncestor tests (#305) add ErrUnknownAncestor tests * worker test include l1 msgs (#306) * worker test include l1 msgs * move L1 message index update next to block insertion --------- Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * exclude l1 messages from transaction count limit in block (#307) * exclude l1 messages from transaction count limit in block * fix comments * trigger ci * nit --------- Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * Expose queueIndex on Transaction (#316) expose queueIndex on Transaction * test that l1msg doesn't count in maxTxPerBlock limit (#312) * test that l1msg doesn't count in maxTxPerBlock limit * fix, comment * retrigger ci * change order inside test --------- Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Co-authored-by: Péter Garamvölgyi <th307q@gmail.com> * reuse trace nonce field for queueIndex * expose scroll APIs on the geth console * add L1 message query APIs * Trigger new block on new l1 messages (#343) * trigger new block on new l1 messages * typo * initialize l1MsgCh * fix worker l1msg tests (#345) --------- Co-authored-by: Nazarii Denha <dengaaa2002@gmail.com> * test(worker): ensure that l1 messages are included in the correct order (#346) test that l1msgs added in correct order * rename enqueueIndex --> queueIndex * move QueueIndex into transaction * improve l1 db interface * formatting * bump version * print l1config * add API to query latest included message queue index * clean up tx limit logic * add clarifying comments and todos to ValidateL1Messages * improve db comments and logs * clean up L1MessageTx type handling * format * format * improve L1 message block check * fix missing L1 event handling * fix TestL1MessageValidationFailure * simplify sync height resume logic * make l1Config.l1MessageQueueAddress non-pointer * improve command line flags * remove todo * use abigen tools for log filtering * cache block L1 message count * nit: fix variable name case * improve logs * flush pending writes to DB before shutdown --------- Co-authored-by: Nazarii Denha <dengaaa2002@gmail.com> Co-authored-by: Max Wolff <max@scroll.io> Co-authored-by: Haichen Shen <shenhaichen@gmail.com> Co-authored-by: Max Wolff <maxcwolff@gmail.com> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Co-authored-by: HAOYUatHZ <haoyu@protonmail.com>
1 parent 4867699 commit 983d630

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1988
-99
lines changed

accounts/abi/bind/backends/simulated.go

+1
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ func (m callMsg) Gas() uint64 { return m.CallMsg.Gas }
814814
func (m callMsg) Value() *big.Int { return m.CallMsg.Value }
815815
func (m callMsg) Data() []byte { return m.CallMsg.Data }
816816
func (m callMsg) AccessList() types.AccessList { return m.CallMsg.AccessList }
817+
func (m callMsg) IsL1MessageTx() bool { return false }
817818

818819
// filterBackend implements filters.Backend to support filtering for logs without
819820
// taking bloom-bits acceleration structures into account.

cmd/devp2p/internal/ethtest/suite_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func setupGeth(stack *node.Node) error {
9797
TrieDirtyCache: 16,
9898
TrieTimeout: 60 * time.Minute,
9999
SnapshotCache: 10,
100-
})
100+
}, nil)
101101
if err != nil {
102102
return err
103103
}

cmd/geth/main.go

+3
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ var (
158158
utils.MinerNotifyFullFlag,
159159
configFileFlag,
160160
utils.CatalystFlag,
161+
utils.L1EndpointFlag,
162+
utils.L1ConfirmationsFlag,
163+
utils.L1DeploymentBlockFlag,
161164
}
162165

163166
rpcFlags = []cli.Flag{

cmd/utils/flags.go

+72-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package utils
1919

2020
import (
2121
"crypto/ecdsa"
22+
"errors"
2223
"fmt"
2324
"io"
2425
"io/ioutil"
@@ -41,6 +42,7 @@ import (
4142
"github.com/scroll-tech/go-ethereum/accounts/keystore"
4243
"github.com/scroll-tech/go-ethereum/common"
4344
"github.com/scroll-tech/go-ethereum/common/fdlimit"
45+
"github.com/scroll-tech/go-ethereum/common/hexutil"
4446
"github.com/scroll-tech/go-ethereum/consensus"
4547
"github.com/scroll-tech/go-ethereum/consensus/clique"
4648
"github.com/scroll-tech/go-ethereum/consensus/ethash"
@@ -53,6 +55,7 @@ import (
5355
"github.com/scroll-tech/go-ethereum/eth/ethconfig"
5456
"github.com/scroll-tech/go-ethereum/eth/gasprice"
5557
"github.com/scroll-tech/go-ethereum/eth/tracers"
58+
"github.com/scroll-tech/go-ethereum/ethclient"
5659
"github.com/scroll-tech/go-ethereum/ethdb"
5760
"github.com/scroll-tech/go-ethereum/ethstats"
5861
"github.com/scroll-tech/go-ethereum/graphql"
@@ -70,6 +73,7 @@ import (
7073
"github.com/scroll-tech/go-ethereum/p2p/nat"
7174
"github.com/scroll-tech/go-ethereum/p2p/netutil"
7275
"github.com/scroll-tech/go-ethereum/params"
76+
"github.com/scroll-tech/go-ethereum/rpc"
7377
)
7478

7579
func init() {
@@ -794,6 +798,20 @@ var (
794798
Name: "catalyst",
795799
Usage: "Catalyst mode (eth2 integration testing)",
796800
}
801+
802+
// L1Settings
803+
L1EndpointFlag = cli.StringFlag{
804+
Name: "l1.endpoint",
805+
Usage: "Endpoint of L1 HTTP-RPC server",
806+
}
807+
L1ConfirmationsFlag = cli.StringFlag{
808+
Name: "l1.confirmations",
809+
Usage: "Number of confirmations on L1 needed for finalization, or \"safe\" or \"finalized\"",
810+
}
811+
L1DeploymentBlockFlag = cli.Int64Flag{
812+
Name: "l1.sync.startblock",
813+
Usage: "L1 block height to start syncing from. Should be set to the L1 message queue deployment block number.",
814+
}
797815
)
798816

799817
// MakeDataDir retrieves the currently requested data directory, terminating
@@ -1226,6 +1244,7 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
12261244
setNodeUserIdent(ctx, cfg)
12271245
setDataDir(ctx, cfg)
12281246
setSmartCard(ctx, cfg)
1247+
setL1(ctx, cfg)
12291248

12301249
if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
12311250
cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
@@ -1251,6 +1270,42 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
12511270
}
12521271
}
12531272

1273+
func unmarshalBlockNumber(input string) (rpc.BlockNumber, error) {
1274+
switch input {
1275+
case "finalized":
1276+
return rpc.FinalizedBlockNumber, nil
1277+
case "safe":
1278+
return rpc.SafeBlockNumber, nil
1279+
}
1280+
blockNum, err := hexutil.DecodeUint64(input)
1281+
if err == nil && blockNum <= math.MaxInt64 {
1282+
return rpc.BlockNumber(blockNum), nil
1283+
}
1284+
blockNum, err = strconv.ParseUint(input, 10, 64)
1285+
if err == nil && blockNum <= math.MaxInt64 {
1286+
return rpc.BlockNumber(blockNum), nil
1287+
}
1288+
return 0, errors.New("incorrect value")
1289+
}
1290+
1291+
func setL1(ctx *cli.Context, cfg *node.Config) {
1292+
var err error
1293+
if ctx.GlobalIsSet(L1EndpointFlag.Name) {
1294+
cfg.L1Endpoint = ctx.GlobalString(L1EndpointFlag.Name)
1295+
}
1296+
if ctx.GlobalIsSet(L1ConfirmationsFlag.Name) {
1297+
cfg.L1Confirmations, err = unmarshalBlockNumber(ctx.GlobalString(L1ConfirmationsFlag.Name))
1298+
if err != nil {
1299+
panic(fmt.Sprintf("invalid value for flag %s: %s", L1ConfirmationsFlag.Name, ctx.GlobalString(L1ConfirmationsFlag.Name)))
1300+
}
1301+
} else {
1302+
cfg.L1Confirmations = rpc.FinalizedBlockNumber
1303+
}
1304+
if ctx.GlobalIsSet(L1DeploymentBlockFlag.Name) {
1305+
cfg.L1DeploymentBlock = ctx.GlobalUint64(L1DeploymentBlockFlag.Name)
1306+
}
1307+
}
1308+
12541309
func setSmartCard(ctx *cli.Context, cfg *node.Config) {
12551310
// Skip enabling smartcards if no path is set
12561311
path := ctx.GlobalString(SmartCardDaemonPathFlag.Name)
@@ -1732,7 +1787,23 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
17321787
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
17331788
return backend.ApiBackend, nil
17341789
}
1735-
backend, err := eth.New(stack, cfg)
1790+
1791+
// initialize L1 client for sync service
1792+
// note: we need to do this here to avoid circular dependency
1793+
l1EndpointUrl := stack.Config().L1Endpoint
1794+
var l1Client *ethclient.Client
1795+
1796+
if l1EndpointUrl != "" {
1797+
var err error
1798+
l1Client, err = ethclient.Dial(l1EndpointUrl)
1799+
if err != nil {
1800+
Fatalf("Unable to connect to L1 endpoint at %v: %v", l1EndpointUrl, err)
1801+
}
1802+
1803+
log.Info("Initialized L1 client", "endpoint", l1EndpointUrl)
1804+
}
1805+
1806+
backend, err := eth.New(stack, cfg, l1Client)
17361807
if err != nil {
17371808
Fatalf("Failed to register the Ethereum service: %v", err)
17381809
}

consensus/errors.go

+15
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,19 @@ var (
3737

3838
// ErrInvalidTxCount is returned if a block contains too many transactions.
3939
ErrInvalidTxCount = errors.New("invalid transaction count")
40+
41+
// ErrMissingL1MessageData is returned if a block contains L1 messages that the
42+
// node has not synced yet. In this case we insert the block into the future
43+
// queue and process it again later.
44+
ErrMissingL1MessageData = errors.New("unknown L1 message data")
45+
46+
// ErrInvalidL1MessageOrder is returned if a block contains L1 messages in the wrong
47+
// order. Possible scenarios are: (1) L1 messages do not follow their QueueIndex order,
48+
// (2) the block skipped one or more L1 messages, (3) L1 messages are not included in
49+
// a contiguous block at the front of the block.
50+
ErrInvalidL1MessageOrder = errors.New("invalid L1 message order")
51+
52+
// ErrUnknownL1Message is returned if a block contains an L1 message that does not
53+
// match the corresponding message in the node's local database.
54+
ErrUnknownL1Message = errors.New("unknown L1 message")
4055
)

console/console_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester {
110110
if confOverride != nil {
111111
confOverride(ethConf)
112112
}
113-
ethBackend, err := eth.New(stack, ethConf)
113+
ethBackend, err := eth.New(stack, ethConf, nil)
114114
if err != nil {
115115
t.Fatalf("failed to register Ethereum protocol: %v", err)
116116
}

core/block_validator.go

+69-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121

2222
"github.com/scroll-tech/go-ethereum/consensus"
23+
"github.com/scroll-tech/go-ethereum/core/rawdb"
2324
"github.com/scroll-tech/go-ethereum/core/state"
2425
"github.com/scroll-tech/go-ethereum/core/types"
2526
"github.com/scroll-tech/go-ethereum/params"
@@ -54,7 +55,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
5455
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
5556
return ErrKnownBlock
5657
}
57-
if !v.config.Scroll.IsValidTxCount(len(block.Transactions())) {
58+
if !v.config.Scroll.IsValidL2TxCount(block.CountL2Tx()) {
5859
return consensus.ErrInvalidTxCount
5960
}
6061
// Check if block payload size is smaller than the max size
@@ -78,6 +79,73 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
7879
}
7980
return consensus.ErrPrunedAncestor
8081
}
82+
return v.ValidateL1Messages(block)
83+
}
84+
85+
// ValidateL1Messages validates L1 messages contained in a block.
86+
// We check the following conditions:
87+
// - L1 messages are in a contiguous section at the front of the block.
88+
// - The first L1 message's QueueIndex is right after the last L1 message included in the chain.
89+
// - L1 messages follow the QueueIndex order. No L1 message is skipped.
90+
// - The L1 messages included in the block match the node's view of the L1 ledger.
91+
func (v *BlockValidator) ValidateL1Messages(block *types.Block) error {
92+
// no further processing if the block contains no L1 messages
93+
if block.L1MessageCount() == 0 {
94+
return nil
95+
}
96+
97+
if v.config.Scroll.L1Config == nil {
98+
// TODO: should we allow follower nodes to skip L1 message verification?
99+
panic("Running on L1Message-enabled network but no l1Config was provided")
100+
}
101+
102+
nextQueueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(v.bc.db, block.ParentHash())
103+
if nextQueueIndex == nil {
104+
// we'll reprocess this block at a later time
105+
return consensus.ErrMissingL1MessageData
106+
}
107+
queueIndex := *nextQueueIndex
108+
109+
L1SectionOver := false
110+
it := rawdb.IterateL1MessagesFrom(v.bc.db, queueIndex)
111+
112+
for _, tx := range block.Transactions() {
113+
if !tx.IsL1MessageTx() {
114+
L1SectionOver = true
115+
continue // we do not verify L2 transactions here
116+
}
117+
118+
// check that L1 messages are before L2 transactions
119+
if L1SectionOver {
120+
return consensus.ErrInvalidL1MessageOrder
121+
}
122+
123+
// check queue index
124+
// TODO: account for skipped messages here
125+
if tx.AsL1MessageTx().QueueIndex != queueIndex {
126+
return consensus.ErrInvalidL1MessageOrder
127+
}
128+
129+
queueIndex += 1
130+
131+
if exists := it.Next(); !exists {
132+
// we'll reprocess this block at a later time
133+
return consensus.ErrMissingL1MessageData
134+
}
135+
136+
// check that the L1 message in the block is the same that we collected from L1
137+
msg := it.L1Message()
138+
expectedHash := types.NewTx(&msg).Hash()
139+
140+
if tx.Hash() != expectedHash {
141+
return consensus.ErrUnknownL1Message
142+
}
143+
}
144+
145+
// TODO: consider adding a rule to enforce L1Config.NumL1MessagesPerBlock.
146+
// If there are L1 messages available, sequencer nodes should include them.
147+
// However, this is hard to enforce as different nodes might have different views of L1.
148+
81149
return nil
82150
}
83151

core/blockchain.go

+24-2
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
277277
return nil, ErrNoGenesis
278278
}
279279

280+
// initialize L1 message index for genesis block
281+
rawdb.WriteFirstQueueIndexNotInL2Block(db, bc.genesisBlock.Hash(), 0)
282+
280283
var nilBlock *types.Block
281284
bc.currentBlock.Store(nilBlock)
282285
bc.currentFastBlock.Store(nilBlock)
@@ -695,6 +698,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
695698
batch := bc.db.NewBatch()
696699
rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
697700
rawdb.WriteBlock(batch, genesis)
701+
rawdb.WriteFirstQueueIndexNotInL2Block(batch, genesis.Hash(), 0)
698702
if err := batch.Write(); err != nil {
699703
log.Crit("Failed to write genesis block", "err", err)
700704
}
@@ -1176,6 +1180,14 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
11761180
batch := bc.db.NewBatch()
11771181
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
11781182
rawdb.WriteBlock(batch, block)
1183+
1184+
queueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(bc.db, block.ParentHash())
1185+
if queueIndex != nil {
1186+
// note: we can insert blocks with header-only ancestors here,
1187+
// so queueIndex might not yet be available in DB.
1188+
rawdb.WriteFirstQueueIndexNotInL2Block(batch, block.Hash(), *queueIndex+uint64(block.L1MessageCount()))
1189+
}
1190+
11791191
if err := batch.Write(); err != nil {
11801192
log.Crit("Failed to write block into disk", "err", err)
11811193
}
@@ -1230,6 +1242,15 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
12301242
rawdb.WriteBlock(blockBatch, block)
12311243
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
12321244
rawdb.WritePreimages(blockBatch, state.Preimages())
1245+
1246+
queueIndex := rawdb.ReadFirstQueueIndexNotInL2Block(bc.db, block.ParentHash())
1247+
if queueIndex == nil {
1248+
// We expect that we only insert contiguous chain segments,
1249+
// so the parent will always be inserted first.
1250+
log.Crit("Queue index in DB is nil", "parent", block.ParentHash(), "hash", block.Hash())
1251+
}
1252+
rawdb.WriteFirstQueueIndexNotInL2Block(blockBatch, block.Hash(), *queueIndex+uint64(block.L1MessageCount()))
1253+
12331254
if err := blockBatch.Write(); err != nil {
12341255
log.Crit("Failed to write block into disk", "err", err)
12351256
}
@@ -1500,7 +1521,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
15001521
return bc.insertSideChain(block, it)
15011522

15021523
// First block is future, shove it (and all children) to the future queue (unknown ancestor)
1503-
case errors.Is(err, consensus.ErrFutureBlock) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())):
1524+
case errors.Is(err, consensus.ErrFutureBlock) || errors.Is(err, consensus.ErrMissingL1MessageData) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())):
15041525
for block != nil && (it.index == 0 || errors.Is(err, consensus.ErrUnknownAncestor)) {
15051526
log.Debug("Future block, postponing import", "number", block.Number(), "hash", block.Hash())
15061527
if err := bc.addFutureBlock(block); err != nil {
@@ -2175,11 +2196,12 @@ Chain config: %v
21752196
21762197
Number: %v
21772198
Hash: 0x%x
2199+
ParentHash: 0x%x
21782200
%v
21792201
21802202
Error: %v
21812203
##############################
2182-
`, bc.chainConfig, block.Number(), block.Hash(), receiptString, err))
2204+
`, bc.chainConfig, block.Number(), block.Hash(), block.ParentHash(), receiptString, err))
21832205
}
21842206

21852207
// InsertHeaderChain attempts to insert the given header chain in to the local

0 commit comments

Comments
 (0)