handle PoA block difficulty during block creation

- in vmState
- in txpool
- in sealing engine

fix #1105
This commit is contained in:
jangko 2022-06-14 13:01:51 +07:00
parent 6325712aa6
commit 77be2f66d2
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
9 changed files with 65 additions and 22 deletions

View File

@ -12,8 +12,6 @@
## Mining Support for Clique PoA Consensus Protocol ## Mining Support for Clique PoA Consensus Protocol
## ================================================ ## ================================================
## ##
## Note that mining in currently unsupported by `NIMBUS`
##
## For details see ## For details see
## `EIP-225 <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-225.md>`_ ## `EIP-225 <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-225.md>`_
## and ## and
@ -322,7 +320,7 @@ proc seal*(c: Clique; ethBlock: var EthBlock):
ok() ok()
# clique/clique.go(673): func (c *Clique) CalcDifficulty(chain [..] # clique/clique.go(673): func (c *Clique) CalcDifficulty(chain [..]
proc calcDifficulty(c: Clique; proc calcDifficulty*(c: Clique;
parent: BlockHeader): Result[DifficultyInt,CliqueError] parent: BlockHeader): Result[DifficultyInt,CliqueError]
{.gcsafe, raises: [Defect,CatchableError].} = {.gcsafe, raises: [Defect,CatchableError].} =
## For the Consensus Engine, `calcDifficulty()` is the difficulty adjustment ## For the Consensus Engine, `calcDifficulty()` is the difficulty adjustment

View File

@ -126,8 +126,6 @@ proc generateBlock(engine: SealingEngineRef,
timestamp = getTime(), timestamp = getTime(),
prevRandao = Hash256()): Result[void, string] = prevRandao = Hash256()): Result[void, string] =
# deviation from standard block generator # deviation from standard block generator
# - no local and remote transactions inclusion(need tx pool)
# - no receipts from tx
# - no DAO hard fork # - no DAO hard fork
# - no local and remote uncles inclusion # - no local and remote uncles inclusion
@ -188,6 +186,20 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
clique.authorize(engine.signer, signerFunc) clique.authorize(engine.signer, signerFunc)
proc diffCalculator(timeStamp: EthTime, parent: BlockHeader): DifficultyInt {.gcsafe, raises:[].} =
# pesky Nim effect system
try:
discard timestamp
let rc = clique.calcDifficulty(parent)
if rc.isErr:
return 0.u256
rc.get()
except:
0.u256
# switch to PoA difficulty calculator
engine.txPool.calcDifficulty = diffCalculator
# convert times.Duration to chronos.Duration # convert times.Duration to chronos.Duration
let period = chronos.seconds(clique.cfg.period.inSeconds) let period = chronos.seconds(clique.cfg.period.inSeconds)

View File

