diff --git a/core/blockchain.go b/core/blockchain.go index 0f2c065ced..3bb681d7c3 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1244,7 +1244,7 @@ func (bc *BlockChain) stopWithoutSaving() { bc.scope.Close() // Signal shutdown to all goroutines. - bc.StopInsert() + bc.InterruptInsert(true) // Now wait for all chain modifications to end and persistent goroutines to exit. // @@ -1318,11 +1318,15 @@ func (bc *BlockChain) Stop() { log.Info("Blockchain stopped") } -// StopInsert interrupts all insertion methods, causing them to return -// errInsertionInterrupted as soon as possible. Insertion is permanently disabled after -// calling this method. -func (bc *BlockChain) StopInsert() { - bc.procInterrupt.Store(true) +// InterruptInsert interrupts all insertion methods, causing them to return +// errInsertionInterrupted as soon as possible, or resume the chain insertion +// if required. +func (bc *BlockChain) InterruptInsert(on bool) { + if on { + bc.procInterrupt.Store(true) + } else { + bc.procInterrupt.Store(false) + } } // insertStopped returns true after StopInsert has been called. diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 8f8f219597..539aaef40e 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -199,8 +199,8 @@ type BlockChain interface { // InsertChain inserts a batch of blocks into the local chain. InsertChain(types.Blocks) (int, error) - // StopInsert interrupts the inserting process. - StopInsert() + // InterruptInsert whether disables the chain insertion. + InterruptInsert(on bool) // InsertReceiptChain inserts a batch of blocks along with their receipts // into the local chain. Blocks older than the specified `ancientLimit` @@ -630,16 +630,15 @@ func (d *Downloader) cancel() { // Cancel aborts all of the operations and waits for all download goroutines to // finish before returning. func (d *Downloader) Cancel() { + d.blockchain.InterruptInsert(true) d.cancel() d.cancelWg.Wait() + d.blockchain.InterruptInsert(false) } // Terminate interrupts the downloader, canceling all pending operations. // The downloader cannot be reused after calling Terminate. func (d *Downloader) Terminate() { - // Signal to stop inserting in-flight blocks - d.blockchain.StopInsert() - // Close the termination channel (make sure double close is allowed) d.quitLock.Lock() select { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8f736226c7..db0297ae5a 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1831,8 +1831,16 @@ func (api *DebugAPI) ChaindbCompact() error { } // SetHead rewinds the head of the blockchain to a previous block. -func (api *DebugAPI) SetHead(number hexutil.Uint64) { +func (api *DebugAPI) SetHead(number hexutil.Uint64) error { + header := api.b.CurrentHeader() + if header == nil { + return errors.New("current header is not available") + } + if header.Number.Uint64() <= uint64(number) { + return errors.New("not allowed to rewind to a future block") + } api.b.SetHead(uint64(number)) + return nil } // NetAPI offers network related RPC methods