@@ -110,6 +110,7 @@ const (
110110 bodyCacheLimit = 256
111111 blockCacheLimit = 256
112112 receiptsCacheLimit = 32
113+ sidecarsCacheLimit = 1024
113114 txLookupCacheLimit = 1024
114115 maxFutureBlocks = 256
115116 maxTimeFutureBlocks = 30
@@ -263,11 +264,13 @@ type BlockChain struct {
263264 currentFinalBlock atomic.Pointer [types.Header ] // Latest (consensus) finalized block
264265 currentSafeBlock atomic.Pointer [types.Header ] // Latest (consensus) safe block
265266 historyPrunePoint atomic.Pointer [history.PrunePoint ]
267+ chasingHead atomic.Pointer [types.Header ]
266268
267269 bodyCache * lru.Cache [common.Hash , * types.Body ]
268270 bodyRLPCache * lru.Cache [common.Hash , rlp.RawValue ]
269271 receiptsCache * lru.Cache [common.Hash , []* types.Receipt ]
270272 blockCache * lru.Cache [common.Hash , * types.Block ]
273+ sidecarsCache * lru.Cache [common.Hash , types.BlobSidecars ]
271274
272275 txLookupLock sync.RWMutex
273276 txLookupCache * lru.Cache [common.Hash , txLookup ]
@@ -333,6 +336,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
333336 bodyRLPCache : lru.NewCache [common.Hash , rlp.RawValue ](bodyCacheLimit ),
334337 receiptsCache : lru.NewCache [common.Hash , []* types.Receipt ](receiptsCacheLimit ),
335338 blockCache : lru.NewCache [common.Hash , * types.Block ](blockCacheLimit ),
339+ sidecarsCache : lru.NewCache [common.Hash , types.BlobSidecars ](sidecarsCacheLimit ),
336340 txLookupCache : lru.NewCache [common.Hash , txLookup ](txLookupCacheLimit ),
337341 futureBlocks : lru.NewCache [common.Hash , * types.Block ](maxFutureBlocks ),
338342 engine : engine ,
@@ -360,6 +364,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
360364 bc .currentSnapBlock .Store (nil )
361365 bc .currentFinalBlock .Store (nil )
362366 bc .currentSafeBlock .Store (nil )
367+ bc .chasingHead .Store (nil )
363368
364369 // Update chain info data metrics
365370 chainInfoGauge .Update (metrics.GaugeInfoValue {"chain_id" : bc .chainConfig .ChainID .String ()})
@@ -1010,6 +1015,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
10101015 // removed in the hc.SetHead function.
10111016 rawdb .DeleteBody (db , hash , num )
10121017 rawdb .DeleteReceipts (db , hash , num )
1018+ rawdb .DeleteBlobSidecars (db , hash , num )
10131019 }
10141020 // Todo(rjl493456442) txlookup, log index, etc
10151021 }
@@ -1035,6 +1041,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
10351041 bc .bodyRLPCache .Purge ()
10361042 bc .receiptsCache .Purge ()
10371043 bc .blockCache .Purge ()
1044+ bc .sidecarsCache .Purge ()
10381045 bc .txLookupCache .Purge ()
10391046 bc .futureBlocks .Purge ()
10401047
@@ -1085,6 +1092,16 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
10851092 return nil
10861093}
10871094
1095+ // UpdateChasingHead update remote best chain head, used by DA check now.
1096+ func (bc * BlockChain ) UpdateChasingHead (head * types.Header ) {
1097+ bc .chasingHead .Store (head )
1098+ }
1099+
1100+ // ChasingHead return the best chain head of peers.
1101+ func (bc * BlockChain ) ChasingHead () * types.Header {
1102+ return bc .chasingHead .Load ()
1103+ }
1104+
10881105// Reset purges the entire blockchain, restoring it to its genesis state.
10891106func (bc * BlockChain ) Reset () error {
10901107 return bc .ResetWithGenesisBlock (bc .genesisBlock )
@@ -1348,6 +1365,16 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
13481365 if n , err := bc .hc .ValidateHeaderChain (headers ); err != nil {
13491366 return n , err
13501367 }
1368+
1369+ // check DA after cancun
1370+ lastBlk := blockChain [len (blockChain )- 1 ]
1371+ if bc .chainConfig .DBFT != nil && bc .chainConfig .IsCancun (lastBlk .Number (), lastBlk .Time ()) {
1372+ if _ , err := CheckDataAvailableInBatch (bc , blockChain ); err != nil {
1373+ log .Debug ("CheckDataAvailableInBatch" , "err" , err )
1374+ return 0 , err
1375+ }
1376+ }
1377+
13511378 // Hold the mutation lock
13521379 if ! bc .chainmu .TryLock () {
13531380 return 0 , errChainStopped
@@ -1406,7 +1433,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
14061433 return 0 , consensus .ErrUnknownAncestor
14071434 }
14081435 td := new (big.Int ).Add (ptd , blockChain [0 ].Difficulty ())
1409- writeSize , err := rawdb .WriteAncientBlocks (bc .db , blockChain , receiptChain , td )
1436+ writeSize , err := rawdb .WriteAncientBlocksWithBlobs (bc .db , blockChain , receiptChain , td )
14101437 if err != nil {
14111438 log .Error ("Error importing chain data to ancients" , "err" , err )
14121439 return 0 , err
@@ -1472,6 +1499,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
14721499 rawdb .WriteCanonicalHash (batch , block .Hash (), block .NumberU64 ())
14731500 rawdb .WriteBlock (batch , block )
14741501 rawdb .WriteReceipts (batch , block .Hash (), block .NumberU64 (), receiptChain [i ])
1502+ if bc .chainConfig .IsCancun (block .Number (), block .Time ()) {
1503+ rawdb .WriteBlobSidecars (batch , block .Hash (), block .NumberU64 (), block .Sidecars ())
1504+ }
14751505
14761506 // Write everything belongs to the blocks into the database. So that
14771507 // we can ensure all components of body is completed(body, receipts)
@@ -1546,6 +1576,10 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
15461576 batch := bc .db .NewBatch ()
15471577 rawdb .WriteTd (batch , block .Hash (), block .NumberU64 (), td )
15481578 rawdb .WriteBlock (batch , block )
1579+ // if cancun is enabled, here need to write sidecars too
1580+ if bc .chainConfig .IsCancun (block .Number (), block .Time ()) {
1581+ rawdb .WriteBlobSidecars (batch , block .Hash (), block .NumberU64 (), block .Sidecars ())
1582+ }
15491583 if err := batch .Write (); err != nil {
15501584 log .Crit ("Failed to write block into disk" , "err" , err )
15511585 }
@@ -1584,10 +1618,17 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
15841618 rawdb .WriteTd (blockBatch , block .Hash (), block .NumberU64 (), externTd )
15851619 rawdb .WriteBlock (blockBatch , block )
15861620 rawdb .WriteReceipts (blockBatch , block .Hash (), block .NumberU64 (), receipts )
1621+ // if cancun is enabled, here need to write sidecars too
1622+ if bc .chainConfig .IsCancun (block .Number (), block .Time ()) {
1623+ rawdb .WriteBlobSidecars (blockBatch , block .Hash (), block .NumberU64 (), block .Sidecars ())
1624+ }
15871625 rawdb .WritePreimages (blockBatch , statedb .Preimages ())
15881626 if err := blockBatch .Write (); err != nil {
15891627 log .Crit ("Failed to write block into disk" , "err" , err )
15901628 }
1629+ if bc .chainConfig .IsCancun (block .Number (), block .Time ()) {
1630+ bc .sidecarsCache .Add (block .Hash (), block .Sidecars ())
1631+ }
15911632 // Commit all cached state changes into underlying memory database.
15921633 root , err := statedb .Commit (block .NumberU64 (), bc .chainConfig .IsEIP158 (block .Number ()), bc .chainConfig .IsCancun (block .Number (), block .Time ()))
15931634 if err != nil {
@@ -1802,6 +1843,14 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
18021843 bc .chainHeadFeed .Send (ChainHeadEvent {Header : lastCanon .Header ()})
18031844 }
18041845 }()
1846+
1847+ // check block data available first
1848+ if bc .chainConfig .DBFT != nil {
1849+ if index , err := CheckDataAvailableInBatch (bc , chain ); err != nil {
1850+ return nil , index , err
1851+ }
1852+ }
1853+
18051854 // Start the parallel header verifier
18061855 headers := make ([]* types.Header , len (chain ))
18071856 for i , block := range chain {
@@ -2316,6 +2365,9 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator, ma
23162365 // Append the next block to our batch
23172366 block := bc .GetBlock (hashes [i ], numbers [i ])
23182367
2368+ if bc .chainConfig .IsCancun (block .Number (), block .Time ()) {
2369+ block = block .WithSidecars (bc .GetSidecarsByHash (hashes [i ]))
2370+ }
23192371 blocks = append (blocks , block )
23202372 memory += block .Size ()
23212373
@@ -2387,6 +2439,9 @@ func (bc *BlockChain) recoverAncestors(block *types.Block, makeWitness bool) (co
23872439 } else {
23882440 b = bc .GetBlock (hashes [i ], numbers [i ])
23892441 }
2442+ if bc .chainConfig .IsCancun (b .Number (), b .Time ()) {
2443+ b = b .WithSidecars (bc .GetSidecarsByHash (b .Hash ()))
2444+ }
23902445 if _ , _ , err := bc .insertChain (types.Blocks {b }, false , makeWitness && i == 0 ); err != nil {
23912446 return b .ParentHash (), err
23922447 }
@@ -2719,6 +2774,7 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
27192774}
27202775
27212776// reportBlock logs a bad block error.
2777+ // bad block need not save receipts & sidecars.
27222778func (bc * BlockChain ) reportBlock (block * types.Block , res * ProcessResult , err error ) {
27232779 var receipts types.Receipts
27242780 if res != nil {
0 commit comments