Update terminal total difficulty handling (#992)

why:
  Testing against a replay unit test for Devnet4 made it necessary to
  adjust the TTD handling. Without updated, importing fails at block #5646
  which is the parent of the terminal PoW block. Similar considerations
  apply for Devnet5 and Kiln.
This commit is contained in:
Jordan Hrycaj 2022-03-15 17:21:41 +00:00 committed by GitHub
parent a4b70918ed
commit 534fb528a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 59 deletions

View File

@ -67,7 +67,6 @@ type
txEnv: TxChainPackerEnv ## Assorted parameters, tx packer environment
# EIP-4399 and EIP-3675
ttdReached: bool ## Total Terminal Difficulty reached
prevRandao: Hash256 ## POS block randomness
# ------------------------------------------------------------------------------
@ -85,8 +84,7 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; fee: Option[UInt256])
fee = fee,
prevRandao= dh.prevRandao,
miner = dh.miner,
chainDB = dh.db,
ttdReached= dh.ttdReached)
chainDB = dh.db)
dh.txEnv.txRoot = BLANK_ROOT_HASH
dh.txEnv.stateRoot = dh.txEnv.vmState.parent.stateRoot
@ -309,10 +307,6 @@ proc `txRoot=`*(dh: TxChainRef; val: Hash256) =
## Setter
dh.txEnv.txRoot = val
proc `ttdReached=`*(dh: TxChainRef; val: bool) =
## Setter
dh.ttdReached = val
proc `prevRandao=`*(dh: TxChainRef; val: Hash256) =
## Setter
dh.prevRandao = val

View File

