|
@@ -28,6 +28,8 @@ import (
|
|
|
"sync/atomic"
|
|
"sync/atomic"
|
|
|
"time"
|
|
"time"
|
|
|
|
|
|
|
|
|
|
+ lru "github.com/hashicorp/golang-lru"
|
|
|
|
|
+
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
"github.com/ethereum/go-ethereum/common/mclock"
|
|
"github.com/ethereum/go-ethereum/common/mclock"
|
|
|
"github.com/ethereum/go-ethereum/common/prque"
|
|
"github.com/ethereum/go-ethereum/common/prque"
|
|
@@ -44,7 +46,6 @@ import (
|
|
|
"github.com/ethereum/go-ethereum/params"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
|
"github.com/ethereum/go-ethereum/trie"
|
|
"github.com/ethereum/go-ethereum/trie"
|
|
|
- lru "github.com/hashicorp/golang-lru"
|
|
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
var (
|
|
@@ -200,8 +201,9 @@ type BlockChain struct {
|
|
|
|
|
|
|
|
chainmu sync.RWMutex // blockchain insertion lock
|
|
chainmu sync.RWMutex // blockchain insertion lock
|
|
|
|
|
|
|
|
- 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!)
|
|
|
|
|
|
|
+ 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!)
|
|
|
|
|
+ highestVerifiedHeader atomic.Value
|
|
|
|
|
|
|
|
stateCache state.Database // State database to reuse between imports (contains state cache)
|
|
stateCache state.Database // State database to reuse between imports (contains state cache)
|
|
|
bodyCache *lru.Cache // Cache for the most recent block bodies
|
|
bodyCache *lru.Cache // Cache for the most recent block bodies
|
|
@@ -310,6 +312,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
|
|
bc.currentBlock.Store(nilBlock)
|
|
bc.currentBlock.Store(nilBlock)
|
|
|
bc.currentFastBlock.Store(nilBlock)
|
|
bc.currentFastBlock.Store(nilBlock)
|
|
|
|
|
|
|
|
|
|
+ var nilHeader *types.Header
|
|
|
|
|
+ bc.highestVerifiedHeader.Store(nilHeader)
|
|
|
|
|
+
|
|
|
// Initialize the chain with ancient data if it isn't empty.
|
|
// Initialize the chain with ancient data if it isn't empty.
|
|
|
var txIndexBlock uint64
|
|
var txIndexBlock uint64
|
|
|
|
|
|
|
@@ -2039,6 +2044,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return it.index, err
|
|
return it.index, err
|
|
|
}
|
|
}
|
|
|
|
|
+ bc.updateHighestVerifiedHeader(block.Header())
|
|
|
|
|
+
|
|
|
// Enable prefetching to pull in trie node paths while processing transactions
|
|
// Enable prefetching to pull in trie node paths while processing transactions
|
|
|
statedb.StartPrefetcher("chain")
|
|
statedb.StartPrefetcher("chain")
|
|
|
|
|
|
|
@@ -2144,6 +2151,29 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
|
|
|
return it.index, err
|
|
return it.index, err
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+func (bc *BlockChain) updateHighestVerifiedHeader(header *types.Header) {
|
|
|
|
|
+ if header == nil || header.Number == nil {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ currentHeader := bc.highestVerifiedHeader.Load().(*types.Header)
|
|
|
|
|
+ if currentHeader == nil {
|
|
|
|
|
+ bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ newTD := big.NewInt(0).Add(bc.GetTdByHash(header.ParentHash), header.Difficulty)
|
|
|
|
|
+ oldTD := big.NewInt(0).Add(bc.GetTdByHash(currentHeader.ParentHash), currentHeader.Difficulty)
|
|
|
|
|
+
|
|
|
|
|
+ if newTD.Cmp(oldTD) > 0 {
|
|
|
|
|
+ bc.highestVerifiedHeader.Store(types.CopyHeader(header))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (bc *BlockChain) GetHighestVerifiedHeader() *types.Header {
|
|
|
|
|
+ return bc.highestVerifiedHeader.Load().(*types.Header)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// insertSideChain is called when an import batch hits upon a pruned ancestor
|
|
// 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
|
|
// error, which happens when a sidechain with a sufficiently old fork-block is
|
|
|
// found.
|
|
// found.
|