Blockchain
WriteBlocks
// WriteBlocks writes a batch of blocks
func (b *Blockchain) WriteBlocks(blocks []*types.Block) error {
if len(blocks) == 0 {
return fmt.Errorf("no headers found to insert")
}
parent, ok := b.readHeader(blocks[0].ParentHash())
if !ok {
return fmt.Errorf("parent of %s (%d) not found: %s", blocks[0].Hash().String(), blocks[0].Number(), blocks[0].ParentHash())
}
// validate chain
for i := 0; i < len(blocks); i++ {
block := blocks[i]
if block.Number()-1 != parent.Number {
return fmt.Errorf("number sequence not correct at %d, %d and %d", i, block.Number(), parent.Number)
}
if block.ParentHash() != parent.Hash {
return fmt.Errorf("parent hash not correct")
}
if err := b.consensus.VerifyHeader(parent, block.Header, false, true); err != nil {
return fmt.Errorf("failed to verify the header: %v", err)
}
// verify body data
if hash := buildroot.CalculateUncleRoot(block.Uncles); hash != block.Header.Sha3Uncles {
return fmt.Errorf("uncle root hash mismatch: have %s, want %s", hash, block.Header.Sha3Uncles)
}
if hash := buildroot.CalculateTransactionsRoot(block.Transactions); hash != block.Header.TxRoot {
return fmt.Errorf("transaction root hash mismatch: have %s, want %s", hash, block.Header.TxRoot)
}
parent = block.Header
}
// Write chain
for indx, block := range blocks {
header := block.Header
body := block.Body()
if err := b.db.WriteBody(header.Hash, block.Body()); err != nil {
return err
}
b.bodiesCache.Add(header.Hash, body)
// Verify uncles. It requires to have the bodies on memory
if err := b.VerifyUncles(block); err != nil {
return err
}
// Process and validate the block
if err := b.processBlock(blocks[indx]); err != nil {
return err
}
// Write the header to the chain
evnt := &Event{}
if err := b.writeHeaderImpl(evnt, header); err != nil {
return err
}
b.dispatchEvent(evnt)
// Update the average gas price
b.UpdateGasPriceAvg(new(big.Int).SetUint64(header.GasUsed))
}
return nil
}Blockchain Subscriptions
Last updated