core, light: address comments

This commit is contained in:
rjl493456442 2019-11-19 21:24:28 +08:00
parent 3c57935687
commit 51390a57ba
3 changed files with 47 additions and 50 deletions

View file

@ -538,21 +538,21 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
// Prepare the genesis block and reinitialise the chain // Prepare the genesis block and reinitialise the chain
batch := bc.db.NewBatch() batch := bc.db.NewBatch()
bc.hc.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
rawdb.WriteBlock(batch, genesis) rawdb.WriteBlock(batch, genesis)
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to write genesis block", "err", err) log.Crit("Failed to write genesis block", "err", err)
} }
bc.genesisBlock = genesis bc.writeHeadBlock(genesis)
bc.writeHeadBlock(bc.genesisBlock)
// Last update all in-memory chain markers
bc.genesisBlock = genesis
bc.currentBlock.Store(bc.genesisBlock) bc.currentBlock.Store(bc.genesisBlock)
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) headBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
bc.hc.SetGenesis(bc.genesisBlock.Header()) bc.hc.SetGenesis(bc.genesisBlock.Header())
bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
bc.currentFastBlock.Store(bc.genesisBlock) bc.currentFastBlock.Store(bc.genesisBlock)
headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
return nil return nil
} }
@ -621,28 +621,28 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) {
updateHeads := rawdb.ReadCanonicalHash(bc.db, block.NumberU64()) != block.Hash() updateHeads := rawdb.ReadCanonicalHash(bc.db, block.NumberU64()) != block.Hash()
// Add the block to the canonical chain number scheme and mark as the head // Add the block to the canonical chain number scheme and mark as the head
// First write all header chain relative indexes
batch := bc.db.NewBatch() batch := bc.db.NewBatch()
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64()) rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
if updateHeads {
bc.hc.WriteHeadHeader(batch, block.Header())
}
// Then write all block chain relative indexes
rawdb.WriteTxLookupEntries(batch, block) rawdb.WriteTxLookupEntries(batch, block)
rawdb.WriteHeadBlockHash(batch, block.Hash()) rawdb.WriteHeadBlockHash(batch, block.Hash())
bc.currentBlock.Store(block)
headBlockGauge.Update(int64(block.NumberU64()))
// If the block is better than our head or is on a different chain, force update heads // If the block is better than our head or is on a different chain, force update heads
if updateHeads { if updateHeads {
rawdb.WriteHeadHeaderHash(batch, block.Hash())
rawdb.WriteHeadFastBlockHash(batch, block.Hash()) rawdb.WriteHeadFastBlockHash(batch, block.Hash())
bc.currentFastBlock.Store(block)
headFastBlockGauge.Update(int64(block.NumberU64()))
} }
// Flush the whole batch into the disk, exit the node if failed
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to update chain indexes and markers", "err", err) log.Crit("Failed to update chain indexes and markers", "err", err)
} }
// Update all in-memory chain markers in the last step
if updateHeads {
bc.hc.SetCurrentHeader(block.Header())
bc.currentFastBlock.Store(block)
headFastBlockGauge.Update(int64(block.NumberU64()))
}
bc.currentBlock.Store(block)
headBlockGauge.Update(int64(block.NumberU64()))
} }
// Genesis retrieves the chain's genesis block. // Genesis retrieves the chain's genesis block.
@ -892,9 +892,15 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
for i := len(chain) - 1; i >= 0; i-- { for i := len(chain) - 1; i >= 0; i-- {
hash := chain[i] hash := chain[i]
// Degrade the chain markers if they are explictly reverted.
// In thoery we should update all in-memory markers in the
// last step, however the direction of rollback is from high
// to low, so it's safe the update in-memory markers directly.
currentHeader := bc.hc.CurrentHeader() currentHeader := bc.hc.CurrentHeader()
if currentHeader.Hash() == hash { if currentHeader.Hash() == hash {
bc.hc.WriteHeadHeader(batch, bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1)) newHeadHeader := bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1)
rawdb.WriteHeadHeaderHash(batch, currentHeader.ParentHash)
bc.hc.SetCurrentHeader(newHeadHeader)
} }
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash { if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash {
newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1) newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1)
@ -1240,15 +1246,15 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
var lastWrite uint64 var lastWrite uint64
// writeSideBlock writes only the block and its metadata to the database, // writeBlockWithState writes only the block and its metadata to the database,
// but does not write any state. This is used to construct competing side forks // but does not write any state. This is used to construct competing side forks
// up to the point where they exceed the canonical total difficulty. // up to the point where they exceed the canonical total difficulty.
func (bc *BlockChain) writeSideBlock(block *types.Block, td *big.Int) (err error) { func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (err error) {
bc.wg.Add(1) bc.wg.Add(1)
defer bc.wg.Done() defer bc.wg.Done()
batch := bc.db.NewBatch() batch := bc.db.NewBatch()
bc.hc.WriteTd(batch, block.Hash(), block.NumberU64(), td) rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
rawdb.WriteBlock(batch, block) rawdb.WriteBlock(batch, block)
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to write block into disk", "err", err) log.Crit("Failed to write block into disk", "err", err)
@ -1301,11 +1307,10 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// Note all the components of block(td, hash->number map, header, body, receipts) // Note all the components of block(td, hash->number map, header, body, receipts)
// should be written atomically. BlockBatch is used for containing all components. // should be written atomically. BlockBatch is used for containing all components.
blockBatch := bc.db.NewBatch() blockBatch := bc.db.NewBatch()
if err := bc.hc.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd); err != nil { rawdb.WriteTd(blockBatch, block.Hash(), block.NumberU64(), externTd)
return NonStatTy, err
}
rawdb.WriteBlock(blockBatch, block) rawdb.WriteBlock(blockBatch, block)
rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts) rawdb.WriteReceipts(blockBatch, block.Hash(), block.NumberU64(), receipts)
rawdb.WritePreimages(blockBatch, state.Preimages())
if err := blockBatch.Write(); err != nil { if err := blockBatch.Write(); err != nil {
log.Crit("Failed to write block into disk", "err", err) log.Crit("Failed to write block into disk", "err", err)
} }
@ -1393,10 +1398,6 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
return NonStatTy, err return NonStatTy, err
} }
} }
// Preimages is a specical helper data, we don't need to
// consider the atomicity.
rawdb.WritePreimages(bc.db, state.Preimages())
status = CanonStatTy status = CanonStatTy
} else { } else {
status = SideStatTy status = SideStatTy
@ -1801,7 +1802,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
if !bc.HasBlock(block.Hash(), block.NumberU64()) { if !bc.HasBlock(block.Hash(), block.NumberU64()) {
start := time.Now() start := time.Now()
if err := bc.writeSideBlock(block, externTd); err != nil { if err := bc.writeBlockWithoutState(block, externTd); err != nil {
return it.index, nil, nil, err return it.index, nil, nil, err
} }
log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(), log.Debug("Injected sidechain block", "number", block.Number(), "hash", block.Hash(),

View file

@ -157,7 +157,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
// Note all the components of header(td, hash->number index and header) should // Note all the components of header(td, hash->number index and header) should
// be written atomically. // be written atomically.
headerBatch := hc.chainDb.NewBatch() headerBatch := hc.chainDb.NewBatch()
hc.WriteTd(headerBatch, hash, number, externTd) rawdb.WriteTd(headerBatch, hash, number, externTd)
rawdb.WriteHeader(headerBatch, header) rawdb.WriteHeader(headerBatch, header)
if err := headerBatch.Write(); err != nil { if err := headerBatch.Write(); err != nil {
log.Crit("Failed to write header into disk", "err", err) log.Crit("Failed to write header into disk", "err", err)
@ -200,6 +200,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
if err := markerBatch.Write(); err != nil { if err := markerBatch.Write(); err != nil {
log.Crit("Failed to write header markers into disk", "err", err) log.Crit("Failed to write header markers into disk", "err", err)
} }
// Last step update all in-memory head header markers
hc.currentHeaderHash = hash hc.currentHeaderHash = hash
hc.currentHeader.Store(types.CopyHeader(header)) hc.currentHeader.Store(types.CopyHeader(header))
headHeaderGauge.Update(header.Number.Int64()) headHeaderGauge.Update(header.Number.Int64())
@ -208,6 +209,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
} else { } else {
status = SideStatTy status = SideStatTy
} }
hc.tdCache.Add(hash, externTd)
hc.headerCache.Add(hash, header) hc.headerCache.Add(hash, header)
hc.numberCache.Add(hash, number) hc.numberCache.Add(hash, number)
return return
@ -411,14 +413,6 @@ func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int {
return hc.GetTd(hash, *number) return hc.GetTd(hash, *number)
} }
// WriteTd stores a block's total difficulty into the database, also caching it
// along the way.
func (hc *HeaderChain) WriteTd(db ethdb.KeyValueWriter, hash common.Hash, number uint64, td *big.Int) error {
rawdb.WriteTd(db, hash, number, td)
hc.tdCache.Add(hash, new(big.Int).Set(td))
return nil
}
// GetHeader retrieves a block header from the database by hash and number, // GetHeader retrieves a block header from the database by hash and number,
// caching it if found. // caching it if found.
func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header { func (hc *HeaderChain) GetHeader(hash common.Hash, number uint64) *types.Header {
@ -475,20 +469,14 @@ func (hc *HeaderChain) CurrentHeader() *types.Header {
return hc.currentHeader.Load().(*types.Header) return hc.currentHeader.Load().(*types.Header)
} }
// SetCurrentHeader sets the current head header of the canonical chain. // SetCurrentHeader sets the in-memory head header marker of the canonical chan
// as the given header.
func (hc *HeaderChain) SetCurrentHeader(head *types.Header) { func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
hc.currentHeader.Store(head) hc.currentHeader.Store(head)
hc.currentHeaderHash = head.Hash() hc.currentHeaderHash = head.Hash()
headHeaderGauge.Update(head.Number.Int64()) headHeaderGauge.Update(head.Number.Int64())
} }
// WriteHeadHeader sets the current head header of the canonical chain
// and write the marker into database.
func (hc *HeaderChain) WriteHeadHeader(db ethdb.KeyValueWriter, head *types.Header) {
rawdb.WriteHeadHeaderHash(db, head.Hash())
hc.SetCurrentHeader(head)
}
type ( type (
// UpdateHeadBlocksCallback is a callback function that is called by SetHead // UpdateHeadBlocksCallback is a callback function that is called by SetHead
// before head header is updated. // before head header is updated.

View file

@ -200,14 +200,12 @@ func (lc *LightChain) ResetWithGenesisBlock(genesis *types.Block) {
batch := lc.chainDb.NewBatch() batch := lc.chainDb.NewBatch()
rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty()) rawdb.WriteTd(batch, genesis.Hash(), genesis.NumberU64(), genesis.Difficulty())
rawdb.WriteBlock(batch, genesis) rawdb.WriteBlock(batch, genesis)
rawdb.WriteHeadHeaderHash(batch, genesis.Hash())
lc.genesisBlock = genesis
lc.hc.SetGenesis(lc.genesisBlock.Header())
lc.hc.WriteHeadHeader(batch, lc.genesisBlock.Header())
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to reset genesis block", "err", err) log.Crit("Failed to reset genesis block", "err", err)
} }
lc.genesisBlock = genesis
lc.hc.SetGenesis(lc.genesisBlock.Header())
} }
// Accessors // Accessors
@ -327,13 +325,22 @@ func (lc *LightChain) Rollback(chain []common.Hash) {
lc.chainmu.Lock() lc.chainmu.Lock()
defer lc.chainmu.Unlock() defer lc.chainmu.Unlock()
batch := lc.chainDb.NewBatch()
for i := len(chain) - 1; i >= 0; i-- { for i := len(chain) - 1; i >= 0; i-- {
hash := chain[i] hash := chain[i]
// Degrade the chain markers if they are explictly reverted.
// In thoery we should update all in-memory markers in the
// last step, however the direction of rollback is from high
// to low, so it's safe the update in-memory markers directly.
if head := lc.hc.CurrentHeader(); head.Hash() == hash { if head := lc.hc.CurrentHeader(); head.Hash() == hash {
lc.hc.WriteHeadHeader(lc.chainDb, lc.GetHeader(head.ParentHash, head.Number.Uint64()-1)) rawdb.WriteHeadHeaderHash(batch, head.ParentHash)
lc.hc.SetCurrentHeader(lc.GetHeader(head.ParentHash, head.Number.Uint64()-1))
} }
} }
if err := batch.Write(); err != nil {
log.Crit("Failed to rollback light chain", "error", err)
}
} }
// postChainEvents iterates over the events generated by a chain insertion and // postChainEvents iterates over the events generated by a chain insertion and
@ -497,7 +504,8 @@ func (lc *LightChain) SyncCheckpoint(ctx context.Context, checkpoint *params.Tru
// Ensure the chain didn't move past the latest block while retrieving it // Ensure the chain didn't move past the latest block while retrieving it
if lc.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() { if lc.hc.CurrentHeader().Number.Uint64() < header.Number.Uint64() {
log.Info("Updated latest header based on CHT", "number", header.Number, "hash", header.Hash(), "age", common.PrettyAge(time.Unix(int64(header.Time), 0))) log.Info("Updated latest header based on CHT", "number", header.Number, "hash", header.Hash(), "age", common.PrettyAge(time.Unix(int64(header.Time), 0)))
lc.hc.WriteHeadHeader(lc.chainDb, header) rawdb.WriteHeadHeaderHash(lc.chainDb, header.Hash())
lc.hc.SetCurrentHeader(header)
} }
return true return true
} }