Skip to content

Commit 801570d

Browse files
authored
Merge pull request ethereum#293 from nextyio/rollback
Rollback and syncing
2 parents 64b9d34 + 9787b34 commit 801570d

File tree

7 files changed

+57
-38
lines changed

7 files changed

+57
-38
lines changed

accounts/abi/bind/backends/simulated.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ type SimulatedBackend struct {
7070
func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
7171
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
7272
genesis.MustCommit(database)
73-
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil)
73+
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil)
7474

7575
backend := &SimulatedBackend{
7676
database: database,

cmd/gonex/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
137137
utils.SetDashboardConfig(ctx, &cfg.Dashboard)
138138

139139
if ctx.GlobalIsSet(utils.RollbackFlag.Name) {
140-
cfg.Eth.RollbackNumber = ctx.GlobalInt64(utils.RollbackFlag.Name)
140+
cfg.Eth.RollbackNumber = big.NewInt(ctx.GlobalInt64(utils.RollbackFlag.Name))
141141
}
142142

143143
return stack, cfg

cmd/utils/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
17671767
cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
17681768
}
17691769
vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
1770-
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil)
1770+
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil)
17711771
if err != nil {
17721772
Fatalf("Can't create BlockChain: %v", err)
17731773
}

core/blockchain.go

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ type BlockChain struct {
181181
// NewBlockChain returns a fully initialised block chain using information
182182
// available in the database. It initialises the default Ethereum Validator and
183183
// Processor.
184-
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool) (*BlockChain, error) {
184+
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(block *types.Block) bool, rollbackNumber *big.Int) (*BlockChain, error) {
185185
if cacheConfig == nil {
186186
cacheConfig = &CacheConfig{
187187
TrieCleanLimit: 256,
@@ -235,6 +235,27 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
235235
if err := bc.loadLastState(); err != nil {
236236
return nil, err
237237
}
238+
239+
if rollbackNumber != nil {
240+
number := bc.CurrentHeader().Number.Uint64()
241+
var rollback uint64
242+
if rollbackNumber.Sign() >= 0 {
243+
rollback = rollbackNumber.Uint64()
244+
} else {
245+
r := uint64(-rollbackNumber.Int64())
246+
if number > r {
247+
rollback = number - r
248+
}
249+
}
250+
if rollback > number {
251+
log.Error("Rollback number is older than chain head", "number", number, "rollback", rollback)
252+
} else {
253+
log.Warn("Rolling-back chain as requested", "number", number, "rollback", rollback)
254+
bc.SetHead(rollback)
255+
log.Error("Chain rollback was successful, resuming normal operation")
256+
}
257+
}
258+
238259
// The first thing the node will do is reconstruct the verification data for
239260
// the head block (ethash cache or clique voting snapshot). Might as well do
240261
// it in advance.
@@ -390,27 +411,38 @@ func (bc *BlockChain) SetHead(head uint64) error {
390411
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) {
391412
// Rewind the block chain, ensuring we don't end up with a stateless head block
392413
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() < currentBlock.NumberU64() {
393-
newHeadBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
394-
if newHeadBlock == nil {
395-
newHeadBlock = bc.genesisBlock
396-
} else {
397-
if _, err := state.New(newHeadBlock.Root(), bc.stateCache); err != nil {
398-
// Rewound state missing, rolled back to before pivot, reset to genesis
399-
newHeadBlock = bc.genesisBlock
414+
newHeadBlock := func() *types.Block {
415+
number := header.Number.Uint64()
416+
// rolling back until a block with state found
417+
for n := number; n > 0; n-- {
418+
b := bc.GetBlockByNumber(n)
419+
if b == nil {
420+
continue
421+
}
422+
if _, err := state.New(b.Root(), bc.stateCache); err != nil {
423+
continue
424+
}
425+
return b
400426
}
401-
}
427+
return bc.genesisBlock
428+
}()
402429
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash())
403430
bc.currentBlock.Store(newHeadBlock)
404431
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
405432
}
406433

407434
// Rewind the fast block in a simpleton way to the target head
408435
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() {
409-
newHeadFastBlock := bc.GetBlock(header.Hash(), header.Number.Uint64())
410-
// If either blocks reached nil, reset to the genesis state
411-
if newHeadFastBlock == nil {
412-
newHeadFastBlock = bc.genesisBlock
413-
}
436+
newHeadFastBlock := func() *types.Block {
437+
// rolling back until a block is found
438+
for n := header.Number.Uint64(); n > 0; n-- {
439+
if b := bc.GetBlockByNumber(n); b != nil {
440+
return b
441+
}
442+
}
443+
return bc.genesisBlock
444+
}()
445+
414446
rawdb.WriteHeadFastBlockHash(db, newHeadFastBlock.Hash())
415447
bc.currentFastBlock.Store(newHeadFastBlock)
416448
headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64()))
@@ -1730,7 +1762,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
17301762
// The method writes all (header-and-body-valid) blocks to disk, then tries to
17311763
// switch over to the new chain if the TD exceeded the current chain.
17321764
func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (int, []interface{}, []*types.Log, error) {
1733-
externTd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
1765+
externHash := block.ParentHash()
1766+
externTd := bc.GetTd(externHash, block.NumberU64()-1)
17341767
current := bc.CurrentBlock()
17351768
// The first sidechain block error is already verified to be ErrPrunedAncestor.
17361769
// Since we don't import them here, we expect ErrUnknownAncestor for the remaining
@@ -1766,6 +1799,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
17661799
return it.index, nil, nil, errors.New("sidechain ghost-state attack")
17671800
}
17681801
}
1802+
externHash = block.Hash()
17691803
externTd = new(big.Int).Add(externTd, block.Difficulty())
17701804

17711805
if !bc.HasBlock(block.Hash(), block.NumberU64()) {
@@ -1786,7 +1820,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
17861820
// If the externTd was larger than our local TD, we now need to reimport the previous
17871821
// blocks to regenerate the required state
17881822
localTd := bc.GetTd(current.Hash(), current.NumberU64())
1789-
if ChainCompare(localTd, externTd, current.Hash(), block.Hash()) > 0 {
1823+
if ChainCompare(localTd, externTd, current.Hash(), externHash) > 0 {
17901824
log.Info("Sidechain written to disk", "start", it.first().NumberU64(), "end", it.previous().Number, "sidetd", externTd, "localtd", localTd)
17911825
return it.index, nil, nil, err
17921826
}

eth/backend.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -187,26 +187,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
187187
TrieTimeLimit: config.TrieTimeout,
188188
}
189189
)
190-
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve)
190+
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, eth.shouldPreserve, config.RollbackNumber)
191191
if err != nil {
192192
return nil, err
193193
}
194194

195-
number := eth.blockchain.CurrentHeader().Number.Uint64()
196-
var rollback uint64
197-
if config.RollbackNumber > 0 {
198-
rollback = uint64(config.RollbackNumber)
199-
} else if config.RollbackNumber < 0 {
200-
rollback = uint64(number - uint64(-config.RollbackNumber))
201-
}
202-
if rollback > number {
203-
log.Error("Rollback number is older than chain head", "number", number, "rollback", rollback)
204-
} else if rollback > 0 {
205-
log.Warn("Rolling-back chain as requested", "number", number, "rollback", rollback)
206-
eth.blockchain.SetHead(rollback)
207-
log.Error("Chain rollback was successful, resuming normal operation")
208-
}
209-
210195
// Rewind the chain in case of an incompatible config upgrade.
211196
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
212197
log.Warn("Rewinding chain to upgrade configuration", "err", compat)

eth/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ type Config struct {
159159
// Istanbul block override (TODO: remove after the fork)
160160
OverrideIstanbul *big.Int
161161

162-
// Rollback is the block number the chain will be rolled back to.
163-
RollbackNumber int64
162+
// RollbackNumber is the block number the chain will be rolled back to.
163+
RollbackNumber *big.Int `toml:",omitempty"`
164164

165165
// PriceServiceURL is service enpoint for the consensus.
166166
PriceServiceURL string

tests/block_test_util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (t *BlockTest) Run() error {
118118
} else {
119119
engine = ethash.NewShared()
120120
}
121-
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanLimit: 0}, config, engine, vm.Config{}, nil)
121+
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanLimit: 0}, config, engine, vm.Config{}, nil, nil)
122122
if err != nil {
123123
return err
124124
}

0 commit comments

Comments
 (0)