Proof-of-stakiness based on block header (#2682)
* Proof-of-stakiness based on block header * Remove unnecessary PoS check from test_txpool2 * Fix engine api simulator * Fix indentation * Fix vmstate debug util * Fix MainNet ForkId calculation issue
This commit is contained in:
parent
a3bb5d4428
commit
76c2a75a53
|
@ -72,10 +72,6 @@ proc envConfig*(conf: ChainConfig): NimbusConf =
|
||||||
result.networkParams.config = conf
|
result.networkParams.config = conf
|
||||||
|
|
||||||
proc newEngineEnv*(conf: var NimbusConf, chainFile: string, enableAuth: bool): EngineEnv =
|
proc newEngineEnv*(conf: var NimbusConf, chainFile: string, enableAuth: bool): EngineEnv =
|
||||||
if chainFile.len > 0:
|
|
||||||
# disable clique if we are using PoW chain
|
|
||||||
conf.networkParams.config.consensusType = ConsensusType.POW
|
|
||||||
|
|
||||||
let ctx = newEthContext()
|
let ctx = newEthContext()
|
||||||
ctx.am.importPrivateKey(sealerKey).isOkOr:
|
ctx.am.importPrivateKey(sealerKey).isOkOr:
|
||||||
echo error
|
echo error
|
||||||
|
|
|
@ -64,7 +64,7 @@ proc processBlock(
|
||||||
discard com.db.persistUncles(blk.uncles)
|
discard com.db.persistUncles(blk.uncles)
|
||||||
|
|
||||||
# EIP-3675: no reward for miner in POA/POS
|
# EIP-3675: no reward for miner in POA/POS
|
||||||
if com.consensus == ConsensusType.POW:
|
if com.proofOfStake(header):
|
||||||
vmState.calculateReward(header, blk.uncles)
|
vmState.calculateReward(header, blk.uncles)
|
||||||
|
|
||||||
vmState.mutateStateDB:
|
vmState.mutateStateDB:
|
||||||
|
@ -95,8 +95,6 @@ proc setBlock*(c: ChainRef; blk: EthBlock): Result[void, string] =
|
||||||
let dbTx = c.db.ctx.newTransaction()
|
let dbTx = c.db.ctx.newTransaction()
|
||||||
defer: dbTx.dispose()
|
defer: dbTx.dispose()
|
||||||
|
|
||||||
c.com.hardForkTransition(header)
|
|
||||||
|
|
||||||
# Needed for figuring out whether KVT cleanup is due (see at the end)
|
# Needed for figuring out whether KVT cleanup is due (see at the end)
|
||||||
let
|
let
|
||||||
vmState = c.getVmState(header).valueOr:
|
vmState = c.getVmState(header).valueOr:
|
||||||
|
@ -105,7 +103,7 @@ proc setBlock*(c: ChainRef; blk: EthBlock): Result[void, string] =
|
||||||
? vmState.processBlock(blk)
|
? vmState.processBlock(blk)
|
||||||
|
|
||||||
if not c.db.persistHeader(
|
if not c.db.persistHeader(
|
||||||
header, c.com.consensus == ConsensusType.POS, c.com.startOfHistory):
|
header, c.com.proofOfStake(header), c.com.startOfHistory):
|
||||||
return err("Could not persist header")
|
return err("Could not persist header")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -48,7 +48,7 @@ proc setupELClient*(conf: ChainConfig, node: JsonNode): TestEnv =
|
||||||
doAssert stateDB.rootHash == genesisHeader.stateRoot
|
doAssert stateDB.rootHash == genesisHeader.stateRoot
|
||||||
|
|
||||||
doAssert com.db.persistHeader(genesisHeader,
|
doAssert com.db.persistHeader(genesisHeader,
|
||||||
com.consensus == ConsensusType.POS)
|
com.proofOfStake(genesisHeader))
|
||||||
doAssert(com.db.getCanonicalHead().blockHash ==
|
doAssert(com.db.getCanonicalHead().blockHash ==
|
||||||
genesisHeader.blockHash)
|
genesisHeader.blockHash)
|
||||||
|
|
||||||
|
|
|
@ -449,7 +449,6 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig =
|
||||||
of MainNet:
|
of MainNet:
|
||||||
const mainNetTTD = parse("58750000000000000000000",UInt256)
|
const mainNetTTD = parse("58750000000000000000000",UInt256)
|
||||||
ChainConfig(
|
ChainConfig(
|
||||||
consensusType: ConsensusType.POW,
|
|
||||||
chainId: MainNet.ChainId,
|
chainId: MainNet.ChainId,
|
||||||
# Genesis (Frontier): # 2015-07-30 15:26:13 UTC
|
# Genesis (Frontier): # 2015-07-30 15:26:13 UTC
|
||||||
# Frontier Thawing: 200_000.BlockNumber, # 2015-09-07 21:33:09 UTC
|
# Frontier Thawing: 200_000.BlockNumber, # 2015-09-07 21:33:09 UTC
|
||||||
|
@ -469,6 +468,7 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig =
|
||||||
londonBlock: Opt.some(12_965_000.BlockNumber), # 2021-08-05 12:33:42 UTC
|
londonBlock: Opt.some(12_965_000.BlockNumber), # 2021-08-05 12:33:42 UTC
|
||||||
arrowGlacierBlock: Opt.some(13_773_000.BlockNumber), # 2021-12-09 19:55:23 UTC
|
arrowGlacierBlock: Opt.some(13_773_000.BlockNumber), # 2021-12-09 19:55:23 UTC
|
||||||
grayGlacierBlock: Opt.some(15_050_000.BlockNumber), # 2022-06-30 10:54:04 UTC
|
grayGlacierBlock: Opt.some(15_050_000.BlockNumber), # 2022-06-30 10:54:04 UTC
|
||||||
|
posBlock: Opt.some(15_537_394.BlockNumber), # 2022-09-15 05:42:42 UTC
|
||||||
terminalTotalDifficulty: Opt.some(mainNetTTD),
|
terminalTotalDifficulty: Opt.some(mainNetTTD),
|
||||||
shanghaiTime: Opt.some(1_681_338_455.EthTime), # 2023-04-12 10:27:35 UTC
|
shanghaiTime: Opt.some(1_681_338_455.EthTime), # 2023-04-12 10:27:35 UTC
|
||||||
cancunTime: Opt.some(1_710_338_135.EthTime), # 2024-03-13 13:55:35 UTC
|
cancunTime: Opt.some(1_710_338_135.EthTime), # 2024-03-13 13:55:35 UTC
|
||||||
|
@ -476,7 +476,6 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig =
|
||||||
of SepoliaNet:
|
of SepoliaNet:
|
||||||
const sepoliaTTD = parse("17000000000000000",UInt256)
|
const sepoliaTTD = parse("17000000000000000",UInt256)
|
||||||
ChainConfig(
|
ChainConfig(
|
||||||
consensusType: ConsensusType.POW,
|
|
||||||
chainId: SepoliaNet.ChainId,
|
chainId: SepoliaNet.ChainId,
|
||||||
homesteadBlock: Opt.some(0.BlockNumber),
|
homesteadBlock: Opt.some(0.BlockNumber),
|
||||||
daoForkSupport: false,
|
daoForkSupport: false,
|
||||||
|
@ -498,7 +497,6 @@ func chainConfigForNetwork*(id: NetworkId): ChainConfig =
|
||||||
)
|
)
|
||||||
of HoleskyNet:
|
of HoleskyNet:
|
||||||
ChainConfig(
|
ChainConfig(
|
||||||
consensusType: ConsensusType.POS,
|
|
||||||
chainId: HoleskyNet.ChainId,
|
chainId: HoleskyNet.ChainId,
|
||||||
homesteadBlock: Opt.some(0.BlockNumber),
|
homesteadBlock: Opt.some(0.BlockNumber),
|
||||||
eip150Block: Opt.some(0.BlockNumber),
|
eip150Block: Opt.some(0.BlockNumber),
|
||||||
|
|
|
@ -72,9 +72,6 @@ type
|
||||||
|
|
||||||
syncState: SyncState
|
syncState: SyncState
|
||||||
|
|
||||||
# one of POW/POS, updated after calling `hardForkTransition`
|
|
||||||
consensusType: ConsensusType
|
|
||||||
|
|
||||||
syncReqNewHead: SyncReqNewHeadCB
|
syncReqNewHead: SyncReqNewHeadCB
|
||||||
## Call back function for the sync processor. This function stages
|
## Call back function for the sync processor. This function stages
|
||||||
## the arguent header to a private aerea for subsequent processing.
|
## the arguent header to a private aerea for subsequent processing.
|
||||||
|
@ -102,22 +99,12 @@ type
|
||||||
# Forward declarations
|
# Forward declarations
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
func hardForkTransition*(
|
proc proofOfStake*(com: CommonRef, header: Header): bool {.gcsafe.}
|
||||||
com: CommonRef, forkDeterminer: ForkDeterminationInfo)
|
|
||||||
{.gcsafe, raises: [].}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Private helper functions
|
# Private helper functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
func consensusTransition(com: CommonRef, fork: HardFork) =
|
|
||||||
if fork >= MergeFork:
|
|
||||||
com.consensusType = ConsensusType.POS
|
|
||||||
else:
|
|
||||||
# restore consensus type to original config
|
|
||||||
# this could happen during reorg
|
|
||||||
com.consensusType = com.config.consensusType
|
|
||||||
|
|
||||||
func setForkId(com: CommonRef, genesis: BlockHeader) =
|
func setForkId(com: CommonRef, genesis: BlockHeader) =
|
||||||
com.genesisHash = genesis.blockHash
|
com.genesisHash = genesis.blockHash
|
||||||
let genesisCRC = crc32(0, com.genesisHash.data)
|
let genesisCRC = crc32(0, com.genesisHash.data)
|
||||||
|
@ -142,7 +129,7 @@ proc initializeDb(com: CommonRef) =
|
||||||
doAssert(com.genesisHeader.number == 0.BlockNumber,
|
doAssert(com.genesisHeader.number == 0.BlockNumber,
|
||||||
"can't commit genesis block with number > 0")
|
"can't commit genesis block with number > 0")
|
||||||
doAssert(com.db.persistHeader(com.genesisHeader,
|
doAssert(com.db.persistHeader(com.genesisHeader,
|
||||||
com.consensusType == ConsensusType.POS,
|
com.proofOfStake(com.genesisHeader),
|
||||||
startOfHistory=com.genesisHeader.parentHash),
|
startOfHistory=com.genesisHeader.parentHash),
|
||||||
"can persist genesis header")
|
"can persist genesis header")
|
||||||
doAssert(canonicalHeadHashKey().toOpenArray in kvt)
|
doAssert(canonicalHeadHashKey().toOpenArray in kvt)
|
||||||
|
@ -196,11 +183,6 @@ proc init(com : CommonRef,
|
||||||
com.pruneHistory= pruneHistory
|
com.pruneHistory= pruneHistory
|
||||||
com.pos = CasperRef.new
|
com.pos = CasperRef.new
|
||||||
|
|
||||||
# com.consensusType
|
|
||||||
# is set by hardForkTransition.
|
|
||||||
# set it before creating genesis block
|
|
||||||
# TD need to be some(0.u256) because it can be the genesis
|
|
||||||
# already at the MergeFork
|
|
||||||
const TimeZero = EthTime(0)
|
const TimeZero = EthTime(0)
|
||||||
|
|
||||||
# com.forkIdCalculator and com.genesisHash are set
|
# com.forkIdCalculator and com.genesisHash are set
|
||||||
|
@ -214,8 +196,6 @@ proc init(com : CommonRef,
|
||||||
)
|
)
|
||||||
fork = toHardFork(com.forkTransitionTable, forkDeterminer)
|
fork = toHardFork(com.forkTransitionTable, forkDeterminer)
|
||||||
|
|
||||||
com.consensusTransition(fork)
|
|
||||||
|
|
||||||
# Must not overwrite the global state on the single state DB
|
# Must not overwrite the global state on the single state DB
|
||||||
if not db.getBlockHeader(0.BlockNumber, com.genesisHeader):
|
if not db.getBlockHeader(0.BlockNumber, com.genesisHeader):
|
||||||
com.genesisHeader = toGenesisHeader(genesis,
|
com.genesisHeader = toGenesisHeader(genesis,
|
||||||
|
@ -223,35 +203,22 @@ proc init(com : CommonRef,
|
||||||
|
|
||||||
com.setForkId(com.genesisHeader)
|
com.setForkId(com.genesisHeader)
|
||||||
com.pos.timestamp = genesis.timestamp
|
com.pos.timestamp = genesis.timestamp
|
||||||
else:
|
|
||||||
com.hardForkTransition(ForkDeterminationInfo(
|
|
||||||
number: 0.BlockNumber,
|
|
||||||
td: Opt.some(0.u256),
|
|
||||||
time: Opt.some(TimeZero)
|
|
||||||
))
|
|
||||||
|
|
||||||
# By default, history begins at genesis.
|
# By default, history begins at genesis.
|
||||||
com.startOfHistory = GENESIS_PARENT_HASH
|
com.startOfHistory = GENESIS_PARENT_HASH
|
||||||
|
|
||||||
com.initializeDb()
|
com.initializeDb()
|
||||||
|
|
||||||
proc getTd(com: CommonRef, blockHash: Hash256): Opt[DifficultyInt] =
|
proc isBlockAfterTtd(com: CommonRef, header: Header): bool =
|
||||||
var td: DifficultyInt
|
if com.config.terminalTotalDifficulty.isNone:
|
||||||
if not com.db.getTd(blockHash, td):
|
return false
|
||||||
# TODO: Is this really ok?
|
|
||||||
Opt.none(DifficultyInt)
|
|
||||||
else:
|
|
||||||
Opt.some(td)
|
|
||||||
|
|
||||||
func needTdForHardForkDetermination(com: CommonRef): bool =
|
let
|
||||||
let t = com.forkTransitionTable.mergeForkTransitionThreshold
|
ttd = com.config.terminalTotalDifficulty.get()
|
||||||
t.ttdPassed.isNone and t.number.isNone and t.ttd.isSome
|
ptd = com.db.getScore(header.parentHash).valueOr:
|
||||||
|
return false
|
||||||
proc getTdIfNecessary(com: CommonRef, blockHash: Hash256): Opt[DifficultyInt] =
|
td = ptd + header.difficulty
|
||||||
if needTdForHardForkDetermination(com):
|
ptd >= ttd and td >= ttd
|
||||||
getTd(com, blockHash)
|
|
||||||
else:
|
|
||||||
Opt.none(DifficultyInt)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public constructors
|
# Public constructors
|
||||||
|
@ -307,7 +274,6 @@ func clone*(com: CommonRef, db: CoreDbRef): CommonRef =
|
||||||
genesisHeader: com.genesisHeader,
|
genesisHeader: com.genesisHeader,
|
||||||
syncProgress : com.syncProgress,
|
syncProgress : com.syncProgress,
|
||||||
networkId : com.networkId,
|
networkId : com.networkId,
|
||||||
consensusType: com.consensusType,
|
|
||||||
pos : com.pos,
|
pos : com.pos,
|
||||||
pruneHistory : com.pruneHistory)
|
pruneHistory : com.pruneHistory)
|
||||||
|
|
||||||
|
@ -322,38 +288,6 @@ func toHardFork*(
|
||||||
com: CommonRef, forkDeterminer: ForkDeterminationInfo): HardFork =
|
com: CommonRef, forkDeterminer: ForkDeterminationInfo): HardFork =
|
||||||
toHardFork(com.forkTransitionTable, forkDeterminer)
|
toHardFork(com.forkTransitionTable, forkDeterminer)
|
||||||
|
|
||||||
func hardForkTransition(
|
|
||||||
com: CommonRef, forkDeterminer: ForkDeterminationInfo) =
|
|
||||||
## When consensus type already transitioned to POS,
|
|
||||||
## the storage can choose not to store TD anymore,
|
|
||||||
## at that time, TD is no longer needed to find a fork
|
|
||||||
## TD only needed during transition from POW to POS.
|
|
||||||
## Same thing happen before London block, TD can be ignored.
|
|
||||||
|
|
||||||
let fork = com.toHardFork(forkDeterminer)
|
|
||||||
com.consensusTransition(fork)
|
|
||||||
|
|
||||||
func hardForkTransition*(
|
|
||||||
com: CommonRef,
|
|
||||||
number: BlockNumber,
|
|
||||||
td: Opt[DifficultyInt],
|
|
||||||
time: Opt[EthTime]) =
|
|
||||||
com.hardForkTransition(ForkDeterminationInfo(
|
|
||||||
number: number, time: time, td: td))
|
|
||||||
|
|
||||||
proc hardForkTransition*(
|
|
||||||
com: CommonRef,
|
|
||||||
parentHash: Hash256,
|
|
||||||
number: BlockNumber,
|
|
||||||
time: Opt[EthTime]) =
|
|
||||||
com.hardForkTransition(number, getTdIfNecessary(com, parentHash), time)
|
|
||||||
|
|
||||||
proc hardForkTransition*(
|
|
||||||
com: CommonRef, header: BlockHeader)
|
|
||||||
{.gcsafe, raises: [].} =
|
|
||||||
com.hardForkTransition(
|
|
||||||
header.parentHash, header.number, Opt.some(header.timestamp))
|
|
||||||
|
|
||||||
func toEVMFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): EVMFork =
|
func toEVMFork*(com: CommonRef, forkDeterminer: ForkDeterminationInfo): EVMFork =
|
||||||
## similar to toFork, but produce EVMFork
|
## similar to toFork, but produce EVMFork
|
||||||
let fork = com.toHardFork(forkDeterminer)
|
let fork = com.toHardFork(forkDeterminer)
|
||||||
|
@ -380,17 +314,6 @@ func forkId*(com: CommonRef, head: BlockNumber, time: EthTime): ForkID {.gcsafe.
|
||||||
func isEIP155*(com: CommonRef, number: BlockNumber): bool =
|
func isEIP155*(com: CommonRef, number: BlockNumber): bool =
|
||||||
com.config.eip155Block.isSome and number >= com.config.eip155Block.get
|
com.config.eip155Block.isSome and number >= com.config.eip155Block.get
|
||||||
|
|
||||||
proc isBlockAfterTtd*(com: CommonRef, header: BlockHeader): bool =
|
|
||||||
if com.config.terminalTotalDifficulty.isNone:
|
|
||||||
return false
|
|
||||||
|
|
||||||
let
|
|
||||||
ttd = com.config.terminalTotalDifficulty.get()
|
|
||||||
ptd = com.db.getScore(header.parentHash).valueOr:
|
|
||||||
return false
|
|
||||||
td = ptd + header.difficulty
|
|
||||||
ptd >= ttd and td >= ttd
|
|
||||||
|
|
||||||
func isShanghaiOrLater*(com: CommonRef, t: EthTime): bool =
|
func isShanghaiOrLater*(com: CommonRef, t: EthTime): bool =
|
||||||
com.config.shanghaiTime.isSome and t >= com.config.shanghaiTime.get
|
com.config.shanghaiTime.isSome and t >= com.config.shanghaiTime.get
|
||||||
|
|
||||||
|
@ -400,11 +323,15 @@ func isCancunOrLater*(com: CommonRef, t: EthTime): bool =
|
||||||
func isPragueOrLater*(com: CommonRef, t: EthTime): bool =
|
func isPragueOrLater*(com: CommonRef, t: EthTime): bool =
|
||||||
com.config.pragueTime.isSome and t >= com.config.pragueTime.get
|
com.config.pragueTime.isSome and t >= com.config.pragueTime.get
|
||||||
|
|
||||||
proc consensus*(com: CommonRef, header: BlockHeader): ConsensusType =
|
proc proofOfStake*(com: CommonRef, header: Header): bool =
|
||||||
if com.isBlockAfterTtd(header):
|
if com.config.posBlock.isSome:
|
||||||
return ConsensusType.POS
|
# see comments of posBlock in common/hardforks.nim
|
||||||
|
header.number >= com.config.posBlock.get
|
||||||
return com.config.consensusType
|
elif com.config.mergeForkBlock.isSome:
|
||||||
|
header.number >= com.config.mergeForkBlock.get
|
||||||
|
else:
|
||||||
|
# This costly check is only executed from test suite
|
||||||
|
com.isBlockAfterTtd(header)
|
||||||
|
|
||||||
proc syncReqNewHead*(com: CommonRef; header: BlockHeader)
|
proc syncReqNewHead*(com: CommonRef; header: BlockHeader)
|
||||||
{.gcsafe, raises: [].} =
|
{.gcsafe, raises: [].} =
|
||||||
|
@ -441,9 +368,6 @@ func pos*(com: CommonRef): CasperRef =
|
||||||
func db*(com: CommonRef): CoreDbRef =
|
func db*(com: CommonRef): CoreDbRef =
|
||||||
com.db
|
com.db
|
||||||
|
|
||||||
func consensus*(com: CommonRef): ConsensusType =
|
|
||||||
com.consensusType
|
|
||||||
|
|
||||||
func eip150Block*(com: CommonRef): Opt[BlockNumber] =
|
func eip150Block*(com: CommonRef): Opt[BlockNumber] =
|
||||||
com.config.eip150Block
|
com.config.eip150Block
|
||||||
|
|
||||||
|
|
|
@ -18,15 +18,6 @@ import
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
type
|
type
|
||||||
ConsensusType* {.pure.} = enum
|
|
||||||
# Proof of Work
|
|
||||||
# algorithm: Ethash
|
|
||||||
POW
|
|
||||||
|
|
||||||
# Proof of Stake
|
|
||||||
# algorithm: Casper
|
|
||||||
POS
|
|
||||||
|
|
||||||
HardFork* = enum
|
HardFork* = enum
|
||||||
Frontier
|
Frontier
|
||||||
Homestead
|
Homestead
|
||||||
|
@ -166,6 +157,14 @@ type
|
||||||
arrowGlacierBlock* : Opt[BlockNumber]
|
arrowGlacierBlock* : Opt[BlockNumber]
|
||||||
grayGlacierBlock* : Opt[BlockNumber]
|
grayGlacierBlock* : Opt[BlockNumber]
|
||||||
|
|
||||||
|
# posBlock does not participate in ForkId
|
||||||
|
# calculation, and in config file
|
||||||
|
# specially crafted for network depends
|
||||||
|
# solely on TTD for transition to PoS
|
||||||
|
# e.g. MainNet, but now has pass the transition
|
||||||
|
posBlock*
|
||||||
|
{.dontSerialize.} : Opt[BlockNumber]
|
||||||
|
|
||||||
# mergeNetsplitBlock is an alias to mergeForkBlock
|
# mergeNetsplitBlock is an alias to mergeForkBlock
|
||||||
# and is used for geth compatibility layer
|
# and is used for geth compatibility layer
|
||||||
mergeNetsplitBlock* : Opt[BlockNumber]
|
mergeNetsplitBlock* : Opt[BlockNumber]
|
||||||
|
@ -177,8 +176,6 @@ type
|
||||||
|
|
||||||
terminalTotalDifficulty*: Opt[UInt256]
|
terminalTotalDifficulty*: Opt[UInt256]
|
||||||
terminalTotalDifficultyPassed*: Opt[bool]
|
terminalTotalDifficultyPassed*: Opt[bool]
|
||||||
consensusType*
|
|
||||||
{.dontSerialize.} : ConsensusType
|
|
||||||
|
|
||||||
# These are used for checking that the values of the fields
|
# These are used for checking that the values of the fields
|
||||||
# are in a valid order.
|
# are in a valid order.
|
||||||
|
|
|
@ -52,14 +52,18 @@ func newChain*(com: CommonRef,
|
||||||
vmState: vmState
|
vmState: vmState
|
||||||
)
|
)
|
||||||
|
|
||||||
func newChain*(com: CommonRef): ChainRef =
|
proc newChain*(com: CommonRef): ChainRef =
|
||||||
## Constructor for the `Chain` descriptor object. All sub-object descriptors
|
## Constructor for the `Chain` descriptor object. All sub-object descriptors
|
||||||
## are initialised with defaults. So is extra block chain validation
|
## are initialised with defaults. So is extra block chain validation
|
||||||
let extraValidation = com.consensus == ConsensusType.POS
|
try:
|
||||||
ChainRef(
|
let header = com.db.getCanonicalHead()
|
||||||
|
let extraValidation = com.proofOfStake(header)
|
||||||
|
return ChainRef(
|
||||||
com: com,
|
com: com,
|
||||||
extraValidation: extraValidation,
|
extraValidation: extraValidation,
|
||||||
)
|
)
|
||||||
|
except CatchableError:
|
||||||
|
doAssert(false, "no canonical head")
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Public `Chain` getters
|
# Public `Chain` getters
|
||||||
|
|
|
@ -74,7 +74,6 @@ proc processBlock(c: ForkedChainRef,
|
||||||
|
|
||||||
let vmState = BaseVMState()
|
let vmState = BaseVMState()
|
||||||
vmState.init(parent, header, c.com)
|
vmState.init(parent, header, c.com)
|
||||||
c.com.hardForkTransition(header)
|
|
||||||
|
|
||||||
if c.extraValidation:
|
if c.extraValidation:
|
||||||
?c.com.validateHeaderAndKinship(blk, vmState.parent, checkSealOK = false)
|
?c.com.validateHeaderAndKinship(blk, vmState.parent, checkSealOK = false)
|
||||||
|
|
|
@ -85,8 +85,6 @@ proc persistBlocksImpl(
|
||||||
defer:
|
defer:
|
||||||
dbTx.dispose()
|
dbTx.dispose()
|
||||||
|
|
||||||
c.com.hardForkTransition(blocks[0].header)
|
|
||||||
|
|
||||||
# Note that `0 < headers.len`, assured when called from `persistBlocks()`
|
# Note that `0 < headers.len`, assured when called from `persistBlocks()`
|
||||||
let
|
let
|
||||||
vmState =
|
vmState =
|
||||||
|
@ -123,7 +121,6 @@ proc persistBlocksImpl(
|
||||||
let skipValidation =
|
let skipValidation =
|
||||||
NoFullValidation in flags and header.number != toBlock or NoValidation in flags
|
NoFullValidation in flags and header.number != toBlock or NoValidation in flags
|
||||||
|
|
||||||
c.com.hardForkTransition(header)
|
|
||||||
|
|
||||||
if blks > 0:
|
if blks > 0:
|
||||||
template parent(): BlockHeader =
|
template parent(): BlockHeader =
|
||||||
|
@ -161,7 +158,7 @@ proc persistBlocksImpl(
|
||||||
let blockHash = header.blockHash()
|
let blockHash = header.blockHash()
|
||||||
if NoPersistHeader notin flags:
|
if NoPersistHeader notin flags:
|
||||||
if not c.db.persistHeader(
|
if not c.db.persistHeader(
|
||||||
blockHash, header, c.com.consensus == ConsensusType.POS, c.com.startOfHistory
|
blockHash, header, c.com.proofOfStake(header), c.com.startOfHistory
|
||||||
):
|
):
|
||||||
return err("Could not persist header")
|
return err("Could not persist header")
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ proc processBlock*(
|
||||||
?vmState.procBlkPreamble(blk, skipValidation, skipReceipts, skipUncles)
|
?vmState.procBlkPreamble(blk, skipValidation, skipReceipts, skipUncles)
|
||||||
|
|
||||||
# EIP-3675: no reward for miner in POA/POS
|
# EIP-3675: no reward for miner in POA/POS
|
||||||
if vmState.com.consensus == ConsensusType.POW:
|
if not vmState.com.proofOfStake(blk.header):
|
||||||
vmState.calculateReward(blk.header, blk.uncles)
|
vmState.calculateReward(blk.header, blk.uncles)
|
||||||
|
|
||||||
?vmState.procBlkEpilogue(blk, skipValidation, skipReceipts)
|
?vmState.procBlkEpilogue(blk, skipValidation, skipReceipts)
|
||||||
|
|
|
@ -113,8 +113,6 @@ proc setupVMState(com: CommonRef; parent: BlockHeader): BaseVMState =
|
||||||
# BaseVMState querying any hardfork/consensus from CommonRef
|
# BaseVMState querying any hardfork/consensus from CommonRef
|
||||||
|
|
||||||
let pos = com.pos
|
let pos = com.pos
|
||||||
com.hardForkTransition(
|
|
||||||
parent.blockHash, parent.number+1, Opt.some(pos.timestamp))
|
|
||||||
|
|
||||||
let blockCtx = BlockContext(
|
let blockCtx = BlockContext(
|
||||||
timestamp : pos.timestamp,
|
timestamp : pos.timestamp,
|
||||||
|
|
|
@ -76,7 +76,7 @@ proc validateHeader(
|
||||||
if header.extraData != daoForkBlockExtraData:
|
if header.extraData != daoForkBlockExtraData:
|
||||||
return err("header extra data should be marked DAO")
|
return err("header extra data should be marked DAO")
|
||||||
|
|
||||||
if com.consensus == ConsensusType.POS:
|
if com.proofOfStake(header):
|
||||||
# EIP-4399 and EIP-3675
|
# EIP-4399 and EIP-3675
|
||||||
# no need to check mixHash because EIP-4399 override this field
|
# no need to check mixHash because EIP-4399 override this field
|
||||||
# checking rule
|
# checking rule
|
||||||
|
@ -338,7 +338,7 @@ proc validateHeaderAndKinship*(
|
||||||
if blk.uncles.len > MAX_UNCLES:
|
if blk.uncles.len > MAX_UNCLES:
|
||||||
return err("Number of uncles exceed limit.")
|
return err("Number of uncles exceed limit.")
|
||||||
|
|
||||||
if com.consensus != ConsensusType.POS:
|
if not com.proofOfStake(header):
|
||||||
? com.validateUncles(header, blk.uncles, checkSealOK)
|
? com.validateUncles(header, blk.uncles, checkSealOK)
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
|
@ -56,6 +56,7 @@ func blockCtx(com: CommonRef, header: BlockHeader):
|
||||||
difficulty : header.difficulty,
|
difficulty : header.difficulty,
|
||||||
coinbase : header.coinbase,
|
coinbase : header.coinbase,
|
||||||
excessBlobGas: header.excessBlobGas.get(0'u64),
|
excessBlobGas: header.excessBlobGas.get(0'u64),
|
||||||
|
parentHash : header.parentHash,
|
||||||
)
|
)
|
||||||
|
|
||||||
# --------------
|
# --------------
|
||||||
|
@ -241,8 +242,15 @@ func blockNumber*(vmState: BaseVMState): BlockNumber =
|
||||||
# and not head.number
|
# and not head.number
|
||||||
vmState.parent.number + 1
|
vmState.parent.number + 1
|
||||||
|
|
||||||
func difficultyOrPrevRandao*(vmState: BaseVMState): UInt256 =
|
proc proofOfStake*(vmState: BaseVMState): bool =
|
||||||
if vmState.com.consensus == ConsensusType.POS:
|
vmState.com.proofOfStake(Header(
|
||||||
|
number: vmState.blockNumber,
|
||||||
|
parentHash: vmState.blockCtx.parentHash,
|
||||||
|
difficulty: vmState.blockCtx.difficulty,
|
||||||
|
))
|
||||||
|
|
||||||
|
proc difficultyOrPrevRandao*(vmState: BaseVMState): UInt256 =
|
||||||
|
if vmState.proofOfStake():
|
||||||
# EIP-4399/EIP-3675
|
# EIP-4399/EIP-3675
|
||||||
UInt256.fromBytesBE(vmState.blockCtx.prevRandao.data)
|
UInt256.fromBytesBE(vmState.blockCtx.prevRandao.data)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -46,6 +46,7 @@ type
|
||||||
difficulty* : UInt256
|
difficulty* : UInt256
|
||||||
coinbase* : EthAddress
|
coinbase* : EthAddress
|
||||||
excessBlobGas* : uint64
|
excessBlobGas* : uint64
|
||||||
|
parentHash* : Hash32
|
||||||
|
|
||||||
TxContext* = object
|
TxContext* = object
|
||||||
origin* : EthAddress
|
origin* : EthAddress
|
||||||
|
|
|
@ -18,9 +18,6 @@ import
|
||||||
./utils,
|
./utils,
|
||||||
./state_dump
|
./state_dump
|
||||||
|
|
||||||
proc `$`(hash: Hash256): string =
|
|
||||||
hash.data.toHex
|
|
||||||
|
|
||||||
proc `$`(bloom: BloomFilter): string =
|
proc `$`(bloom: BloomFilter): string =
|
||||||
bloom.toHex
|
bloom.toHex
|
||||||
|
|
||||||
|
@ -84,7 +81,7 @@ proc debugAccounts*(vmState: BaseVMState): string =
|
||||||
res.pretty
|
res.pretty
|
||||||
|
|
||||||
proc debug*(vms: BaseVMState): string =
|
proc debug*(vms: BaseVMState): string =
|
||||||
result.add "com.consensus : " & $vms.com.consensus & "\n"
|
result.add "proofOfStake : " & $vms.proofOfStake() & "\n"
|
||||||
result.add "parent : " & $vms.parent.blockHash & "\n"
|
result.add "parent : " & $vms.parent.blockHash & "\n"
|
||||||
result.add "timestamp : " & $vms.blockCtx.timestamp & "\n"
|
result.add "timestamp : " & $vms.blockCtx.timestamp & "\n"
|
||||||
result.add "gasLimit : " & $vms.blockCtx.gasLimit & "\n"
|
result.add "gasLimit : " & $vms.blockCtx.gasLimit & "\n"
|
||||||
|
|
|
@ -75,7 +75,7 @@ proc executeCase(node: JsonNode): bool =
|
||||||
stateDB.persist()
|
stateDB.persist()
|
||||||
|
|
||||||
if not com.db.persistHeader(env.genesisHeader,
|
if not com.db.persistHeader(env.genesisHeader,
|
||||||
com.consensus == ConsensusType.POS):
|
com.proofOfStake(env.genesisHeader)):
|
||||||
debugEcho "Failed to put genesis header into database"
|
debugEcho "Failed to put genesis header into database"
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
@ -147,7 +147,9 @@ when isMainModule:
|
||||||
var testStatusIMPL: TestStatus
|
var testStatusIMPL: TestStatus
|
||||||
let node = json.parseFile(name)
|
let node = json.parseFile(name)
|
||||||
executeFile(node, testStatusIMPL)
|
executeFile(node, testStatusIMPL)
|
||||||
|
if testStatusIMPL == FAILED:
|
||||||
|
quit(QuitFailure)
|
||||||
|
|
||||||
executeFile("tests/fixtures/eth_tests/BlockchainTests/ValidBlocks/bcWalletTest/walletReorganizeOwners.json")
|
executeFile("tests/fixtures/eth_tests/BlockchainTests/GeneralStateTests/stTransactionTest/ValueOverflowParis.json")
|
||||||
else:
|
else:
|
||||||
blockchainJsonMain()
|
blockchainJsonMain()
|
||||||
|
|
|
@ -14,9 +14,6 @@ import
|
||||||
../nimbus/config,
|
../nimbus/config,
|
||||||
../nimbus/common/common
|
../nimbus/common/common
|
||||||
|
|
||||||
#import ../nimbus/db/aristo/aristo_debug
|
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
baseDir = [".", "tests", ".."/"tests", $DirSep] # path containg repo
|
baseDir = [".", "tests", ".."/"tests", $DirSep] # path containg repo
|
||||||
repoDir = [".", "customgenesis"] # alternative repo paths
|
repoDir = [".", "customgenesis"] # alternative repo paths
|
||||||
|
@ -31,9 +28,15 @@ proc findFilePath(file: string): string =
|
||||||
|
|
||||||
proc makeGenesis(networkId: NetworkId): BlockHeader =
|
proc makeGenesis(networkId: NetworkId): BlockHeader =
|
||||||
let com = CommonRef.new(newCoreDbRef DefaultDbMemory, params = networkParams(networkId))
|
let com = CommonRef.new(newCoreDbRef DefaultDbMemory, params = networkParams(networkId))
|
||||||
#debugEcho pp(com.db.defCtx.mpt)
|
|
||||||
com.genesisHeader
|
com.genesisHeader
|
||||||
|
|
||||||
|
proc proofOfStake(params: NetworkParams): bool =
|
||||||
|
let com = CommonRef.new(newCoreDbRef DefaultDbMemory,
|
||||||
|
networkId = params.config.chainId.NetworkId,
|
||||||
|
params = params)
|
||||||
|
let header = com.genesisHeader
|
||||||
|
com.proofOfStake(header)
|
||||||
|
|
||||||
proc genesisTest() =
|
proc genesisTest() =
|
||||||
suite "Genesis":
|
suite "Genesis":
|
||||||
test "Correct mainnet hash":
|
test "Correct mainnet hash":
|
||||||
|
@ -56,9 +59,9 @@ proc customGenesisTest() =
|
||||||
check loadNetworkParams("berlin2000.json".findFilePath, cga)
|
check loadNetworkParams("berlin2000.json".findFilePath, cga)
|
||||||
check loadNetworkParams("chainid7.json".findFilePath, cgb)
|
check loadNetworkParams("chainid7.json".findFilePath, cgb)
|
||||||
check loadNetworkParams("noconfig.json".findFilePath, cgc)
|
check loadNetworkParams("noconfig.json".findFilePath, cgc)
|
||||||
check cga.config.consensusType == ConsensusType.POW
|
check cga.proofOfStake() == false
|
||||||
check cgb.config.consensusType == ConsensusType.POW
|
check cgb.proofOfStake() == false
|
||||||
check cgc.config.consensusType == ConsensusType.POW
|
check cgc.proofOfStake() == false
|
||||||
|
|
||||||
test "Devnet4.json (aka Kintsugi in all but chainId)":
|
test "Devnet4.json (aka Kintsugi in all but chainId)":
|
||||||
var cg: NetworkParams
|
var cg: NetworkParams
|
||||||
|
@ -68,7 +71,7 @@ proc customGenesisTest() =
|
||||||
let genesisHash = hash32"a28d8d73e087a01d09d8cb806f60863652f30b6b6dfa4e0157501ff07d422399"
|
let genesisHash = hash32"a28d8d73e087a01d09d8cb806f60863652f30b6b6dfa4e0157501ff07d422399"
|
||||||
check com.genesisHeader.stateRoot == stateRoot
|
check com.genesisHeader.stateRoot == stateRoot
|
||||||
check com.genesisHeader.blockHash == genesisHash
|
check com.genesisHeader.blockHash == genesisHash
|
||||||
check com.consensus == ConsensusType.POW
|
check com.proofOfStake(com.genesisHeader) == false
|
||||||
|
|
||||||
test "Devnet5.json (aka Kiln in all but chainId and TTD)":
|
test "Devnet5.json (aka Kiln in all but chainId and TTD)":
|
||||||
var cg: NetworkParams
|
var cg: NetworkParams
|
||||||
|
@ -78,7 +81,7 @@ proc customGenesisTest() =
|
||||||
let genesisHash = hash32"51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8"
|
let genesisHash = hash32"51c7fe41be669f69c45c33a56982cbde405313342d9e2b00d7c91a7b284dd4f8"
|
||||||
check com.genesisHeader.stateRoot == stateRoot
|
check com.genesisHeader.stateRoot == stateRoot
|
||||||
check com.genesisHeader.blockHash == genesisHash
|
check com.genesisHeader.blockHash == genesisHash
|
||||||
check com.consensus == ConsensusType.POW
|
check com.proofOfStake(com.genesisHeader) == false
|
||||||
|
|
||||||
test "Mainnet shadow fork 1":
|
test "Mainnet shadow fork 1":
|
||||||
var cg: NetworkParams
|
var cg: NetworkParams
|
||||||
|
@ -90,7 +93,7 @@ proc customGenesisTest() =
|
||||||
check com.genesisHeader.stateRoot == stateRoot
|
check com.genesisHeader.stateRoot == stateRoot
|
||||||
check com.genesisHeader.blockHash == genesisHash
|
check com.genesisHeader.blockHash == genesisHash
|
||||||
check com.ttd.get == ttd
|
check com.ttd.get == ttd
|
||||||
check com.consensus == ConsensusType.POW
|
check com.proofOfStake(com.genesisHeader) == false
|
||||||
|
|
||||||
test "Geth shadow fork 1":
|
test "Geth shadow fork 1":
|
||||||
# parse using geth format should produce the same result with nimbus format
|
# parse using geth format should produce the same result with nimbus format
|
||||||
|
@ -103,7 +106,7 @@ proc customGenesisTest() =
|
||||||
check com.genesisHeader.stateRoot == stateRoot
|
check com.genesisHeader.stateRoot == stateRoot
|
||||||
check com.genesisHeader.blockHash == genesisHash
|
check com.genesisHeader.blockHash == genesisHash
|
||||||
check com.ttd.get == ttd
|
check com.ttd.get == ttd
|
||||||
check com.consensus == ConsensusType.POW
|
check com.proofOfStake(com.genesisHeader) == false
|
||||||
check cg.config.mergeNetsplitBlock.isSome
|
check cg.config.mergeNetsplitBlock.isSome
|
||||||
check cg.config.mergeNetsplitBlock.get == 14660963.BlockNumber
|
check cg.config.mergeNetsplitBlock.get == 14660963.BlockNumber
|
||||||
check cg.config.mergeNetsplitBlock == cg.config.mergeForkBlock
|
check cg.config.mergeNetsplitBlock == cg.config.mergeForkBlock
|
||||||
|
|
|
@ -96,6 +96,7 @@ proc initEnv(envFork: HardFork): TestEnv =
|
||||||
)
|
)
|
||||||
|
|
||||||
if envFork >= MergeFork:
|
if envFork >= MergeFork:
|
||||||
|
conf.networkParams.config.mergeForkBlock = Opt.some(0'u64)
|
||||||
conf.networkParams.config.terminalTotalDifficulty = Opt.some(100.u256)
|
conf.networkParams.config.terminalTotalDifficulty = Opt.some(100.u256)
|
||||||
|
|
||||||
if envFork >= Shanghai:
|
if envFork >= Shanghai:
|
||||||
|
@ -158,8 +159,6 @@ proc runTxPoolPosTest() =
|
||||||
return
|
return
|
||||||
|
|
||||||
blk = r.get.blk
|
blk = r.get.blk
|
||||||
check com.isBlockAfterTtd(blk.header)
|
|
||||||
|
|
||||||
body = BlockBody(
|
body = BlockBody(
|
||||||
transactions: blk.txs,
|
transactions: blk.txs,
|
||||||
uncles: blk.uncles
|
uncles: blk.uncles
|
||||||
|
@ -214,8 +213,6 @@ proc runTxPoolBlobhashTest() =
|
||||||
|
|
||||||
let bundle = r.get
|
let bundle = r.get
|
||||||
blk = bundle.blk
|
blk = bundle.blk
|
||||||
check com.isBlockAfterTtd(blk.header)
|
|
||||||
|
|
||||||
body = BlockBody(
|
body = BlockBody(
|
||||||
transactions: blk.txs,
|
transactions: blk.txs,
|
||||||
uncles: blk.uncles,
|
uncles: blk.uncles,
|
||||||
|
@ -301,8 +298,6 @@ proc runTxHeadDelta(noisy = true) =
|
||||||
return
|
return
|
||||||
|
|
||||||
let blk = r.get.blk
|
let blk = r.get.blk
|
||||||
check com.isBlockAfterTtd(blk.header)
|
|
||||||
|
|
||||||
let body = BlockBody(
|
let body = BlockBody(
|
||||||
transactions: blk.txs,
|
transactions: blk.txs,
|
||||||
uncles: blk.uncles)
|
uncles: blk.uncles)
|
||||||
|
@ -333,8 +328,8 @@ proc runGetBlockBodyTest() =
|
||||||
var
|
var
|
||||||
env = initEnv(Cancun)
|
env = initEnv(Cancun)
|
||||||
blockTime = EthTime.now()
|
blockTime = EthTime.now()
|
||||||
parentHeader: BlockHeader
|
parentHeader: Header
|
||||||
currentHeader: BlockHeader
|
currentHeader: Header
|
||||||
|
|
||||||
suite "Test get parent transactions after persistBlock":
|
suite "Test get parent transactions after persistBlock":
|
||||||
test "TxPool create first block":
|
test "TxPool create first block":
|
||||||
|
|
Loading…
Reference in New Issue