@ -772,6 +772,11 @@ proc `feeRecipient=`*(xp: TxPoolRef; beneficiary: EthAddress) =
## a.k.a miner in PoW chain or coinbase ## a.k.a miner in PoW chain or coinbase
xp.chain.miner = beneficiary xp.chain.miner = beneficiary
proc `calcDifficulty=`*(xp: TxPoolRef; val: DifficultyCalculator) =
## Setter, either PoW or PoA difficulty calculator
## PoS difficulty always zero
xp.chain.calcDifficulty = val
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Public functions, per-tx-item operations # Public functions, per-tx-item operations
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -20,6 +20,7 @@ import
../../forks, ../../forks,
../../p2p/executor, ../../p2p/executor,
../../utils, ../../utils,
../../utils/difficulty,
../../vm_state, ../../vm_state,
../../vm_types, ../../vm_types,
./tx_chain/[tx_basefee, tx_gaslimits], ./tx_chain/[tx_basefee, tx_gaslimits],
@ -53,6 +54,8 @@ type
txRoot: Hash256 ## `rootHash` after packing txRoot: Hash256 ## `rootHash` after packing
stateRoot: Hash256 ## `stateRoot` after packing stateRoot: Hash256 ## `stateRoot` after packing
DifficultyCalculator* = proc(timeStamp: EthTime, parent: BlockHeader): DifficultyInt {.gcsafe, raises:[].}
TxChainRef* = ref object ##\ TxChainRef* = ref object ##\
## State cache of the transaction environment for creating a new\ ## State cache of the transaction environment for creating a new\
## block. This state is typically synchrionised with the canonical\ ## block. This state is typically synchrionised with the canonical\
@ -69,6 +72,9 @@ type
# EIP-4399 and EIP-3675 # EIP-4399 and EIP-3675
prevRandao: Hash256 ## PoS block randomness prevRandao: Hash256 ## PoS block randomness
# overrideable difficulty calculator
calcDifficulty: DifficultyCalculator
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Private functions # Private functions
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -77,12 +83,16 @@ proc resetTxEnv(dh: TxChainRef; parent: BlockHeader; fee: Option[UInt256])
{.gcsafe,raises: [Defect,CatchableError].} = {.gcsafe,raises: [Defect,CatchableError].} =
dh.txEnv.reset dh.txEnv.reset
let timestamp = getTime().utc.toTime
# we don't consider PoS difficulty here
# because that is handled in vmState
dh.txEnv.vmState = BaseVMState.new( dh.txEnv.vmState = BaseVMState.new(
parent = parent, parent = parent,
timestamp = getTime().utc.toTime, timestamp = timestamp,
gasLimit = (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit), gasLimit = (if dh.maxMode: dh.limits.maxLimit else: dh.limits.trgLimit),
fee = fee, fee = fee,
prevRandao= dh.prevRandao, prevRandao= dh.prevRandao,
difficulty= dh.calcDifficulty(timestamp, parent),
miner = dh.miner, miner = dh.miner,
chainDB = dh.db) chainDB = dh.db)
@ -118,6 +128,12 @@ proc new*(T: type TxChainRef; db: BaseChainDB; miner: EthAddress): T
result.miner = miner result.miner = miner
result.lhwm.lwmTrg = TRG_THRESHOLD_PER_CENT result.lhwm.lwmTrg = TRG_THRESHOLD_PER_CENT
result.lhwm.hwmMax = MAX_THRESHOLD_PER_CENT result.lhwm.hwmMax = MAX_THRESHOLD_PER_CENT
result.calcDifficulty = proc(timeStamp: EthTime, parent: BlockHeader):
DifficultyInt {.gcsafe, raises:[].} =
try:
db.config.calcDifficulty(timestamp, parent)
except:
0.u256
result.update(db.getCanonicalHead) result.update(db.getCanonicalHead)
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -311,6 +327,10 @@ proc `prevRandao=`*(dh: TxChainRef; val: Hash256) =
## Setter ## Setter
dh.prevRandao = val dh.prevRandao = val
proc `calcDifficulty=`*(dh: TxChainRef; val: DifficultyCalculator) =
## Setter
dh.calcDifficulty = val
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# End # End
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View File

