mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-14 12:06:40 +00:00
check first
Signed-off-by: Delweng <delweng@gmail.com>
This commit is contained in:
parent
8788d37829
commit
7f61b8b7e4
8 changed files with 35 additions and 28 deletions
|
|
@ -735,14 +735,6 @@ func (bc *BlockChain) initializeHistoryPruning(latest uint64) error {
|
||||||
// was snap synced or full synced and in which state, the method will try to
|
// was snap synced or full synced and in which state, the method will try to
|
||||||
// delete minimal data from disk whilst retaining chain consistency.
|
// delete minimal data from disk whilst retaining chain consistency.
|
||||||
func (bc *BlockChain) SetHead(head uint64) error {
|
func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
// Only allowed to rewind to a block that is later than the oldest state block.
|
|
||||||
firstStateBlock, err := bc.triedb.FirstStateBlock()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if head < firstStateBlock {
|
|
||||||
return fmt.Errorf("cannot rewind to block %d, oldest available state is at block %d", head, firstStateBlock)
|
|
||||||
}
|
|
||||||
if _, err := bc.setHeadBeyondRoot(head, 0, common.Hash{}, false); err != nil {
|
if _, err := bc.setHeadBeyondRoot(head, 0, common.Hash{}, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -2827,3 +2819,8 @@ func (bc *BlockChain) GetTrieFlushInterval() time.Duration {
|
||||||
func (bc *BlockChain) StateSizer() *state.SizeTracker {
|
func (bc *BlockChain) StateSizer() *state.SizeTracker {
|
||||||
return bc.stateSizer
|
return bc.stateSizer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FirstStateBlock returns the first available state block number that is stored in the database.
|
||||||
|
func (bc *BlockChain) FirstStateBlock() (uint64, error) {
|
||||||
|
return bc.triedb.FirstStateBlock()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package eth
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -61,9 +62,16 @@ func (b *EthAPIBackend) CurrentBlock() *types.Header {
|
||||||
return b.eth.blockchain.CurrentBlock()
|
return b.eth.blockchain.CurrentBlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) SetHead(number uint64) {
|
func (b *EthAPIBackend) SetHead(number uint64) error {
|
||||||
|
firstStateBlock, err := b.eth.blockchain.FirstStateBlock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if number < firstStateBlock {
|
||||||
|
return fmt.Errorf("cannot rewind to block %d, oldest available state is at block %d", number, firstStateBlock)
|
||||||
|
}
|
||||||
b.eth.handler.downloader.Cancel()
|
b.eth.handler.downloader.Cancel()
|
||||||
b.eth.blockchain.SetHead(number)
|
return b.eth.blockchain.SetHead(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
||||||
|
|
|
||||||
|
|
@ -1933,8 +1933,7 @@ func (api *DebugAPI) SetHead(number hexutil.Uint64) error {
|
||||||
if header.Number.Uint64() <= uint64(number) {
|
if header.Number.Uint64() <= uint64(number) {
|
||||||
return errors.New("not allowed to rewind to a future block")
|
return errors.New("not allowed to rewind to a future block")
|
||||||
}
|
}
|
||||||
api.b.SetHead(uint64(number))
|
return api.b.SetHead(uint64(number))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetAPI offers network related RPC methods
|
// NetAPI offers network related RPC methods
|
||||||
|
|
|
||||||
|
|
@ -487,7 +487,7 @@ func (b testBackend) RPCGasCap() uint64 { return 10000000
|
||||||
func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
|
func (b testBackend) RPCEVMTimeout() time.Duration { return time.Second }
|
||||||
func (b testBackend) RPCTxFeeCap() float64 { return 0 }
|
func (b testBackend) RPCTxFeeCap() float64 { return 0 }
|
||||||
func (b testBackend) UnprotectedAllowed() bool { return false }
|
func (b testBackend) UnprotectedAllowed() bool { return false }
|
||||||
func (b testBackend) SetHead(number uint64) {}
|
func (b testBackend) SetHead(number uint64) error { return nil }
|
||||||
func (b testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
func (b testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
||||||
if number == rpc.LatestBlockNumber {
|
if number == rpc.LatestBlockNumber {
|
||||||
return b.chain.CurrentBlock(), nil
|
return b.chain.CurrentBlock(), nil
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ type Backend interface {
|
||||||
UnprotectedAllowed() bool // allows only for EIP155 transactions.
|
UnprotectedAllowed() bool // allows only for EIP155 transactions.
|
||||||
|
|
||||||
// Blockchain API
|
// Blockchain API
|
||||||
SetHead(number uint64)
|
SetHead(number uint64) error
|
||||||
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
|
||||||
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
|
||||||
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
|
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ func (b *backendMock) RPCGasCap() uint64 { return 0 }
|
||||||
func (b *backendMock) RPCEVMTimeout() time.Duration { return time.Second }
|
func (b *backendMock) RPCEVMTimeout() time.Duration { return time.Second }
|
||||||
func (b *backendMock) RPCTxFeeCap() float64 { return 0 }
|
func (b *backendMock) RPCTxFeeCap() float64 { return 0 }
|
||||||
func (b *backendMock) UnprotectedAllowed() bool { return false }
|
func (b *backendMock) UnprotectedAllowed() bool { return false }
|
||||||
func (b *backendMock) SetHead(number uint64) {}
|
func (b *backendMock) SetHead(number uint64) error { return nil }
|
||||||
func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -385,7 +385,7 @@ func (db *Database) SnapshotCompleted() bool {
|
||||||
return pdb.SnapshotCompleted()
|
return pdb.SnapshotCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FirstStateBlock
|
// FirstStateBlock returns the first available state block number that is stored in the database.
|
||||||
func (db *Database) FirstStateBlock() (uint64, error) {
|
func (db *Database) FirstStateBlock() (uint64, error) {
|
||||||
pdb, ok := db.backend.(*pathdb.Database)
|
pdb, ok := db.backend.(*pathdb.Database)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
||||||
|
|
@ -695,20 +695,23 @@ func (db *Database) SnapshotCompleted() bool {
|
||||||
|
|
||||||
// FirstStateBlock returns the block number of the oldest state snapshot in the freezer or disk layer.
|
// FirstStateBlock returns the block number of the oldest state snapshot in the freezer or disk layer.
|
||||||
func (db *Database) FirstStateBlock() (uint64, error) {
|
func (db *Database) FirstStateBlock() (uint64, error) {
|
||||||
var (
|
freezer := db.stateFreezer
|
||||||
m meta
|
if freezer == nil {
|
||||||
err error
|
return 0, errors.New("freezer is not available")
|
||||||
tailID = db.tree.bottom().stateID()
|
|
||||||
)
|
|
||||||
|
|
||||||
if db.stateFreezer != nil {
|
|
||||||
tailID, err = db.stateFreezer.Tail()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blob := rawdb.ReadStateHistoryMeta(db.diskdb, tailID)
|
tailID, err := freezer.Tail()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// No state has been persistent
|
||||||
|
if tailID == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
blob := rawdb.ReadStateHistoryMeta(freezer, tailID+1)
|
||||||
|
var m meta
|
||||||
if err := m.decode(blob); err != nil {
|
if err := m.decode(blob); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue