2015-07-06 17:54:22 -07:00
// Copyright 2014 The go-ethereum Authors
2015-07-22 09:48:40 -07:00
// This file is part of the go-ethereum library.
2015-07-06 17:54:22 -07:00
//
2015-07-23 09:35:11 -07:00
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-06 17:54:22 -07:00
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
2015-07-22 09:48:40 -07:00
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-06 17:54:22 -07:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-07-22 09:48:40 -07:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-06 17:54:22 -07:00
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
2015-07-22 09:48:40 -07:00
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-06 17:54:22 -07:00
2015-07-06 20:08:16 -07:00
// Package core implements the Ethereum consensus protocol.
2014-12-04 01:28:02 -08:00
package core
2014-02-14 14:56:09 -08:00
import (
2015-07-10 05:29:40 -07:00
"errors"
2014-09-24 02:39:17 -07:00
"fmt"
2015-03-18 05:36:48 -07:00
"io"
2014-07-29 15:31:15 -07:00
"math/big"
2015-10-13 02:04:25 -07:00
mrand "math/rand"
2014-12-18 04:12:54 -08:00
"sync"
2015-06-12 07:45:53 -07:00
"sync/atomic"
2015-04-04 07:35:23 -07:00
"time"
2014-07-29 15:31:15 -07:00
2015-03-16 03:27:38 -07:00
"github.com/ethereum/go-ethereum/common"
2017-10-31 15:24:11 -07:00
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/common/mclock"
2018-09-03 08:33:21 -07:00
"github.com/ethereum/go-ethereum/common/prque"
2017-10-31 15:24:11 -07:00
"github.com/ethereum/go-ethereum/consensus"
2018-05-23 22:32:26 -07:00
"github.com/ethereum/go-ethereum/core/rawdb"
2015-03-23 14:59:19 -07:00
"github.com/ethereum/go-ethereum/core/state"
2015-03-16 15:48:18 -07:00
"github.com/ethereum/go-ethereum/core/types"
2015-10-19 07:08:17 -07:00
"github.com/ethereum/go-ethereum/core/vm"
2015-09-14 00:35:57 -07:00
"github.com/ethereum/go-ethereum/ethdb"
2014-12-03 05:05:19 -08:00
"github.com/ethereum/go-ethereum/event"
2017-10-31 15:24:11 -07:00
"github.com/ethereum/go-ethereum/log"
2015-06-29 06:11:01 -07:00
"github.com/ethereum/go-ethereum/metrics"
2017-10-31 15:24:11 -07:00
"github.com/ethereum/go-ethereum/params"
2015-09-07 10:43:01 -07:00
"github.com/ethereum/go-ethereum/rlp"
2015-10-05 09:37:56 -07:00
"github.com/ethereum/go-ethereum/trie"
2020-05-11 13:15:27 -07:00
lru "github.com/hashicorp/golang-lru"
2014-02-14 14:56:09 -08:00
)
2015-03-03 00:44:41 -08:00
var (
2020-04-29 07:50:56 -07:00
headBlockGauge = metrics . NewRegisteredGauge ( "chain/head/block" , nil )
headHeaderGauge = metrics . NewRegisteredGauge ( "chain/head/header" , nil )
headFastBlockGauge = metrics . NewRegisteredGauge ( "chain/head/receipt" , nil )
accountReadTimer = metrics . NewRegisteredTimer ( "chain/account/reads" , nil )
accountHashTimer = metrics . NewRegisteredTimer ( "chain/account/hashes" , nil )
accountUpdateTimer = metrics . NewRegisteredTimer ( "chain/account/updates" , nil )
accountCommitTimer = metrics . NewRegisteredTimer ( "chain/account/commits" , nil )
storageReadTimer = metrics . NewRegisteredTimer ( "chain/storage/reads" , nil )
storageHashTimer = metrics . NewRegisteredTimer ( "chain/storage/hashes" , nil )
storageUpdateTimer = metrics . NewRegisteredTimer ( "chain/storage/updates" , nil )
storageCommitTimer = metrics . NewRegisteredTimer ( "chain/storage/commits" , nil )
blockInsertTimer = metrics . NewRegisteredTimer ( "chain/inserts" , nil )
blockValidationTimer = metrics . NewRegisteredTimer ( "chain/validation" , nil )
blockExecutionTimer = metrics . NewRegisteredTimer ( "chain/execution" , nil )
blockWriteTimer = metrics . NewRegisteredTimer ( "chain/write" , nil )
blockReorgAddMeter = metrics . NewRegisteredMeter ( "chain/reorg/drop" , nil )
blockReorgDropMeter = metrics . NewRegisteredMeter ( "chain/reorg/add" , nil )
blockPrefetchExecuteTimer = metrics . NewRegisteredTimer ( "chain/prefetch/executes" , nil )
blockPrefetchInterruptMeter = metrics . NewRegisteredMeter ( "chain/prefetch/interrupts" , nil )
errInsertionInterrupted = errors . New ( "insertion is interrupted" )
2015-03-03 00:44:41 -08:00
)
2014-06-23 04:54:10 -07:00
2015-04-20 11:37:40 -07:00
const (
2015-08-31 10:21:02 -07:00
bodyCacheLimit = 256
2015-06-19 09:16:09 -07:00
blockCacheLimit = 256
2018-09-29 13:53:31 -07:00
receiptsCacheLimit = 32
2020-04-29 07:50:56 -07:00
txLookupCacheLimit = 1024
2015-06-05 05:07:49 -07:00
maxFutureBlocks = 256
maxTimeFutureBlocks = 30
2017-10-31 15:24:11 -07:00
badBlockLimit = 10
2020-04-29 07:50:56 -07:00
TriesInMemory = 128
2017-10-31 15:24:11 -07:00
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
2020-04-29 07:50:56 -07:00
//
// Changelog:
//
// - Version 4
// The following incompatible database changes were added:
// * the `BlockNumber`, `TxHash`, `TxIndex`, `BlockHash` and `Index` fields of log are deleted
// * the `Bloom` field of receipt is deleted
// * the `BlockIndex` and `TxIndex` fields of txlookup are deleted
// - Version 5
// The following incompatible database changes were added:
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are no longer stored for a receipt
// * the `TxHash`, `GasCost`, and `ContractAddress` fields are computed by looking up the
// receipts' corresponding block
// - Version 6
// The following incompatible database changes were added:
// * Transaction lookup information stores the corresponding block number instead of block hash
// - Version 7
// The following incompatible database changes were added:
// * Use freezer as the ancient database to maintain all ancient data
BlockChainVersion uint64 = 7
2015-04-20 11:37:40 -07:00
)
2015-01-02 03:07:54 -08:00
2018-05-23 22:32:26 -07:00
// CacheConfig contains the configuration values for the trie caching/pruning
// that's resident in a blockchain.
type CacheConfig struct {
2020-04-29 07:50:56 -07:00
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
TrieCleanNoPrefetch bool // Whether to disable heuristic state prefetching for followup blocks
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
TrieDirtyDisabled bool // Whether to disable trie write caching and GC altogether (archive node)
TrieTimeLimit time . Duration // Time limit after which to flush the current in-memory trie to disk
2018-05-23 22:32:26 -07:00
}
2015-10-19 07:08:17 -07:00
// BlockChain represents the canonical chain given a database with a genesis
// block. The Blockchain manages chain imports, reverts, chain reorganisations.
//
// Importing blocks in to the block chain happens according to the set of rules
// defined by the two stage Validator. Processing of blocks is done using the
// Processor which processes the included transaction. The validation of the state
// is done in the second part of the Validator. Failing results in aborting of
// the import.
//
// The BlockChain also helps in returning blocks from **any** chain included
// in the database as well as blocks that represents the canonical chain. It's
// important to note that GetBlock can return any block and does not need to be
// included in the canonical one where as GetBlockByNumber always represents the
// canonical chain.
2015-08-31 08:09:50 -07:00
type BlockChain struct {
2018-05-23 22:32:26 -07:00
chainConfig * params . ChainConfig // Chain & network configuration
cacheConfig * CacheConfig // Cache configuration for pruning
db ethdb . Database // Low level persistent database to store final content in
triegc * prque . Prque // Priority queue mapping block numbers to tries to gc
gcproc time . Duration // Accumulates canonical block processing for trie dumping
2017-10-31 15:24:11 -07:00
hc * HeaderChain
rmLogsFeed event . Feed
chainFeed event . Feed
chainSideFeed event . Feed
chainHeadFeed event . Feed
logsFeed event . Feed
2020-04-29 07:50:56 -07:00
blockProcFeed event . Feed
2017-10-31 15:24:11 -07:00
scope event . SubscriptionScope
genesisBlock * types . Block
2015-12-15 19:26:23 -08:00
2016-03-08 06:55:27 -08:00
chainmu sync . RWMutex // blockchain insertion lock
2015-04-28 08:48:46 -07:00
2018-05-23 22:32:26 -07:00
currentBlock atomic . Value // Current head of the block chain
currentFastBlock atomic . Value // Current head of the fast-sync chain (may be above the block chain!)
2014-02-14 14:56:09 -08:00
2018-09-29 13:53:31 -07:00
stateCache state . Database // State database to reuse between imports (contains state cache)
bodyCache * lru . Cache // Cache for the most recent block bodies
bodyRLPCache * lru . Cache // Cache for the most recent block bodies in RLP encoded format
receiptsCache * lru . Cache // Cache for the most recent receipts per block
blockCache * lru . Cache // Cache for the most recent entire blocks
2020-04-29 07:50:56 -07:00
txLookupCache * lru . Cache // Cache for the most recent transaction lookup data.
2018-09-29 13:53:31 -07:00
futureBlocks * lru . Cache // future blocks are blocks added for later processing
2015-03-20 07:54:42 -07:00
2016-03-08 06:55:27 -08:00
quit chan struct { } // blockchain quit channel
2016-03-15 09:12:03 -07:00
running int32 // running must be called atomically
2015-06-12 07:45:53 -07:00
// procInterrupt must be atomically called
2016-03-08 06:55:27 -08:00
procInterrupt int32 // interrupt signaler for block processing
wg sync . WaitGroup // chain processing wait group for shutting down
2015-05-16 16:42:30 -07:00
2020-04-29 07:50:56 -07:00
engine consensus . Engine
validator Validator // Block and state validator interface
prefetcher Prefetcher // Block state prefetcher interface
processor Processor // Block transaction processor interface
vmConfig vm . Config
2017-10-31 15:24:11 -07:00
2020-04-29 07:50:56 -07:00
badBlocks * lru . Cache // Bad block cache
shouldPreserve func ( * types . Block ) bool // Function used to determine whether should preserve the given block.
terminateInsert func ( common . Hash , uint64 ) bool // Testing hook used to terminate ancient receipt chain insertion.
2017-03-27 14:15:24 -07:00
2017-10-31 15:24:11 -07:00
privateStateCache state . Database // Private state database to reuse between imports (contains state cache)
2014-12-18 04:12:54 -08:00
}
2014-02-14 14:56:09 -08:00
2015-10-19 07:08:17 -07:00
// NewBlockChain returns a fully initialised block chain using information
2017-10-31 15:24:11 -07:00
// available in the database. It initialises the default Ethereum Validator and
2015-10-19 07:08:17 -07:00
// Processor.
2018-09-20 10:02:15 -07:00
func NewBlockChain ( db ethdb . Database , cacheConfig * CacheConfig , chainConfig * params . ChainConfig , engine consensus . Engine , vmConfig vm . Config , shouldPreserve func ( block * types . Block ) bool ) ( * BlockChain , error ) {
2018-05-23 22:32:26 -07:00
if cacheConfig == nil {
cacheConfig = & CacheConfig {
2020-04-29 07:50:56 -07:00
TrieCleanLimit : 256 ,
TrieDirtyLimit : 256 ,
TrieTimeLimit : 5 * time . Minute ,
2018-05-23 22:32:26 -07:00
}
}
2015-08-31 10:21:02 -07:00
bodyCache , _ := lru . New ( bodyCacheLimit )
bodyRLPCache , _ := lru . New ( bodyCacheLimit )
2018-09-29 13:53:31 -07:00
receiptsCache , _ := lru . New ( receiptsCacheLimit )
2015-08-31 10:21:02 -07:00
blockCache , _ := lru . New ( blockCacheLimit )
2020-04-29 07:50:56 -07:00
txLookupCache , _ := lru . New ( txLookupCacheLimit )
2015-08-31 10:21:02 -07:00
futureBlocks , _ := lru . New ( maxFutureBlocks )
2017-10-31 15:24:11 -07:00
badBlocks , _ := lru . New ( badBlockLimit )
2015-08-31 10:21:02 -07:00
2015-08-31 08:09:50 -07:00
bc := & BlockChain {
2019-01-29 03:08:50 -08:00
chainConfig : chainConfig ,
cacheConfig : cacheConfig ,
db : db ,
triegc : prque . New ( nil ) ,
2020-04-29 07:50:56 -07:00
stateCache : state . NewDatabaseWithCache ( db , cacheConfig . TrieCleanLimit ) ,
2019-01-29 03:08:50 -08:00
quit : make ( chan struct { } ) ,
shouldPreserve : shouldPreserve ,
bodyCache : bodyCache ,
bodyRLPCache : bodyRLPCache ,
receiptsCache : receiptsCache ,
blockCache : blockCache ,
2020-04-29 07:50:56 -07:00
txLookupCache : txLookupCache ,
2019-01-29 03:08:50 -08:00
futureBlocks : futureBlocks ,
engine : engine ,
vmConfig : vmConfig ,
badBlocks : badBlocks ,
2018-05-23 22:32:26 -07:00
privateStateCache : state . NewDatabase ( db ) ,
2015-04-20 11:37:40 -07:00
}
2020-04-29 07:50:56 -07:00
bc . validator = NewBlockValidator ( chainConfig , bc , engine )
bc . prefetcher = newStatePrefetcher ( chainConfig , bc , engine )
bc . processor = NewStateProcessor ( chainConfig , bc , engine )
2015-12-15 19:26:23 -08:00
var err error
2018-05-23 22:32:26 -07:00
bc . hc , err = NewHeaderChain ( db , chainConfig , engine , bc . getProcInterrupt )
2015-10-13 02:04:25 -07:00
if err != nil {
return nil , err
}
2015-07-10 05:29:40 -07:00
bc . genesisBlock = bc . GetBlockByNumber ( 0 )
if bc . genesisBlock == nil {
2016-03-01 14:32:43 -08:00
return nil , ErrNoGenesis
2015-07-10 05:29:40 -07:00
}
2020-04-29 07:50:56 -07:00
var nilBlock * types . Block
bc . currentBlock . Store ( nilBlock )
bc . currentFastBlock . Store ( nilBlock )
// Initialize the chain with ancient data if it isn't empty.
if bc . empty ( ) {
rawdb . InitDatabaseFromFreezer ( bc . db )
}
2015-09-21 05:36:29 -07:00
if err := bc . loadLastState ( ) ; err != nil {
2015-07-10 05:29:40 -07:00
return nil , err
2015-06-08 03:12:13 -07:00
}
2020-04-29 07:50:56 -07:00
// The first thing the node will do is reconstruct the verification data for
// the head block (ethash cache or clique voting snapshot). Might as well do
// it in advance.
bc . engine . VerifyHeader ( bc , bc . CurrentHeader ( ) , true )
if frozen , err := bc . db . Ancients ( ) ; err == nil && frozen > 0 {
var (
needRewind bool
low uint64
)
// The head full block may be rolled back to a very low height due to
// blockchain repair. If the head full block is even lower than the ancient
// chain, truncate the ancient store.
fullBlock := bc . CurrentBlock ( )
if fullBlock != nil && fullBlock != bc . genesisBlock && fullBlock . NumberU64 ( ) < frozen - 1 {
needRewind = true
low = fullBlock . NumberU64 ( )
}
// In fast sync, it may happen that ancient data has been written to the
// ancient store, but the LastFastBlock has not been updated, truncate the
// extra data here.
fastBlock := bc . CurrentFastBlock ( )
if fastBlock != nil && fastBlock . NumberU64 ( ) < frozen - 1 {
needRewind = true
if fastBlock . NumberU64 ( ) < low || low == 0 {
low = fastBlock . NumberU64 ( )
}
}
if needRewind {
var hashes [ ] common . Hash
previous := bc . CurrentHeader ( ) . Number . Uint64 ( )
for i := low + 1 ; i <= bc . CurrentHeader ( ) . Number . Uint64 ( ) ; i ++ {
hashes = append ( hashes , rawdb . ReadCanonicalHash ( bc . db , i ) )
}
bc . Rollback ( hashes )
log . Warn ( "Truncate ancient chain" , "from" , previous , "to" , low )
}
}
2015-04-20 03:58:17 -07:00
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
2017-10-31 15:24:11 -07:00
for hash := range BadHashes {
2016-04-05 06:22:04 -07:00
if header := bc . GetHeaderByHash ( hash ) ; header != nil {
2017-10-31 15:24:11 -07:00
// get the canonical block corresponding to the offending header's number
headerByNumber := bc . GetHeaderByNumber ( header . Number . Uint64 ( ) )
// make sure the headerByNumber (if present) is in our current canonical chain
if headerByNumber != nil && headerByNumber . Hash ( ) == header . Hash ( ) {
log . Error ( "Found bad hash, rewinding chain" , "number" , header . Number , "hash" , header . ParentHash )
bc . SetHead ( header . Number . Uint64 ( ) - 1 )
log . Error ( "Chain rewind was successful, resuming normal operation" )
}
2015-04-20 03:58:17 -07:00
}
}
2015-03-13 06:37:54 -07:00
// Take ownership of this particular state
2015-03-06 06:50:44 -08:00
go bc . update ( )
2015-06-08 03:12:13 -07:00
return bc , nil
2015-02-18 04:14:21 -08:00
}
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) getProcInterrupt ( ) bool {
return atomic . LoadInt32 ( & bc . procInterrupt ) == 1
2015-12-15 19:26:23 -08:00
}
2020-04-29 07:50:56 -07:00
// GetVMConfig returns the block chain VM config.
func ( bc * BlockChain ) GetVMConfig ( ) * vm . Config {
return & bc . vmConfig
}
// empty returns an indicator whether the blockchain is empty.
// Note, it's a special case that we connect a non-empty ancient
// database with an empty node, so that we can plugin the ancient
// into node seamlessly.
func ( bc * BlockChain ) empty ( ) bool {
genesis := bc . genesisBlock . Hash ( )
for _ , hash := range [ ] common . Hash { rawdb . ReadHeadBlockHash ( bc . db ) , rawdb . ReadHeadHeaderHash ( bc . db ) , rawdb . ReadHeadFastBlockHash ( bc . db ) } {
if hash != genesis {
return false
}
}
return true
}
2015-09-21 05:36:29 -07:00
// loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) loadLastState ( ) error {
2015-09-21 05:36:29 -07:00
// Restore the last known head block
2018-05-23 22:32:26 -07:00
head := rawdb . ReadHeadBlockHash ( bc . db )
2015-09-21 05:36:29 -07:00
if head == ( common . Hash { } ) {
// Corrupt or empty database, init from scratch
2017-10-31 15:24:11 -07:00
log . Warn ( "Empty database, resetting chain" )
return bc . Reset ( )
}
// Make sure the entire head block is available
currentBlock := bc . GetBlockByHash ( head )
if currentBlock == nil {
// Corrupt or empty database, init from scratch
log . Warn ( "Head block missing, resetting chain" , "hash" , head )
return bc . Reset ( )
2015-09-21 05:36:29 -07:00
}
2017-10-31 15:24:11 -07:00
// Make sure the state associated with the block is available
if _ , err := state . New ( currentBlock . Root ( ) , bc . stateCache ) ; err != nil {
// Dangling block without a state associated, init from scratch
2018-05-23 22:32:26 -07:00
log . Warn ( "Head state missing, repairing chain" , "number" , currentBlock . Number ( ) , "hash" , currentBlock . Hash ( ) )
if err := bc . repair ( & currentBlock ) ; err != nil {
return err
}
2020-04-29 07:50:56 -07:00
rawdb . WriteHeadBlockHash ( bc . db , currentBlock . Hash ( ) )
2017-10-31 15:24:11 -07:00
}
// Quorum
2020-04-29 07:50:56 -07:00
if _ , err := state . New ( rawdb . GetPrivateStateRoot ( bc . db , currentBlock . Root ( ) ) , bc . privateStateCache ) ; err != nil {
2017-10-31 15:24:11 -07:00
log . Warn ( "Head private state missing, resetting chain" , "number" , currentBlock . Number ( ) , "hash" , currentBlock . Hash ( ) )
return bc . Reset ( )
}
// /Quorum
// Everything seems to be fine, set as the head block
2018-05-23 22:32:26 -07:00
bc . currentBlock . Store ( currentBlock )
2020-04-29 07:50:56 -07:00
headBlockGauge . Update ( int64 ( currentBlock . NumberU64 ( ) ) )
2017-10-31 15:24:11 -07:00
2015-09-21 05:36:29 -07:00
// Restore the last known head header
2018-05-23 22:32:26 -07:00
currentHeader := currentBlock . Header ( )
if head := rawdb . ReadHeadHeaderHash ( bc . db ) ; head != ( common . Hash { } ) {
2017-10-31 15:24:11 -07:00
if header := bc . GetHeaderByHash ( head ) ; header != nil {
2015-12-15 19:26:23 -08:00
currentHeader = header
2015-09-21 05:36:29 -07:00
}
}
2017-10-31 15:24:11 -07:00
bc . hc . SetCurrentHeader ( currentHeader )
2015-09-30 09:23:31 -07:00
// Restore the last known head fast block
2018-05-23 22:32:26 -07:00
bc . currentFastBlock . Store ( currentBlock )
2020-04-29 07:50:56 -07:00
headFastBlockGauge . Update ( int64 ( currentBlock . NumberU64 ( ) ) )
2018-05-23 22:32:26 -07:00
if head := rawdb . ReadHeadFastBlockHash ( bc . db ) ; head != ( common . Hash { } ) {
2017-10-31 15:24:11 -07:00
if block := bc . GetBlockByHash ( head ) ; block != nil {
2018-05-23 22:32:26 -07:00
bc . currentFastBlock . Store ( block )
2020-04-29 07:50:56 -07:00
headFastBlockGauge . Update ( int64 ( block . NumberU64 ( ) ) )
2015-09-30 09:23:31 -07:00
}
}
2016-09-22 12:04:58 -07:00
// Issue a status log for the user
2018-05-23 22:32:26 -07:00
currentFastBlock := bc . CurrentFastBlock ( )
2017-10-31 15:24:11 -07:00
headerTd := bc . GetTd ( currentHeader . Hash ( ) , currentHeader . Number . Uint64 ( ) )
2018-05-23 22:32:26 -07:00
blockTd := bc . GetTd ( currentBlock . Hash ( ) , currentBlock . NumberU64 ( ) )
fastTd := bc . GetTd ( currentFastBlock . Hash ( ) , currentFastBlock . NumberU64 ( ) )
2015-09-21 05:36:29 -07:00
2020-04-29 07:50:56 -07:00
log . Info ( "Loaded most recent local header" , "number" , currentHeader . Number , "hash" , currentHeader . Hash ( ) , "td" , headerTd , "age" , common . PrettyAge ( time . Unix ( int64 ( currentHeader . Time ) , 0 ) ) )
log . Info ( "Loaded most recent local full block" , "number" , currentBlock . Number ( ) , "hash" , currentBlock . Hash ( ) , "td" , blockTd , "age" , common . PrettyAge ( time . Unix ( int64 ( currentBlock . Time ( ) ) , 0 ) ) )
log . Info ( "Loaded most recent local fast block" , "number" , currentFastBlock . Number ( ) , "hash" , currentFastBlock . Hash ( ) , "td" , fastTd , "age" , common . PrettyAge ( time . Unix ( int64 ( currentFastBlock . Time ( ) ) , 0 ) ) )
2015-09-21 05:36:29 -07:00
return nil
}
2015-10-13 02:04:25 -07:00
// SetHead rewinds the local chain to a new head. In the case of headers, everything
// above the new head will be deleted and the new one set. In the case of blocks
// though, the head may be further rewound if block bodies are missing (non-archive
// nodes after a fast sync).
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) SetHead ( head uint64 ) error {
log . Warn ( "Rewinding blockchain" , "target" , head )
2020-04-29 07:50:56 -07:00
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
updateFn := func ( db ethdb . KeyValueWriter , header * types . Header ) {
// Rewind the block chain, ensuring we don't end up with a stateless head block
if currentBlock := bc . CurrentBlock ( ) ; currentBlock != nil && header . Number . Uint64 ( ) < currentBlock . NumberU64 ( ) {
newHeadBlock := bc . GetBlock ( header . Hash ( ) , header . Number . Uint64 ( ) )
if newHeadBlock == nil {
newHeadBlock = bc . genesisBlock
} else {
if _ , err := state . New ( newHeadBlock . Root ( ) , bc . stateCache ) ; err != nil {
// Rewound state missing, rolled back to before pivot, reset to genesis
newHeadBlock = bc . genesisBlock
}
}
rawdb . WriteHeadBlockHash ( db , newHeadBlock . Hash ( ) )
bc . currentBlock . Store ( newHeadBlock )
headBlockGauge . Update ( int64 ( newHeadBlock . NumberU64 ( ) ) )
}
// Rewind the fast block in a simpleton way to the target head
if currentFastBlock := bc . CurrentFastBlock ( ) ; currentFastBlock != nil && header . Number . Uint64 ( ) < currentFastBlock . NumberU64 ( ) {
newHeadFastBlock := bc . GetBlock ( header . Hash ( ) , header . Number . Uint64 ( ) )
// If either blocks reached nil, reset to the genesis state
if newHeadFastBlock == nil {
newHeadFastBlock = bc . genesisBlock
}
rawdb . WriteHeadFastBlockHash ( db , newHeadFastBlock . Hash ( ) )
bc . currentFastBlock . Store ( newHeadFastBlock )
headFastBlockGauge . Update ( int64 ( newHeadFastBlock . NumberU64 ( ) ) )
}
}
2015-04-20 03:29:02 -07:00
2017-10-31 15:24:11 -07:00
// Rewind the header chain, deleting all block bodies until then
2020-04-29 07:50:56 -07:00
delFn := func ( db ethdb . KeyValueWriter , hash common . Hash , num uint64 ) {
// Ignore the error here since light client won't hit this path
frozen , _ := bc . db . Ancients ( )
if num + 1 <= frozen {
// Truncate all relative data(header, total difficulty, body, receipt
// and canonical hash) from ancient store.
if err := bc . db . TruncateAncients ( num + 1 ) ; err != nil {
log . Crit ( "Failed to truncate ancient data" , "number" , num , "err" , err )
}
// Remove the hash <-> number mapping from the active store.
rawdb . DeleteHeaderNumber ( db , hash )
} else {
// Remove relative body and receipts from the active store.
// The header, total difficulty and canonical hash will be
// removed in the hc.SetHead function.
rawdb . DeleteBody ( db , hash , num )
rawdb . DeleteReceipts ( db , hash , num )
}
// Todo(rjl493456442) txlookup, bloombits, etc
2015-09-30 09:23:31 -07:00
}
2020-04-29 07:50:56 -07:00
bc . hc . SetHead ( head , updateFn , delFn )
2015-12-15 19:26:23 -08:00
2015-09-21 05:36:29 -07:00
// Clear out any stale content from the caches
2015-08-31 10:21:02 -07:00
bc . bodyCache . Purge ( )
bc . bodyRLPCache . Purge ( )
2018-09-29 13:53:31 -07:00
bc . receiptsCache . Purge ( )
2015-08-31 10:21:02 -07:00
bc . blockCache . Purge ( )
2020-04-29 07:50:56 -07:00
bc . txLookupCache . Purge ( )
2015-08-31 10:21:02 -07:00
bc . futureBlocks . Purge ( )
2015-04-20 03:29:02 -07:00
2017-10-31 15:24:11 -07:00
return bc . loadLastState ( )
2015-04-20 03:29:02 -07:00
}
2015-10-05 09:37:56 -07:00
// FastSyncCommitHead sets the current head block to the one defined by the hash
// irrelevant what the chain contents were prior.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) FastSyncCommitHead ( hash common . Hash ) error {
2015-10-13 02:04:25 -07:00
// Make sure that both the block as well at its state trie exists
2017-10-31 15:24:11 -07:00
block := bc . GetBlockByHash ( hash )
2015-10-05 09:37:56 -07:00
if block == nil {
return fmt . Errorf ( "non existent block [%x…]" , hash [ : 4 ] )
}
2020-04-29 07:50:56 -07:00
if _ , err := trie . NewSecure ( block . Root ( ) , bc . stateCache . TrieDB ( ) ) ; err != nil {
2015-10-05 09:37:56 -07:00
return err
}
// If all checks out, manually set the head block
2020-04-29 07:50:56 -07:00
bc . chainmu . Lock ( )
2018-05-23 22:32:26 -07:00
bc . currentBlock . Store ( block )
2020-04-29 07:50:56 -07:00
headBlockGauge . Update ( int64 ( block . NumberU64 ( ) ) )
bc . chainmu . Unlock ( )
2015-10-05 09:37:56 -07:00
2017-10-31 15:24:11 -07:00
log . Info ( "Committed new head block" , "number" , block . Number ( ) , "hash" , hash )
2015-10-05 09:37:56 -07:00
return nil
}
2015-10-19 07:08:17 -07:00
// GasLimit returns the gas limit of the current HEAD block.
2018-05-23 22:32:26 -07:00
func ( bc * BlockChain ) GasLimit ( ) uint64 {
2020-04-29 07:50:56 -07:00
bc . chainmu . RLock ( )
defer bc . chainmu . RUnlock ( )
2014-12-10 10:59:12 -08:00
2017-10-31 15:24:11 -07:00
if bc . Config ( ) . IsQuorum {
2018-05-29 06:05:18 -07:00
return math . MaxBig256 . Uint64 ( ) // HACK(joel) a very large number
2017-10-31 15:24:11 -07:00
} else {
2018-05-29 06:05:18 -07:00
return bc . CurrentBlock ( ) . GasLimit ( )
2017-10-31 15:24:11 -07:00
}
2014-12-18 04:12:54 -08:00
}
2015-09-21 05:36:29 -07:00
// CurrentBlock retrieves the current head block of the canonical chain. The
2015-10-13 02:04:25 -07:00
// block is retrieved from the blockchain's internal cache.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) CurrentBlock ( ) * types . Block {
2018-05-23 22:32:26 -07:00
return bc . currentBlock . Load ( ) . ( * types . Block )
2014-02-14 14:56:09 -08:00
}
2015-09-30 09:23:31 -07:00
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
2015-10-13 02:04:25 -07:00
// chain. The block is retrieved from the blockchain's internal cache.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) CurrentFastBlock ( ) * types . Block {
2018-05-23 22:32:26 -07:00
return bc . currentFastBlock . Load ( ) . ( * types . Block )
2014-12-14 10:20:37 -08:00
}
2015-10-19 07:08:17 -07:00
// Validator returns the current validator.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) Validator ( ) Validator {
return bc . validator
2015-10-19 07:08:17 -07:00
}
// Processor returns the current processor.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) Processor ( ) Processor {
return bc . processor
2015-10-19 07:08:17 -07:00
}
// State returns a new mutable state based on the current HEAD block.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) State ( ) ( * state . StateDB , * state . StateDB , error ) {
return bc . StateAt ( bc . CurrentBlock ( ) . Root ( ) )
2016-09-27 03:13:13 -07:00
}
// StateAt returns a new mutable state based on a particular point in time.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) StateAt ( root common . Hash ) ( * state . StateDB , * state . StateDB , error ) {
publicStateDb , publicStateDbErr := state . New ( root , bc . stateCache )
2016-10-31 04:46:40 -07:00
if publicStateDbErr != nil {
return nil , nil , publicStateDbErr
}
2020-04-29 07:50:56 -07:00
privateStateDb , privateStateDbErr := state . New ( rawdb . GetPrivateStateRoot ( bc . db , root ) , bc . privateStateCache )
2016-10-31 04:46:40 -07:00
if privateStateDbErr != nil {
return nil , nil , privateStateDbErr
}
return publicStateDb , privateStateDb , nil
2014-12-10 10:59:12 -08:00
}
2020-04-29 07:50:56 -07:00
// StateCache returns the caching database underpinning the blockchain instance.
func ( bc * BlockChain ) StateCache ( ) ( state . Database , state . Database ) {
return bc . stateCache , bc . privateStateCache
}
2015-08-31 10:21:02 -07:00
// Reset purges the entire blockchain, restoring it to its genesis state.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) Reset ( ) error {
return bc . ResetWithGenesisBlock ( bc . genesisBlock )
2015-03-13 10:29:42 -07:00
}
2015-08-31 10:21:02 -07:00
// ResetWithGenesisBlock purges the entire blockchain, restoring it to the
// specified genesis state.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) ResetWithGenesisBlock ( genesis * types . Block ) error {
2015-09-30 09:23:31 -07:00
// Dump the entire block chain and purge the caches
2017-10-31 15:24:11 -07:00
if err := bc . SetHead ( 0 ) ; err != nil {
return err
}
2020-04-29 07:50:56 -07:00
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
2015-03-03 09:41:51 -08:00
2015-10-13 02:04:25 -07:00
// Prepare the genesis block and reinitialise the chain
2016-04-05 06:22:04 -07:00
if err := bc . hc . WriteTd ( genesis . Hash ( ) , genesis . NumberU64 ( ) , genesis . Difficulty ( ) ) ; err != nil {
2017-10-31 15:24:11 -07:00
log . Crit ( "Failed to write genesis block TD" , "err" , err )
2015-09-07 10:43:01 -07:00
}
2018-05-23 22:32:26 -07:00
rawdb . WriteBlock ( bc . db , genesis )
2015-09-22 14:55:31 -07:00
bc . genesisBlock = genesis
2015-03-03 09:41:51 -08:00
bc . insert ( bc . genesisBlock )
2018-05-23 22:32:26 -07:00
bc . currentBlock . Store ( bc . genesisBlock )
2020-04-29 07:50:56 -07:00
headBlockGauge . Update ( int64 ( bc . genesisBlock . NumberU64 ( ) ) )
2015-12-15 19:26:23 -08:00
bc . hc . SetGenesis ( bc . genesisBlock . Header ( ) )
bc . hc . SetCurrentHeader ( bc . genesisBlock . Header ( ) )
2018-05-23 22:32:26 -07:00
bc . currentFastBlock . Store ( bc . genesisBlock )
2020-04-29 07:50:56 -07:00
headFastBlockGauge . Update ( int64 ( bc . genesisBlock . NumberU64 ( ) ) )
2017-10-31 15:24:11 -07:00
return nil
2015-03-03 09:41:51 -08:00
}
2018-05-23 22:32:26 -07:00
// repair tries to repair the current blockchain by rolling back the current block
// until one with associated state is found. This is needed to fix incomplete db
// writes caused either by crashes/power outages, or simply non-committed tries.
//
// This method only rolls back the current block. The current header and current
// fast block are left intact.
func ( bc * BlockChain ) repair ( head * * types . Block ) error {
for {
// Abort if we've rewound to a head block that does have associated state
if _ , err := state . New ( ( * head ) . Root ( ) , bc . stateCache ) ; err == nil {
log . Info ( "Rewound blockchain to past state" , "number" , ( * head ) . Number ( ) , "hash" , ( * head ) . Hash ( ) )
return nil
}
// Otherwise rewind one block and recheck state availability there
2020-04-29 07:50:56 -07:00
block := bc . GetBlock ( ( * head ) . ParentHash ( ) , ( * head ) . NumberU64 ( ) - 1 )
if block == nil {
return fmt . Errorf ( "missing block %d [%x]" , ( * head ) . NumberU64 ( ) - 1 , ( * head ) . ParentHash ( ) )
}
* head = block
2018-05-23 22:32:26 -07:00
}
}
2015-03-18 05:36:48 -07:00
// Export writes the active chain to the given writer.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) Export ( w io . Writer ) error {
2018-05-23 22:32:26 -07:00
return bc . ExportN ( w , uint64 ( 0 ) , bc . CurrentBlock ( ) . NumberU64 ( ) )
2015-06-05 20:01:54 -07:00
}
// ExportN writes a subset of the active chain to the given writer.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) ExportN ( w io . Writer , first uint64 , last uint64 ) error {
2020-04-29 07:50:56 -07:00
bc . chainmu . RLock ( )
defer bc . chainmu . RUnlock ( )
2015-04-04 14:04:19 -07:00
2015-06-05 20:01:54 -07:00
if first > last {
return fmt . Errorf ( "export failed: first (%d) is greater than last (%d)" , first , last )
}
2017-10-31 15:24:11 -07:00
log . Info ( "Exporting batch of blocks" , "count" , last - first + 1 )
2015-04-13 01:13:52 -07:00
2018-07-26 04:26:24 -07:00
start , reported := time . Now ( ) , time . Now ( )
2015-06-05 20:01:54 -07:00
for nr := first ; nr <= last ; nr ++ {
2017-10-31 15:24:11 -07:00
block := bc . GetBlockByNumber ( nr )
2015-04-20 07:02:50 -07:00
if block == nil {
return fmt . Errorf ( "export failed on #%d: not found" , nr )
}
if err := block . EncodeRLP ( w ) ; err != nil {
2015-03-18 05:36:48 -07:00
return err
}
2018-07-26 04:26:24 -07:00
if time . Since ( reported ) >= statsReportLimit {
log . Info ( "Exporting blocks" , "exported" , block . NumberU64 ( ) - first , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) )
reported = time . Now ( )
}
2014-12-17 03:57:35 -08:00
}
2015-03-18 05:36:48 -07:00
return nil
2014-12-17 03:57:35 -08:00
}
2015-09-21 05:36:29 -07:00
// insert injects a new head block into the current block chain. This method
// assumes that the block is indeed a true head. It will also reset the head
2015-10-28 08:40:24 -07:00
// header and the head fast sync block to this very same block if they are older
// or if they are on a different side chain.
2015-09-21 05:36:29 -07:00
//
// Note, this function assumes that the `mu` mutex is held!
2015-08-31 08:09:50 -07:00
func ( bc * BlockChain ) insert ( block * types . Block ) {
2015-10-28 08:40:24 -07:00
// If the block is on a side chain or an unknown one, force other heads onto it too
2018-05-23 22:32:26 -07:00
updateHeads := rawdb . ReadCanonicalHash ( bc . db , block . NumberU64 ( ) ) != block . Hash ( )
2015-10-28 08:40:24 -07:00
2015-09-07 10:43:01 -07:00
// Add the block to the canonical chain number scheme and mark as the head
2018-05-23 22:32:26 -07:00
rawdb . WriteCanonicalHash ( bc . db , block . Hash ( ) , block . NumberU64 ( ) )
rawdb . WriteHeadBlockHash ( bc . db , block . Hash ( ) )
2015-10-28 08:40:24 -07:00
2018-05-23 22:32:26 -07:00
bc . currentBlock . Store ( block )
2020-04-29 07:50:56 -07:00
headBlockGauge . Update ( int64 ( block . NumberU64 ( ) ) )
2018-05-23 22:32:26 -07:00
// If the block is better than our head or is on a different chain, force update heads
2015-10-28 08:40:24 -07:00
if updateHeads {
2015-12-15 19:26:23 -08:00
bc . hc . SetCurrentHeader ( block . Header ( ) )
2018-05-23 22:32:26 -07:00
rawdb . WriteHeadFastBlockHash ( bc . db , block . Hash ( ) )
2015-10-28 08:40:24 -07:00
2018-05-23 22:32:26 -07:00
bc . currentFastBlock . Store ( block )
2020-04-29 07:50:56 -07:00
headFastBlockGauge . Update ( int64 ( block . NumberU64 ( ) ) )
2015-10-28 08:40:24 -07:00
}
2014-12-05 07:26:39 -08:00
}
2017-10-31 15:24:11 -07:00
// Genesis retrieves the chain's genesis block.
2015-08-31 08:09:50 -07:00
func ( bc * BlockChain ) Genesis ( ) * types . Block {
2014-02-14 14:56:09 -08:00
return bc . genesisBlock
}
2015-09-07 10:43:01 -07:00
// GetBody retrieves a block body (transactions and uncles) from the database by
// hash, caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBody ( hash common . Hash ) * types . Body {
2015-08-31 10:21:02 -07:00
// Short circuit if the body's already in the cache, retrieve otherwise
2017-10-31 15:24:11 -07:00
if cached , ok := bc . bodyCache . Get ( hash ) ; ok {
2015-09-07 10:43:01 -07:00
body := cached . ( * types . Body )
return body
2014-08-21 05:47:58 -07:00
}
2018-05-23 22:32:26 -07:00
number := bc . hc . GetBlockNumber ( hash )
if number == nil {
return nil
}
body := rawdb . ReadBody ( bc . db , hash , * number )
2015-09-07 10:43:01 -07:00
if body == nil {
return nil
2015-08-31 10:21:02 -07:00
}
// Cache the found body for next time and return
2017-10-31 15:24:11 -07:00
bc . bodyCache . Add ( hash , body )
2015-09-07 10:43:01 -07:00
return body
2015-08-31 10:21:02 -07:00
}
2015-01-28 12:12:26 -08:00
2015-08-31 10:21:02 -07:00
// GetBodyRLP retrieves a block body in RLP encoding from the database by hash,
// caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBodyRLP ( hash common . Hash ) rlp . RawValue {
2015-08-31 10:21:02 -07:00
// Short circuit if the body's already in the cache, retrieve otherwise
2017-10-31 15:24:11 -07:00
if cached , ok := bc . bodyRLPCache . Get ( hash ) ; ok {
2015-09-07 10:43:01 -07:00
return cached . ( rlp . RawValue )
2015-08-31 10:21:02 -07:00
}
2018-05-23 22:32:26 -07:00
number := bc . hc . GetBlockNumber ( hash )
if number == nil {
return nil
}
body := rawdb . ReadBodyRLP ( bc . db , hash , * number )
2015-09-07 10:43:01 -07:00
if len ( body ) == 0 {
2015-08-31 10:21:02 -07:00
return nil
2014-08-21 05:47:58 -07:00
}
2015-08-31 10:21:02 -07:00
// Cache the found body for next time and return
2017-10-31 15:24:11 -07:00
bc . bodyRLPCache . Add ( hash , body )
2015-08-31 10:21:02 -07:00
return body
}
2014-08-21 05:47:58 -07:00
2017-10-31 15:24:11 -07:00
// HasBlock checks if a block is fully present in the database or not.
func ( bc * BlockChain ) HasBlock ( hash common . Hash , number uint64 ) bool {
if bc . blockCache . Contains ( hash ) {
return true
}
2018-05-23 22:32:26 -07:00
return rawdb . HasBody ( bc . db , hash , number )
}
2020-04-29 07:50:56 -07:00
// HasFastBlock checks if a fast block is fully present in the database or not.
func ( bc * BlockChain ) HasFastBlock ( hash common . Hash , number uint64 ) bool {
if ! bc . HasBlock ( hash , number ) {
return false
}
if bc . receiptsCache . Contains ( hash ) {
return true
}
return rawdb . HasReceipts ( bc . db , hash , number )
}
2018-05-23 22:32:26 -07:00
// HasState checks if state trie is fully present in the database or not.
func ( bc * BlockChain ) HasState ( hash common . Hash ) bool {
_ , err := bc . stateCache . OpenTrie ( hash )
return err == nil
2014-08-21 05:47:58 -07:00
}
2015-12-29 04:01:08 -08:00
// HasBlockAndState checks if a block and associated state trie is fully present
// in the database or not, caching it if present.
2018-05-23 22:32:26 -07:00
func ( bc * BlockChain ) HasBlockAndState ( hash common . Hash , number uint64 ) bool {
2015-12-29 04:01:08 -08:00
// Check first that the block itself is known
2018-05-23 22:32:26 -07:00
block := bc . GetBlock ( hash , number )
2015-12-29 04:01:08 -08:00
if block == nil {
return false
}
2018-05-23 22:32:26 -07:00
return bc . HasState ( block . Root ( ) )
2015-12-29 04:01:08 -08:00
}
2016-04-05 06:22:04 -07:00
// GetBlock retrieves a block from the database by hash and number,
// caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBlock ( hash common . Hash , number uint64 ) * types . Block {
2015-08-31 10:21:02 -07:00
// Short circuit if the block's already in the cache, retrieve otherwise
2017-10-31 15:24:11 -07:00
if block , ok := bc . blockCache . Get ( hash ) ; ok {
2015-06-19 07:21:20 -07:00
return block . ( * types . Block )
}
2018-05-23 22:32:26 -07:00
block := rawdb . ReadBlock ( bc . db , hash , number )
2015-07-01 07:15:02 -07:00
if block == nil {
2014-12-23 04:48:44 -08:00
return nil
}
2015-08-31 10:21:02 -07:00
// Cache the found block for next time and return
2017-10-31 15:24:11 -07:00
bc . blockCache . Add ( block . Hash ( ) , block )
2015-08-31 10:21:02 -07:00
return block
2014-02-14 14:56:09 -08:00
}
2016-04-05 06:22:04 -07:00
// GetBlockByHash retrieves a block from the database by hash, caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBlockByHash ( hash common . Hash ) * types . Block {
2018-05-23 22:32:26 -07:00
number := bc . hc . GetBlockNumber ( hash )
if number == nil {
return nil
}
return bc . GetBlock ( hash , * number )
2016-04-05 06:22:04 -07:00
}
2015-08-31 10:21:02 -07:00
// GetBlockByNumber retrieves a block from the database by number, caching it
// (associated with its hash) if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBlockByNumber ( number uint64 ) * types . Block {
2018-05-23 22:32:26 -07:00
hash := rawdb . ReadCanonicalHash ( bc . db , number )
2015-08-31 10:21:02 -07:00
if hash == ( common . Hash { } ) {
return nil
}
2017-10-31 15:24:11 -07:00
return bc . GetBlock ( hash , number )
2015-08-31 10:21:02 -07:00
}
2015-04-18 12:23:42 -07:00
2018-05-23 22:32:26 -07:00
// GetReceiptsByHash retrieves the receipts for all transactions in a given block.
func ( bc * BlockChain ) GetReceiptsByHash ( hash common . Hash ) types . Receipts {
2018-09-29 13:53:31 -07:00
if receipts , ok := bc . receiptsCache . Get ( hash ) ; ok {
return receipts . ( types . Receipts )
}
2018-05-23 22:32:26 -07:00
number := rawdb . ReadHeaderNumber ( bc . db , hash )
if number == nil {
return nil
}
2020-04-29 07:50:56 -07:00
receipts := rawdb . ReadReceipts ( bc . db , hash , * number , bc . chainConfig )
if receipts == nil {
return nil
}
2018-09-29 13:53:31 -07:00
bc . receiptsCache . Add ( hash , receipts )
return receipts
2018-05-23 22:32:26 -07:00
}
2015-06-16 03:41:50 -07:00
// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
2017-10-31 15:24:11 -07:00
// [deprecated by eth/62]
func ( bc * BlockChain ) GetBlocksFromHash ( hash common . Hash , n int ) ( blocks [ ] * types . Block ) {
number := bc . hc . GetBlockNumber ( hash )
2018-05-23 22:32:26 -07:00
if number == nil {
return nil
}
2015-06-16 03:41:50 -07:00
for i := 0 ; i < n ; i ++ {
2018-05-23 22:32:26 -07:00
block := bc . GetBlock ( hash , * number )
2015-06-16 03:41:50 -07:00
if block == nil {
break
}
blocks = append ( blocks , block )
hash = block . ParentHash ( )
2018-05-23 22:32:26 -07:00
* number --
2015-06-16 03:41:50 -07:00
}
return
}
2015-09-21 05:36:29 -07:00
// GetUnclesInChain retrieves all the uncles from a given block backwards until
// a specific distance is reached.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetUnclesInChain ( block * types . Block , length int ) [ ] * types . Header {
2015-09-21 05:36:29 -07:00
uncles := [ ] * types . Header { }
2015-01-09 08:38:35 -08:00
for i := 0 ; block != nil && i < length ; i ++ {
uncles = append ( uncles , block . Uncles ( ) ... )
2017-10-31 15:24:11 -07:00
block = bc . GetBlock ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
2015-01-09 08:38:35 -08:00
}
2015-09-21 05:36:29 -07:00
return uncles
2014-11-17 03:12:55 -08:00
}
2014-09-26 04:32:54 -07:00
2018-05-23 22:32:26 -07:00
// TrieNode retrieves a blob of data associated with a trie node (or code hash)
// either from ephemeral in-memory cache, or from persistent storage.
func ( bc * BlockChain ) TrieNode ( hash common . Hash ) ( [ ] byte , error ) {
return bc . stateCache . TrieDB ( ) . Node ( hash )
}
2015-10-19 07:08:17 -07:00
// Stop stops the blockchain service. If any imports are currently in progress
// it will abort them using the procInterrupt.
2015-08-31 08:09:50 -07:00
func ( bc * BlockChain ) Stop ( ) {
2015-08-01 03:32:28 -07:00
if ! atomic . CompareAndSwapInt32 ( & bc . running , 0 , 1 ) {
return
}
2017-10-31 15:24:11 -07:00
// Unsubscribe all subscriptions registered from blockchain
bc . scope . Close ( )
2015-03-06 06:50:44 -08:00
close ( bc . quit )
2015-06-12 07:45:53 -07:00
atomic . StoreInt32 ( & bc . procInterrupt , 1 )
2015-04-30 08:50:23 -07:00
bc . wg . Wait ( )
2018-05-23 22:32:26 -07:00
// Ensure the state of a recent block is also stored to disk before exiting.
// We're writing three different states to catch different restart scenarios:
// - HEAD: So we don't need to reprocess any blocks in the general case
// - HEAD-1: So we don't do large reorgs if our HEAD becomes an uncle
// - HEAD-127: So we have a hard limit on the number of blocks reexecuted
2020-04-29 07:50:56 -07:00
if ! bc . cacheConfig . TrieDirtyDisabled {
2018-05-23 22:32:26 -07:00
triedb := bc . stateCache . TrieDB ( )
2020-04-29 07:50:56 -07:00
for _ , offset := range [ ] uint64 { 0 , 1 , TriesInMemory - 1 } {
2018-05-23 22:32:26 -07:00
if number := bc . CurrentBlock ( ) . NumberU64 ( ) ; number > offset {
recent := bc . GetBlockByNumber ( number - offset )
log . Info ( "Writing cached state to disk" , "block" , recent . Number ( ) , "hash" , recent . Hash ( ) , "root" , recent . Root ( ) )
if err := triedb . Commit ( recent . Root ( ) , true ) ; err != nil {
log . Error ( "Failed to commit recent state trie" , "err" , err )
}
}
}
for ! bc . triegc . Empty ( ) {
2018-07-24 01:15:38 -07:00
triedb . Dereference ( bc . triegc . PopItem ( ) . ( common . Hash ) )
2018-05-23 22:32:26 -07:00
}
2018-07-24 01:15:38 -07:00
if size , _ := triedb . Size ( ) ; size != 0 {
2018-05-23 22:32:26 -07:00
log . Error ( "Dangling trie nodes after full cleanup" )
}
}
2017-10-31 15:24:11 -07:00
log . Info ( "Blockchain manager stopped" )
2015-03-06 06:50:44 -08:00
}
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) procFutureBlocks ( ) {
blocks := make ( [ ] * types . Block , 0 , bc . futureBlocks . Len ( ) )
for _ , hash := range bc . futureBlocks . Keys ( ) {
if block , exist := bc . futureBlocks . Peek ( hash ) ; exist {
2016-03-08 06:55:27 -08:00
blocks = append ( blocks , block . ( * types . Block ) )
}
2015-06-29 13:42:13 -07:00
}
2015-05-29 09:55:42 -07:00
if len ( blocks ) > 0 {
types . BlockBy ( types . Number ) . Sort ( blocks )
2017-10-31 15:24:11 -07:00
// Insert one by one as chain insertion needs contiguous ancestry between blocks
for i := range blocks {
bc . InsertChain ( blocks [ i : i + 1 ] )
}
2015-05-29 09:55:42 -07:00
}
2015-04-04 07:35:23 -07:00
}
2017-10-31 15:24:11 -07:00
// WriteStatus status of write
2015-12-15 19:26:23 -08:00
type WriteStatus byte
2015-06-29 03:12:30 -07:00
const (
2015-12-15 19:26:23 -08:00
NonStatTy WriteStatus = iota
2015-07-03 02:24:42 -07:00
CanonStatTy
SideStatTy
2015-06-29 03:12:30 -07:00
)
2015-10-09 06:21:47 -07:00
// Rollback is designed to remove a chain of links from the database that aren't
// certain enough to be valid.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) Rollback ( chain [ ] common . Hash ) {
2020-04-29 07:50:56 -07:00
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
2015-10-13 02:04:25 -07:00
2015-10-09 06:21:47 -07:00
for i := len ( chain ) - 1 ; i >= 0 ; i -- {
hash := chain [ i ]
2017-10-31 15:24:11 -07:00
currentHeader := bc . hc . CurrentHeader ( )
2016-04-05 06:22:04 -07:00
if currentHeader . Hash ( ) == hash {
2017-10-31 15:24:11 -07:00
bc . hc . SetCurrentHeader ( bc . GetHeader ( currentHeader . ParentHash , currentHeader . Number . Uint64 ( ) - 1 ) )
2015-10-09 06:21:47 -07:00
}
2018-05-23 22:32:26 -07:00
if currentFastBlock := bc . CurrentFastBlock ( ) ; currentFastBlock . Hash ( ) == hash {
newFastBlock := bc . GetBlock ( currentFastBlock . ParentHash ( ) , currentFastBlock . NumberU64 ( ) - 1 )
rawdb . WriteHeadFastBlockHash ( bc . db , newFastBlock . Hash ( ) )
2020-04-29 07:50:56 -07:00
bc . currentFastBlock . Store ( newFastBlock )
headFastBlockGauge . Update ( int64 ( newFastBlock . NumberU64 ( ) ) )
2015-10-09 06:21:47 -07:00
}
2018-05-23 22:32:26 -07:00
if currentBlock := bc . CurrentBlock ( ) ; currentBlock . Hash ( ) == hash {
newBlock := bc . GetBlock ( currentBlock . ParentHash ( ) , currentBlock . NumberU64 ( ) - 1 )
rawdb . WriteHeadBlockHash ( bc . db , newBlock . Hash ( ) )
2020-04-29 07:50:56 -07:00
bc . currentBlock . Store ( newBlock )
headBlockGauge . Update ( int64 ( newBlock . NumberU64 ( ) ) )
2015-10-09 06:21:47 -07:00
}
}
2020-04-29 07:50:56 -07:00
// Truncate ancient data which exceeds the current header.
//
// Notably, it can happen that system crashes without truncating the ancient data
// but the head indicator has been updated in the active store. Regarding this issue,
// system will self recovery by truncating the extra data during the setup phase.
if err := bc . truncateAncient ( bc . hc . CurrentHeader ( ) . Number . Uint64 ( ) ) ; err != nil {
log . Crit ( "Truncate ancient store failed" , "err" , err )
}
2015-10-09 06:21:47 -07:00
}
2020-04-29 07:50:56 -07:00
// truncateAncient rewinds the blockchain to the specified header and deletes all
// data in the ancient store that exceeds the specified header.
func ( bc * BlockChain ) truncateAncient ( head uint64 ) error {
frozen , err := bc . db . Ancients ( )
if err != nil {
return err
}
// Short circuit if there is no data to truncate in ancient store.
if frozen <= head + 1 {
return nil
2018-05-23 22:32:26 -07:00
}
2020-04-29 07:50:56 -07:00
// Truncate all the data in the freezer beyond the specified head
if err := bc . db . TruncateAncients ( head + 1 ) ; err != nil {
return err
}
// Clear out any stale content from the caches
bc . hc . headerCache . Purge ( )
bc . hc . tdCache . Purge ( )
bc . hc . numberCache . Purge ( )
2015-09-30 09:23:31 -07:00
2020-04-29 07:50:56 -07:00
// Clear out any stale content from the caches
bc . bodyCache . Purge ( )
bc . bodyRLPCache . Purge ( )
bc . receiptsCache . Purge ( )
bc . blockCache . Purge ( )
bc . txLookupCache . Purge ( )
bc . futureBlocks . Purge ( )
2015-09-30 09:23:31 -07:00
2020-04-29 07:50:56 -07:00
log . Info ( "Rewind ancient data" , "number" , head )
2018-05-23 22:32:26 -07:00
return nil
2017-10-31 15:24:11 -07:00
}
2015-10-07 02:14:30 -07:00
2020-04-29 07:50:56 -07:00
// numberHash is just a container for a number and a hash, to represent a block
type numberHash struct {
number uint64
hash common . Hash
}
2017-10-31 15:24:11 -07:00
// InsertReceiptChain attempts to complete an already existing header chain with
// transaction and receipt data.
2020-04-29 07:50:56 -07:00
func ( bc * BlockChain ) InsertReceiptChain ( blockChain types . Blocks , receiptChain [ ] types . Receipts , ancientLimit uint64 ) ( int , error ) {
// We don't require the chainMu here since we want to maximize the
// concurrency of header insertion and receipt insertion.
2017-10-31 15:24:11 -07:00
bc . wg . Add ( 1 )
defer bc . wg . Done ( )
2020-04-29 07:50:56 -07:00
var (
ancientBlocks , liveBlocks types . Blocks
ancientReceipts , liveReceipts [ ] types . Receipts
)
2017-10-31 15:24:11 -07:00
// Do a sanity check that the provided chain is actually ordered and linked
2020-04-29 07:50:56 -07:00
for i := 0 ; i < len ( blockChain ) ; i ++ {
if i != 0 {
if blockChain [ i ] . NumberU64 ( ) != blockChain [ i - 1 ] . NumberU64 ( ) + 1 || blockChain [ i ] . ParentHash ( ) != blockChain [ i - 1 ] . Hash ( ) {
log . Error ( "Non contiguous receipt insert" , "number" , blockChain [ i ] . Number ( ) , "hash" , blockChain [ i ] . Hash ( ) , "parent" , blockChain [ i ] . ParentHash ( ) ,
"prevnumber" , blockChain [ i - 1 ] . Number ( ) , "prevhash" , blockChain [ i - 1 ] . Hash ( ) )
return 0 , fmt . Errorf ( "non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])" , i - 1 , blockChain [ i - 1 ] . NumberU64 ( ) ,
blockChain [ i - 1 ] . Hash ( ) . Bytes ( ) [ : 4 ] , i , blockChain [ i ] . NumberU64 ( ) , blockChain [ i ] . Hash ( ) . Bytes ( ) [ : 4 ] , blockChain [ i ] . ParentHash ( ) . Bytes ( ) [ : 4 ] )
}
}
if blockChain [ i ] . NumberU64 ( ) <= ancientLimit {
ancientBlocks , ancientReceipts = append ( ancientBlocks , blockChain [ i ] ) , append ( ancientReceipts , receiptChain [ i ] )
} else {
liveBlocks , liveReceipts = append ( liveBlocks , blockChain [ i ] ) , append ( liveReceipts , receiptChain [ i ] )
2015-09-30 09:23:31 -07:00
}
2015-10-07 02:14:30 -07:00
}
2017-10-31 15:24:11 -07:00
var (
stats = struct { processed , ignored int32 } { }
start = time . Now ( )
2020-04-29 07:50:56 -07:00
size = 0
2017-10-31 15:24:11 -07:00
)
2020-04-29 07:50:56 -07:00
// updateHead updates the head fast sync block if the inserted blocks are better
// and returns a indicator whether the inserted blocks are canonical.
updateHead := func ( head * types . Block ) bool {
bc . chainmu . Lock ( )
// Rewind may have occurred, skip in that case.
if bc . CurrentHeader ( ) . Number . Cmp ( head . Number ( ) ) >= 0 {
currentFastBlock , td := bc . CurrentFastBlock ( ) , bc . GetTd ( head . Hash ( ) , head . NumberU64 ( ) )
if bc . GetTd ( currentFastBlock . Hash ( ) , currentFastBlock . NumberU64 ( ) ) . Cmp ( td ) < 0 {
rawdb . WriteHeadFastBlockHash ( bc . db , head . Hash ( ) )
bc . currentFastBlock . Store ( head )
headFastBlockGauge . Update ( int64 ( head . NumberU64 ( ) ) )
bc . chainmu . Unlock ( )
return true
}
2017-10-31 15:24:11 -07:00
}
2020-04-29 07:50:56 -07:00
bc . chainmu . Unlock ( )
return false
}
// writeAncient writes blockchain and corresponding receipt chain into ancient store.
//
// this function only accepts canonical chain data. All side chain will be reverted
// eventually.
writeAncient := func ( blockChain types . Blocks , receiptChain [ ] types . Receipts ) ( int , error ) {
var (
previous = bc . CurrentFastBlock ( )
batch = bc . db . NewBatch ( )
)
// If any error occurs before updating the head or we are inserting a side chain,
// all the data written this time wll be rolled back.
defer func ( ) {
if previous != nil {
if err := bc . truncateAncient ( previous . NumberU64 ( ) ) ; err != nil {
log . Crit ( "Truncate ancient store failed" , "err" , err )
}
}
} ( )
var deleted [ ] * numberHash
for i , block := range blockChain {
// Short circuit insertion if shutting down or processing failed
if atomic . LoadInt32 ( & bc . procInterrupt ) == 1 {
return 0 , errInsertionInterrupted
}
// Short circuit insertion if it is required(used in testing only)
if bc . terminateInsert != nil && bc . terminateInsert ( block . Hash ( ) , block . NumberU64 ( ) ) {
return i , errors . New ( "insertion is terminated for testing purpose" )
}
// Short circuit if the owner header is unknown
if ! bc . HasHeader ( block . Hash ( ) , block . NumberU64 ( ) ) {
return i , fmt . Errorf ( "containing header #%d [%x…] unknown" , block . Number ( ) , block . Hash ( ) . Bytes ( ) [ : 4 ] )
}
var (
start = time . Now ( )
logged = time . Now ( )
count int
)
// Migrate all ancient blocks. This can happen if someone upgrades from Geth
// 1.8.x to 1.9.x mid-fast-sync. Perhaps we can get rid of this path in the
// long term.
for {
// We can ignore the error here since light client won't hit this code path.
frozen , _ := bc . db . Ancients ( )
if frozen >= block . NumberU64 ( ) {
break
}
h := rawdb . ReadCanonicalHash ( bc . db , frozen )
b := rawdb . ReadBlock ( bc . db , h , frozen )
size += rawdb . WriteAncientBlock ( bc . db , b , rawdb . ReadReceipts ( bc . db , h , frozen , bc . chainConfig ) , rawdb . ReadTd ( bc . db , h , frozen ) )
count += 1
// Always keep genesis block in active database.
if b . NumberU64 ( ) != 0 {
deleted = append ( deleted , & numberHash { b . NumberU64 ( ) , b . Hash ( ) } )
}
if time . Since ( logged ) > 8 * time . Second {
log . Info ( "Migrating ancient blocks" , "count" , count , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) )
logged = time . Now ( )
}
// Don't collect too much in-memory, write it out every 100K blocks
if len ( deleted ) > 100000 {
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
if err := bc . db . Sync ( ) ; err != nil {
return 0 , err
}
// Wipe out canonical block data.
for _ , nh := range deleted {
rawdb . DeleteBlockWithoutNumber ( batch , nh . hash , nh . number )
rawdb . DeleteCanonicalHash ( batch , nh . number )
}
if err := batch . Write ( ) ; err != nil {
return 0 , err
}
batch . Reset ( )
// Wipe out side chain too.
for _ , nh := range deleted {
for _ , hash := range rawdb . ReadAllHashes ( bc . db , nh . number ) {
rawdb . DeleteBlock ( batch , hash , nh . number )
}
}
if err := batch . Write ( ) ; err != nil {
return 0 , err
}
batch . Reset ( )
deleted = deleted [ 0 : ]
}
}
if count > 0 {
log . Info ( "Migrated ancient blocks" , "count" , count , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) )
}
// Flush data into ancient database.
size += rawdb . WriteAncientBlock ( bc . db , block , receiptChain [ i ] , bc . GetTd ( block . Hash ( ) , block . NumberU64 ( ) ) )
rawdb . WriteTxLookupEntries ( batch , block )
stats . processed ++
2017-10-31 15:24:11 -07:00
}
2020-04-29 07:50:56 -07:00
// Flush all tx-lookup index data.
size += batch . ValueSize ( )
if err := batch . Write ( ) ; err != nil {
return 0 , err
2017-10-31 15:24:11 -07:00
}
2020-04-29 07:50:56 -07:00
batch . Reset ( )
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
if err := bc . db . Sync ( ) ; err != nil {
return 0 , err
2017-10-31 15:24:11 -07:00
}
2020-04-29 07:50:56 -07:00
if ! updateHead ( blockChain [ len ( blockChain ) - 1 ] ) {
return 0 , errors . New ( "side blocks can't be accepted as the ancient chain data" )
}
previous = nil // disable rollback explicitly
2018-05-23 22:32:26 -07:00
2020-04-29 07:50:56 -07:00
// Wipe out canonical block data.
for _ , nh := range deleted {
rawdb . DeleteBlockWithoutNumber ( batch , nh . hash , nh . number )
rawdb . DeleteCanonicalHash ( batch , nh . number )
}
for _ , block := range blockChain {
// Always keep genesis block in active database.
if block . NumberU64 ( ) != 0 {
rawdb . DeleteBlockWithoutNumber ( batch , block . Hash ( ) , block . NumberU64 ( ) )
rawdb . DeleteCanonicalHash ( batch , block . NumberU64 ( ) )
}
}
if err := batch . Write ( ) ; err != nil {
return 0 , err
}
batch . Reset ( )
2017-10-31 15:24:11 -07:00
2020-04-29 07:50:56 -07:00
// Wipe out side chain too.
for _ , nh := range deleted {
for _ , hash := range rawdb . ReadAllHashes ( bc . db , nh . number ) {
rawdb . DeleteBlock ( batch , hash , nh . number )
}
}
for _ , block := range blockChain {
// Always keep genesis block in active database.
if block . NumberU64 ( ) != 0 {
for _ , hash := range rawdb . ReadAllHashes ( bc . db , block . NumberU64 ( ) ) {
rawdb . DeleteBlock ( batch , hash , block . NumberU64 ( ) )
}
2015-09-30 09:23:31 -07:00
}
}
2017-10-31 15:24:11 -07:00
if err := batch . Write ( ) ; err != nil {
return 0 , err
2015-10-07 02:14:30 -07:00
}
2020-04-29 07:50:56 -07:00
return 0 , nil
}
// writeLive writes blockchain and corresponding receipt chain into active store.
writeLive := func ( blockChain types . Blocks , receiptChain [ ] types . Receipts ) ( int , error ) {
batch := bc . db . NewBatch ( )
for i , block := range blockChain {
// Short circuit insertion if shutting down or processing failed
if atomic . LoadInt32 ( & bc . procInterrupt ) == 1 {
return 0 , errInsertionInterrupted
}
// Short circuit if the owner header is unknown
if ! bc . HasHeader ( block . Hash ( ) , block . NumberU64 ( ) ) {
return i , fmt . Errorf ( "containing header #%d [%x…] unknown" , block . Number ( ) , block . Hash ( ) . Bytes ( ) [ : 4 ] )
}
if bc . HasBlock ( block . Hash ( ) , block . NumberU64 ( ) ) {
stats . ignored ++
continue
}
// Write all the data out into the database
rawdb . WriteBody ( batch , block . Hash ( ) , block . NumberU64 ( ) , block . Body ( ) )
rawdb . WriteReceipts ( batch , block . Hash ( ) , block . NumberU64 ( ) , receiptChain [ i ] )
rawdb . WriteTxLookupEntries ( batch , block )
stats . processed ++
if batch . ValueSize ( ) >= ethdb . IdealBatchSize {
if err := batch . Write ( ) ; err != nil {
return 0 , err
}
size += batch . ValueSize ( )
batch . Reset ( )
}
}
if batch . ValueSize ( ) > 0 {
size += batch . ValueSize ( )
if err := batch . Write ( ) ; err != nil {
return 0 , err
}
}
updateHead ( blockChain [ len ( blockChain ) - 1 ] )
return 0 , nil
}
// Write downloaded chain data and corresponding receipt chain data.
if len ( ancientBlocks ) > 0 {
if n , err := writeAncient ( ancientBlocks , ancientReceipts ) ; err != nil {
if err == errInsertionInterrupted {
return 0 , nil
}
return n , err
}
2015-10-07 02:14:30 -07:00
}
2020-04-29 07:50:56 -07:00
if len ( liveBlocks ) > 0 {
if n , err := writeLive ( liveBlocks , liveReceipts ) ; err != nil {
if err == errInsertionInterrupted {
return 0 , nil
}
return n , err
2017-10-31 15:24:11 -07:00
}
2016-10-18 01:18:07 -07:00
}
2015-09-30 09:23:31 -07:00
2020-04-29 07:50:56 -07:00
head := blockChain [ len ( blockChain ) - 1 ]
2018-09-20 01:41:59 -07:00
context := [ ] interface { } {
"count" , stats . processed , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) ,
2020-04-29 07:50:56 -07:00
"number" , head . Number ( ) , "hash" , head . Hash ( ) , "age" , common . PrettyAge ( time . Unix ( int64 ( head . Time ( ) ) , 0 ) ) ,
"size" , common . StorageSize ( size ) ,
2018-09-20 01:41:59 -07:00
}
if stats . ignored > 0 {
context = append ( context , [ ] interface { } { "ignored" , stats . ignored } ... )
}
log . Info ( "Imported new block receipts" , context ... )
2015-09-30 09:23:31 -07:00
return 0 , nil
}
2018-05-23 22:32:26 -07:00
var lastWrite uint64
2020-04-29 07:50:56 -07:00
// writeBlockWithoutState writes only the block and its metadata to the database,
2018-05-23 22:32:26 -07:00
// 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.
2020-04-29 07:50:56 -07:00
func ( bc * BlockChain ) writeBlockWithoutState ( block * types . Block , td * big . Int ) ( err error ) {
2018-05-23 22:32:26 -07:00
bc . wg . Add ( 1 )
defer bc . wg . Done ( )
if err := bc . hc . WriteTd ( block . Hash ( ) , block . NumberU64 ( ) , td ) ; err != nil {
return err
}
rawdb . WriteBlock ( bc . db , block )
return nil
}
2020-04-29 07:50:56 -07:00
// writeKnownBlock updates the head block flag with a known block
// and introduces chain reorg if necessary.
func ( bc * BlockChain ) writeKnownBlock ( block * types . Block ) error {
bc . wg . Add ( 1 )
defer bc . wg . Done ( )
current := bc . CurrentBlock ( )
if block . ParentHash ( ) != current . Hash ( ) {
if err := bc . reorg ( current , block ) ; err != nil {
return err
}
}
// Write the positional metadata for transaction/receipt lookups.
// Preimages here is empty, ignore it.
rawdb . WriteTxLookupEntries ( bc . db , block )
bc . insert ( block )
return nil
}
2018-05-23 22:32:26 -07:00
// WriteBlockWithState writes the block and all associated state to the database.
2018-11-29 01:56:02 -08:00
func ( bc * BlockChain ) WriteBlockWithState ( block * types . Block , receipts [ ] * types . Receipt , state , privateState * state . StateDB ) ( status WriteStatus , err error ) {
2020-04-29 07:50:56 -07:00
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
return bc . writeBlockWithState ( block , receipts , state , privateState )
}
// QUORUM
// checks if the consensus engine is Rfat
2020-05-11 13:15:27 -07:00
func ( bc * BlockChain ) isRaft ( ) bool {
2020-04-29 07:50:56 -07:00
return bc . chainConfig . IsQuorum && bc . chainConfig . Istanbul == nil && bc . chainConfig . Clique == nil
}
// function specifically added for Raft consensus. This is called from mintNewBlock
// to commit public and private state using bc.chainmu lock
// added to avoid concurrent map errors in high stress conditions
func ( bc * BlockChain ) CommitBlockWithState ( deleteEmptyObjects bool , state , privateState * state . StateDB ) error {
// check if consensus is not Raft
if ! bc . isRaft ( ) {
return errors . New ( "error function can be called only for Raft consensus" )
}
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
if _ , err := state . Commit ( deleteEmptyObjects ) ; err != nil {
return fmt . Errorf ( "error committing public state: %v" , err )
}
if _ , err := privateState . Commit ( deleteEmptyObjects ) ; err != nil {
return fmt . Errorf ( "error committing private state: %v" , err )
}
return nil
}
2020-05-11 13:15:27 -07:00
2020-04-29 07:50:56 -07:00
// END QUORUM
// writeBlockWithState writes the block and all associated state to the database,
// but is expects the chain mutex to be held.
func ( bc * BlockChain ) writeBlockWithState ( block * types . Block , receipts [ ] * types . Receipt , state , privateState * state . StateDB ) ( status WriteStatus , err error ) {
2017-10-31 15:24:11 -07:00
bc . wg . Add ( 1 )
defer bc . wg . Done ( )
2015-06-29 03:12:30 -07:00
2015-09-07 10:43:01 -07:00
// Calculate the total difficulty of the block
2017-10-31 15:24:11 -07:00
ptd := bc . GetTd ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
2015-09-07 10:43:01 -07:00
if ptd == nil {
2017-10-31 15:24:11 -07:00
return NonStatTy , consensus . ErrUnknownAncestor
2015-09-07 10:43:01 -07:00
}
2015-09-29 04:24:28 -07:00
// Make sure no inconsistent state is leaked during insertion
2020-02-11 12:21:13 -08:00
// Quorum
// Write private state changes to database
privateRoot , err := privateState . Commit ( bc . chainConfig . IsEIP158 ( block . Number ( ) ) )
if err != nil {
return NonStatTy , err
}
2020-04-29 07:50:56 -07:00
if err := rawdb . WritePrivateStateRoot ( bc . db , block . Root ( ) , privateRoot ) ; err != nil {
2020-02-11 12:21:13 -08:00
log . Error ( "Failed writing private state root" , "err" , err )
return NonStatTy , err
}
// Explicit commit for privateStateTriedb
privateTriedb := bc . privateStateCache . TrieDB ( )
if err := privateTriedb . Commit ( privateRoot , false ) ; err != nil {
return NonStatTy , err
}
// /Quorum
2018-05-23 22:32:26 -07:00
currentBlock := bc . CurrentBlock ( )
localTd := bc . GetTd ( currentBlock . Hash ( ) , currentBlock . NumberU64 ( ) )
2016-07-08 06:59:19 -07:00
externTd := new ( big . Int ) . Add ( block . Difficulty ( ) , ptd )
2016-07-26 07:37:04 -07:00
// Irrelevant of the canonical status, write the block itself to the database
2017-10-31 15:24:11 -07:00
if err := bc . hc . WriteTd ( block . Hash ( ) , block . NumberU64 ( ) , externTd ) ; err != nil {
return NonStatTy , err
2016-07-26 07:37:04 -07:00
}
2018-08-14 08:34:33 -07:00
rawdb . WriteBlock ( bc . db , block )
2018-05-23 22:32:26 -07:00
root , err := state . Commit ( bc . chainConfig . IsEIP158 ( block . Number ( ) ) )
2018-09-13 20:59:10 -07:00
2018-05-23 22:32:26 -07:00
if err != nil {
2017-10-31 15:24:11 -07:00
return NonStatTy , err
}
2018-05-23 22:32:26 -07:00
triedb := bc . stateCache . TrieDB ( )
// If we're running an archive node, always flush
2020-04-29 07:50:56 -07:00
if bc . cacheConfig . TrieDirtyDisabled {
2018-05-23 22:32:26 -07:00
if err := triedb . Commit ( root , false ) ; err != nil {
return NonStatTy , err
}
2018-09-13 20:59:10 -07:00
2018-05-23 22:32:26 -07:00
} else {
// Full but not archive node, do proper garbage collection
triedb . Reference ( root , common . Hash { } ) // metadata reference to keep trie alive
2018-09-03 08:33:21 -07:00
bc . triegc . Push ( root , - int64 ( block . NumberU64 ( ) ) )
2018-05-23 22:32:26 -07:00
2020-04-29 07:50:56 -07:00
if current := block . NumberU64 ( ) ; current > TriesInMemory {
2018-06-04 00:47:43 -07:00
// If we exceeded our memory allowance, flush matured singleton nodes to disk
var (
nodes , imgs = triedb . Size ( )
2020-04-29 07:50:56 -07:00
limit = common . StorageSize ( bc . cacheConfig . TrieDirtyLimit ) * 1024 * 1024
2018-06-04 00:47:43 -07:00
)
if nodes > limit || imgs > 4 * 1024 * 1024 {
triedb . Cap ( limit - ethdb . IdealBatchSize )
}
2018-05-23 22:32:26 -07:00
// Find the next state trie we need to commit
2020-04-29 07:50:56 -07:00
chosen := current - TriesInMemory
2018-05-23 22:32:26 -07:00
2018-06-04 00:47:43 -07:00
// If we exceeded out time allowance, flush an entire trie to disk
if bc . gcproc > bc . cacheConfig . TrieTimeLimit {
2020-04-29 07:50:56 -07:00
// If the header is missing (canonical chain behind), we're reorging a low
// diff sidechain. Suspend committing until this operation is completed.
header := bc . GetHeaderByNumber ( chosen )
if header == nil {
log . Warn ( "Reorg in progress, trie commit postponed" , "number" , chosen )
} else {
// If we're exceeding limits but haven't reached a large enough memory gap,
// warn the user that the system is becoming unstable.
if chosen < lastWrite + TriesInMemory && bc . gcproc >= 2 * bc . cacheConfig . TrieTimeLimit {
log . Info ( "State in memory for too long, committing" , "time" , bc . gcproc , "allowance" , bc . cacheConfig . TrieTimeLimit , "optimum" , float64 ( chosen - lastWrite ) / TriesInMemory )
}
// Flush an entire trie and restart the counters
triedb . Commit ( header . Root , true )
lastWrite = chosen
bc . gcproc = 0
2018-05-23 22:32:26 -07:00
}
}
// Garbage collect anything below our required write retention
for ! bc . triegc . Empty ( ) {
root , number := bc . triegc . Pop ( )
if uint64 ( - number ) > chosen {
bc . triegc . Push ( root , number )
break
}
2018-07-24 01:15:38 -07:00
triedb . Dereference ( root . ( common . Hash ) )
2018-05-23 22:32:26 -07:00
}
}
2016-07-26 07:37:04 -07:00
}
2018-08-14 08:34:33 -07:00
// Write other block data using a batch.
batch := bc . db . NewBatch ( )
2018-05-23 22:32:26 -07:00
rawdb . WriteReceipts ( batch , block . Hash ( ) , block . NumberU64 ( ) , receipts )
2016-07-26 07:37:04 -07:00
2015-09-29 04:24:28 -07:00
// If the total difficulty is higher than our known, add it to the canonical chain
2016-01-12 02:54:29 -08:00
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
2018-05-23 22:32:26 -07:00
reorg := externTd . Cmp ( localTd ) > 0
currentBlock = bc . CurrentBlock ( )
if ! reorg && externTd . Cmp ( localTd ) == 0 {
2018-09-20 05:09:30 -07:00
// Split same-difficulty blocks by number, then preferentially select
// the block generated by the local miner as the canonical block.
if block . NumberU64 ( ) < currentBlock . NumberU64 ( ) {
reorg = true
} else if block . NumberU64 ( ) == currentBlock . NumberU64 ( ) {
2018-09-20 10:02:15 -07:00
var currentPreserve , blockPreserve bool
if bc . shouldPreserve != nil {
currentPreserve , blockPreserve = bc . shouldPreserve ( currentBlock ) , bc . shouldPreserve ( block )
2018-09-20 05:09:30 -07:00
}
2018-09-20 10:02:15 -07:00
reorg = ! currentPreserve && ( blockPreserve || mrand . Float64 ( ) < 0.5 )
2018-09-20 05:09:30 -07:00
}
2018-05-23 22:32:26 -07:00
}
if reorg {
2016-03-15 11:55:39 -07:00
// Reorganise the chain if the parent is not the head block
2018-05-23 22:32:26 -07:00
if block . ParentHash ( ) != currentBlock . Hash ( ) {
if err := bc . reorg ( currentBlock , block ) ; err != nil {
2015-07-03 02:24:42 -07:00
return NonStatTy , err
2015-06-29 03:12:30 -07:00
}
}
2018-05-23 22:32:26 -07:00
// Write the positional metadata for transaction/receipt lookups and preimages
rawdb . WriteTxLookupEntries ( batch , block )
2018-11-09 02:51:07 -08:00
rawdb . WritePreimages ( batch , state . Preimages ( ) )
2018-05-23 22:32:26 -07:00
2015-09-29 04:24:28 -07:00
status = CanonStatTy
2015-06-29 03:12:30 -07:00
} else {
2015-07-03 02:24:42 -07:00
status = SideStatTy
2015-06-29 03:12:30 -07:00
}
2017-10-31 15:24:11 -07:00
if err := batch . Write ( ) ; err != nil {
return NonStatTy , err
}
2016-03-08 06:55:27 -08:00
2017-10-31 15:24:11 -07:00
// Set new head.
if status == CanonStatTy {
bc . insert ( block )
}
bc . futureBlocks . Remove ( block . Hash ( ) )
return status , nil
}
2015-06-29 03:12:30 -07:00
2020-04-29 07:50:56 -07:00
// addFutureBlock checks if the block is within the max allowed window to get
// accepted for future processing, and returns an error if the block is too far
// ahead and was not added.
func ( bc * BlockChain ) addFutureBlock ( block * types . Block ) error {
max := uint64 ( time . Now ( ) . Unix ( ) + maxTimeFutureBlocks )
if block . Time ( ) > max {
return fmt . Errorf ( "future block timestamp %v > allowed %v" , block . Time ( ) , max )
}
bc . futureBlocks . Add ( block . Hash ( ) , block )
return nil
}
2017-10-31 15:24:11 -07:00
// InsertChain attempts to insert the given batch of blocks in to the canonical
// chain or, otherwise, create a fork. If an error is returned it will return
// the index number of the failing block as well an error describing what went
// wrong.
//
// After insertion is done, all accumulated events will be fired.
func ( bc * BlockChain ) InsertChain ( chain types . Blocks ) ( int , error ) {
2020-04-29 07:50:56 -07:00
// Sanity check that we have something meaningful to import
if len ( chain ) == 0 {
return 0 , nil
}
bc . blockProcFeed . Send ( true )
defer bc . blockProcFeed . Send ( false )
// Remove already known canon-blocks
var (
block , prev * types . Block
)
// Do a sanity check that the provided chain is actually ordered and linked
for i := 1 ; i < len ( chain ) ; i ++ {
block = chain [ i ]
prev = chain [ i - 1 ]
if block . NumberU64 ( ) != prev . NumberU64 ( ) + 1 || block . ParentHash ( ) != prev . Hash ( ) {
// Chain broke ancestry, log a message (programming error) and skip insertion
log . Error ( "Non contiguous block insert" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"parent" , block . ParentHash ( ) , "prevnumber" , prev . Number ( ) , "prevhash" , prev . Hash ( ) )
return 0 , fmt . Errorf ( "non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])" , i - 1 , prev . NumberU64 ( ) ,
prev . Hash ( ) . Bytes ( ) [ : 4 ] , i , block . NumberU64 ( ) , block . Hash ( ) . Bytes ( ) [ : 4 ] , block . ParentHash ( ) . Bytes ( ) [ : 4 ] )
}
}
// Pre-checks passed, start the full block imports
bc . wg . Add ( 1 )
bc . chainmu . Lock ( )
n , events , logs , err := bc . insertChain ( chain , true )
bc . chainmu . Unlock ( )
bc . wg . Done ( )
2017-10-31 15:24:11 -07:00
bc . PostChainEvents ( events , logs )
return n , err
2015-06-29 03:12:30 -07:00
}
2018-02-08 07:55:52 -08:00
// Given a slice of public receipts and an overlapping (smaller) slice of
// private receipts, return a new slice where the default for each location is
// the public receipt but we take the private receipt in each place we have
// one.
func mergeReceipts ( pub , priv types . Receipts ) types . Receipts {
m := make ( map [ common . Hash ] * types . Receipt )
for _ , receipt := range pub {
m [ receipt . TxHash ] = receipt
}
for _ , receipt := range priv {
m [ receipt . TxHash ] = receipt
}
ret := make ( types . Receipts , 0 , len ( pub ) )
for _ , pubReceipt := range pub {
ret = append ( ret , m [ pubReceipt . TxHash ] )
}
return ret
}
2020-04-29 07:50:56 -07:00
// insertChain is the internal implementation of InsertChain, which assumes that
// 1) chains are contiguous, and 2) The chain mutex is held.
//
// This method is split out so that import batches that require re-injecting
// historical blocks can do so without releasing the lock, which could lead to
// racey behaviour. If a sidechain import is in progress, and the historic state
// is imported, but then new canon-head is added before the actual sidechain
// completes, then the historic state could be pruned again
func ( bc * BlockChain ) insertChain ( chain types . Blocks , verifySeals bool ) ( int , [ ] interface { } , [ ] * types . Log , error ) {
// If the chain is terminating, don't even bother starting up
if atomic . LoadInt32 ( & bc . procInterrupt ) == 1 {
2020-05-12 12:32:50 -07:00
log . Debug ( "Premature abort during blocks processing" )
// QUORUM
if bc . isRaft ( ) {
// Only returns an error for raft mode
return 0 , nil , nil , ErrAbortBlocksProcessing
}
2018-06-04 04:09:16 -07:00
return 0 , nil , nil , nil
}
2020-04-29 07:50:56 -07:00
// Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
senderCacher . recoverFromBlocks ( types . MakeSigner ( bc . chainConfig , chain [ 0 ] . Number ( ) ) , chain )
2015-05-16 15:55:02 -07:00
2015-05-29 09:07:23 -07:00
// A queued approach to delivering events. This is generally
// faster than direct delivery and requires much less mutex
// acquiring.
2015-04-04 14:04:19 -07:00
var (
2017-10-31 15:24:11 -07:00
stats = insertStats { startTime : mclock . Now ( ) }
2015-10-19 07:08:17 -07:00
events = make ( [ ] interface { } , 0 , len ( chain ) )
2017-10-31 15:24:11 -07:00
lastCanon * types . Block
coalescedLogs [ ] * types . Log
2015-04-04 14:04:19 -07:00
)
2017-10-31 15:24:11 -07:00
// Start the parallel header verifier
headers := make ( [ ] * types . Header , len ( chain ) )
seals := make ( [ ] bool , len ( chain ) )
for i , block := range chain {
headers [ i ] = block . Header ( )
2020-04-29 07:50:56 -07:00
seals [ i ] = verifySeals
2017-10-31 15:24:11 -07:00
}
abort , results := bc . engine . VerifyHeaders ( bc , headers , seals )
defer close ( abort )
2015-05-16 16:42:30 -07:00
2020-04-29 07:50:56 -07:00
// Peek the error for the first block to decide the directing import logic
it := newInsertIterator ( chain , results , bc . validator )
2018-06-04 04:09:16 -07:00
2020-04-29 07:50:56 -07:00
block , err := it . next ( )
// Left-trim all the known blocks
if err == ErrKnownBlock {
// First block (and state) is known
// 1. We did a roll-back, and should now do a re-import
// 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
// from the canonical chain, which has not been verified.
// Skip all known blocks that are behind us
var (
current = bc . CurrentBlock ( )
localTd = bc . GetTd ( current . Hash ( ) , current . NumberU64 ( ) )
externTd = bc . GetTd ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 ) // The first block can't be nil
)
for block != nil && err == ErrKnownBlock {
externTd = new ( big . Int ) . Add ( externTd , block . Difficulty ( ) )
if localTd . Cmp ( externTd ) < 0 {
break
}
log . Debug ( "Ignoring already known block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) )
stats . ignored ++
block , err = it . next ( )
}
// The remaining blocks are still known blocks, the only scenario here is:
// During the fast sync, the pivot point is already submitted but rollback
// happens. Then node resets the head full block to a lower height via `rollback`
// and leaves a few known blocks in the database.
//
// When node runs a fast sync again, it can re-import a batch of known blocks via
// `insertChain` while a part of them have higher total difficulty than current
// head full block(new pivot point).
for block != nil && err == ErrKnownBlock {
log . Debug ( "Writing previously known block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) )
if err := bc . writeKnownBlock ( block ) ; err != nil {
return it . index , nil , nil , err
}
lastCanon = block
block , err = it . next ( )
}
// Falls through to the block import
}
switch {
// First block is pruned, insert as sidechain and reorg only if TD grows enough
case err == consensus . ErrPrunedAncestor :
log . Debug ( "Pruned ancestor, inserting as sidechain" , "number" , block . Number ( ) , "hash" , block . Hash ( ) )
return bc . insertSideChain ( block , it )
// First block is future, shove it (and all children) to the future queue (unknown ancestor)
case err == consensus . ErrFutureBlock || ( err == consensus . ErrUnknownAncestor && bc . futureBlocks . Contains ( it . first ( ) . ParentHash ( ) ) ) :
for block != nil && ( it . index == 0 || err == consensus . ErrUnknownAncestor ) {
log . Debug ( "Future block, postponing import" , "number" , block . Number ( ) , "hash" , block . Hash ( ) )
if err := bc . addFutureBlock ( block ) ; err != nil {
return it . index , events , coalescedLogs , err
}
block , err = it . next ( )
}
stats . queued += it . processed ( )
stats . ignored += it . remaining ( )
// If there are any still remaining, mark as ignored
return it . index , events , coalescedLogs , err
// Some other error occurred, abort
case err != nil :
bc . futureBlocks . Remove ( block . Hash ( ) )
stats . ignored += len ( it . chain )
bc . reportBlock ( block , nil , err )
return it . index , events , coalescedLogs , err
}
// No validation errors for the first block (or chain prefix skipped)
for ; block != nil && err == nil || err == ErrKnownBlock ; block , err = it . next ( ) {
2017-10-31 15:24:11 -07:00
// If the chain is terminating, stop processing blocks
if atomic . LoadInt32 ( & bc . procInterrupt ) == 1 {
log . Debug ( "Premature abort during blocks processing" )
2019-11-29 11:13:37 -08:00
// QUORUM
2020-04-29 07:50:56 -07:00
if bc . isRaft ( ) {
2019-11-29 11:13:37 -08:00
// Only returns an error for raft mode
2020-04-29 07:50:56 -07:00
return it . index , events , coalescedLogs , ErrAbortBlocksProcessing
2019-11-29 11:13:37 -08:00
}
// END QUORUM
2015-06-12 07:45:53 -07:00
break
}
2017-10-31 15:24:11 -07:00
// If the header is a banned one, straight out abort
if BadHashes [ block . Hash ( ) ] {
bc . reportBlock ( block , nil , ErrBlacklistedHash )
2020-04-29 07:50:56 -07:00
return it . index , events , coalescedLogs , ErrBlacklistedHash
2015-06-12 07:45:53 -07:00
}
2020-04-29 07:50:56 -07:00
// If the block is known (in the middle of the chain), it's a special case for
// Clique blocks where they can share state among each other, so importing an
// older block might complete the state of the subsequent one. In this case,
// just skip the block (we already validated it once fully (and crashed), since
// its header and body was already in the database).
if err == ErrKnownBlock {
logger := log . Debug
if bc . chainConfig . Clique == nil {
logger = log . Warn
2015-06-12 07:45:53 -07:00
}
2020-04-29 07:50:56 -07:00
logger ( "Inserted known block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"uncles" , len ( block . Uncles ( ) ) , "txs" , len ( block . Transactions ( ) ) , "gas" , block . GasUsed ( ) ,
"root" , block . Root ( ) )
2015-04-04 07:35:23 -07:00
2020-04-29 07:50:56 -07:00
if err := bc . writeKnownBlock ( block ) ; err != nil {
return it . index , nil , nil , err
2015-06-12 07:45:53 -07:00
}
2020-04-29 07:50:56 -07:00
stats . processed ++
2015-04-04 14:04:19 -07:00
2020-04-29 07:50:56 -07:00
// We can assume that logs are empty here, since the only way for consecutive
// Clique blocks to have the same state is if there are no transactions.
events = append ( events , ChainEvent { block , block . Hash ( ) , nil } )
lastCanon = block
2015-04-20 03:01:20 -07:00
2020-04-29 07:50:56 -07:00
continue
2016-10-31 04:46:40 -07:00
}
2020-04-29 07:50:56 -07:00
// Retrieve the parent block and it's state to execute on top
start := time . Now ( )
2018-05-29 06:05:18 -07:00
2020-04-29 07:50:56 -07:00
parent := it . previous ( )
if parent == nil {
parent = bc . GetHeader ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
}
2018-05-29 06:05:18 -07:00
// alias state.New because we introduce a variable named state on the next line
stateNew := state . New
2020-04-29 07:50:56 -07:00
statedb , err := state . New ( parent . Root , bc . stateCache )
2016-10-31 04:46:40 -07:00
if err != nil {
2020-04-29 07:50:56 -07:00
return it . index , events , coalescedLogs , err
2016-05-19 03:24:14 -07:00
}
2017-10-31 15:24:11 -07:00
// Quorum
2020-04-29 07:50:56 -07:00
privateStateRoot := rawdb . GetPrivateStateRoot ( bc . db , parent . Root )
2017-10-31 15:24:11 -07:00
privateState , err := stateNew ( privateStateRoot , bc . privateStateCache )
2015-10-19 07:08:17 -07:00
if err != nil {
2020-04-29 07:50:56 -07:00
return it . index , events , coalescedLogs , err
2015-06-12 07:45:53 -07:00
}
2017-10-31 15:24:11 -07:00
// /Quorum
2020-04-29 07:50:56 -07:00
// If we have a followup block, run that against the current state to pre-cache
// transactions and probabilistically some of the account/storage trie nodes.
var followupInterrupt uint32
if ! bc . cacheConfig . TrieCleanNoPrefetch {
if followup , err := it . peek ( ) ; followup != nil && err == nil {
go func ( start time . Time ) {
throwaway , _ := state . New ( parent . Root , bc . stateCache )
privatest , _ := stateNew ( privateStateRoot , bc . privateStateCache )
bc . prefetcher . Prefetch ( followup , throwaway , privatest , bc . vmConfig , & followupInterrupt )
blockPrefetchExecuteTimer . Update ( time . Since ( start ) )
if atomic . LoadUint32 ( & followupInterrupt ) == 1 {
blockPrefetchInterruptMeter . Mark ( 1 )
}
} ( time . Now ( ) )
}
}
// Process block using the parent state as reference point
substart := time . Now ( )
receipts , privateReceipts , logs , usedGas , err := bc . processor . Process ( block , statedb , privateState , bc . vmConfig )
2015-10-19 07:08:17 -07:00
if err != nil {
2017-10-31 15:24:11 -07:00
bc . reportBlock ( block , receipts , err )
2020-04-29 07:50:56 -07:00
atomic . StoreUint32 ( & followupInterrupt , 1 )
return it . index , events , coalescedLogs , err
2015-10-19 07:08:17 -07:00
}
2020-04-29 07:50:56 -07:00
// Update the metrics touched during block processing
accountReadTimer . Update ( statedb . AccountReads ) // Account reads are complete, we can mark them
storageReadTimer . Update ( statedb . StorageReads ) // Storage reads are complete, we can mark them
accountUpdateTimer . Update ( statedb . AccountUpdates ) // Account updates are complete, we can mark them
storageUpdateTimer . Update ( statedb . StorageUpdates ) // Storage updates are complete, we can mark them
triehash := statedb . AccountHashes + statedb . StorageHashes // Save to not double count in validation
trieproc := statedb . AccountReads + statedb . AccountUpdates
trieproc += statedb . StorageReads + statedb . StorageUpdates
blockExecutionTimer . Update ( time . Since ( substart ) - trieproc - triehash )
2015-10-19 07:08:17 -07:00
// Validate the state using the default validator
2020-04-29 07:50:56 -07:00
substart = time . Now ( )
if err := bc . validator . ValidateState ( block , bc . GetBlockByHash ( parent . Hash ( ) ) , statedb , receipts , usedGas ) ; err != nil {
2017-10-31 15:24:11 -07:00
bc . reportBlock ( block , receipts , err )
2020-04-29 07:50:56 -07:00
atomic . StoreUint32 ( & followupInterrupt , 1 )
return it . index , events , coalescedLogs , err
2015-10-19 07:08:17 -07:00
}
2018-02-08 07:55:52 -08:00
allReceipts := mergeReceipts ( receipts , privateReceipts )
2020-04-29 07:50:56 -07:00
proctime := time . Since ( start )
// Update the metrics touched during block validation
accountHashTimer . Update ( statedb . AccountHashes ) // Account hashes are complete, we can mark them
storageHashTimer . Update ( statedb . StorageHashes ) // Storage hashes are complete, we can mark them
blockValidationTimer . Update ( time . Since ( substart ) - ( statedb . AccountHashes + statedb . StorageHashes - triehash ) )
2018-05-23 22:32:26 -07:00
2017-10-31 15:24:11 -07:00
// Write the block to the chain and get the status.
2020-04-29 07:50:56 -07:00
substart = time . Now ( )
status , err := bc . writeBlockWithState ( block , allReceipts , statedb , privateState )
2015-06-29 03:12:30 -07:00
if err != nil {
2020-04-29 07:50:56 -07:00
atomic . StoreUint32 ( & followupInterrupt , 1 )
return it . index , events , coalescedLogs , err
2015-06-29 03:12:30 -07:00
}
2020-04-29 07:50:56 -07:00
atomic . StoreUint32 ( & followupInterrupt , 1 )
if err := rawdb . WritePrivateBlockBloom ( bc . db , block . NumberU64 ( ) , privateReceipts ) ; err != nil {
return it . index , events , coalescedLogs , err
2018-02-08 07:59:24 -08:00
}
2020-04-29 07:50:56 -07:00
// Update the metrics touched during block commit
accountCommitTimer . Update ( statedb . AccountCommits ) // Account commits are complete, we can mark them
storageCommitTimer . Update ( statedb . StorageCommits ) // Storage commits are complete, we can mark them
blockWriteTimer . Update ( time . Since ( substart ) - statedb . AccountCommits - statedb . StorageCommits )
blockInsertTimer . UpdateSince ( start )
2015-06-29 03:12:30 -07:00
switch status {
2015-07-03 02:24:42 -07:00
case CanonStatTy :
2020-04-29 07:50:56 -07:00
log . Debug ( "Inserted new block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"uncles" , len ( block . Uncles ( ) ) , "txs" , len ( block . Transactions ( ) ) , "gas" , block . GasUsed ( ) ,
"elapsed" , common . PrettyDuration ( time . Since ( start ) ) ,
"root" , block . Root ( ) )
2017-10-31 15:24:11 -07:00
coalescedLogs = append ( coalescedLogs , logs ... )
2015-10-12 05:04:38 -07:00
events = append ( events , ChainEvent { block , block . Hash ( ) , logs } )
2017-10-31 15:24:11 -07:00
lastCanon = block
2015-07-03 02:24:42 -07:00
2018-05-23 22:32:26 -07:00
// Only count canonical blocks for GC processing time
bc . gcproc += proctime
2015-07-03 02:24:42 -07:00
case SideStatTy :
2020-04-29 07:50:56 -07:00
log . Debug ( "Inserted forked block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"diff" , block . Difficulty ( ) , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) ,
"txs" , len ( block . Transactions ( ) ) , "gas" , block . GasUsed ( ) , "uncles" , len ( block . Uncles ( ) ) ,
"root" , block . Root ( ) )
2017-10-31 15:24:11 -07:00
events = append ( events , ChainSideEvent { block } )
2020-04-29 07:50:56 -07:00
default :
// This in theory is impossible, but lets be nice to our future selves and leave
// a log, instead of trying to track down blocks imports that don't emit logs.
log . Warn ( "Inserted block with unknown status" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"diff" , block . Difficulty ( ) , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) ,
"txs" , len ( block . Transactions ( ) ) , "gas" , block . GasUsed ( ) , "uncles" , len ( block . Uncles ( ) ) ,
"root" , block . Root ( ) )
2015-06-12 04:36:38 -07:00
}
2015-06-12 07:45:53 -07:00
stats . processed ++
2018-05-23 22:32:26 -07:00
stats . usedGas += usedGas
2018-06-04 00:47:43 -07:00
2020-04-29 07:50:56 -07:00
dirty , _ := bc . stateCache . TrieDB ( ) . Size ( )
stats . report ( chain , it . index , dirty )
2014-11-04 03:46:33 -08:00
}
2020-04-29 07:50:56 -07:00
// Any blocks remaining here? The only ones we care about are the future ones
if block != nil && err == consensus . ErrFutureBlock {
if err := bc . addFutureBlock ( block ) ; err != nil {
return it . index , events , coalescedLogs , err
}
block , err = it . next ( )
for ; block != nil && err == consensus . ErrUnknownAncestor ; block , err = it . next ( ) {
if err := bc . addFutureBlock ( block ) ; err != nil {
return it . index , events , coalescedLogs , err
}
stats . queued ++
}
}
stats . ignored += it . remaining ( )
2017-10-31 15:24:11 -07:00
// Append a single chain head event if we've progressed the chain
2018-05-23 22:32:26 -07:00
if lastCanon != nil && bc . CurrentBlock ( ) . Hash ( ) == lastCanon . Hash ( ) {
2017-10-31 15:24:11 -07:00
events = append ( events , ChainHeadEvent { lastCanon } )
}
2020-04-29 07:50:56 -07:00
return it . index , events , coalescedLogs , err
2014-11-17 03:12:55 -08:00
}
2015-01-02 03:07:54 -08:00
2020-04-29 07:50:56 -07:00
// insertSideChain is called when an import batch hits upon a pruned ancestor
// error, which happens when a sidechain with a sufficiently old fork-block is
// found.
//
// The method writes all (header-and-body-valid) blocks to disk, then tries to
// switch over to the new chain if the TD exceeded the current chain.
func ( bc * BlockChain ) insertSideChain ( block * types . Block , it * insertIterator ) ( int , [ ] interface { } , [ ] * types . Log , error ) {
2016-10-18 01:18:07 -07:00
var (
2020-04-29 07:50:56 -07:00
externTd * big . Int
current = bc . CurrentBlock ( )
2016-10-18 01:18:07 -07:00
)
2020-04-29 07:50:56 -07:00
// The first sidechain block error is already verified to be ErrPrunedAncestor.
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining
// ones. Any other errors means that the block is invalid, and should not be written
// to disk.
err := consensus . ErrPrunedAncestor
for ; block != nil && ( err == consensus . ErrPrunedAncestor ) ; block , err = it . next ( ) {
// Check the canonical state root for that number
if number := block . NumberU64 ( ) ; current . NumberU64 ( ) >= number {
canonical := bc . GetBlockByNumber ( number )
if canonical != nil && canonical . Hash ( ) == block . Hash ( ) {
// Not a sidechain block, this is a re-import of a canon block which has it's state pruned
// Collect the TD of the block. Since we know it's a canon one,
// we can get it directly, and not (like further below) use
// the parent and then add the block on top
externTd = bc . GetTd ( block . Hash ( ) , block . NumberU64 ( ) )
continue
}
if canonical != nil && canonical . Root ( ) == block . Root ( ) {
// This is most likely a shadow-state attack. When a fork is imported into the
// database, and it eventually reaches a block height which is not pruned, we
// just found that the state already exist! This means that the sidechain block
// refers to a state which already exists in our canon chain.
//
// If left unchecked, we would now proceed importing the blocks, without actually
// having verified the state of the previous blocks.
log . Warn ( "Sidechain ghost-state attack detected" , "number" , block . NumberU64 ( ) , "sideroot" , block . Root ( ) , "canonroot" , canonical . Root ( ) )
// If someone legitimately side-mines blocks, they would still be imported as usual. However,
// we cannot risk writing unverified blocks to disk when they obviously target the pruning
// mechanism.
return it . index , nil , nil , errors . New ( "sidechain ghost-state attack" )
}
2016-10-18 01:18:07 -07:00
}
2020-04-29 07:50:56 -07:00
if externTd == nil {
externTd = bc . GetTd ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
2018-09-20 01:41:59 -07:00
}
2020-04-29 07:50:56 -07:00
externTd = new ( big . Int ) . Add ( externTd , block . Difficulty ( ) )
2018-09-20 01:41:59 -07:00
2020-04-29 07:50:56 -07:00
if ! bc . HasBlock ( block . Hash ( ) , block . NumberU64 ( ) ) {
start := time . Now ( )
if err := bc . writeBlockWithoutState ( block , externTd ) ; err != nil {
return it . index , nil , nil , err
}
log . Debug ( "Injected sidechain block" , "number" , block . Number ( ) , "hash" , block . Hash ( ) ,
"diff" , block . Difficulty ( ) , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) ,
"txs" , len ( block . Transactions ( ) ) , "gas" , block . GasUsed ( ) , "uncles" , len ( block . Uncles ( ) ) ,
"root" , block . Root ( ) )
2017-10-31 15:24:11 -07:00
}
2020-04-29 07:50:56 -07:00
}
// At this point, we've written all sidechain blocks to database. Loop ended
// either on some other error or all were processed. If there was some other
// error, we can ignore the rest of those blocks.
//
// If the externTd was larger than our local TD, we now need to reimport the previous
// blocks to regenerate the required state
localTd := bc . GetTd ( current . Hash ( ) , current . NumberU64 ( ) )
if localTd . Cmp ( externTd ) > 0 {
log . Info ( "Sidechain written to disk" , "start" , it . first ( ) . NumberU64 ( ) , "end" , it . previous ( ) . Number , "sidetd" , externTd , "localtd" , localTd )
return it . index , nil , nil , err
}
// Gather all the sidechain hashes (full blocks may be memory heavy)
var (
hashes [ ] common . Hash
numbers [ ] uint64
)
parent := it . previous ( )
for parent != nil && ! bc . HasState ( parent . Root ) {
hashes = append ( hashes , parent . Hash ( ) )
numbers = append ( numbers , parent . Number . Uint64 ( ) )
2016-10-18 01:18:07 -07:00
2020-04-29 07:50:56 -07:00
parent = bc . GetHeader ( parent . ParentHash , parent . Number . Uint64 ( ) - 1 )
2016-10-07 05:25:01 -07:00
}
2020-04-29 07:50:56 -07:00
if parent == nil {
return it . index , nil , nil , errors . New ( "missing parent" )
}
// Import all the pruned blocks to make the state available
var (
blocks [ ] * types . Block
memory common . StorageSize
)
for i := len ( hashes ) - 1 ; i >= 0 ; i -- {
// Append the next block to our batch
block := bc . GetBlock ( hashes [ i ] , numbers [ i ] )
2016-10-07 05:25:01 -07:00
2020-04-29 07:50:56 -07:00
blocks = append ( blocks , block )
memory += block . Size ( )
// If memory use grew too large, import and continue. Sadly we need to discard
// all raised events and logs from notifications since we're too heavy on the
// memory here.
if len ( blocks ) >= 2048 || memory > 64 * 1024 * 1024 {
log . Info ( "Importing heavy sidechain segment" , "blocks" , len ( blocks ) , "start" , blocks [ 0 ] . NumberU64 ( ) , "end" , block . NumberU64 ( ) )
if _ , _ , _ , err := bc . insertChain ( blocks , false ) ; err != nil {
return 0 , nil , nil , err
}
blocks , memory = blocks [ : 0 ] , 0
// If the chain is terminating, stop processing blocks
if atomic . LoadInt32 ( & bc . procInterrupt ) == 1 {
log . Debug ( "Premature abort during blocks processing" )
return 0 , nil , nil , nil
}
}
2016-10-07 05:25:01 -07:00
}
2020-04-29 07:50:56 -07:00
if len ( blocks ) > 0 {
log . Info ( "Importing sidechain segment" , "start" , blocks [ 0 ] . NumberU64 ( ) , "end" , blocks [ len ( blocks ) - 1 ] . NumberU64 ( ) )
return bc . insertChain ( blocks , false )
}
return 0 , nil , nil , nil
2016-10-07 05:25:01 -07:00
}
2020-04-29 07:50:56 -07:00
// reorg takes two blocks, an old chain and a new chain and will reconstruct the
// blocks and inserts them to be part of the new canonical chain and accumulates
// potential missing transactions and post an event about them.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) reorg ( oldBlock , newBlock * types . Block ) error {
2015-05-13 13:27:18 -07:00
var (
2017-10-31 15:24:11 -07:00
newChain types . Blocks
oldChain types . Blocks
commonBlock * types . Block
2020-04-29 07:50:56 -07:00
deletedTxs types . Transactions
addedTxs types . Transactions
2017-10-31 15:24:11 -07:00
deletedLogs [ ] * types . Log
2020-04-29 07:50:56 -07:00
rebirthLogs [ ] * types . Log
2015-11-30 15:11:24 -08:00
// collectLogs collects the logs that were generated during the
// processing of the block that corresponds with the given hash.
2020-04-29 07:50:56 -07:00
// These logs are later announced as deleted or reborn
collectLogs = func ( hash common . Hash , removed bool ) {
2018-05-23 22:32:26 -07:00
number := bc . hc . GetBlockNumber ( hash )
if number == nil {
return
}
2020-04-29 07:50:56 -07:00
receipts := rawdb . ReadReceipts ( bc . db , hash , * number , bc . chainConfig )
2015-11-30 15:11:24 -08:00
for _ , receipt := range receipts {
2017-10-31 15:24:11 -07:00
for _ , log := range receipt . Logs {
2020-04-29 07:50:56 -07:00
l := * log
if removed {
l . Removed = true
deletedLogs = append ( deletedLogs , & l )
} else {
rebirthLogs = append ( rebirthLogs , & l )
}
2017-10-31 15:24:11 -07:00
}
2015-11-30 15:11:24 -08:00
}
}
2015-05-13 13:27:18 -07:00
)
2020-04-29 07:50:56 -07:00
// Reduce the longer chain to the same number as the shorter one
2015-05-15 06:30:34 -07:00
if oldBlock . NumberU64 ( ) > newBlock . NumberU64 ( ) {
2020-04-29 07:50:56 -07:00
// Old chain is longer, gather all transactions and logs as deleted ones
2017-10-31 15:24:11 -07:00
for ; oldBlock != nil && oldBlock . NumberU64 ( ) != newBlock . NumberU64 ( ) ; oldBlock = bc . GetBlock ( oldBlock . ParentHash ( ) , oldBlock . NumberU64 ( ) - 1 ) {
2016-03-07 09:11:52 -08:00
oldChain = append ( oldChain , oldBlock )
2015-08-17 05:01:41 -07:00
deletedTxs = append ( deletedTxs , oldBlock . Transactions ( ) ... )
2020-04-29 07:50:56 -07:00
collectLogs ( oldBlock . Hash ( ) , true )
2015-05-15 06:30:34 -07:00
}
} else {
2020-04-29 07:50:56 -07:00
// New chain is longer, stash all blocks away for subsequent insertion
2017-10-31 15:24:11 -07:00
for ; newBlock != nil && newBlock . NumberU64 ( ) != oldBlock . NumberU64 ( ) ; newBlock = bc . GetBlock ( newBlock . ParentHash ( ) , newBlock . NumberU64 ( ) - 1 ) {
2015-05-15 06:30:34 -07:00
newChain = append ( newChain , newBlock )
}
2015-04-29 03:43:24 -07:00
}
2015-05-28 09:18:23 -07:00
if oldBlock == nil {
2020-04-29 07:50:56 -07:00
return fmt . Errorf ( "invalid old chain" )
2015-05-28 09:18:23 -07:00
}
if newBlock == nil {
2020-04-29 07:50:56 -07:00
return fmt . Errorf ( "invalid new chain" )
2015-05-28 09:18:23 -07:00
}
2020-04-29 07:50:56 -07:00
// Both sides of the reorg are at the same number, reduce both until the common
// ancestor is found
2015-04-13 15:18:38 -07:00
for {
2020-04-29 07:50:56 -07:00
// If the common ancestor was found, bail out
2015-04-13 15:18:38 -07:00
if oldBlock . Hash ( ) == newBlock . Hash ( ) {
2015-05-13 13:27:18 -07:00
commonBlock = oldBlock
2015-04-13 15:18:38 -07:00
break
}
2020-04-29 07:50:56 -07:00
// Remove an old block as well as stash away a new block
2016-03-07 09:11:52 -08:00
oldChain = append ( oldChain , oldBlock )
2015-08-17 05:01:41 -07:00
deletedTxs = append ( deletedTxs , oldBlock . Transactions ( ) ... )
2020-04-29 07:50:56 -07:00
collectLogs ( oldBlock . Hash ( ) , true )
newChain = append ( newChain , newBlock )
2015-04-29 03:43:24 -07:00
2020-04-29 07:50:56 -07:00
// Step back with both chains
oldBlock = bc . GetBlock ( oldBlock . ParentHash ( ) , oldBlock . NumberU64 ( ) - 1 )
2015-05-28 06:35:50 -07:00
if oldBlock == nil {
2020-04-29 07:50:56 -07:00
return fmt . Errorf ( "invalid old chain" )
2015-05-28 06:35:50 -07:00
}
2020-04-29 07:50:56 -07:00
newBlock = bc . GetBlock ( newBlock . ParentHash ( ) , newBlock . NumberU64 ( ) - 1 )
2015-05-28 06:35:50 -07:00
if newBlock == nil {
2020-04-29 07:50:56 -07:00
return fmt . Errorf ( "invalid new chain" )
2015-05-28 06:35:50 -07:00
}
2015-04-13 15:18:38 -07:00
}
2017-10-31 15:24:11 -07:00
// Ensure the user sees large reorgs
if len ( oldChain ) > 0 && len ( newChain ) > 0 {
2020-04-29 07:50:56 -07:00
logFn := log . Info
msg := "Chain reorg detected"
2017-10-31 15:24:11 -07:00
if len ( oldChain ) > 63 {
2020-04-29 07:50:56 -07:00
msg = "Large chain reorg detected"
2017-10-31 15:24:11 -07:00
logFn = log . Warn
}
2020-04-29 07:50:56 -07:00
logFn ( msg , "number" , commonBlock . Number ( ) , "hash" , commonBlock . Hash ( ) ,
2017-10-31 15:24:11 -07:00
"drop" , len ( oldChain ) , "dropfrom" , oldChain [ 0 ] . Hash ( ) , "add" , len ( newChain ) , "addfrom" , newChain [ 0 ] . Hash ( ) )
2020-04-29 07:50:56 -07:00
blockReorgAddMeter . Mark ( int64 ( len ( newChain ) ) )
blockReorgDropMeter . Mark ( int64 ( len ( oldChain ) ) )
2017-10-31 15:24:11 -07:00
} else {
log . Error ( "Impossible reorg, please file an issue" , "oldnum" , oldBlock . Number ( ) , "oldhash" , oldBlock . Hash ( ) , "newnum" , newBlock . Number ( ) , "newhash" , newBlock . Hash ( ) )
2015-05-13 13:27:18 -07:00
}
2020-04-29 07:50:56 -07:00
// Insert the new chain(except the head block(reverse order)),
// taking care of the proper incremental order.
for i := len ( newChain ) - 1 ; i >= 1 ; i -- {
// Insert the block in the canonical way, re-writing history
2018-05-23 22:32:26 -07:00
bc . insert ( newChain [ i ] )
2020-04-29 07:50:56 -07:00
// Collect reborn logs due to chain reorg
collectLogs ( newChain [ i ] . Hash ( ) , false )
// Write lookup entries for hash based transaction/receipt searches
2018-05-23 22:32:26 -07:00
rawdb . WriteTxLookupEntries ( bc . db , newChain [ i ] )
addedTxs = append ( addedTxs , newChain [ i ] . Transactions ( ) ... )
2015-08-17 05:01:41 -07:00
}
2020-04-29 07:50:56 -07:00
// When transactions get deleted from the database, the receipts that were
// created in the fork must also be deleted
2018-07-02 01:16:30 -07:00
batch := bc . db . NewBatch ( )
2020-04-29 07:50:56 -07:00
for _ , tx := range types . TxDifference ( deletedTxs , addedTxs ) {
2018-07-02 01:16:30 -07:00
rawdb . DeleteTxLookupEntry ( batch , tx . Hash ( ) )
2015-11-30 15:11:24 -08:00
}
2020-04-29 07:50:56 -07:00
// Delete any canonical number assignments above the new head
number := bc . CurrentBlock ( ) . NumberU64 ( )
for i := number + 1 ; ; i ++ {
hash := rawdb . ReadCanonicalHash ( bc . db , i )
if hash == ( common . Hash { } ) {
break
}
rawdb . DeleteCanonicalHash ( batch , i )
}
2018-07-02 01:16:30 -07:00
batch . Write ( )
2020-04-29 07:50:56 -07:00
// If any logs need to be fired, do it now. In theory we could avoid creating
// this goroutine if there are no events to fire, but realistcally that only
// ever happens if we're reorging empty blocks, which will only happen on idle
// networks where performance is not an issue either way.
//
// TODO(karalabe): Can we get rid of the goroutine somehow to guarantee correct
// event ordering?
go func ( ) {
if len ( deletedLogs ) > 0 {
bc . rmLogsFeed . Send ( RemovedLogsEvent { deletedLogs } )
}
if len ( rebirthLogs ) > 0 {
bc . logsFeed . Send ( rebirthLogs )
}
if len ( oldChain ) > 0 {
2016-03-07 09:11:52 -08:00
for _ , block := range oldChain {
2017-10-31 15:24:11 -07:00
bc . chainSideFeed . Send ( ChainSideEvent { Block : block } )
2016-03-07 09:11:52 -08:00
}
2020-04-29 07:50:56 -07:00
}
} ( )
2015-05-28 06:35:50 -07:00
return nil
2015-04-13 15:18:38 -07:00
}
2017-10-31 15:24:11 -07:00
// PostChainEvents iterates over the events generated by a chain insertion and
// posts them into the event feed.
// TODO: Should not expose PostChainEvents. The chain events should be posted in WriteBlock.
func ( bc * BlockChain ) PostChainEvents ( events [ ] interface { } , logs [ ] * types . Log ) {
// post event logs for further processing
if logs != nil {
bc . logsFeed . Send ( logs )
2017-03-27 14:15:24 -07:00
}
2017-10-31 15:24:11 -07:00
for _ , event := range events {
switch ev := event . ( type ) {
case ChainEvent :
bc . chainFeed . Send ( ev )
2017-03-27 14:15:24 -07:00
2017-10-31 15:24:11 -07:00
case ChainHeadEvent :
bc . chainHeadFeed . Send ( ev )
2017-03-27 14:15:24 -07:00
2017-10-31 15:24:11 -07:00
case ChainSideEvent :
bc . chainSideFeed . Send ( ev )
2015-10-12 05:04:38 -07:00
}
}
}
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) update ( ) {
2018-05-23 22:32:26 -07:00
futureTimer := time . NewTicker ( 5 * time . Second )
defer futureTimer . Stop ( )
2015-03-06 06:50:44 -08:00
for {
select {
2018-05-23 22:32:26 -07:00
case <- futureTimer . C :
2017-10-31 15:24:11 -07:00
bc . procFutureBlocks ( )
case <- bc . quit :
2015-10-12 05:04:38 -07:00
return
2015-03-06 06:50:44 -08:00
}
}
}
2015-05-16 16:42:30 -07:00
2017-10-31 15:24:11 -07:00
// BadBlocks returns a list of the last 'bad blocks' that the client has seen on the network
2018-06-11 01:03:40 -07:00
func ( bc * BlockChain ) BadBlocks ( ) [ ] * types . Block {
blocks := make ( [ ] * types . Block , 0 , bc . badBlocks . Len ( ) )
2017-10-31 15:24:11 -07:00
for _ , hash := range bc . badBlocks . Keys ( ) {
2018-06-11 01:03:40 -07:00
if blk , exist := bc . badBlocks . Peek ( hash ) ; exist {
block := blk . ( * types . Block )
blocks = append ( blocks , block )
2017-10-31 15:24:11 -07:00
}
}
2018-06-11 01:03:40 -07:00
return blocks
2018-05-31 21:23:38 -07:00
}
2018-07-24 01:15:38 -07:00
// HasBadBlock returns whether the block with the hash is a bad block. dep: Istanbul
func ( bc * BlockChain ) HasBadBlock ( hash common . Hash ) bool {
return bc . badBlocks . Contains ( hash )
}
2017-10-31 15:24:11 -07:00
// addBadBlock adds a bad block to the bad-block LRU cache
func ( bc * BlockChain ) addBadBlock ( block * types . Block ) {
2018-06-11 01:03:40 -07:00
bc . badBlocks . Add ( block . Hash ( ) , block )
2017-10-31 15:24:11 -07:00
}
2016-05-24 09:49:54 -07:00
// reportBlock logs a bad block error.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) reportBlock ( block * types . Block , receipts types . Receipts , err error ) {
bc . addBadBlock ( block )
var receiptString string
2020-04-29 07:50:56 -07:00
for i , receipt := range receipts {
receiptString += fmt . Sprintf ( "\t %d: cumulative: %v gas: %v contract: %v status: %v tx: %v logs: %v bloom: %x state: %x\n" ,
i , receipt . CumulativeGasUsed , receipt . GasUsed , receipt . ContractAddress . Hex ( ) ,
receipt . Status , receipt . TxHash . Hex ( ) , receipt . Logs , receipt . Bloom , receipt . PostState )
2015-08-18 05:14:45 -07:00
}
2017-10-31 15:24:11 -07:00
log . Error ( fmt . Sprintf ( `
# # # # # # # # # # BAD BLOCK # # # # # # # # #
Chain config : % v
Number : % v
Hash : 0 x % x
% v
Error : % v
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2018-05-23 22:32:26 -07:00
` , bc . chainConfig , block . Number ( ) , block . Hash ( ) , receiptString , err ) )
2015-05-29 09:07:23 -07:00
}
2015-12-15 19:26:23 -08:00
// InsertHeaderChain attempts to insert the given header chain in to the local
// chain, possibly creating a reorg. If an error is returned, it will return the
// index number of the failing header as well an error describing what went wrong.
//
// The verify parameter can be used to fine tune whether nonce verification
// should be done or not. The reason behind the optional check is because some
2016-03-15 09:12:03 -07:00
// of the header retrieval mechanisms already need to verify nonces, as well as
2015-12-15 19:26:23 -08:00
// because nonces can be verified sparsely, not needing to check each.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) InsertHeaderChain ( chain [ ] * types . Header , checkFreq int ) ( int , error ) {
start := time . Now ( )
if i , err := bc . hc . ValidateHeaderChain ( chain , checkFreq ) ; err != nil {
return i , err
}
2015-12-15 19:26:23 -08:00
// Make sure only one thread manipulates the chain at once
2017-10-31 15:24:11 -07:00
bc . chainmu . Lock ( )
defer bc . chainmu . Unlock ( )
2015-12-15 19:26:23 -08:00
2017-10-31 15:24:11 -07:00
bc . wg . Add ( 1 )
defer bc . wg . Done ( )
2015-12-15 19:26:23 -08:00
whFunc := func ( header * types . Header ) error {
2017-10-31 15:24:11 -07:00
_ , err := bc . hc . WriteHeader ( header )
2015-12-15 19:26:23 -08:00
return err
}
2017-10-31 15:24:11 -07:00
return bc . hc . InsertHeaderChain ( chain , whFunc , start )
2015-12-15 19:26:23 -08:00
}
// CurrentHeader retrieves the current head header of the canonical chain. The
// header is retrieved from the HeaderChain's internal cache.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) CurrentHeader ( ) * types . Header {
return bc . hc . CurrentHeader ( )
2015-12-15 19:26:23 -08:00
}
// GetTd retrieves a block's total difficulty in the canonical chain from the
2016-04-05 06:22:04 -07:00
// database by hash and number, caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetTd ( hash common . Hash , number uint64 ) * big . Int {
return bc . hc . GetTd ( hash , number )
2016-04-05 06:22:04 -07:00
}
// GetTdByHash retrieves a block's total difficulty in the canonical chain from the
2015-12-15 19:26:23 -08:00
// database by hash, caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetTdByHash ( hash common . Hash ) * big . Int {
return bc . hc . GetTdByHash ( hash )
2016-04-05 06:22:04 -07:00
}
// GetHeader retrieves a block header from the database by hash and number,
// caching it if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetHeader ( hash common . Hash , number uint64 ) * types . Header {
return bc . hc . GetHeader ( hash , number )
2015-12-15 19:26:23 -08:00
}
2016-04-05 06:22:04 -07:00
// GetHeaderByHash retrieves a block header from the database by hash, caching it if
2015-12-15 19:26:23 -08:00
// found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetHeaderByHash ( hash common . Hash ) * types . Header {
return bc . hc . GetHeaderByHash ( hash )
2015-12-15 19:26:23 -08:00
}
// HasHeader checks if a block header is present in the database or not, caching
// it if present.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) HasHeader ( hash common . Hash , number uint64 ) bool {
return bc . hc . HasHeader ( hash , number )
2015-12-15 19:26:23 -08:00
}
2020-04-29 07:50:56 -07:00
// GetCanonicalHash returns the canonical hash for a given block number
func ( bc * BlockChain ) GetCanonicalHash ( number uint64 ) common . Hash {
return bc . hc . GetCanonicalHash ( number )
}
2015-12-15 19:26:23 -08:00
// GetBlockHashesFromHash retrieves a number of block hashes starting at a given
// hash, fetching towards the genesis block.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetBlockHashesFromHash ( hash common . Hash , max uint64 ) [ ] common . Hash {
return bc . hc . GetBlockHashesFromHash ( hash , max )
2015-12-15 19:26:23 -08:00
}
2018-06-12 06:52:54 -07:00
// GetAncestor retrieves the Nth ancestor of a given block. It assumes that either the given block or
// a close ancestor of it is canonical. maxNonCanonical points to a downwards counter limiting the
// number of blocks to be individually checked before we reach the canonical chain.
//
// Note: ancestor == 0 returns the same block, 1 returns its parent and so on.
func ( bc * BlockChain ) GetAncestor ( hash common . Hash , number , ancestor uint64 , maxNonCanonical * uint64 ) ( common . Hash , uint64 ) {
return bc . hc . GetAncestor ( hash , number , ancestor , maxNonCanonical )
}
2015-12-15 19:26:23 -08:00
// GetHeaderByNumber retrieves a block header from the database by number,
// caching it (associated with its hash) if found.
2017-10-31 15:24:11 -07:00
func ( bc * BlockChain ) GetHeaderByNumber ( number uint64 ) * types . Header {
return bc . hc . GetHeaderByNumber ( number )
2015-12-15 19:26:23 -08:00
}
2016-04-29 04:02:54 -07:00
2020-04-29 07:50:56 -07:00
// GetTransactionLookup retrieves the lookup associate with the given transaction
// hash from the cache or database.
func ( bc * BlockChain ) GetTransactionLookup ( hash common . Hash ) * rawdb . LegacyTxLookupEntry {
// Short circuit if the txlookup already in the cache, retrieve otherwise
if lookup , exist := bc . txLookupCache . Get ( hash ) ; exist {
return lookup . ( * rawdb . LegacyTxLookupEntry )
}
tx , blockHash , blockNumber , txIndex := rawdb . ReadTransaction ( bc . db , hash )
if tx == nil {
return nil
}
lookup := & rawdb . LegacyTxLookupEntry { BlockHash : blockHash , BlockIndex : blockNumber , Index : txIndex }
bc . txLookupCache . Add ( hash , lookup )
return lookup
}
// Config retrieves the chain's fork configuration.
2018-05-23 22:32:26 -07:00
func ( bc * BlockChain ) Config ( ) * params . ChainConfig { return bc . chainConfig }
2017-10-31 15:24:11 -07:00
// Engine retrieves the blockchain's consensus engine.
func ( bc * BlockChain ) Engine ( ) consensus . Engine { return bc . engine }
// SubscribeRemovedLogsEvent registers a subscription of RemovedLogsEvent.
func ( bc * BlockChain ) SubscribeRemovedLogsEvent ( ch chan <- RemovedLogsEvent ) event . Subscription {
return bc . scope . Track ( bc . rmLogsFeed . Subscribe ( ch ) )
}
// SubscribeChainEvent registers a subscription of ChainEvent.
func ( bc * BlockChain ) SubscribeChainEvent ( ch chan <- ChainEvent ) event . Subscription {
return bc . scope . Track ( bc . chainFeed . Subscribe ( ch ) )
}
// SubscribeChainHeadEvent registers a subscription of ChainHeadEvent.
func ( bc * BlockChain ) SubscribeChainHeadEvent ( ch chan <- ChainHeadEvent ) event . Subscription {
return bc . scope . Track ( bc . chainHeadFeed . Subscribe ( ch ) )
}
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
func ( bc * BlockChain ) SubscribeChainSideEvent ( ch chan <- ChainSideEvent ) event . Subscription {
return bc . scope . Track ( bc . chainSideFeed . Subscribe ( ch ) )
}
// SubscribeLogsEvent registers a subscription of []*types.Log.
func ( bc * BlockChain ) SubscribeLogsEvent ( ch chan <- [ ] * types . Log ) event . Subscription {
return bc . scope . Track ( bc . logsFeed . Subscribe ( ch ) )
}
2020-04-29 07:50:56 -07:00
// SubscribeBlockProcessingEvent registers a subscription of bool where true means
// block processing has started while false means it has stopped.
func ( bc * BlockChain ) SubscribeBlockProcessingEvent ( ch chan <- bool ) event . Subscription {
return bc . scope . Track ( bc . blockProcFeed . Subscribe ( ch ) )
}