@ -67,6 +67,7 @@ proc init(
gasLimit: GasInt; gasLimit: GasInt;
fee: Option[UInt256]; fee: Option[UInt256];
prevRandao: Hash256; prevRandao: Hash256;
difficulty: UInt256;
miner: EthAddress; miner: EthAddress;
chainDB: BaseChainDB; chainDB: BaseChainDB;
ttdReached: bool; ttdReached: bool;
@ -80,6 +81,7 @@ proc init(
self.gasLimit = gasLimit self.gasLimit = gasLimit
self.fee = fee self.fee = fee
self.prevRandao = prevRandao self.prevRandao = prevRandao
self.blockDifficulty = difficulty
self.chainDB = chainDB self.chainDB = chainDB
self.ttdReached = ttdReached self.ttdReached = ttdReached
self.tracer = tracer self.tracer = tracer
@ -96,6 +98,7 @@ proc init(
gasLimit: GasInt; gasLimit: GasInt;
fee: Option[UInt256]; fee: Option[UInt256];
prevRandao: Hash256; prevRandao: Hash256;
difficulty: UInt256;
miner: EthAddress; miner: EthAddress;
chainDB: BaseChainDB; chainDB: BaseChainDB;
tracerFlags: set[TracerFlags]) tracerFlags: set[TracerFlags])
@ -109,6 +112,7 @@ proc init(
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao= prevRandao, prevRandao= prevRandao,
difficulty= difficulty,
miner = miner, miner = miner,
chainDB = chainDB, chainDB = chainDB,
ttdReached= chainDB.isTtdReached(parent.blockHash), ttdReached= chainDB.isTtdReached(parent.blockHash),
@ -132,6 +136,7 @@ proc new*(
gasLimit: GasInt; ## tx env: gas limit gasLimit: GasInt; ## tx env: gas limit
fee: Option[UInt256]; ## tx env: optional base fee fee: Option[UInt256]; ## tx env: optional base fee
prevRandao: Hash256; ## tx env: POS block randomness prevRandao: Hash256; ## tx env: POS block randomness
difficulty: UInt256, ## tx env: difficulty
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
chainDB: BaseChainDB; ## block chain database chainDB: BaseChainDB; ## block chain database
tracerFlags: set[TracerFlags] = {}; tracerFlags: set[TracerFlags] = {};
@ -152,6 +157,7 @@ proc new*(
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao = prevRandao, prevRandao = prevRandao,
difficulty = difficulty,
miner = miner, miner = miner,
chainDB = chainDB, chainDB = chainDB,
tracerFlags = tracerFlags) tracerFlags = tracerFlags)
@ -162,6 +168,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit: GasInt; ## tx env: gas limit gasLimit: GasInt; ## tx env: gas limit
fee: Option[UInt256]; ## tx env: optional base fee fee: Option[UInt256]; ## tx env: optional base fee
prevRandao:Hash256; ## tx env: POS block randomness prevRandao:Hash256; ## tx env: POS block randomness
difficulty:UInt256, ## tx env: difficulty
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
pruneTrie: bool = true): bool pruneTrie: bool = true): bool
{.gcsafe, raises: [Defect,CatchableError].} = {.gcsafe, raises: [Defect,CatchableError].} =
@ -187,6 +194,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao = prevRandao, prevRandao = prevRandao,
difficulty = difficulty,
miner = miner, miner = miner,
chainDB = db, chainDB = db,
ttdReached = db.isTtdReached(parent.blockHash), ttdReached = db.isTtdReached(parent.blockHash),
@ -211,6 +219,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit = header.gasLimit, gasLimit = header.gasLimit,
fee = header.fee, fee = header.fee,
prevRandao= header.prevRandao, prevRandao= header.prevRandao,
difficulty= header.difficulty,
miner = self.chainDB.getMinerAddress(header), miner = self.chainDB.getMinerAddress(header),
pruneTrie = pruneTrie) pruneTrie = pruneTrie)
@ -249,6 +258,7 @@ proc init*(
gasLimit = header.gasLimit, gasLimit = header.gasLimit,
fee = header.fee, fee = header.fee,
prevRandao = header.prevRandao, prevRandao = header.prevRandao,
difficulty = header.difficulty,
miner = chainDB.getMinerAddress(header), miner = chainDB.getMinerAddress(header),
chainDB = chainDB, chainDB = chainDB,
tracerFlags = tracerFlags) tracerFlags = tracerFlags)
@ -305,12 +315,6 @@ proc setupTxContext*(vmState: BaseVMState, origin: EthAddress, gasPrice: GasInt,
vmState.chainDB.config.toFork(vmState.parent.blockNumber + 1) vmState.chainDB.config.toFork(vmState.parent.blockNumber + 1)
vmState.gasCosts = vmState.fork.forkToSchedule vmState.gasCosts = vmState.fork.forkToSchedule
proc consensusEnginePoA*(vmState: BaseVMState): bool =
# PoA consensus engine have no reward for miner
# TODO: this need to be fixed somehow
# using `real` engine configuration
vmState.chainDB.config.poaEngine
method coinbase*(vmState: BaseVMState): EthAddress {.base, gcsafe.} = method coinbase*(vmState: BaseVMState): EthAddress {.base, gcsafe.} =
vmState.minerAddress vmState.minerAddress
@ -324,7 +328,7 @@ method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
# EIP-4399/EIP-3675 # EIP-4399/EIP-3675
UInt256.fromBytesBE(vmState.prevRandao.data, allowPadding = false) UInt256.fromBytesBE(vmState.prevRandao.data, allowPadding = false)
else: else:
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent) vmState.blockDifficulty
method baseFee*(vmState: BaseVMState): UInt256 {.base, gcsafe.} = method baseFee*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
if vmState.fee.isSome: if vmState.fee.isSome:

