fixes regression caused by recent changes in eth state handling

detected when running hive consensus simulator.
when processing an invalid block header and then
a new valid block header with the same block number,
the state root of the stateDB object should be updated
or reverted to parent stateRoot.

using intermediate stateRoot will trigger the hexary trie assertion.
This commit is contained in:
jangko 2021-11-09 17:46:23 +07:00
parent e710aa9423
commit 7b67914453
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 19 additions and 6 deletions

View File

@ -43,6 +43,7 @@ type
forkIds: array[ChainFork, ForkID]
blockZeroHash: KeccakHash
lastBlockHash: KeccakHash
parentStateRoot: KeccakHash
extraValidation: bool ##\
## Trigger extra validation, currently within `persistBlocks()`
@ -227,6 +228,10 @@ proc lastBlockHash*(c: Chain): auto {.inline.} =
## Getter
c.lastBlockHash
proc parentStateRoot*(c: Chain): auto {.inline.} =
## Getter
c.parentStateRoot
proc currentBlock*(c: Chain): BlockHeader
{.gcsafe, raises: [Defect,CatchableError].} =
## currentBlock retrieves the current head block of the canonical chain.
@ -253,6 +258,10 @@ proc `lastBlockHash=`*(c: Chain; blockHash: KeccakHash) {.inline.} =
## Setter.
c.lastBlockHash = blockHash
proc `parentStateRoot=`*(c: Chain; stateRoot: KeccakHash) {.inline.} =
## Setter.
c.parentStateRoot = stateRoot
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -51,14 +51,17 @@ proc persistBlocksImpl(c: Chain; headers: openarray[BlockHeader];
let (header, body) = (headers[i], bodies[i])
if header.parentHash != c.lastBlockHash:
# reinit the stateDB if there is some interruption
let parent = c.db.getBlockHeader(header.parentHash)
c.db.initStateDB(parent.stateRoot)
c.parentStateRoot = parent.stateRoot
# initStateDB will return the last known state
# if the stateRoot is match
c.db.initStateDB(c.parentStateRoot)
let
let
vmState = newBaseVMState(c.db.stateDB, header, c.db)
validationResult = vmState.processBlock(c.clique, header, body)
when not defined(release):
if validationResult == ValidationResult.Error and
body.transactions.calcTxRoot == header.txRoot:
@ -99,8 +102,9 @@ proc persistBlocksImpl(c: Chain; headers: openarray[BlockHeader];
# so the rpc return consistent result
# between eth_blockNumber and eth_syncing
c.db.currentBlock = header.blockNumber
c.lastBlockHash = headers[^1].blockHash
c.lastBlockHash = header.blockHash
c.parentStateRoot = header.stateRoot
transaction.commit()
# ------------------------------------------------------------------------------