all: change chain head markers from block to header #26777 (#1846)

This commit is contained in:
Daniel Liu 2025-12-16 11:36:51 +08:00 committed by GitHub
parent cbb0605e0f
commit 999ded17da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
38 changed files with 386 additions and 304 deletions

View file

@ -156,7 +156,11 @@ func NewXDCSimulatedBackend(alloc types.GenesisAlloc, gasLimit uint64, chainConf
backend.events = filters.NewEventSystem(backend.filterSystem, false) backend.events = filters.NewEventSystem(backend.filterSystem, false)
blockchain.Client = backend blockchain.Client = backend
backend.rollback(blockchain.CurrentBlock())
header := backend.blockchain.CurrentBlock()
block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
backend.rollback(block)
return backend return backend
} }
@ -179,7 +183,10 @@ func NewSimulatedBackend(alloc types.GenesisAlloc, gasLimit uint64) *SimulatedBa
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{}) backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
backend.events = filters.NewEventSystem(backend.filterSystem, false) backend.events = filters.NewEventSystem(backend.filterSystem, false)
backend.rollback(blockchain.CurrentBlock()) header := backend.blockchain.CurrentBlock()
block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
backend.rollback(block)
return backend return backend
} }
@ -212,7 +219,10 @@ func (b *SimulatedBackend) Rollback() {
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
b.rollback(b.blockchain.CurrentBlock()) header := b.blockchain.CurrentBlock()
block := b.blockchain.GetBlock(header.Hash(), header.Number.Uint64())
b.rollback(block)
} }
func (b *SimulatedBackend) rollback(parent *types.Block) { func (b *SimulatedBackend) rollback(parent *types.Block) {
@ -252,7 +262,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error {
// stateByBlockNumber retrieves a state by a given blocknumber. // stateByBlockNumber retrieves a state by a given blocknumber.
func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 { if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number) == 0 {
return b.blockchain.State() return b.blockchain.State()
} }
block, err := b.blockByNumber(ctx, blockNumber) block, err := b.blockByNumber(ctx, blockNumber)
@ -334,7 +344,7 @@ func (b *SimulatedBackend) ForEachStorageAt(ctx context.Context, contract common
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
return errBlockNumberUnsupported return errBlockNumberUnsupported
} }
stateDB, _ := b.blockchain.State() stateDB, _ := b.blockchain.State()
@ -408,7 +418,7 @@ func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (
// (associated with its hash) if found without Lock. // (associated with its hash) if found without Lock.
func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { func (b *SimulatedBackend) blockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 { if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
return b.blockchain.CurrentBlock(), nil return b.blockByHash(ctx, b.blockchain.CurrentBlock().Hash())
} }
block := b.blockchain.GetBlockByNumber(uint64(number.Int64())) block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
@ -540,7 +550,7 @@ func (b *SimulatedBackend) CallContract(ctx context.Context, call ethereum.CallM
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 { if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number) != 0 {
return nil, errBlockNumberUnsupported return nil, errBlockNumberUnsupported
} }
return b.callContractAtHead(ctx, call) return b.callContractAtHead(ctx, call)
@ -563,7 +573,8 @@ func (b *SimulatedBackend) callContractAtHead(ctx context.Context, call ethereum
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB) header := b.blockchain.CurrentBlock()
res, err := b.callContract(ctx, call, header, stateDB)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -580,7 +591,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu
defer b.mu.Unlock() defer b.mu.Unlock()
defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot()) defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -642,7 +653,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
call.Gas = gas call.Gas = gas
snapshot := b.pendingState.Snapshot() snapshot := b.pendingState.Snapshot()
res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState) res, err := b.callContract(ctx, call, b.pendingBlock.Header(), b.pendingState)
b.pendingState.RevertToSnapshot(snapshot) b.pendingState.RevertToSnapshot(snapshot)
if err != nil { if err != nil {
@ -692,7 +703,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs
// callContract implements common code between normal and pending contract calls. // callContract implements common code between normal and pending contract calls.
// state is modified during execution, make sure to copy it if necessary. // state is modified during execution, make sure to copy it if necessary.
func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) { func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Header, stateDB *state.StateDB) (*core.ExecutionResult, error) {
// Gas prices post 1559 need to be initialized // Gas prices post 1559 need to be initialized
if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
@ -763,7 +774,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Create a new environment which holds all relevant information // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
txContext := core.NewEVMTxContext(msg) txContext := core.NewEVMTxContext(msg)
evmContext := core.NewEVMBlockContext(block.Header(), b.blockchain, nil) evmContext := core.NewEVMBlockContext(block, b.blockchain, nil)
// Create a new environment which holds all relevant information // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, txContext, stateDB, nil, b.config, vm.Config{NoBaseFee: true}) vmenv := vm.NewEVM(evmContext, txContext, stateDB, nil, b.config, vm.Config{NoBaseFee: true})
@ -958,7 +969,7 @@ func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNum
if fb.bc.Config().XDPoS == nil { if fb.bc.Config().XDPoS == nil {
return nil, errors.New("only XDPoS v2 supports committed block lookup") return nil, errors.New("only XDPoS v2 supports committed block lookup")
} }
current := fb.bc.CurrentBlock().Header() current := fb.bc.CurrentBlock()
if fb.bc.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 { if fb.bc.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 {
confirmedHash := fb.bc.Engine().(*XDPoS.XDPoS).EngineV2.GetLatestCommittedBlockInfo().Hash confirmedHash := fb.bc.Engine().(*XDPoS.XDPoS).EngineV2.GetLatestCommittedBlockInfo().Hash
return fb.bc.GetHeaderByHash(confirmedHash), nil return fb.bc.GetHeaderByHash(confirmedHash), nil

View file

@ -1254,7 +1254,7 @@ func TestFork(t *testing.T) {
sim.Commit() sim.Commit()
} }
// 3. // 3.
if sim.blockchain.CurrentBlock().NumberU64() != uint64(n) { if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n) {
t.Error("wrong chain length") t.Error("wrong chain length")
} }
// 4. // 4.
@ -1264,7 +1264,7 @@ func TestFork(t *testing.T) {
sim.Commit() sim.Commit()
} }
// 6. // 6.
if sim.blockchain.CurrentBlock().NumberU64() != uint64(n+1) { if sim.blockchain.CurrentBlock().Number.Uint64() != uint64(n+1) {
t.Error("wrong chain length") t.Error("wrong chain length")
} }
} }
@ -1421,7 +1421,7 @@ func TestCommitReturnValue(t *testing.T) {
sim := simTestBackend(testAddr) sim := simTestBackend(testAddr)
defer sim.Close() defer sim.Close()
startBlockHeight := sim.blockchain.CurrentBlock().NumberU64() startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
// Test if Commit returns the correct block hash // Test if Commit returns the correct block hash
h1 := sim.Commit() h1 := sim.Commit()

View file

@ -190,7 +190,7 @@ func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block
head := chain.CurrentBlock() head := chain.CurrentBlock()
for i, block := range blocks { for i, block := range blocks {
// If we're behind the chain head, only check block, state is available at head // If we're behind the chain head, only check block, state is available at head
if head.NumberU64() > block.NumberU64() { if head.Number.Uint64() > block.NumberU64() {
if !chain.HasBlock(block.Hash(), block.NumberU64()) { if !chain.HasBlock(block.Hash(), block.NumberU64()) {
return blocks[i:] return blocks[i:]
} }

View file

@ -491,17 +491,15 @@ func (x *XDPoS) GetAuthorisedSignersFromSnapshot(chain consensus.ChainReader, he
} }
} }
func (x *XDPoS) FindParentBlockToAssign(chain consensus.ChainReader, currentBlock *types.Block) *types.Block { func (x *XDPoS) FindParentBlockToAssign(chain consensus.ChainReader, currentBlock *types.Header) *types.Block {
switch x.config.BlockConsensusVersion(currentBlock.Number()) { var parent *types.Block = nil
case params.ConsensusEngineVersion2: if x.config.BlockConsensusVersion(currentBlock.Number) == params.ConsensusEngineVersion2 {
block := x.EngineV2.FindParentBlockToAssign(chain) parent = x.EngineV2.FindParentBlockToAssign(chain)
if block == nil {
return currentBlock
}
return block
default: // Default "v1"
return currentBlock
} }
if parent == nil {
parent = chain.GetBlock(currentBlock.Hash(), currentBlock.Number.Uint64())
}
return parent
} }
/** /**

View file

@ -205,7 +205,7 @@ func TestCallUpdateM1WithSmartContractTranscation(t *testing.T) {
func TestCallUpdateM1WhenForkedBlockBackToMainChain(t *testing.T) { func TestCallUpdateM1WhenForkedBlockBackToMainChain(t *testing.T) {
blockchain, backend, currentBlock, signer, signFn := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig) blockchain, backend, currentBlock, signer, signFn := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
// Check initial signer, by default, acc3 is in the signerList // Check initial signer, by default, acc3 is in the signerList
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -337,7 +337,7 @@ func TestCallUpdateM1WhenForkedBlockBackToMainChain(t *testing.T) {
t.Fatalf("acc1,3should NOT sit in the signer list") t.Fatalf("acc1,3should NOT sit in the signer list")
} }
signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -360,7 +360,7 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
} }
t.Logf("Account %v have balance of: %v", acc1Addr.String(), state.GetBalance(acc1Addr)) t.Logf("Account %v have balance of: %v", acc1Addr.String(), state.GetBalance(acc1Addr))
// Check initial signer // Check initial signer
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -493,7 +493,7 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
t.Fatalf("account 2 should sit in the signer list") t.Fatalf("account 2 should sit in the signer list")
} }
signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -516,7 +516,7 @@ func TestStatesShouldBeUpdatedWhenForkedBlockBecameMainChainAtGapBlock(t *testin
func TestVoteShouldNotBeAffectedByFork(t *testing.T) { func TestVoteShouldNotBeAffectedByFork(t *testing.T) {
blockchain, backend, parentBlock, signer, signFn := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig) blockchain, backend, parentBlock, signer, signFn := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig)
// Check initial signer, by default, acc3 is in the signerList // Check initial signer, by default, acc3 is in the signerList
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -19,7 +19,7 @@ func TestRaceConditionOnBlockchainReadAndWrite(t *testing.T) {
} }
t.Logf("Account %v have balance of: %v", acc1Addr.String(), state.GetBalance(acc1Addr)) t.Logf("Account %v have balance of: %v", acc1Addr.String(), state.GetBalance(acc1Addr))
// Check initial signer // Check initial signer
signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err := GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -157,7 +157,7 @@ func TestRaceConditionOnBlockchainReadAndWrite(t *testing.T) {
t.Fatalf("account 2 should sit in the signer list") t.Fatalf("account 2 should sit in the signer list")
} }
signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock().Header()) signers, err = GetSnapshotSigner(blockchain, blockchain.CurrentBlock())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -241,11 +241,12 @@ func TestGetParentBlock(t *testing.T) {
adaptor := blockchain.Engine().(*XDPoS.XDPoS) adaptor := blockchain.Engine().(*XDPoS.XDPoS)
// V1 // V1
block := adaptor.FindParentBlockToAssign(blockchain, block900) block := adaptor.FindParentBlockToAssign(blockchain, block900.Header())
assert.Equal(t, block, block900) assert.Equal(t, block.Number(), block900.Number())
assert.Equal(t, block.Hash(), block900.Hash())
// Initialise // Initialise
err := adaptor.EngineV2.Initial(blockchain, block.Header()) err := adaptor.EngineV2.Initial(blockchain, block900.Header())
assert.Nil(t, err) assert.Nil(t, err)
// V2 // V2
@ -260,7 +261,7 @@ func TestGetParentBlock(t *testing.T) {
block902 := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, block901, blockNum, 1, blockCoinBase, signer, signFn, nil, nil, "") block902 := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, block901, blockNum, 1, blockCoinBase, signer, signFn, nil, nil, "")
err = blockchain.InsertBlock(block902) err = blockchain.InsertBlock(block902)
assert.Nil(t, err) assert.Nil(t, err)
block = adaptor.FindParentBlockToAssign(blockchain, block902) block = adaptor.FindParentBlockToAssign(blockchain, block902.Header())
assert.Equal(t, block.Number(), block900.Number())
assert.Equal(t, block900.Hash(), block.Hash()) assert.Equal(t, block.Hash(), block900.Hash())
} }

View file

@ -187,8 +187,8 @@ type BlockChain struct {
// Readers don't need to take it, they can just read the database. // Readers don't need to take it, they can just read the database.
chainmu *syncx.ClosableMutex chainmu *syncx.ClosableMutex
currentBlock atomic.Value // Current head of the block chain currentBlock atomic.Pointer[types.Header] // Current head of the chain
currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) currentSnapBlock atomic.Pointer[types.Header] // Current head of snap-sync
bodyCache *lru.Cache[common.Hash, *types.Body] // Cache for the most recent block bodies bodyCache *lru.Cache[common.Hash, *types.Body] // Cache for the most recent block bodies
bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] // Cache for the most recent block bodies in RLP encoded format bodyRLPCache *lru.Cache[common.Hash, rlp.RawValue] // Cache for the most recent block bodies in RLP encoded format
@ -289,9 +289,8 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
return nil, ErrNoGenesis return nil, ErrNoGenesis
} }
var nilBlock *types.Block bc.currentBlock.Store(nil)
bc.currentBlock.Store(nilBlock) bc.currentSnapBlock.Store(nil)
bc.currentFastBlock.Store(nilBlock)
// Update chain info data metrics // Update chain info data metrics
chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()}) chainInfoGauge.Update(metrics.GaugeInfoValue{"chain_id": bc.chainConfig.ChainID.String()})
@ -319,16 +318,18 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
} }
if bc.logger != nil && bc.logger.OnGenesisBlock != nil { if bc.logger != nil && bc.logger.OnGenesisBlock != nil {
if block := bc.CurrentBlock(); block.NumberU64() == 0 { block := bc.CurrentBlock()
if block == nil {
return nil, errors.New("live blockchain tracer requires current block to be set")
}
if block.Number != nil && block.Number.Sign() == 0 {
alloc, err := getGenesisState(bc.db, block.Hash()) alloc, err := getGenesisState(bc.db, block.Hash())
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to get genesis state: %w", err) return nil, fmt.Errorf("failed to get genesis state: %w", err)
} }
if alloc == nil { if alloc == nil {
return nil, fmt.Errorf("live blockchain tracer requires genesis alloc to be set") return nil, fmt.Errorf("live blockchain tracer requires genesis alloc to be set")
} }
bc.logger.OnGenesisBlock(bc.genesisBlock, alloc) bc.logger.OnGenesisBlock(bc.genesisBlock, alloc)
} }
} }
@ -339,7 +340,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
return bc, nil return bc, nil
} }
// NewBlockChainEx extend old blockchain, add order state db // NewBlockChainEx extend old blockchain, add order state db
func NewBlockChainEx(db ethdb.Database, XDCxDb ethdb.XDCxDatabase, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) { func NewBlockChainEx(db ethdb.Database, XDCxDb ethdb.XDCxDatabase, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config) (*BlockChain, error) {
blockchain, err := NewBlockChain(db, cacheConfig, chainConfig, engine, vmConfig) blockchain, err := NewBlockChain(db, cacheConfig, chainConfig, engine, vmConfig)
@ -367,24 +367,24 @@ func (bc *BlockChain) loadLastState() error {
return bc.Reset() return bc.Reset()
} }
// Make sure the entire head block is available // Make sure the entire head block is available
currentBlock := bc.GetBlockByHash(head) headBlock := bc.GetBlockByHash(head)
if currentBlock == nil { if headBlock == nil {
// Corrupt or empty database, init from scratch // Corrupt or empty database, init from scratch
log.Warn("Head block missing, resetting chain", "hash", head) log.Warn("Head block missing, resetting chain", "hash", head)
return bc.Reset() return bc.Reset()
} }
// Make sure the state associated with the block is available // Make sure the state associated with the block is available
repair := false repair := false
if !bc.HasState(currentBlock.Root()) { if !bc.HasState(headBlock.Root()) {
repair = true repair = true
} else { } else {
engine, ok := bc.Engine().(*XDPoS.XDPoS) engine, ok := bc.Engine().(*XDPoS.XDPoS)
if ok { if ok {
tradingService := engine.GetXDCXService() tradingService := engine.GetXDCXService()
lendingService := engine.GetLendingService() lendingService := engine.GetLendingService()
if bc.Config().IsTIPXDCX(currentBlock.Number()) && bc.chainConfig.XDPoS != nil && currentBlock.NumberU64() > bc.chainConfig.XDPoS.Epoch && tradingService != nil && lendingService != nil { if bc.Config().IsTIPXDCX(headBlock.Number()) && bc.chainConfig.XDPoS != nil && headBlock.NumberU64() > bc.chainConfig.XDPoS.Epoch && tradingService != nil && lendingService != nil {
author, _ := bc.Engine().Author(currentBlock.Header()) author, _ := bc.Engine().Author(headBlock.Header())
tradingRoot, err := tradingService.GetTradingStateRoot(currentBlock, author) tradingRoot, err := tradingService.GetTradingStateRoot(headBlock, author)
if err != nil { if err != nil {
repair = true repair = true
} else { } else {
@ -397,7 +397,7 @@ func (bc *BlockChain) loadLastState() error {
} }
if !repair { if !repair {
lendingRoot, err := lendingService.GetLendingStateRoot(currentBlock, author) lendingRoot, err := lendingService.GetLendingStateRoot(headBlock, author)
if err != nil { if err != nil {
repair = true repair = true
} else { } else {
@ -414,45 +414,50 @@ func (bc *BlockChain) loadLastState() error {
} }
if repair { if repair {
// Dangling block without a state associated, init from scratch // Dangling block without a state associated, init from scratch
log.Warn("Head state missing, repairing chain", "number", currentBlock.Number(), "hash", currentBlock.Hash()) log.Warn("Head state missing, repairing chain", "number", headBlock.Number(), "hash", headBlock.Hash())
if err := bc.repair(&currentBlock); err != nil { if err := bc.repair(&headBlock); err != nil {
return err return err
} }
} }
// Everything seems to be fine, set as the head block // Everything seems to be fine, set as the head block
bc.currentBlock.Store(currentBlock) bc.currentBlock.Store(headBlock.Header())
headBlockGauge.Update(int64(currentBlock.NumberU64())) headBlockGauge.Update(int64(headBlock.NumberU64()))
// Restore the last known head header // Restore the last known head header
currentHeader := currentBlock.Header() headHeader := headBlock.Header()
if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) { if head := rawdb.ReadHeadHeaderHash(bc.db); head != (common.Hash{}) {
if header := bc.GetHeaderByHash(head); header != nil { if header := bc.GetHeaderByHash(head); header != nil {
currentHeader = header headHeader = header
} }
} }
bc.hc.SetCurrentHeader(currentHeader) bc.hc.SetCurrentHeader(headHeader)
// Restore the last known head fast block // Restore the last known head fast block
bc.currentFastBlock.Store(currentBlock) bc.currentSnapBlock.Store(headBlock.Header())
headFastBlockGauge.Update(int64(currentBlock.NumberU64())) headFastBlockGauge.Update(int64(headBlock.NumberU64()))
if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) {
if block := bc.GetBlockByHash(head); block != nil { if block := bc.GetBlockByHash(head); block != nil {
bc.currentFastBlock.Store(block) bc.currentSnapBlock.Store(block.Header())
headFastBlockGauge.Update(int64(block.NumberU64())) headFastBlockGauge.Update(int64(block.NumberU64()))
} }
} }
// Issue a status log for the user // Issue a status log for the user
currentFastBlock := bc.CurrentFastBlock() var (
currentSnapBlock = bc.CurrentSnapBlock()
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64()) headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64())
blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64())
fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()) )
if headHeader.Hash() != headBlock.Hash() {
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 header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.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))) log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0)))
if headBlock.Hash() != currentSnapBlock.Hash() {
fastTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64())
log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0)))
}
return nil return nil
} }
@ -465,7 +470,16 @@ func (bc *BlockChain) SetHead(head uint64) error {
return err return err
} }
// Send chain head event to update the transaction pool // Send chain head event to update the transaction pool
bc.chainHeadFeed.Send(ChainHeadEvent{Block: bc.CurrentBlock()}) header := bc.CurrentBlock()
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
if block == nil {
// This should never happen. In practice, previously currentBlock
// contained the entire block whereas now only a "marker", so there
// is an ever so slight chance for a race we should handle.
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
}
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
return nil return nil
} }
@ -483,7 +497,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64) error {
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) { updateFn := func(db ethdb.KeyValueWriter, header *types.Header) {
// Rewind the block chain, ensuring we don't end up with a stateless head block // 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() { if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() < currentBlock.Number.Uint64() {
newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
if newHeadBlock == nil { if newHeadBlock == nil {
newHeadBlock = bc.genesisBlock newHeadBlock = bc.genesisBlock
@ -499,25 +513,25 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64) error {
// In theory we should update all in-memory markers in the // In theory we should update all in-memory markers in the
// last step, however the direction of SetHead is from high // last step, however the direction of SetHead is from high
// to low, so it's safe the update in-memory markers directly. // to low, so it's safe the update in-memory markers directly.
bc.currentBlock.Store(newHeadBlock) bc.currentBlock.Store(newHeadBlock.Header())
headBlockGauge.Update(int64(newHeadBlock.NumberU64())) headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
} }
// Rewind the fast block in a simpleton way to the target head // Rewind the fast block in a simpleton way to the target head
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() { if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock != nil && header.Number.Uint64() < currentSnapBlock.Number.Uint64() {
newHeadFastBlock := bc.GetBlock(header.Hash(), header.Number.Uint64()) newHeadSnapBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
// If either blocks reached nil, reset to the genesis state // If either blocks reached nil, reset to the genesis state
if newHeadFastBlock == nil { if newHeadSnapBlock == nil {
newHeadFastBlock = bc.genesisBlock newHeadSnapBlock = bc.genesisBlock
} }
rawdb.WriteHeadFastBlockHash(db, newHeadFastBlock.Hash()) rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash())
// Degrade the chain markers if they are explicitly reverted. // Degrade the chain markers if they are explicitly reverted.
// In theory we should update all in-memory markers in the // In theory we should update all in-memory markers in the
// last step, however the direction of SetHead is from high // last step, however the direction of SetHead is from high
// to low, so it's safe the update in-memory markers directly. // to low, so it's safe the update in-memory markers directly.
bc.currentFastBlock.Store(newHeadFastBlock) bc.currentSnapBlock.Store(newHeadSnapBlock.Header())
headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64()))
} }
} }
@ -572,7 +586,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
if !bc.chainmu.TryLock() { if !bc.chainmu.TryLock() {
return errChainStopped return errChainStopped
} }
bc.currentBlock.Store(block) bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64())) headBlockGauge.Update(int64(block.NumberU64()))
bc.chainmu.Unlock() bc.chainmu.Unlock()
@ -652,11 +666,11 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
// Last update all in-memory chain markers // Last update all in-memory chain markers
bc.genesisBlock = genesis bc.genesisBlock = genesis
bc.currentBlock.Store(bc.genesisBlock) bc.currentBlock.Store(bc.genesisBlock.Header())
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) headBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
bc.hc.SetGenesis(bc.genesisBlock.Header()) bc.hc.SetGenesis(bc.genesisBlock.Header())
bc.hc.SetCurrentHeader(bc.genesisBlock.Header()) bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
bc.currentFastBlock.Store(bc.genesisBlock) bc.currentSnapBlock.Store(bc.genesisBlock.Header())
headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
return nil return nil
} }
@ -713,7 +727,7 @@ func (bc *BlockChain) repair(head **types.Block) error {
// Export writes the active chain to the given writer. // Export writes the active chain to the given writer.
func (bc *BlockChain) Export(w io.Writer) error { func (bc *BlockChain) Export(w io.Writer) error {
return bc.ExportN(w, uint64(0), bc.CurrentBlock().NumberU64()) return bc.ExportN(w, uint64(0), bc.CurrentBlock().Number.Uint64())
} }
// ExportN writes a subset of the active chain to the given writer. // ExportN writes a subset of the active chain to the given writer.
@ -775,10 +789,10 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block, writeBlock bool) {
// Update all in-memory chain markers in the last step // Update all in-memory chain markers in the last step
bc.hc.SetCurrentHeader(block.Header()) bc.hc.SetCurrentHeader(block.Header())
bc.currentFastBlock.Store(block) bc.currentSnapBlock.Store(block.Header())
headFastBlockGauge.Update(int64(blockNumberU64)) headFastBlockGauge.Update(int64(blockNumberU64))
bc.currentBlock.Store(block) bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64())) headBlockGauge.Update(int64(block.NumberU64()))
// save cache BlockSigners // save cache BlockSigners
@ -855,7 +869,7 @@ func (bc *BlockChain) saveData() {
var lendingService utils.LendingService var lendingService utils.LendingService
triedb := bc.triedb triedb := bc.triedb
engine, _ := bc.Engine().(*XDPoS.XDPoS) engine, _ := bc.Engine().(*XDPoS.XDPoS)
if bc.Config().IsTIPXDCX(bc.CurrentBlock().Number()) && bc.chainConfig.XDPoS != nil && bc.CurrentBlock().NumberU64() > bc.chainConfig.XDPoS.Epoch && engine != nil { if bc.Config().IsTIPXDCX(bc.CurrentBlock().Number) && bc.chainConfig.XDPoS != nil && bc.CurrentBlock().Number.Uint64() > bc.chainConfig.XDPoS.Epoch && engine != nil {
tradingService = engine.GetXDCXService() tradingService = engine.GetXDCXService()
if tradingService != nil && tradingService.GetStateCache() != nil { if tradingService != nil && tradingService.GetStateCache() != nil {
tradingTriedb = tradingService.GetStateCache().TrieDB() tradingTriedb = tradingService.GetStateCache().TrieDB()
@ -866,7 +880,7 @@ func (bc *BlockChain) saveData() {
} }
} }
for _, offset := range []uint64{0, 1, triesInMemory - 1} { for _, offset := range []uint64{0, 1, triesInMemory - 1} {
if number := bc.CurrentBlock().NumberU64(); number > offset { if number := bc.CurrentBlock().Number.Uint64(); number > offset {
recent := bc.GetBlockByNumber(number - offset) recent := bc.GetBlockByNumber(number - offset)
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
@ -1028,16 +1042,24 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
rawdb.WriteHeadHeaderHash(batch, currentHeader.ParentHash) rawdb.WriteHeadHeaderHash(batch, currentHeader.ParentHash)
bc.hc.SetCurrentHeader(newHeadHeader) bc.hc.SetCurrentHeader(newHeadHeader)
} }
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash { if currentSnapBlock := bc.CurrentSnapBlock(); currentSnapBlock.Hash() == hash {
newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1) newFastBlock := bc.GetBlock(currentSnapBlock.ParentHash, currentSnapBlock.Number.Uint64()-1)
rawdb.WriteHeadFastBlockHash(batch, currentFastBlock.ParentHash()) if newFastBlock == nil {
bc.currentFastBlock.Store(newFastBlock) log.Error("Rollback failed", "number", currentSnapBlock.Number.Uint64()-1, "hash", currentSnapBlock.ParentHash.Hex())
return
}
rawdb.WriteHeadFastBlockHash(batch, currentSnapBlock.ParentHash)
bc.currentSnapBlock.Store(newFastBlock.Header())
headFastBlockGauge.Update(int64(newFastBlock.NumberU64())) headFastBlockGauge.Update(int64(newFastBlock.NumberU64()))
} }
if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash { if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash {
newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1) newBlock := bc.GetBlock(currentBlock.ParentHash, currentBlock.Number.Uint64()-1)
rawdb.WriteHeadBlockHash(batch, currentBlock.ParentHash()) if newBlock == nil {
bc.currentBlock.Store(newBlock) log.Error("Rollback failed", "number", currentBlock.Number.Uint64()-1, "hash", currentBlock.ParentHash.Hex())
return
}
rawdb.WriteHeadBlockHash(batch, currentBlock.ParentHash)
bc.currentBlock.Store(newBlock.Header())
headBlockGauge.Update(int64(newBlock.NumberU64())) headBlockGauge.Update(int64(newBlock.NumberU64()))
} }
} }
@ -1129,10 +1151,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
} }
head := blockChain[len(blockChain)-1] head := blockChain[len(blockChain)-1]
if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case
currentFastBlock := bc.CurrentFastBlock() currentSnapBlock := bc.CurrentSnapBlock()
if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 { if bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64()).Cmp(td) < 0 {
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) rawdb.WriteHeadFastBlockHash(bc.db, head.Hash())
bc.currentFastBlock.Store(head) bc.currentSnapBlock.Store(head.Header())
headFastBlockGauge.Update(int64(head.NumberU64())) headFastBlockGauge.Update(int64(head.NumberU64()))
} }
} }
@ -1193,7 +1215,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
} }
// Make sure no inconsistent state is leaked during insertion // Make sure no inconsistent state is leaked during insertion
currentBlock := bc.CurrentBlock() currentBlock := bc.CurrentBlock()
localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) localTd := bc.GetTd(currentBlock.Hash(), currentBlock.Number.Uint64())
externTd := new(big.Int).Add(block.Difficulty(), ptd) externTd := new(big.Int).Add(block.Difficulty(), ptd)
// Irrelevant of the canonical status, write the block itself to the database. // Irrelevant of the canonical status, write the block itself to the database.
@ -1360,12 +1382,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
currentBlock = bc.CurrentBlock() currentBlock = bc.CurrentBlock()
if !reorg && externTd.Cmp(localTd) == 0 { if !reorg && externTd.Cmp(localTd) == 0 {
// Split same-difficulty blocks by number // Split same-difficulty blocks by number
reorg = block.NumberU64() > currentBlock.NumberU64() reorg = block.NumberU64() > currentBlock.Number.Uint64()
} }
if reorg { if reorg {
// Reorganise the chain if the parent is not the head block // Reorganise the chain if the parent is not the head block
if block.ParentHash() != currentBlock.Hash() { if block.ParentHash() != currentBlock.Hash() {
if err := bc.reorg(currentBlock.Header(), block.Header()); err != nil { if err := bc.reorg(currentBlock, block.Header()); err != nil {
return NonStatTy, err return NonStatTy, err
} }
} }
@ -1514,7 +1536,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
// from the canonical chain, which has not been verified. // from the canonical chain, which has not been verified.
case err == ErrKnownBlock: case err == ErrKnownBlock:
// Skip all known blocks that behind us // Skip all known blocks that behind us
current := bc.CurrentBlock().NumberU64() current := bc.CurrentBlock().Number.Uint64()
for block != nil && err == ErrKnownBlock && current >= block.NumberU64() { for block != nil && err == ErrKnownBlock && current >= block.NumberU64() {
stats.ignored++ stats.ignored++
@ -1742,7 +1764,7 @@ func (bc *BlockChain) processBlock(block *types.Block, parent *types.Header, sta
func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (int, []interface{}, []*types.Log, error) { func (bc *BlockChain) insertSidechain(block *types.Block, it *insertIterator) (int, []interface{}, []*types.Log, error) {
var ( var (
externTd *big.Int externTd *big.Int
current = bc.CurrentBlock().NumberU64() current = bc.CurrentBlock().Number.Uint64()
) )
// The first sidechain block error is already verified to be ErrPrunedAncestor. // The first sidechain block error is already verified to be ErrPrunedAncestor.
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining // Since we don't import them here, we expect ErrUnknownAncestor for the remaining
@ -1913,14 +1935,14 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
case err == ErrKnownBlock: case err == ErrKnownBlock:
// Block and state both already known. However if the current block is below // Block and state both already known. However if the current block is below
// this number we did a rollback and we should reimport it nonetheless. // this number we did a rollback and we should reimport it nonetheless.
if bc.CurrentBlock().NumberU64() >= block.NumberU64() { if bc.CurrentBlock().Number.Uint64() >= block.NumberU64() {
return nil, ErrKnownBlock return nil, ErrKnownBlock
} }
case err == consensus.ErrPrunedAncestor: case err == consensus.ErrPrunedAncestor:
// Block competing with the canonical chain, store in the db, but don't process // Block competing with the canonical chain, store in the db, but don't process
// until the competitor TD goes above the canonical TD // until the competitor TD goes above the canonical TD
currentBlock := bc.CurrentBlock() currentBlock := bc.CurrentBlock()
localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) localTd := bc.GetTd(currentBlock.Hash(), currentBlock.Number.Uint64())
externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty()) externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty())
if localTd.Cmp(externTd) > 0 { if localTd.Cmp(externTd) > 0 {
return nil, err return nil, err

View file

@ -37,16 +37,16 @@ func (bc *BlockChain) CurrentHeader() *types.Header {
return bc.hc.CurrentHeader() return bc.hc.CurrentHeader()
} }
// CurrentBlock retrieves the current head block of the canonical chain. The // CurrentBlock retrieves the current head header of the canonical chain. The
// block is retrieved from the blockchain's internal cache. // header is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentBlock() *types.Block { func (bc *BlockChain) CurrentBlock() *types.Header {
return bc.currentBlock.Load().(*types.Block) return bc.currentBlock.Load()
} }
// CurrentFastBlock retrieves the current fast-sync head block of the canonical // CurrentSnapBlock retrieves the current snap-sync head header of the canonical
// chain. The block is retrieved from the blockchain's internal cache. // chain. The header is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentFastBlock() *types.Block { func (bc *BlockChain) CurrentSnapBlock() *types.Header {
return bc.currentFastBlock.Load().(*types.Block) return bc.currentSnapBlock.Load()
} }
// HasHeader checks if a block header is present in the database or not, caching // HasHeader checks if a block header is present in the database or not, caching
@ -282,7 +282,7 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
// State returns a new mutable state based on the current HEAD block. // State returns a new mutable state based on the current HEAD block.
func (bc *BlockChain) State() (*state.StateDB, error) { func (bc *BlockChain) State() (*state.StateDB, error) {
return bc.StateAt(bc.CurrentBlock().Root()) return bc.StateAt(bc.CurrentBlock().Root)
} }
// StateAt returns a new mutable state based on a particular point in time. // StateAt returns a new mutable state based on a particular point in time.
@ -313,7 +313,7 @@ func (bc *BlockChain) StateCache() state.Database {
// GasLimit returns the gas limit of the current HEAD block. // GasLimit returns the gas limit of the current HEAD block.
func (bc *BlockChain) GasLimit() uint64 { func (bc *BlockChain) GasLimit() uint64 {
return bc.CurrentBlock().GasLimit() return bc.CurrentBlock().GasLimit
} }
// Genesis retrieves the chain's genesis block. // Genesis retrieves the chain's genesis block.

View file

@ -98,7 +98,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
headerChainB []*types.Header headerChainB []*types.Header
) )
if full { if full {
blockChainB = makeBlockChain(blockchain2.CurrentBlock(), n, ethash.NewFaker(), db, forkSeed) blockChainB = makeBlockChain(blockchain2.GetBlockByHash(blockchain2.CurrentBlock().Hash()), n, ethash.NewFaker(), db, forkSeed)
if _, err := blockchain2.InsertChain(blockChainB); err != nil { if _, err := blockchain2.InsertChain(blockChainB); err != nil {
t.Fatalf("failed to insert forking chain: %v", err) t.Fatalf("failed to insert forking chain: %v", err)
} }
@ -129,7 +129,7 @@ func testFork(t *testing.T, blockchain *BlockChain, i, n int, full bool, compara
} }
func printChain(bc *BlockChain) { func printChain(bc *BlockChain) {
for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { for i := bc.CurrentBlock().Number.Uint64(); i > 0; i-- {
b := bc.GetBlockByNumber(i) b := bc.GetBlockByNumber(i)
fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty())
} }
@ -205,7 +205,7 @@ func TestLastBlock(t *testing.T) {
} }
defer blockchain.Stop() defer blockchain.Stop()
blocks := makeBlockChain(blockchain.CurrentBlock(), 1, ethash.NewFullFaker(), blockchain.db, 0) blocks := makeBlockChain(blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 1, ethash.NewFullFaker(), blockchain.db, 0)
if _, err := blockchain.InsertChain(blocks); err != nil { if _, err := blockchain.InsertChain(blocks); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
@ -346,7 +346,7 @@ func testBrokenChain(t *testing.T, full bool) {
// Create a forked chain, and try to insert with a missing link // Create a forked chain, and try to insert with a missing link
if full { if full {
chain := makeBlockChain(blockchain.CurrentBlock(), 5, ethash.NewFaker(), db, forkSeed)[1:] chain := makeBlockChain(blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 5, ethash.NewFaker(), db, forkSeed)[1:]
if err := testBlockChainImport(chain, blockchain); err == nil { if err := testBlockChainImport(chain, blockchain); err == nil {
t.Errorf("broken block chain not reported") t.Errorf("broken block chain not reported")
} }
@ -400,10 +400,10 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
defer blockchain.Stop() defer blockchain.Stop()
// Insert an easy and a difficult chain afterwards // Insert an easy and a difficult chain afterwards
easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) { easyBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), db, len(first), func(i int, b *BlockGen) {
b.OffsetTime(first[i]) b.OffsetTime(first[i])
}) })
diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.CurrentBlock(), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) { diffBlocks, _ := GenerateChain(params.TestChainConfig, blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), ethash.NewFaker(), db, len(second), func(i int, b *BlockGen) {
b.OffsetTime(second[i]) b.OffsetTime(second[i])
}) })
if full { if full {
@ -432,9 +432,9 @@ func testReorg(t *testing.T, first, second []int64, td int64, full bool) {
// Check that the chain is valid number and link wise // Check that the chain is valid number and link wise
if full { if full {
prev := blockchain.CurrentBlock() prev := blockchain.CurrentBlock()
for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, blockchain.GetBlockByNumber(block.NumberU64()-1) { for block := blockchain.GetBlockByNumber(blockchain.CurrentBlock().Number.Uint64() - 1); block.NumberU64() != 0; prev, block = block.Header(), blockchain.GetBlockByNumber(block.NumberU64()-1) {
if prev.ParentHash() != block.Hash() { if prev.ParentHash != block.Hash() {
t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash(), block.Hash()) t.Errorf("parent block hash mismatch: have %x, want %x", prev.ParentHash, block.Hash())
} }
} }
} else { } else {
@ -461,7 +461,7 @@ func testBadHashes(t *testing.T, full bool) {
// Create a chain, ban a hash and try to import // Create a chain, ban a hash and try to import
if full { if full {
blocks := makeBlockChain(blockchain.CurrentBlock(), 3, ethash.NewFaker(), db, 10) blocks := makeBlockChain(blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 3, ethash.NewFaker(), db, 10)
BadHashes[blocks[2].Header().Hash()] = true BadHashes[blocks[2].Header().Hash()] = true
defer func() { delete(BadHashes, blocks[2].Header().Hash()) }() defer func() { delete(BadHashes, blocks[2].Header().Hash()) }()
@ -493,7 +493,7 @@ func testReorgBadHashes(t *testing.T, full bool) {
} }
// Create a chain, import and ban afterwards // Create a chain, import and ban afterwards
headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10) headers := makeHeaderChain(blockchain.CurrentHeader(), 4, ethash.NewFaker(), db, 10)
blocks := makeBlockChain(blockchain.CurrentBlock(), 4, ethash.NewFaker(), db, 10) blocks := makeBlockChain(blockchain.GetBlockByHash(blockchain.CurrentBlock().Hash()), 4, ethash.NewFaker(), db, 10)
if full { if full {
if _, err = blockchain.InsertChain(blocks); err != nil { if _, err = blockchain.InsertChain(blocks); err != nil {
@ -697,10 +697,10 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
} }
// Create a small assertion method to check the three heads // Create a small assertion method to check the three heads
assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) { assert := func(t *testing.T, kind string, chain *BlockChain, header uint64, fast uint64, block uint64) {
if num := chain.CurrentBlock().NumberU64(); num != block { if num := chain.CurrentBlock().Number.Uint64(); num != block {
t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block)
} }
if num := chain.CurrentFastBlock().NumberU64(); num != fast { if num := chain.CurrentSnapBlock().Number.Uint64(); num != fast {
t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast) t.Errorf("%s head fast-block mismatch: have #%v, want #%v", kind, num, fast)
} }
if num := chain.CurrentHeader().Number.Uint64(); num != header { if num := chain.CurrentHeader().Number.Uint64(); num != header {
@ -1258,13 +1258,13 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
t.Fatalf("block %d: failed to insert into chain: %v", i, err) t.Fatalf("block %d: failed to insert into chain: %v", i, err)
} }
if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) t.Errorf("block %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
} }
if _, err := chain.InsertChain(forks[i : i+1]); err != nil { if _, err := chain.InsertChain(forks[i : i+1]); err != nil {
t.Fatalf(" fork %d: failed to insert into chain: %v", i, err) t.Fatalf(" fork %d: failed to insert into chain: %v", i, err)
} }
if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() { if chain.CurrentBlock().Hash() != chain.CurrentHeader().Hash() {
t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number(), chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4]) t.Errorf(" fork %d: current block/header mismatch: block #%d [%x..], header #%d [%x..]", i, chain.CurrentBlock().Number, chain.CurrentBlock().Hash().Bytes()[:4], chain.CurrentHeader().Number, chain.CurrentHeader().Hash().Bytes()[:4])
} }
} }
} }
@ -1433,7 +1433,8 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
b.Fatalf("failed to insert shared chain: %v", err) b.Fatalf("failed to insert shared chain: %v", err)
} }
b.StopTimer() b.StopTimer()
if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { block := chain.GetBlockByHash(chain.CurrentBlock().Hash())
if got := block.Transactions().Len(); got != numTxs*numBlocks {
b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got) b.Fatalf("Transactions were not included, expected %d, got %d", (numTxs * numBlocks), got)
} }
} }
@ -1516,7 +1517,7 @@ func TestBlocksHashCacheUpdate(t *testing.T) {
}) })
t.Run("Expect BlocksHashCache has 4 cached keys after concat a 4-length-chain", func(t *testing.T) { t.Run("Expect BlocksHashCache has 4 cached keys after concat a 4-length-chain", func(t *testing.T) {
concatedChain := makeBlockChain(chain.CurrentBlock(), 4, ethash.NewFullFaker(), chain.db, 0) concatedChain := makeBlockChain(chain.GetBlockByHash(chain.CurrentBlock().Hash()), 4, ethash.NewFullFaker(), chain.db, 0)
if _, err := chain.InsertChain(concatedChain); err != nil { if _, err := chain.InsertChain(concatedChain); err != nil {
t.Fatalf("failed to insert shared chain: %v", err) t.Fatalf("failed to insert shared chain: %v", err)
} }
@ -1540,7 +1541,7 @@ func TestBlocksHashCacheUpdate(t *testing.T) {
t.Run("Expect BlocksHashCache caches when inserting block on syncing", func(t *testing.T) { t.Run("Expect BlocksHashCache caches when inserting block on syncing", func(t *testing.T) {
currentCachedLength := len(chain.blocksHashCache.Keys()) currentCachedLength := len(chain.blocksHashCache.Keys())
singleBlockChain := makeBlockChain(chain.CurrentBlock(), 1, ethash.NewFaker(), chain.db, 0) singleBlockChain := makeBlockChain(chain.GetBlockByHash(chain.CurrentBlock().Hash()), 1, ethash.NewFaker(), chain.db, 0)
chain.insertBlock(singleBlockChain[0]) chain.insertBlock(singleBlockChain[0])
if len(chain.blocksHashCache.Keys()) != currentCachedLength+1 { if len(chain.blocksHashCache.Keys()) != currentCachedLength+1 {

View file

@ -87,7 +87,7 @@ func ExampleGenerateChain() {
} }
state, _ := blockchain.State() state, _ := blockchain.State()
fmt.Printf("last block: #%d\n", blockchain.CurrentBlock().Number()) fmt.Printf("last block: #%d\n", blockchain.CurrentBlock().Number)
fmt.Println("balance of addr1:", state.GetBalance(addr1)) fmt.Println("balance of addr1:", state.GetBalance(addr1))
fmt.Println("balance of addr2:", state.GetBalance(addr2)) fmt.Println("balance of addr2:", state.GetBalance(addr2))
fmt.Println("balance of addr3:", state.GetBalance(addr3)) fmt.Println("balance of addr3:", state.GetBalance(addr3))

View file

@ -43,21 +43,17 @@ func TestDAOForkRangeExtradata(t *testing.T) {
// Create the concurrent, conflicting two nodes // Create the concurrent, conflicting two nodes
proDb := rawdb.NewMemoryDatabase() proDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(proDb) gspec.MustCommit(proDb)
proConf := *params.TestChainConfig proConf := *params.TestChainConfig
proConf.DAOForkBlock = forkBlock proConf.DAOForkBlock = forkBlock
proConf.DAOForkSupport = true proConf.DAOForkSupport = true
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}) proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer proBc.Stop() defer proBc.Stop()
conDb := rawdb.NewMemoryDatabase() conDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(conDb) gspec.MustCommit(conDb)
conConf := *params.TestChainConfig conConf := *params.TestChainConfig
conConf.DAOForkBlock = forkBlock conConf.DAOForkBlock = forkBlock
conConf.DAOForkSupport = false conConf.DAOForkSupport = false
conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}) conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer conBc.Stop() defer conBc.Stop()
@ -73,9 +69,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
} }
@ -85,12 +80,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err) t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) bc.Stop()
blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err == nil { if _, err := conBc.InsertChain(blocks); err == nil {
t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0])
} }
// Create a proper no-fork block for the contra-forker // Create a proper no-fork block for the contra-forker
blocks, _ = GenerateChain(&conConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err != nil { if _, err := conBc.InsertChain(blocks); err != nil {
t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err) t.Fatalf("contra-fork chain didn't accepted no-fork block: %v", err)
} }
@ -98,9 +94,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) gspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
} }
@ -110,12 +105,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err) t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) bc.Stop()
blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err == nil { if _, err := proBc.InsertChain(blocks); err == nil {
t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0])
} }
// Create a proper pro-fork block for the pro-forker // Create a proper pro-fork block for the pro-forker
blocks, _ = GenerateChain(&proConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err != nil { if _, err := proBc.InsertChain(blocks); err != nil {
t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err) t.Fatalf("pro-fork chain didn't accepted pro-fork block: %v", err)
} }
@ -126,7 +122,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}) bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop() defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
} }
@ -136,7 +132,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err) t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&proConf, conBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err != nil { if _, err := conBc.InsertChain(blocks); err != nil {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
} }
@ -146,7 +142,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}) bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{})
defer bc.Stop() defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
} }
@ -156,7 +152,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err) t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&conConf, proBc.CurrentBlock(), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err != nil { if _, err := proBc.InsertChain(blocks); err != nil {
t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)
} }

View file

@ -402,7 +402,7 @@ func TestApplyTransactionWithEVMTracer(t *testing.T) {
blockNumber := big.NewInt(1) blockNumber := big.NewInt(1)
blockHash := genesis.Hash() blockHash := genesis.Hash()
vmContext := NewEVMBlockContext(blockchain.CurrentBlock().Header(), blockchain, nil) vmContext := NewEVMBlockContext(blockchain.CurrentBlock(), blockchain, nil)
evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, nil, blockchain.Config(), vmConfig) evm := vm.NewEVM(vmContext, vm.TxContext{}, statedb, nil, blockchain.Config(), vmConfig)
// Apply transaction // Apply transaction

View file

@ -72,7 +72,7 @@ type LendingPoolConfig struct {
// blockChain_XDCx add order state // blockChain_XDCx add order state
type blockChainLending interface { type blockChainLending interface {
CurrentBlock() *types.Block CurrentBlock() *types.Header
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
LendingStateAt(block *types.Block) (*lendingstate.LendingStateDB, error) LendingStateAt(block *types.Block) (*lendingstate.LendingStateDB, error)
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
@ -151,7 +151,7 @@ type LendingPool struct {
func NewLendingPool(chainconfig *params.ChainConfig, chain blockChainLending) *LendingPool { func NewLendingPool(chainconfig *params.ChainConfig, chain blockChainLending) *LendingPool {
// Sanitize the input to ensure no vulnerable gas prices are set // Sanitize the input to ensure no vulnerable gas prices are set
config := (&DefaultLendingPoolConfig).sanitize() config := (&DefaultLendingPoolConfig).sanitize()
log.Debug("NewLendingPool start...", "current block", chain.CurrentBlock().Header().Number) log.Debug("NewLendingPool start...", "current block", chain.CurrentBlock().Number)
// Create the transaction pool with its initial settings // Create the transaction pool with its initial settings
pool := &LendingPool{ pool := &LendingPool{
config: config, config: config,
@ -165,7 +165,7 @@ func NewLendingPool(chainconfig *params.ChainConfig, chain blockChainLending) *L
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
} }
pool.locals = newLendingAccountSet(pool.signer) pool.locals = newLendingAccountSet(pool.signer)
pool.reset(nil, chain.CurrentBlock()) pool.reset(chain.CurrentBlock())
// If local transactions and journaling is enabled, load from disk // If local transactions and journaling is enabled, load from disk
if !config.NoLocals && config.Journal != "" { if !config.NoLocals && config.Journal != "" {
@ -216,9 +216,13 @@ func (pool *LendingPool) loop() {
if pool.chainconfig.IsHomestead(ev.Block.Number()) { if pool.chainconfig.IsHomestead(ev.Block.Number()) {
pool.homestead = true pool.homestead = true
} }
log.Debug("LendingPool new chain header reset pool", "old", head.Header().Number, "new", ev.Block.Header().Number) if head != nil {
pool.reset(head, ev.Block) log.Debug("LendingPool new chain header reset pool", "old", head.Number, "new", ev.Block.Header().Number)
head = ev.Block } else {
log.Debug("LendingPool new chain header reset pool", "old", "nil", "new", ev.Block.Header().Number)
}
pool.reset(ev.Block.Header())
head = ev.Block.Header()
pool.mu.Unlock() pool.mu.Unlock()
} }
@ -268,19 +272,23 @@ func (pool *LendingPool) loop() {
// reset retrieves the current state of the blockchain and ensures the content // reset retrieves the current state of the blockchain and ensures the content
// of the transaction pool is valid with regard to the chain state. // of the transaction pool is valid with regard to the chain state.
func (pool *LendingPool) reset(oldHead, newblock *types.Block) { func (pool *LendingPool) reset(newHead *types.Header) {
if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number()) || pool.chain.Config().XDPoS == nil || pool.chain.CurrentBlock().NumberU64() <= pool.chain.Config().XDPoS.Epoch { if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number) || pool.chain.Config().XDPoS == nil || pool.chain.CurrentBlock().Number.Uint64() <= pool.chain.Config().XDPoS.Epoch {
return return
} }
// If we're reorging an old state, reinject all dropped transactions // If we're reorging an old state, reinject all dropped transactions
var reinject types.LendingTransactions var reinject types.LendingTransactions
// Initialize the internal state to the current head // Initialize the internal state to the current head
if newblock == nil { if newHead == nil {
newblock = pool.chain.CurrentBlock() newHead = pool.chain.CurrentBlock()
} }
newHead := newblock.Header() newBlock := pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64())
lendingState, err := pool.chain.LendingStateAt(newblock) if newBlock == nil {
log.Error("Not find block to reset LendingPool state", "number", newHead.Number, "hash", newHead.Hash())
return
}
lendingState, err := pool.chain.LendingStateAt(newBlock)
if err != nil { if err != nil {
log.Error("Failed to reset LendingPool state", "err", err) log.Error("Failed to reset LendingPool state", "err", err)
return return
@ -527,7 +535,12 @@ func (pool *LendingPool) validateBalance(cloneStateDb *state.StateDB, cloneLendi
if err != nil { if err != nil {
return err return err
} }
tradingStateDb, err := XDCXServ.GetTradingState(pool.chain.CurrentBlock(), author) newHead := pool.chain.CurrentBlock()
newBlock := pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64())
if newBlock == nil {
return fmt.Errorf("not find block to validate balance, number: %d, hash: %s", newHead.Number, newHead.Hash().Hex())
}
tradingStateDb, err := XDCXServ.GetTradingState(newBlock, author)
if err != nil { if err != nil {
return fmt.Errorf("validateLending: failed to get tradingStateDb. Error: %v", err) return fmt.Errorf("validateLending: failed to get tradingStateDb. Error: %v", err)
} }
@ -808,7 +821,7 @@ func (pool *LendingPool) AddRemotes(txs []*types.LendingTransaction) []error {
// addTx enqueues a single transaction into the pool if it is valid. // addTx enqueues a single transaction into the pool if it is valid.
func (pool *LendingPool) addTx(tx *types.LendingTransaction, local bool) error { func (pool *LendingPool) addTx(tx *types.LendingTransaction, local bool) error {
if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number()) { if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number) {
return nil return nil
} }
tx.CacheHash() tx.CacheHash()

View file

@ -81,7 +81,7 @@ type OrderPoolConfig struct {
// blockChain_XDCx add order state // blockChain_XDCx add order state
type blockChainXDCx interface { type blockChainXDCx interface {
CurrentBlock() *types.Block CurrentBlock() *types.Header
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
OrderStateAt(block *types.Block) (*tradingstate.TradingStateDB, error) OrderStateAt(block *types.Block) (*tradingstate.TradingStateDB, error)
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
@ -160,7 +160,7 @@ type OrderPool struct {
func NewOrderPool(chainconfig *params.ChainConfig, chain blockChainXDCx) *OrderPool { func NewOrderPool(chainconfig *params.ChainConfig, chain blockChainXDCx) *OrderPool {
// Sanitize the input to ensure no vulnerable gas prices are set // Sanitize the input to ensure no vulnerable gas prices are set
config := (&DefaultOrderPoolConfig).sanitize() config := (&DefaultOrderPoolConfig).sanitize()
log.Debug("NewOrderPool start...", "current block", chain.CurrentBlock().Header().Number) log.Debug("NewOrderPool start...", "current block", chain.CurrentBlock().Number)
// Create the transaction pool with its initial settings // Create the transaction pool with its initial settings
pool := &OrderPool{ pool := &OrderPool{
config: config, config: config,
@ -174,7 +174,7 @@ func NewOrderPool(chainconfig *params.ChainConfig, chain blockChainXDCx) *OrderP
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
} }
pool.locals = newOrderAccountSet(pool.signer) pool.locals = newOrderAccountSet(pool.signer)
pool.reset(nil, chain.CurrentBlock()) pool.reset(chain.CurrentBlock())
// If local transactions and journaling is enabled, load from disk // If local transactions and journaling is enabled, load from disk
if !config.NoLocals && config.Journal != "" { if !config.NoLocals && config.Journal != "" {
@ -224,9 +224,13 @@ func (pool *OrderPool) loop() {
if pool.chainconfig.IsHomestead(ev.Block.Number()) { if pool.chainconfig.IsHomestead(ev.Block.Number()) {
pool.homestead = true pool.homestead = true
} }
log.Debug("OrderPool new chain header reset pool", "old", head.Header().Number, "new", ev.Block.Header().Number) if head != nil {
pool.reset(head, ev.Block) log.Debug("OrderPool new chain header reset pool", "old", head.Number, "new", ev.Block.Header().Number)
head = ev.Block } else {
log.Debug("OrderPool new chain header reset pool", "old", "nil", "new", ev.Block.Header().Number)
}
pool.reset(ev.Block.Header())
head = ev.Block.Header()
pool.mu.Unlock() pool.mu.Unlock()
} }
@ -274,19 +278,23 @@ func (pool *OrderPool) loop() {
// reset retrieves the current state of the blockchain and ensures the content // reset retrieves the current state of the blockchain and ensures the content
// of the transaction pool is valid with regard to the chain state. // of the transaction pool is valid with regard to the chain state.
func (pool *OrderPool) reset(oldHead, newblock *types.Block) { func (pool *OrderPool) reset(newHead *types.Header) {
if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number()) || pool.chain.Config().XDPoS == nil || pool.chain.CurrentBlock().NumberU64() <= pool.chain.Config().XDPoS.Epoch { if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number) || pool.chain.Config().XDPoS == nil || pool.chain.CurrentBlock().Number.Uint64() <= pool.chain.Config().XDPoS.Epoch {
return return
} }
// If we're reorging an old state, reinject all dropped transactions // If we're reorging an old state, reinject all dropped transactions
var reinject types.OrderTransactions var reinject types.OrderTransactions
// Initialize the internal state to the current head // Initialize the internal state to the current head
if newblock == nil { if newHead == nil {
newblock = pool.chain.CurrentBlock() newHead = pool.chain.CurrentBlock()
} }
newHead := newblock.Header() newBlock := pool.chain.GetBlock(newHead.Hash(), newHead.Number.Uint64())
orderstate, err := pool.chain.OrderStateAt(newblock) if newBlock == nil {
log.Error("Not find block to reset OrderPool state", "number", newHead.Number, "hash", newHead.Hash())
return
}
orderstate, err := pool.chain.OrderStateAt(newBlock)
if err != nil { if err != nil {
log.Error("Failed to reset OrderPool state", "err", err) log.Error("Failed to reset OrderPool state", "err", err)
return return
@ -722,7 +730,7 @@ func (pool *OrderPool) AddRemotes(txs []*types.OrderTransaction) []error {
// addTx enqueues a single transaction into the pool if it is valid. // addTx enqueues a single transaction into the pool if it is valid.
func (pool *OrderPool) addTx(tx *types.OrderTransaction, local bool) error { func (pool *OrderPool) addTx(tx *types.OrderTransaction, local bool) error {
if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number()) { if !pool.chainconfig.IsTIPXDCXReceiver(pool.chain.CurrentBlock().Number) {
return nil return nil
} }
tx.CacheHash() tx.CacheHash()

View file

@ -162,7 +162,7 @@ const (
// blockChain provides the state of blockchain and current gas limit to do // blockChain provides the state of blockchain and current gas limit to do
// some pre checks in tx pool and event subscribers. // some pre checks in tx pool and event subscribers.
type blockChain interface { type blockChain interface {
CurrentBlock() *types.Block CurrentBlock() *types.Header
GetBlock(hash common.Hash, number uint64) *types.Block GetBlock(hash common.Hash, number uint64) *types.Block
StateAt(root common.Hash) (*state.StateDB, error) StateAt(root common.Hash) (*state.StateDB, error)
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
@ -339,7 +339,7 @@ func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain)
pool.locals.add(addr) pool.locals.add(addr)
} }
pool.priced = newPricedList(pool.all) pool.priced = newPricedList(pool.all)
pool.reset(nil, chain.CurrentBlock().Header()) pool.reset(nil, chain.CurrentBlock())
// Start the reorg loop early so it can handle requests generated during journal loading. // Start the reorg loop early so it can handle requests generated during journal loading.
pool.wg.Go(pool.scheduleReorgLoop) pool.wg.Go(pool.scheduleReorgLoop)
@ -387,8 +387,8 @@ func (pool *TxPool) loop() {
// Handle ChainHeadEvent // Handle ChainHeadEvent
case ev := <-pool.chainHeadCh: case ev := <-pool.chainHeadCh:
if ev.Block != nil { if ev.Block != nil {
pool.requestReset(head.Header(), ev.Block.Header()) pool.requestReset(head, ev.Block.Header())
head = ev.Block head = ev.Block.Header()
} }
// System shutdown. // System shutdown.
@ -1506,7 +1506,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
} }
// Initialize the internal state to the current head // Initialize the internal state to the current head
if newHead == nil { if newHead == nil {
newHead = pool.chain.CurrentBlock().Header() // Special case during testing newHead = pool.chain.CurrentBlock() // Special case during testing
} }
statedb, err := pool.chain.StateAt(newHead.Root) statedb, err := pool.chain.StateAt(newHead.Root)
if err != nil { if err != nil {

View file

@ -83,15 +83,16 @@ func (bc *testBlockChain) Config() *params.ChainConfig {
return nil return nil
} }
func (bc *testBlockChain) CurrentBlock() *types.Block { func (bc *testBlockChain) CurrentBlock() *types.Header {
return types.NewBlock(&types.Header{ return &types.Header{
Root: types.EmptyRootHash, Root: types.EmptyRootHash,
Number: new(big.Int),
GasLimit: atomic.LoadUint64(&bc.gasLimit), GasLimit: atomic.LoadUint64(&bc.gasLimit),
}, nil, nil, trie.NewStackTrie(nil)) }
} }
func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
return bc.CurrentBlock() return types.NewBlock(bc.CurrentBlock(), nil, nil, trie.NewStackTrie(nil))
} }
func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) {

View file

@ -411,7 +411,7 @@ func (b *Block) HashNoValidator() common.Hash {
} }
// Size returns the true RLP encoded storage size of the block, either by encoding // Size returns the true RLP encoded storage size of the block, either by encoding
// and returning it, or returning a previsouly cached value. // and returning it, or returning a previously cached value.
func (b *Block) Size() uint64 { func (b *Block) Size() uint64 {
if size := b.size.Load(); size > 0 { if size := b.size.Load(); size > 0 {
return size return size

View file

@ -242,7 +242,7 @@ func (tx *LendingTransaction) CacheHash() {
} }
// Size returns the true RLP encoded storage size of the transaction, either by // Size returns the true RLP encoded storage size of the transaction, either by
// encoding and returning it, or returning a previsouly cached value. // encoding and returning it, or returning a previously cached value.
func (tx *LendingTransaction) Size() common.StorageSize { func (tx *LendingTransaction) Size() common.StorageSize {
if size := tx.size.Load(); size != nil { if size := tx.size.Load(); size != nil {
return size.(common.StorageSize) return size.(common.StorageSize)

View file

@ -185,7 +185,7 @@ func (tx *OrderTransaction) CacheHash() {
} }
// Size returns the true RLP encoded storage size of the transaction, either by // Size returns the true RLP encoded storage size of the transaction, either by
// encoding and returning it, or returning a previsouly cached value. // encoding and returning it, or returning a previously cached value.
func (tx *OrderTransaction) Size() common.StorageSize { func (tx *OrderTransaction) Size() common.StorageSize {
if size := tx.size.Load(); size != nil { if size := tx.size.Load(); size != nil {
return size.(common.StorageSize) return size.(common.StorageSize)

View file

@ -57,7 +57,7 @@ func (api *EthereumAPI) Mining() bool {
func (api *EthereumAPI) ChainId() hexutil.Uint64 { func (api *EthereumAPI) ChainId() hexutil.Uint64 {
chainID := new(big.Int) chainID := new(big.Int)
if config := api.e.chainConfig; config.IsEIP155(api.e.blockchain.CurrentBlock().Number()) { if config := api.e.chainConfig; config.IsEIP155(api.e.blockchain.CurrentBlock().Number) {
chainID = config.ChainID chainID = config.ChainID
} }
return (hexutil.Uint64)(chainID.Uint64()) return (hexutil.Uint64)(chainID.Uint64())

View file

@ -68,7 +68,7 @@ func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
return b.eth.chainConfig return b.eth.chainConfig
} }
func (b *EthAPIBackend) CurrentBlock() *types.Block { func (b *EthAPIBackend) CurrentBlock() *types.Header {
return b.eth.blockchain.CurrentBlock() return b.eth.blockchain.CurrentBlock()
} }
@ -84,13 +84,13 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
} }
// Otherwise resolve and return the block // Otherwise resolve and return the block
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock().Header(), nil return b.eth.blockchain.CurrentBlock(), nil
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
if b.eth.chainConfig.XDPoS == nil { if b.eth.chainConfig.XDPoS == nil {
return nil, errors.New("PoW does not support confirmed block lookup") return nil, errors.New("PoW does not support confirmed block lookup")
} }
current := b.eth.blockchain.CurrentBlock().Header() current := b.eth.blockchain.CurrentBlock()
if b.eth.blockchain.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 { if b.eth.blockchain.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 {
// TO CHECK: why calling config in XDPoS is blocked (not field and method) // TO CHECK: why calling config in XDPoS is blocked (not field and method)
confirmedHash := b.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash confirmedHash := b.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
@ -136,13 +136,17 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
} }
// Otherwise resolve and return the block // Otherwise resolve and return the block
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock(), nil header := b.eth.blockchain.CurrentBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
if b.eth.chainConfig.XDPoS == nil { if b.eth.chainConfig.XDPoS == nil {
return nil, errors.New("PoW does not support confirmed block lookup") return nil, errors.New("PoW does not support confirmed block lookup")
} }
current := b.eth.blockchain.CurrentBlock().Header() current := b.eth.blockchain.CurrentBlock()
if current == nil {
return nil, errors.New("current block is nil")
}
if b.eth.blockchain.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 { if b.eth.blockchain.Config().XDPoS.BlockConsensusVersion(current.Number) == params.ConsensusEngineVersion2 {
// TO CHECK: why calling config in XDPoS is blocked (not field and method) // TO CHECK: why calling config in XDPoS is blocked (not field and method)
confirmedHash := b.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash confirmedHash := b.XDPoS.EngineV2.GetLatestCommittedBlockInfo().Hash
@ -465,19 +469,19 @@ func (b *EthAPIBackend) GetRewardByHash(hash common.Hash) map[string]map[string]
// 4. Calculate voters's rewards for input masternode // 4. Calculate voters's rewards for input masternode
func (b *EthAPIBackend) GetVotersRewards(masternodeAddr common.Address) map[common.Address]*big.Int { func (b *EthAPIBackend) GetVotersRewards(masternodeAddr common.Address) map[common.Address]*big.Int {
chain := b.eth.blockchain chain := b.eth.blockchain
block := chain.CurrentBlock() header := chain.CurrentBlock()
number := block.Number().Uint64() number := header.Number.Uint64()
engine := b.Engine().(*XDPoS.XDPoS) engine := b.Engine().(*XDPoS.XDPoS)
foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr foundationWalletAddr := chain.Config().XDPoS.FoudationWalletAddr
// calculate for 2 epochs ago // calculate for 2 epochs ago
currentCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, block.Number()) currentCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, header.Number)
if err != nil { if err != nil {
log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for current checkpoint block", "block", block.Number(), "err", err) log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for current checkpoint block", "block", header.Number, "err", err)
} }
lastCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, big.NewInt(int64(currentCheckpointNumber-1))) lastCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, big.NewInt(int64(currentCheckpointNumber-1)))
if err != nil { if err != nil {
log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for last checkpoint block", "block", block.Number(), "err", err) log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for last checkpoint block", "block", header.Number, "err", err)
} }
lastCheckpointBlock := chain.GetBlockByNumber(lastCheckpointNumber) lastCheckpointBlock := chain.GetBlockByNumber(lastCheckpointNumber)
@ -567,8 +571,8 @@ func (b *EthAPIBackend) GetVotersCap(checkpoint *big.Int, masterAddr common.Addr
// ie 30min for each epoch // ie 30min for each epoch
func (b *EthAPIBackend) GetEpochDuration() *big.Int { func (b *EthAPIBackend) GetEpochDuration() *big.Int {
chain := b.eth.blockchain chain := b.eth.blockchain
block := chain.CurrentBlock() header := chain.CurrentBlock()
number := block.Number().Uint64() number := header.Number.Uint64()
lastCheckpointNumber := number - (number % b.ChainConfig().XDPoS.Epoch) lastCheckpointNumber := number - (number % b.ChainConfig().XDPoS.Epoch)
lastCheckpointBlockTime := chain.GetBlockByNumber(lastCheckpointNumber).Time() lastCheckpointBlockTime := chain.GetBlockByNumber(lastCheckpointNumber).Time()
secondToLastCheckpointNumber := lastCheckpointNumber - b.ChainConfig().XDPoS.Epoch secondToLastCheckpointNumber := lastCheckpointNumber - b.ChainConfig().XDPoS.Epoch

View file

@ -55,16 +55,20 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
if blockNr == rpc.PendingBlockNumber { if blockNr == rpc.PendingBlockNumber {
blockNr = rpc.LatestBlockNumber blockNr = rpc.LatestBlockNumber
} }
var block *types.Block var header *types.Header
if blockNr == rpc.LatestBlockNumber { if blockNr == rpc.LatestBlockNumber {
block = api.eth.blockchain.CurrentBlock() header = api.eth.blockchain.CurrentBlock()
} else { } else {
block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr)) block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
if block == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
}
header = block.Header()
} }
if block == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
} }
stateDb, err := api.eth.BlockChain().StateAt(block.Root()) stateDb, err := api.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
} }
@ -128,16 +132,20 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start []b
// the miner and operate on those // the miner and operate on those
_, stateDb = api.eth.miner.Pending() _, stateDb = api.eth.miner.Pending()
} else { } else {
var block *types.Block var header *types.Header
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
block = api.eth.blockchain.CurrentBlock() header = api.eth.blockchain.CurrentBlock()
} else { } else {
block = api.eth.blockchain.GetBlockByNumber(uint64(number)) block := api.eth.blockchain.GetBlockByNumber(uint64(number))
if block == nil {
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
}
header = block.Header()
} }
if block == nil { if header == nil {
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number) return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
} }
stateDb, err = api.eth.BlockChain().StateAt(block.Root()) stateDb, err = api.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return state.IteratorDump{}, err return state.IteratorDump{}, err
} }

View file

@ -235,7 +235,7 @@ func New(stack *node.Node, config *ethconfig.Config, XDCXServ *XDCx.XDCX, lendin
if currentBlock == nil { if currentBlock == nil {
return nil, fmt.Errorf("not find current block when rollback to %d", common.RollbackNumber) return nil, fmt.Errorf("not find current block when rollback to %d", common.RollbackNumber)
} }
currentNumber := currentBlock.NumberU64() currentNumber := currentBlock.Number.Uint64()
if target > currentNumber { if target > currentNumber {
return nil, fmt.Errorf("can't rollback to %d which is greater than current %d", target, currentNumber) return nil, fmt.Errorf("can't rollback to %d which is greater than current %d", target, currentNumber)
} }

View file

@ -189,11 +189,11 @@ type BlockChain interface {
// GetBlockByHash retrieves a block from the local chain. // GetBlockByHash retrieves a block from the local chain.
GetBlockByHash(common.Hash) *types.Block GetBlockByHash(common.Hash) *types.Block
// CurrentBlock retrieves the head block from the local chain. // CurrentBlock retrieves the header of the head block from the local chain.
CurrentBlock() *types.Block CurrentBlock() *types.Header
// CurrentFastBlock retrieves the head fast block from the local chain. // CurrentSnapBlock retrieves the header of the head snap block from the local chain.
CurrentFastBlock() *types.Block CurrentSnapBlock() *types.Header
// FastSyncCommitHead directly commits the head block to a certain entity. // FastSyncCommitHead directly commits the head block to a certain entity.
FastSyncCommitHead(common.Hash) error FastSyncCommitHead(common.Hash) error
@ -264,9 +264,9 @@ func (d *Downloader) Progress() XDPoSChain.SyncProgress {
mode := d.getMode() mode := d.getMode()
switch { switch {
case d.blockchain != nil && mode == FullSync: case d.blockchain != nil && mode == FullSync:
current = d.blockchain.CurrentBlock().NumberU64() current = d.blockchain.CurrentBlock().Number.Uint64()
case d.blockchain != nil && mode == FastSync: case d.blockchain != nil && mode == FastSync:
current = d.blockchain.CurrentFastBlock().NumberU64() current = d.blockchain.CurrentSnapBlock().Number.Uint64()
case d.lightchain != nil: case d.lightchain != nil:
current = d.lightchain.CurrentHeader().Number.Uint64() current = d.lightchain.CurrentHeader().Number.Uint64()
default: default:
@ -671,9 +671,9 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
mode := d.getMode() mode := d.getMode()
switch mode { switch mode {
case FullSync: case FullSync:
localHeight = d.blockchain.CurrentBlock().NumberU64() localHeight = d.blockchain.CurrentBlock().Number.Uint64()
case FastSync: case FastSync:
localHeight = d.blockchain.CurrentFastBlock().NumberU64() localHeight = d.blockchain.CurrentSnapBlock().Number.Uint64()
default: default:
localHeight = d.lightchain.CurrentHeader().Number.Uint64() localHeight = d.lightchain.CurrentHeader().Number.Uint64()
} }
@ -943,8 +943,8 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, pivot uint64)
if mode == LightSync { if mode == LightSync {
head = d.lightchain.CurrentHeader().Number.Uint64() head = d.lightchain.CurrentHeader().Number.Uint64()
} else { } else {
head = d.blockchain.CurrentFastBlock().NumberU64() head = d.blockchain.CurrentSnapBlock().Number.Uint64()
if full := d.blockchain.CurrentBlock().NumberU64(); head < full { if full := d.blockchain.CurrentBlock().Number.Uint64(); head < full {
head = full head = full
} }
} }
@ -1311,14 +1311,14 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
} }
lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0 lastHeader, lastFastBlock, lastBlock := d.lightchain.CurrentHeader().Number, common.Big0, common.Big0
if mode != LightSync { if mode != LightSync {
lastFastBlock = d.blockchain.CurrentFastBlock().Number() lastFastBlock = d.blockchain.CurrentSnapBlock().Number
lastBlock = d.blockchain.CurrentBlock().Number() lastBlock = d.blockchain.CurrentBlock().Number
} }
d.lightchain.Rollback(hashes) d.lightchain.Rollback(hashes)
curFastBlock, curBlock := common.Big0, common.Big0 curFastBlock, curBlock := common.Big0, common.Big0
if mode != LightSync { if mode != LightSync {
curFastBlock = d.blockchain.CurrentFastBlock().Number() curFastBlock = d.blockchain.CurrentSnapBlock().Number
curBlock = d.blockchain.CurrentBlock().Number() curBlock = d.blockchain.CurrentBlock().Number
} }
log.Warn("Rolled back headers", "count", len(hashes), log.Warn("Rolled back headers", "count", len(hashes),
"header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number), "header", fmt.Sprintf("%d->%d", lastHeader, d.lightchain.CurrentHeader().Number),
@ -1360,7 +1360,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
// R: Nothing to give // R: Nothing to give
if mode != LightSync { if mode != LightSync {
head := d.blockchain.CurrentBlock() head := d.blockchain.CurrentBlock()
if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.NumberU64())) > 0 { if !gotHeaders && td.Cmp(d.blockchain.GetTd(head.Hash(), head.Number.Uint64())) > 0 {
return errStallingPeer return errStallingPeer
} }
} }

View file

@ -168,31 +168,31 @@ func (dl *downloadTester) CurrentHeader() *types.Header {
} }
// CurrentBlock retrieves the current head block from the canonical chain. // CurrentBlock retrieves the current head block from the canonical chain.
func (dl *downloadTester) CurrentBlock() *types.Block { func (dl *downloadTester) CurrentBlock() *types.Header {
dl.lock.RLock() dl.lock.RLock()
defer dl.lock.RUnlock() defer dl.lock.RUnlock()
for i := len(dl.ownHashes) - 1; i >= 0; i-- { for i := len(dl.ownHashes) - 1; i >= 0; i-- {
if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil { if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil {
if _, err := dl.stateDb.Get(block.Root().Bytes()); err == nil { if _, err := dl.stateDb.Get(block.Root().Bytes()); err == nil {
return block return block.Header()
} }
} }
} }
return dl.genesis return dl.genesis.Header()
} }
// CurrentFastBlock retrieves the current head fast-sync block from the canonical chain. // CurrentFastBlock retrieves the current head fast-sync block from the canonical chain.
func (dl *downloadTester) CurrentFastBlock() *types.Block { func (dl *downloadTester) CurrentSnapBlock() *types.Header {
dl.lock.RLock() dl.lock.RLock()
defer dl.lock.RUnlock() defer dl.lock.RUnlock()
for i := len(dl.ownHashes) - 1; i >= 0; i-- { for i := len(dl.ownHashes) - 1; i >= 0; i-- {
if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil { if block := dl.ownBlocks[dl.ownHashes[i]]; block != nil {
return block return block.Header()
} }
} }
return dl.genesis return dl.genesis.Header()
} }
// FastSyncCommitHead manually sets the head block to a given hash. // FastSyncCommitHead manually sets the head block to a given hash.
@ -1002,7 +1002,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch)
} }
if mode == FastSync { if mode == FastSync {
if head := tester.CurrentBlock().NumberU64(); head != 0 { if head := tester.CurrentBlock().Number.Uint64(); head != 0 {
t.Errorf("fast sync pivot block #%d not rolled back", head) t.Errorf("fast sync pivot block #%d not rolled back", head)
} }
} }
@ -1025,7 +1025,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch) t.Errorf("rollback head mismatch: have %v, want at most %v", head, 2*fsHeaderSafetyNet+MaxHeaderFetch)
} }
if mode == FastSync { if mode == FastSync {
if head := tester.CurrentBlock().NumberU64(); head != 0 { if head := tester.CurrentBlock().Number.Uint64(); head != 0 {
t.Errorf("fast sync pivot block #%d not rolled back", head) t.Errorf("fast sync pivot block #%d not rolled back", head)
} }
} }

View file

@ -140,7 +140,7 @@ func (d *Downloader) runStateSync(s *stateSync) *stateSync {
// Handle incoming state packs: // Handle incoming state packs:
case pack := <-d.stateCh: case pack := <-d.stateCh:
// Discard any data not requested (or previsouly timed out) // Discard any data not requested (or previously timed out)
req := active[pack.PeerId()] req := active[pack.PeerId()]
if req == nil { if req == nil {
log.Debug("Unrequested node data", "peer", pack.PeerId(), "len", pack.Items()) log.Debug("Unrequested node data", "peer", pack.PeerId(), "len", pack.Items())

View file

@ -49,7 +49,7 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber
number = 0 number = 0
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
return b.chain.CurrentBlock().Header(), nil return b.chain.CurrentBlock(), nil
} }
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
number = testHead number = testHead
@ -72,7 +72,7 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
number = 0 number = 0
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
return b.chain.CurrentBlock(), nil number = rpc.BlockNumber(b.chain.CurrentBlock().Number.Uint64())
} }
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
number = testHead number = testHead

View file

@ -68,7 +68,7 @@ func errResp(code errCode, format string, v ...interface{}) error {
type ProtocolManager struct { type ProtocolManager struct {
networkId uint64 networkId uint64
fastSync uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks) snapSync uint32 // Flag whether snap sync is enabled (gets disabled if we already have blocks)
acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing) acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing)
txpool txPool txpool txPool
@ -151,12 +151,12 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
lendingTxSub: nil, lendingTxSub: nil,
} }
// Figure out whether to allow fast sync or not // Figure out whether to allow fast sync or not
if mode == downloader.FastSync && blockchain.CurrentBlock().NumberU64() > 0 { if mode == downloader.FastSync && blockchain.CurrentBlock().Number.Uint64() > 0 {
log.Warn("Blockchain not empty, fast sync disabled") log.Warn("Blockchain not empty, fast sync disabled")
mode = downloader.FullSync mode = downloader.FullSync
} }
if mode == downloader.FastSync { if mode == downloader.FastSync {
manager.fastSync = uint32(1) manager.snapSync = uint32(1)
} }
// Initiate a sub-protocol for every implemented version we can handle // Initiate a sub-protocol for every implemented version we can handle
manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions)) manager.SubProtocols = make([]p2p.Protocol, 0, len(ProtocolVersions))
@ -215,12 +215,12 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
} }
heighter := func() uint64 { heighter := func() uint64 {
return blockchain.CurrentBlock().NumberU64() return blockchain.CurrentBlock().Number.Uint64()
} }
inserter := func(block *types.Block) error { inserter := func(block *types.Block) error {
// If fast sync is running, deny importing weird blocks // If fast sync is running, deny importing weird blocks
if atomic.LoadUint32(&manager.fastSync) == 1 { if atomic.LoadUint32(&manager.snapSync) == 1 {
log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash()) log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash())
return nil return nil
} }
@ -230,7 +230,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
prepare := func(block *types.Block) error { prepare := func(block *types.Block) error {
// If fast sync is running, deny importing weird blocks // If fast sync is running, deny importing weird blocks
if atomic.LoadUint32(&manager.fastSync) == 1 { if atomic.LoadUint32(&manager.snapSync) == 1 {
log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash()) log.Warn("Discarded bad propagated block", "number", block.Number(), "hash", block.Hash())
return nil return nil
} }
@ -751,7 +751,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// a singe block (as the true TD is below the propagated block), however this // a singe block (as the true TD is below the propagated block), however this
// scenario should easily be covered by the fetcher. // scenario should easily be covered by the fetcher.
currentBlock := pm.blockchain.CurrentBlock() currentBlock := pm.blockchain.CurrentBlock()
if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 { if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.Number.Uint64())) > 0 {
go pm.synchronise(p) go pm.synchronise(p)
} }
} }
@ -1096,7 +1096,7 @@ func (pm *ProtocolManager) NodeInfo() *NodeInfo {
currentBlock := pm.blockchain.CurrentBlock() currentBlock := pm.blockchain.CurrentBlock()
return &NodeInfo{ return &NodeInfo{
Network: pm.networkId, Network: pm.networkId,
Difficulty: pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()), Difficulty: pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.Number.Uint64()),
Genesis: pm.blockchain.Genesis().Hash(), Genesis: pm.blockchain.Genesis().Hash(),
Config: pm.blockchain.Config(), Config: pm.blockchain.Config(),
Head: currentBlock.Hash(), Head: currentBlock.Hash(),

View file

@ -132,20 +132,20 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
&getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1}, &getBlockHeadersData{Origin: hashOrNumber{Number: 0}, Amount: 1},
[]common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()}, []common.Hash{pm.blockchain.GetBlockByNumber(0).Hash()},
}, { }, {
&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64()}, Amount: 1}, &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().Number.Uint64()}, Amount: 1},
[]common.Hash{pm.blockchain.CurrentBlock().Hash()}, []common.Hash{pm.blockchain.CurrentBlock().Hash()},
}, },
// Ensure protocol limits are honored // Ensure protocol limits are honored
{ {
&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true}, &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().Number.Uint64() - 1}, Amount: limit + 10, Reverse: true},
pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit), pm.blockchain.GetBlockHashesFromHash(pm.blockchain.CurrentBlock().Hash(), limit),
}, },
// Check that requesting more than available is handled gracefully // Check that requesting more than available is handled gracefully
{ {
&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 3, Amount: 3}, &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().Number.Uint64() - 4}, Skip: 3, Amount: 3},
[]common.Hash{ []common.Hash{
pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().Number.Uint64() - 4).Hash(),
pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64()).Hash(), pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().Number.Uint64()).Hash(),
}, },
}, { }, {
&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true}, &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 3, Amount: 3, Reverse: true},
@ -156,10 +156,10 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
}, },
// Check that requesting more than available is handled gracefully, even if mid skip // Check that requesting more than available is handled gracefully, even if mid skip
{ {
&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() - 4}, Skip: 2, Amount: 3}, &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().Number.Uint64() - 4}, Skip: 2, Amount: 3},
[]common.Hash{ []common.Hash{
pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 4).Hash(), pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().Number.Uint64() - 4).Hash(),
pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().NumberU64() - 1).Hash(), pm.blockchain.GetBlockByNumber(pm.blockchain.CurrentBlock().Number.Uint64() - 1).Hash(),
}, },
}, { }, {
&getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true}, &getBlockHeadersData{Origin: hashOrNumber{Number: 4}, Skip: 2, Amount: 3, Reverse: true},
@ -196,7 +196,7 @@ func testGetBlockHeaders(t *testing.T, protocol int) {
&getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1}, &getBlockHeadersData{Origin: hashOrNumber{Hash: unknown}, Amount: 1},
[]common.Hash{}, []common.Hash{},
}, { }, {
&getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().NumberU64() + 1}, Amount: 1}, &getBlockHeadersData{Origin: hashOrNumber{Number: pm.blockchain.CurrentBlock().Number.Uint64() + 1}, Amount: 1},
[]common.Hash{}, []common.Hash{},
}, },
} }
@ -270,7 +270,7 @@ func testGetBlockBodies(t *testing.T, protocol int) {
for j := 0; j < tt.random; j++ { for j := 0; j < tt.random; j++ {
for { for {
num := rand.Int63n(int64(pm.blockchain.CurrentBlock().NumberU64())) num := rand.Int63n(int64(pm.blockchain.CurrentBlock().Number.Uint64()))
if !seen[num] { if !seen[num] {
seen[num] = true seen[num] = true
@ -374,7 +374,7 @@ func testGetNodeData(t *testing.T, protocol int) {
statedb.Put(hashes[i].Bytes(), data[i]) statedb.Put(hashes[i].Bytes(), data[i])
} }
accounts := []common.Address{testBank, acc1Addr, acc2Addr} accounts := []common.Address{testBank, acc1Addr, acc2Addr}
for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { for i := uint64(0); i <= pm.blockchain.CurrentBlock().Number.Uint64(); i++ {
trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb)) trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb))
for j, acc := range accounts { for j, acc := range accounts {
@ -438,7 +438,7 @@ func testGetReceipt(t *testing.T, protocol int) {
// Collect the hashes to request, and the response to expect // Collect the hashes to request, and the response to expect
hashes, receipts := []common.Hash{}, []types.Receipts{} hashes, receipts := []common.Hash{}, []types.Receipts{}
for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ { for i := uint64(0); i <= pm.blockchain.CurrentBlock().Number.Uint64(); i++ {
block := pm.blockchain.GetBlockByNumber(i) block := pm.blockchain.GetBlockByNumber(i)
hashes = append(hashes, block.Hash()) hashes = append(hashes, block.Hash())

View file

@ -170,29 +170,29 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
} }
// Make sure the peer's TD is higher than our own // Make sure the peer's TD is higher than our own
currentBlock := pm.blockchain.CurrentBlock() currentBlock := pm.blockchain.CurrentBlock()
td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) td := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.Number.Uint64())
pHead, pTd := peer.Head() pHead, pTd := peer.Head()
if pTd.Cmp(td) <= 0 { if pTd.Cmp(td) <= 0 {
return return
} }
// Otherwise try to sync with the downloader // Otherwise try to sync with the downloader
mode := downloader.FullSync mode := downloader.FullSync
if atomic.LoadUint32(&pm.fastSync) == 1 { if atomic.LoadUint32(&pm.snapSync) == 1 {
// Fast sync was explicitly requested, and explicitly granted // Fast sync was explicitly requested, and explicitly granted
mode = downloader.FastSync mode = downloader.FastSync
} else if currentBlock.NumberU64() == 0 && pm.blockchain.CurrentFastBlock().NumberU64() > 0 { } else if currentBlock.Number.Uint64() == 0 && pm.blockchain.CurrentSnapBlock().Number.Uint64() > 0 {
// The database seems empty as the current block is the genesis. Yet the fast // The database seems empty as the current block is the genesis. Yet the fast
// block is ahead, so fast sync was enabled for this node at a certain point. // block is ahead, so fast sync was enabled for this node at a certain point.
// The only scenario where this can happen is if the user manually (or via a // The only scenario where this can happen is if the user manually (or via a
// bad block) rolled back a fast sync node below the sync point. In this case // bad block) rolled back a fast sync node below the sync point. In this case
// however it's safe to reenable fast sync. // however it's safe to reenable fast sync.
atomic.StoreUint32(&pm.fastSync, 1) atomic.StoreUint32(&pm.snapSync, 1)
mode = downloader.FastSync mode = downloader.FastSync
} }
if mode == downloader.FastSync { if mode == downloader.FastSync {
// Make sure the peer's total difficulty we are synchronizing is higher. // Make sure the peer's total difficulty we are synchronizing is higher.
if pm.blockchain.GetTdByHash(pm.blockchain.CurrentFastBlock().Hash()).Cmp(pTd) >= 0 { if pm.blockchain.GetTdByHash(pm.blockchain.CurrentSnapBlock().Hash()).Cmp(pTd) >= 0 {
return return
} }
} }
@ -201,9 +201,9 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil { if err := pm.downloader.Synchronise(peer.id, pHead, pTd, mode); err != nil {
return return
} }
if atomic.LoadUint32(&pm.fastSync) == 1 { if atomic.LoadUint32(&pm.snapSync) == 1 {
log.Info("Fast sync complete, auto disabling") log.Info("Fast sync complete, auto disabling")
atomic.StoreUint32(&pm.fastSync, 0) atomic.StoreUint32(&pm.snapSync, 0)
} }
atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done atomic.StoreUint32(&pm.acceptTxs, 1) // Mark initial sync done
//if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 { //if head := pm.blockchain.CurrentBlock(); head.NumberU64() > 0 {

View file

@ -31,13 +31,13 @@ import (
func TestFastSyncDisabling(t *testing.T) { func TestFastSyncDisabling(t *testing.T) {
// Create a pristine protocol manager, check that fast sync is left enabled // Create a pristine protocol manager, check that fast sync is left enabled
pmEmpty, _ := newTestProtocolManagerMust(t, downloader.FastSync, 0, nil, nil) pmEmpty, _ := newTestProtocolManagerMust(t, downloader.FastSync, 0, nil, nil)
if atomic.LoadUint32(&pmEmpty.fastSync) == 0 { if atomic.LoadUint32(&pmEmpty.snapSync) == 0 {
t.Fatalf("fast sync disabled on pristine blockchain") t.Fatalf("snap sync disabled on pristine blockchain")
} }
// Create a full protocol manager, check that fast sync gets disabled // Create a full protocol manager, check that snap sync gets disabled
pmFull, _ := newTestProtocolManagerMust(t, downloader.FastSync, 1024, nil, nil) pmFull, _ := newTestProtocolManagerMust(t, downloader.FastSync, 1024, nil, nil)
if atomic.LoadUint32(&pmFull.fastSync) == 1 { if atomic.LoadUint32(&pmFull.snapSync) == 1 {
t.Fatalf("fast sync not disabled on non-empty blockchain") t.Fatalf("snap sync not disabled on non-empty blockchain")
} }
// Sync up the two peers // Sync up the two peers
io1, io2 := p2p.MsgPipe() io1, io2 := p2p.MsgPipe()
@ -48,8 +48,8 @@ func TestFastSyncDisabling(t *testing.T) {
time.Sleep(250 * time.Millisecond) time.Sleep(250 * time.Millisecond)
pmEmpty.synchronise(pmEmpty.peers.BestPeer()) pmEmpty.synchronise(pmEmpty.peers.BestPeer())
// Check that fast sync was disabled // Check that snap sync was disabled
if atomic.LoadUint32(&pmEmpty.fastSync) == 1 { if atomic.LoadUint32(&pmEmpty.snapSync) == 1 {
t.Fatalf("fast sync not disabled after successful synchronisation") t.Fatalf("snap sync not disabled after successful synchronisation")
} }
} }

View file

@ -112,7 +112,7 @@ func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types
func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
return b.chain.CurrentBlock(), nil return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil
} }
return b.chain.GetBlockByNumber(uint64(number)), nil return b.chain.GetBlockByNumber(uint64(number)), nil
} }

View file

@ -773,7 +773,7 @@ func (api *BlockChainAPI) GetMasternodes(ctx context.Context, b *types.Block) ([
if b.Number().Int64() >= 0 { if b.Number().Int64() >= 0 {
curBlockNumber := b.Number().Uint64() curBlockNumber := b.Number().Uint64()
prevBlockNumber := curBlockNumber + (common.MergeSignRange - (curBlockNumber % common.MergeSignRange)) prevBlockNumber := curBlockNumber + (common.MergeSignRange - (curBlockNumber % common.MergeSignRange))
latestBlockNumber := api.b.CurrentBlock().Number().Uint64() latestBlockNumber := api.b.CurrentBlock().Number.Uint64()
if prevBlockNumber >= latestBlockNumber || !api.b.ChainConfig().IsTIP2019(b.Number()) { if prevBlockNumber >= latestBlockNumber || !api.b.ChainConfig().IsTIP2019(b.Number()) {
prevBlockNumber = curBlockNumber prevBlockNumber = curBlockNumber
} }
@ -1122,7 +1122,7 @@ func (api *BlockChainAPI) GetCheckpointFromEpoch(ctx context.Context, epochNum r
epoch := api.b.ChainConfig().XDPoS.Epoch epoch := api.b.ChainConfig().XDPoS.Epoch
if epochNum == rpc.LatestEpochNumber { if epochNum == rpc.LatestEpochNumber {
blockNumer := api.b.CurrentBlock().Number() blockNumer := api.b.CurrentBlock().Number
if engine, ok := api.b.Engine().(*XDPoS.XDPoS); ok { if engine, ok := api.b.Engine().(*XDPoS.XDPoS); ok {
var err error var err error
var currentEpoch uint64 var currentEpoch uint64
@ -1512,7 +1512,7 @@ func (api *BlockChainAPI) findNearestSignedBlock(ctx context.Context, b *types.B
blockNumber := b.Number().Uint64() blockNumber := b.Number().Uint64()
signedBlockNumber := blockNumber + (common.MergeSignRange - (blockNumber % common.MergeSignRange)) signedBlockNumber := blockNumber + (common.MergeSignRange - (blockNumber % common.MergeSignRange))
latestBlockNumber := api.b.CurrentBlock().Number() latestBlockNumber := api.b.CurrentBlock().Number
if signedBlockNumber >= latestBlockNumber.Uint64() || !api.b.ChainConfig().IsTIPSigning(b.Number()) { if signedBlockNumber >= latestBlockNumber.Uint64() || !api.b.ChainConfig().IsTIPSigning(b.Number()) {
signedBlockNumber = blockNumber signedBlockNumber = blockNumber
@ -2083,7 +2083,7 @@ func (s *TransactionAPI) sign(addr common.Address, tx *types.Transaction) (*type
} }
// Request the wallet to sign the transaction // Request the wallet to sign the transaction
var chainID *big.Int var chainID *big.Int
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number) {
chainID = config.ChainID chainID = config.ChainID
} }
return wallet.SignTx(account, tx, chainID) return wallet.SignTx(account, tx, chainID)
@ -2109,7 +2109,7 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
} }
// Print a log with full tx details for manual investigations and interventions // Print a log with full tx details for manual investigations and interventions
signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number()) signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number)
from, err := types.Sender(signer, tx) from, err := types.Sender(signer, tx)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
@ -2150,7 +2150,7 @@ func (s *TransactionAPI) SendTransaction(ctx context.Context, args TransactionAr
tx := args.ToTransaction(types.LegacyTxType) tx := args.ToTransaction(types.LegacyTxType)
var chainID *big.Int var chainID *big.Int
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) { if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number) {
chainID = config.ChainID chainID = config.ChainID
} }
signed, err := wallet.SignTx(account, tx, chainID) signed, err := wallet.SignTx(account, tx, chainID)
@ -2522,7 +2522,7 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
signer := types.MakeSigner(b.ChainConfig(), new(big.Int).SetUint64(blockNumber)) signer := types.MakeSigner(b.ChainConfig(), new(big.Int).SetUint64(blockNumber))
if engine, ok := b.Engine().(*XDPoS.XDPoS); ok { if engine, ok := b.Engine().(*XDPoS.XDPoS); ok {
limitNumber := blockNumber + common.LimitTimeFinality limitNumber := blockNumber + common.LimitTimeFinality
currentNumber := b.CurrentBlock().NumberU64() currentNumber := b.CurrentBlock().Number.Uint64()
if limitNumber > currentNumber { if limitNumber > currentNumber {
limitNumber = currentNumber limitNumber = currentNumber
} }
@ -2564,7 +2564,7 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
// //
// ROI = average_latest_epoch_reward_for_voters*number_of_epoch_per_year/latest_total_cap*100 // ROI = average_latest_epoch_reward_for_voters*number_of_epoch_per_year/latest_total_cap*100
func (api *BlockChainAPI) GetStakerROI() float64 { func (api *BlockChainAPI) GetStakerROI() float64 {
blockNumber := api.b.CurrentBlock().Number().Uint64() blockNumber := api.b.CurrentBlock().Number.Uint64()
lastCheckpointNumber := blockNumber - (blockNumber % api.b.ChainConfig().XDPoS.Epoch) - api.b.ChainConfig().XDPoS.Epoch // calculate for 2 epochs ago lastCheckpointNumber := blockNumber - (blockNumber % api.b.ChainConfig().XDPoS.Epoch) - api.b.ChainConfig().XDPoS.Epoch // calculate for 2 epochs ago
totalCap := new(big.Int).SetUint64(0) totalCap := new(big.Int).SetUint64(0)
@ -2603,7 +2603,7 @@ func (api *BlockChainAPI) GetStakerROIMasternode(masternode common.Address) floa
masternodeReward.Add(masternodeReward, reward) masternodeReward.Add(masternodeReward, reward)
} }
blockNumber := api.b.CurrentBlock().Number().Uint64() blockNumber := api.b.CurrentBlock().Number.Uint64()
lastCheckpointNumber := blockNumber - blockNumber%api.b.ChainConfig().XDPoS.Epoch lastCheckpointNumber := blockNumber - blockNumber%api.b.ChainConfig().XDPoS.Epoch
totalCap := new(big.Int).SetUint64(0) totalCap := new(big.Int).SetUint64(0)
votersCap := api.b.GetVotersCap(new(big.Int).SetUint64(lastCheckpointNumber), masternode, voters) votersCap := api.b.GetVotersCap(new(big.Int).SetUint64(lastCheckpointNumber), masternode, voters)

View file

@ -92,7 +92,7 @@ type Backend interface {
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
Engine() consensus.Engine Engine() consensus.Engine
CurrentBlock() *types.Block CurrentBlock() *types.Header
GetIPCClient() (bind.ContractBackend, error) GetIPCClient() (bind.ContractBackend, error)
GetRewardByHash(hash common.Hash) map[string]map[string]map[string]*big.Int GetRewardByHash(hash common.Hash) map[string]map[string]map[string]*big.Int

View file

@ -317,7 +317,7 @@ func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rp
return nil, nil return nil, nil
} }
func (b *backendMock) CurrentBlock() *types.Block { return nil } func (b *backendMock) CurrentBlock() *types.Header { return nil }
func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
return nil, nil return nil, nil

View file

@ -393,10 +393,18 @@ func (w *worker) getHashrate() int64 {
} }
func getResetTime(chain *core.BlockChain, minePeriod int) time.Duration { func getResetTime(chain *core.BlockChain, minePeriod int) time.Duration {
minePeriodDuration := time.Duration(minePeriod) * time.Second var (
currentBlockTime := int64(chain.CurrentBlock().Time()) currentBlockTime int64 = 0
nowTime := time.Now().UnixMilli() nowTime int64 = 0
resetTime := time.Duration(currentBlockTime)*time.Second + minePeriodDuration - time.Duration(nowTime)*time.Millisecond resetTime time.Duration = 0
minePeriodDuration time.Duration = time.Duration(minePeriod) * time.Second
header *types.Header = chain.CurrentBlock()
)
if header != nil {
currentBlockTime = int64(header.Time)
nowTime = time.Now().UnixMilli()
resetTime = time.Duration(currentBlockTime)*time.Second + minePeriodDuration - time.Duration(nowTime)*time.Millisecond
}
// in case the current block time is not very accurate // in case the current block time is not very accurate
if resetTime > minePeriodDuration || resetTime <= 0 { if resetTime > minePeriodDuration || resetTime <= 0 {
resetTime = minePeriodDuration resetTime = minePeriodDuration
@ -622,6 +630,8 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
return nil return nil
} }
// checkPreCommitWithLock checks whether a new work commit is needed with locks,
// returns the parent block and shouldReturn.
func (w *worker) checkPreCommitWithLock() (*types.Block, bool) { func (w *worker) checkPreCommitWithLock() (*types.Block, bool) {
w.mu.Lock() w.mu.Lock()
defer w.mu.Unlock() defer w.mu.Unlock()
@ -633,15 +643,24 @@ func (w *worker) checkPreCommitWithLock() (*types.Block, bool) {
return w.checkPreCommit() return w.checkPreCommit()
} }
// checkPreCommit checks whether a new work commit is needed,
// returns the parent block and shouldReturn.
func (w *worker) checkPreCommit() (*types.Block, bool) { func (w *worker) checkPreCommit() (*types.Block, bool) {
c := w.engine.(*XDPoS.XDPoS) c := w.engine.(*XDPoS.XDPoS)
var parent *types.Block var parent *types.Block
if c != nil { currentHeader := w.chain.CurrentBlock()
parent = c.FindParentBlockToAssign(w.chain, w.chain.CurrentBlock()) // Guard against nil header (early startup or uninitialised chain).
} else { if currentHeader == nil {
parent = w.chain.CurrentBlock() return nil, true
}
if c != nil {
parent = c.FindParentBlockToAssign(w.chain, currentHeader)
} else {
parent = w.chain.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())
}
if parent == nil {
return nil, true
} }
if parent.Hash().Hex() == w.lastParentBlockCommit { if parent.Hash().Hex() == w.lastParentBlockCommit {
return parent, true return parent, true
} }
@ -670,7 +689,7 @@ func (w *worker) checkPreCommit() (*types.Block, bool) {
func (w *worker) commitNewWork() { func (w *worker) commitNewWork() {
parent, shouldReturn := w.checkPreCommitWithLock() parent, shouldReturn := w.checkPreCommitWithLock()
if shouldReturn { if parent == nil || shouldReturn {
return return
} }
tstart := time.Now() tstart := time.Now()
@ -693,7 +712,7 @@ func (w *worker) commitNewWork() {
defer w.currentMu.Unlock() defer w.currentMu.Unlock()
parent, shouldReturn = w.checkPreCommit() parent, shouldReturn = w.checkPreCommit()
if shouldReturn { if parent == nil || shouldReturn {
return return
} }

View file

@ -286,8 +286,8 @@ func (t *BlockTest) validateImportedHeaders(cm *core.BlockChain, validBlocks []b
// block-by-block, so we can only validate imported headers after // block-by-block, so we can only validate imported headers after
// all blocks have been processed by BlockChain, as they may not // all blocks have been processed by BlockChain, as they may not
// be part of the longest chain until last block is imported. // be part of the longest chain until last block is imported.
for b := cm.CurrentBlock(); b != nil && b.NumberU64() != 0; b = cm.GetBlockByHash(b.Header().ParentHash) { for b := cm.CurrentBlock(); b != nil && b.Number.Uint64() != 0; b = cm.GetHeaderByHash(b.ParentHash) {
if err := validateHeader(bmap[b.Hash()].BlockHeader, b.Header()); err != nil { if err := validateHeader(bmap[b.Hash()].BlockHeader, b); err != nil {
return fmt.Errorf("imported block header validation failed: %v", err) return fmt.Errorf("imported block header validation failed: %v", err)
} }
} }