View File

@ -39,6 +39,7 @@ type
gasLimit* : GasInt gasLimit* : GasInt
fee* : Option[UInt256] fee* : Option[UInt256]
prevRandao* : Hash256 prevRandao* : Hash256
blockDifficulty*: UInt256
ttdReached* : bool ttdReached* : bool
name* : string name* : string
flags* : set[VMFlag] flags* : set[VMFlag]

View File

@ -65,6 +65,7 @@ proc init(
gasLimit: GasInt; gasLimit: GasInt;
fee: Option[UInt256]; fee: Option[UInt256];
prevRandao: Hash256; prevRandao: Hash256;
difficulty: UInt256;
miner: EthAddress; miner: EthAddress;
chainDB: BaseChainDB; chainDB: BaseChainDB;
ttdReached: bool; ttdReached: bool;
@ -78,6 +79,7 @@ proc init(
self.gasLimit = gasLimit self.gasLimit = gasLimit
self.fee = fee self.fee = fee
self.prevRandao = prevRandao self.prevRandao = prevRandao
self.blockDifficulty = difficulty
self.chainDB = chainDB self.chainDB = chainDB
self.ttdReached = ttdReached self.ttdReached = ttdReached
self.tracer = tracer self.tracer = tracer
@ -94,6 +96,7 @@ proc init(
gasLimit: GasInt; gasLimit: GasInt;
fee: Option[UInt256]; fee: Option[UInt256];
prevRandao: Hash256; prevRandao: Hash256;
difficulty: UInt256;
miner: EthAddress; miner: EthAddress;
chainDB: BaseChainDB; chainDB: BaseChainDB;
tracerFlags: set[TracerFlags]) tracerFlags: set[TracerFlags])
@ -107,6 +110,7 @@ proc init(
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao= prevRandao, prevRandao= prevRandao,
difficulty= difficulty,
miner = miner, miner = miner,
chainDB = chainDB, chainDB = chainDB,
ttdReached= chainDB.isTtdReached(parent.blockHash), ttdReached= chainDB.isTtdReached(parent.blockHash),
@ -130,6 +134,7 @@ proc new*(
gasLimit: GasInt; ## tx env: gas limit gasLimit: GasInt; ## tx env: gas limit
fee: Option[UInt256]; ## tx env: optional base fee fee: Option[UInt256]; ## tx env: optional base fee
prevRandao: Hash256; ## tx env: POS block randomness prevRandao: Hash256; ## tx env: POS block randomness
difficulty: UInt256, ## tx env: difficulty
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
chainDB: BaseChainDB; ## block chain database chainDB: BaseChainDB; ## block chain database
tracerFlags: set[TracerFlags] = {}; tracerFlags: set[TracerFlags] = {};
@ -150,6 +155,7 @@ proc new*(
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao = prevRandao, prevRandao = prevRandao,
difficulty = difficulty,
miner = miner, miner = miner,
chainDB = chainDB, chainDB = chainDB,
tracerFlags = tracerFlags) tracerFlags = tracerFlags)
@ -160,6 +166,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit: GasInt; ## tx env: gas limit gasLimit: GasInt; ## tx env: gas limit
fee: Option[UInt256]; ## tx env: optional base fee fee: Option[UInt256]; ## tx env: optional base fee
prevRandao:Hash256; ## tx env: POS block randomness prevRandao:Hash256; ## tx env: POS block randomness
difficulty:UInt256, ## tx env: difficulty
miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA) miner: EthAddress; ## tx env: coinbase(PoW) or signer(PoA)
pruneTrie: bool = true): bool pruneTrie: bool = true): bool
{.gcsafe, raises: [Defect,CatchableError].} = {.gcsafe, raises: [Defect,CatchableError].} =
@ -185,6 +192,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit = gasLimit, gasLimit = gasLimit,
fee = fee, fee = fee,
prevRandao = prevRandao, prevRandao = prevRandao,
difficulty = difficulty,
miner = miner, miner = miner,
chainDB = db, chainDB = db,
ttdReached = db.isTtdReached(parent.blockHash), ttdReached = db.isTtdReached(parent.blockHash),
@ -209,6 +217,7 @@ proc reinit*(self: BaseVMState; ## Object descriptor
gasLimit = header.gasLimit, gasLimit = header.gasLimit,
fee = header.fee, fee = header.fee,
prevRandao= header.prevRandao, prevRandao= header.prevRandao,
difficulty= header.difficulty,
miner = self.chainDB.getMinerAddress(header), miner = self.chainDB.getMinerAddress(header),
pruneTrie = pruneTrie) pruneTrie = pruneTrie)
@ -247,6 +256,7 @@ proc init*(
gasLimit = header.gasLimit, gasLimit = header.gasLimit,
fee = header.fee, fee = header.fee,
prevRandao = header.prevRandao, prevRandao = header.prevRandao,
difficulty = header.difficulty,
miner = chainDB.getMinerAddress(header), miner = chainDB.getMinerAddress(header),
chainDB = chainDB, chainDB = chainDB,
tracerFlags = tracerFlags) tracerFlags = tracerFlags)
@ -290,13 +300,6 @@ proc new*(
tracerFlags = tracerFlags, tracerFlags = tracerFlags,
pruneTrie = pruneTrie) pruneTrie = pruneTrie)
proc consensusEnginePoA*(vmState: BaseVMState): bool =
# PoA consensus engine have no reward for miner
# TODO: this need to be fixed somehow
# using `real` engine configuration
vmState.chainDB.config.poaEngine
method coinbase*(vmState: BaseVMState): EthAddress {.base, gcsafe.} = method coinbase*(vmState: BaseVMState): EthAddress {.base, gcsafe.} =
vmState.minerAddress vmState.minerAddress
@ -310,7 +313,7 @@ method difficulty*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
# EIP-4399/EIP-3675 # EIP-4399/EIP-3675
UInt256.fromBytesBE(vmState.prevRandao.data, allowPadding = false) UInt256.fromBytesBE(vmState.prevRandao.data, allowPadding = false)
else: else:
vmState.chainDB.config.calcDifficulty(vmState.timestamp, vmState.parent) vmState.blockDifficulty
method baseFee*(vmState: BaseVMState): UInt256 {.base, gcsafe.} = method baseFee*(vmState: BaseVMState): UInt256 {.base, gcsafe.} =
if vmState.fee.isSome: if vmState.fee.isSome:

View File

@ -30,6 +30,7 @@ type
gasLimit* : GasInt gasLimit* : GasInt
fee* : Option[UInt256] fee* : Option[UInt256]
prevRandao* : Hash256 prevRandao* : Hash256
blockDifficulty*: UInt256
ttdReached* : bool ttdReached* : bool
name* : string name* : string
flags* : set[VMFlag] flags* : set[VMFlag]

View File

@ -26,7 +26,6 @@ export
vms.blockNumber, vms.blockNumber,
vms.buildWitness, vms.buildWitness,
vms.coinbase, vms.coinbase,
vms.consensusEnginePoA,
vms.difficulty, vms.difficulty,
vms.disableTracing, vms.disableTracing,
vms.enableTracing, vms.enableTracing,