@ -40,11 +40,18 @@ template safeExecutor(info: string; code: untyped) =
let e = getCurrentException()
raise newException(VmStateError, info & "(): " & $e.name & " -- " & e.msg)
proc getMinerAddress(chainDB: BaseChainDB; header: BlockHeader, ttdReached: bool): EthAddress
proc isTtdReached(db: BaseChainDB; blockHash: Hash256): bool
{.gcsafe, raises: [Defect,RlpError].} =
## Returns `true` iff the stored sum of difficulties has reached the
## terminal total difficulty, see EIP3675.
if db.config.terminalTotalDifficulty.isSome:
return db.config.terminalTotalDifficulty.get <= db.getScore(blockHash)
proc getMinerAddress(chainDB: BaseChainDB; header: BlockHeader): EthAddress
{.gcsafe, raises: [Defect,CatchableError].} =
if not chainDB.config.poaEngine or ttdReached:
if not chainDB.config.poaEngine or chainDB.isTtdReached(header.parentHash):
return header.coinbase
let account = header.ecRecover
if account.isErr:
let msg = "Could not recover account address: " & $account.error
@ -91,7 +98,6 @@ proc init(
prevRandao: Hash256;
miner: EthAddress;
chainDB: BaseChainDB;
ttdReached: bool;
tracerFlags: set[TracerFlags])
{.gcsafe, raises: [Defect,CatchableError].} =
var tracer: TransactionTracer
@ -105,7 +111,7 @@ proc init(
prevRandao= prevRandao,
miner = miner,
chainDB = chainDB,
ttdReached= ttdReached,
ttdReached= chainDB.isTtdReached(parent.blockHash),
tracer = tracer)
# --------------
@ -128,7 +134,6 @@ proc new*(
prevRandao: Hash256; ## tx env: POS block randomness
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
chainDB: BaseChainDB; ## block chain database
ttdReached: bool; ## total terminal difficulty reached
tracerFlags: set[TracerFlags] = {};
pruneTrie: bool = true): T
{.gcsafe, raises: [Defect,CatchableError].} =
@ -149,7 +154,6 @@ proc new*(
prevRandao = prevRandao,
miner = miner,
chainDB = chainDB,
ttdReached = ttdReached,
tracerFlags = tracerFlags)
proc reinit*(self: BaseVMState; ## Object descriptor
@ -159,7 +163,6 @@ proc reinit*(self: BaseVMState; ## Object descriptor
fee: Option[Uint256]; ## tx env: optional base fee
prevRandao:Hash256; ## tx env: POS block randomness
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
ttdReached:bool; ## total terminal difficulty reached
pruneTrie: bool = true): bool
{.gcsafe, raises: [Defect,CatchableError].} =
## Re-initialise state descriptor. The `AccountsCache` database is
@ -186,7 +189,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
prevRandao = prevRandao,
miner = miner,
chainDB = db,
ttdReached = ttdReached,
ttdReached = db.isTtdReached(parent.blockHash),
tracer = tracer)
return true
# else: false
@ -202,17 +205,13 @@ proc reinit*(self: BaseVMState; ## Object descriptor
##
## It requires the `header` argument properly initalised so that for PoA
## networks, the miner address is retrievable via `ecRecover()`.
let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd
let miner = self.chainDB.getMinerAddress(header, ttdReached)
self.reinit(
result = self.reinit(
parent = parent,
timestamp = header.timestamp,
gasLimit = header.gasLimit,
fee = header.fee,
prevRandao= header.prevRandao,
miner = miner,
ttdReached= ttdReached,
miner = self.chainDB.getMinerAddress(header),
pruneTrie = pruneTrie)
proc reinit*(self: BaseVMState; ## Object descriptor
@ -243,18 +242,16 @@ proc init*(
##
## It requires the `header` argument properly initalised so that for PoA
## networks, the miner address is retrievable via `ecRecover()`.
let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd
let miner = chainDB.getMinerAddress(header, ttdReached)
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
parent,
header.timestamp,
header.gasLimit,
header.fee,
header.prevRandao,
miner,
chainDB,
ttdReached,
tracerFlags)
self.init(
ac = AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
parent = parent,
timestamp = header.timestamp,
gasLimit = header.gasLimit,
fee = header.fee,
prevRandao = header.prevRandao,
miner = chainDB.getMinerAddress(header),
chainDB = chainDB,
tracerFlags = tracerFlags)
proc new*(
T: type BaseVMState;

View File

@ -39,9 +39,16 @@ template safeExecutor(info: string; code: untyped) =
let e = getCurrentException()
raise newException(VmStateError, info & "(): " & $e.name & " -- " & e.msg)
proc getMinerAddress(chainDB: BaseChainDB; header: BlockHeader, ttdReached: bool): EthAddress
proc isTtdReached(db: BaseChainDB; blockHash: Hash256): bool
{.gcsafe, raises: [Defect,RlpError].} =
## Returns `true` iff the stored sum of difficulties has reached the
## terminal total difficulty, see EIP3675.
if db.config.terminalTotalDifficulty.isSome:
return db.config.terminalTotalDifficulty.get <= db.getScore(blockHash)
proc getMinerAddress(chainDB: BaseChainDB; header: BlockHeader): EthAddress
{.gcsafe, raises: [Defect,CatchableError].} =
if not chainDB.config.poaEngine or ttdReached:
if not chainDB.config.poaEngine or chainDB.isTtdReached(header.parentHash):
return header.coinbase
let account = header.ecRecover
@ -90,7 +97,6 @@ proc init(
prevRandao: Hash256;
miner: EthAddress;
chainDB: BaseChainDB;
ttdReached: bool;
tracerFlags: set[TracerFlags])
{.gcsafe, raises: [Defect,CatchableError].} =
var tracer: TransactionTracer
@ -104,7 +110,7 @@ proc init(
prevRandao= prevRandao,
miner = miner,
chainDB = chainDB,
ttdReached= ttdReached,
ttdReached= chainDB.isTtdReached(parent.blockHash),
tracer = tracer)
# --------------
@ -127,7 +133,6 @@ proc new*(
prevRandao: Hash256; ## tx env: POS block randomness
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
chainDB: BaseChainDB; ## block chain database
ttdReached: bool; ## total terminal difficulty reached
tracerFlags: set[TracerFlags] = {};
pruneTrie: bool = true): T
{.gcsafe, raises: [Defect,CatchableError].} =
@ -148,7 +153,6 @@ proc new*(
prevRandao = prevRandao,
miner = miner,
chainDB = chainDB,
ttdReached = ttdReached,
tracerFlags = tracerFlags)
proc reinit*(self: BaseVMState; ## Object descriptor
@ -158,7 +162,6 @@ proc reinit*(self: BaseVMState; ## Object descriptor
fee: Option[Uint256]; ## tx env: optional base fee
prevRandao:Hash256; ## tx env: POS block randomness
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
ttdReached:bool; ## total terminal difficulty reached
pruneTrie: bool = true): bool
{.gcsafe, raises: [Defect,CatchableError].} =
## Re-initialise state descriptor. The `AccountsCache` database is
@ -185,7 +188,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
prevRandao = prevRandao,
miner = miner,
chainDB = db,
ttdReached = ttdReached,
ttdReached = db.isTtdReached(parent.blockHash),
tracer = tracer)
return true
# else: false
@ -201,16 +204,13 @@ proc reinit*(self: BaseVMState; ## Object descriptor
##
## It requires the `header` argument properly initalised so that for PoA
## networks, the miner address is retrievable via `ecRecover()`.
let ttdReached = self.chainDB.totalDifficulty + header.difficulty > self.chainDB.ttd
let miner = self.chainDB.getMinerAddress(header, ttdReached)
self.reinit(
result = self.reinit(
parent = parent,
timestamp = header.timestamp,
gasLimit = header.gasLimit,
fee = header.fee,
prevRandao= header.prevRandao,
miner = miner,
ttdReached= ttdReached,
miner = self.chainDB.getMinerAddress(header),
pruneTrie = pruneTrie)
proc reinit*(self: BaseVMState; ## Object descriptor
@ -241,18 +241,16 @@ proc init*(
##
## It requires the `header` argument properly initalised so that for PoA
## networks, the miner address is retrievable via `ecRecover()`.
let ttdReached = chainDB.totalDifficulty + header.difficulty > chainDB.ttd
let miner = chainDB.getMinerAddress(header, ttdReached)
self.init(AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
parent,
header.timestamp,
header.gasLimit,
header.fee,
header.prevRandao,
miner,
chainDB,
ttdReached,
tracerFlags)
self.init(
ac = AccountsCache.init(chainDB.db, parent.stateRoot, pruneTrie),
parent = parent,
timestamp = header.timestamp,
gasLimit = header.gasLimit,
fee = header.fee,
prevRandao = header.prevRandao,
miner = chainDB.getMinerAddress(header),
chainDB = chainDB,
tracerFlags = tracerFlags)
proc new*(
T: type BaseVMState;