simplify test_blockchain_json a bit

This commit is contained in:
jangko 2022-12-09 15:17:33 +07:00
parent 93725bdc02
commit 7bab58731b
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
3 changed files with 33 additions and 73 deletions

View File

@ -54,30 +54,6 @@ func computeGasLimit*(parentGasUsed, parentGasLimit, gasFloor, gasCeil: GasInt):
return limit return limit
proc generateHeaderFromParentHeader*(com: CommonRef, parent: BlockHeader,
coinbase: EthAddress, timestamp: Option[EthTime],
gasLimit: GasInt, extraData: Blob, baseFee: Option[UInt256]): BlockHeader =
var lcTimestamp: EthTime
if timestamp.isNone:
lcTimestamp = max(getTime(), parent.timestamp + 1.milliseconds) # Note: Py-evm uses +1 second, not ms
else:
lcTimestamp = timestamp.get()
if lcTimestamp <= parent.timestamp:
raise newException(ValueError, "header.timestamp should be higher than parent.timestamp")
result = BlockHeader(
timestamp: lcTimestamp,
blockNumber: (parent.blockNumber + 1),
difficulty: com.calcDifficulty(lcTimestamp, parent),
gasLimit: gasLimit,
stateRoot: parent.stateRoot,
coinbase: coinbase,
extraData: extraData,
fee: baseFee
)
# CalcGasLimit1559 calculates the next block gas limit under 1559 rules. # CalcGasLimit1559 calculates the next block gas limit under 1559 rules.
func calcGasLimit1559*(parentGasLimit, desiredLimit: GasInt): GasInt = func calcGasLimit1559*(parentGasLimit, desiredLimit: GasInt): GasInt =
let delta = parentGasLimit div GAS_LIMIT_ADJUSTMENT_FACTOR - 1.GasInt let delta = parentGasLimit div GAS_LIMIT_ADJUSTMENT_FACTOR - 1.GasInt

View File

@ -181,8 +181,7 @@ proc getNonce*(dh: TxChainRef; account: EthAddress): AccountNonce
proc getHeader*(dh: TxChainRef): BlockHeader proc getHeader*(dh: TxChainRef): BlockHeader
{.gcsafe,raises: [Defect,CatchableError].} = {.gcsafe,raises: [Defect,CatchableError].} =
## Generate a new header, a child of the cached `head` (similar to ## Generate a new header, a child of the cached `head`
## `utils.generateHeaderFromParentHeader()`.)
let gasUsed = if dh.txEnv.receipts.len == 0: 0.GasInt let gasUsed = if dh.txEnv.receipts.len == 0: 0.GasInt
else: dh.txEnv.receipts[^1].cumulativeGasUsed else: dh.txEnv.receipts[^1].cumulativeGasUsed

View File

@ -24,6 +24,11 @@ import
../nimbus/common/common ../nimbus/common/common
type type
# trick the rlp decoder
# so we can separate the body and header
EthHeader = object
header: BlockHeader
SealEngine = enum SealEngine = enum
NoProof NoProof
Ethash Ethash
@ -31,6 +36,8 @@ type
TestBlock = object TestBlock = object
goodBlock: bool goodBlock: bool
blockRLP : Blob blockRLP : Blob
header : BlockHeader
body : BlockBody
hasException: bool hasException: bool
Tester = object Tester = object
@ -122,14 +129,13 @@ proc parseTester(fixture: JsonNode, testStatusIMPL: var TestStatus): Tester =
result.blocks = parseBlocks(fixture["blocks"]) result.blocks = parseBlocks(fixture["blocks"])
fixture.fromJson "lastblockhash", result.lastBlockHash fixture.fromJson "lastblockhash", result.lastBlockHash
result.genesisHeader = parseHeader(fixture["genesisBlockHeader"], testStatusIMPL)
if "genesisRLP" in fixture: if "genesisRLP" in fixture:
var genesisRLP: Blob var genesisRLP: Blob
fixture.fromJson "genesisRLP", genesisRLP fixture.fromJson "genesisRLP", genesisRLP
let genesisBlock = EthBlock(header: result.genesisHeader) result.genesisHeader = rlp.decode(genesisRLP, EthBlock).header
check genesisRLP == rlp.encode(genesisBlock)
else: else:
result.genesisHeader = parseHeader(fixture["genesisBlockHeader"], testStatusIMPL)
var goodBlock = true var goodBlock = true
for h in result.blocks: for h in result.blocks:
goodBlock = goodBlock and h.goodBlock goodBlock = goodBlock and h.goodBlock
@ -163,45 +169,27 @@ proc blockWitness(vmState: BaseVMState, chainDB: ChainDBRef) =
raise newException(ValidationError, "Invalid trie generated from block witness") raise newException(ValidationError, "Invalid trie generated from block witness")
proc importBlock(tester: var Tester, com: CommonRef, proc importBlock(tester: var Tester, com: CommonRef,
preminedBlock: EthBlock, tb: TestBlock, checkSeal, validation: bool): EthBlock = tb: TestBlock, checkSeal, validation: bool) =
let parentHeader = com.db.getBlockHeader(preminedBlock.header.parentHash) let parentHeader = com.db.getBlockHeader(tb.header.parentHash)
var baseHeaderForImport = generateHeaderFromParentHeader(com, let td = some(com.db.getScore(tb.header.parentHash))
parentHeader, com.hardForkTransition(tb.header.blockNumber, td)
preminedBlock.header.coinbase,
some(preminedBlock.header.timestamp),
preminedBlock.header.gasLimit,
@[],
preminedBlock.header.fee
)
deepCopy(result, preminedBlock)
let td = some(com.db.getScore(preminedBlock.header.parentHash))
com.hardForkTransition(preminedBlock.header.blockNumber, td)
if com.consensus == ConsensusType.POS:
baseHeaderForImport.prevRandao = preminedBlock.header.prevRandao
tester.vmState = BaseVMState.new( tester.vmState = BaseVMState.new(
parentHeader, parentHeader,
baseHeaderForImport, tb.header,
com, com,
(if tester.trace: {TracerFlags.EnableTracing} else: {}), (if tester.trace: {TracerFlags.EnableTracing} else: {}),
) )
let body = BlockBody(
transactions: result.txs,
uncles: result.uncles
)
if validation: if validation:
let rc = com.validateHeaderAndKinship( let rc = com.validateHeaderAndKinship(
result.header, body, checkSeal, pow) tb.header, tb.body, checkSeal, pow)
if rc.isErr: if rc.isErr:
raise newException( raise newException(
ValidationError, "validateHeaderAndKinship: " & rc.error) ValidationError, "validateHeaderAndKinship: " & rc.error)
let res = tester.vmState.processBlockNotPoA(result.header, body) let res = tester.vmState.processBlockNotPoA(tb.header, tb.body)
if res == ValidationResult.Error: if res == ValidationResult.Error:
if not (tb.hasException or (not tb.goodBlock)): if not (tb.hasException or (not tb.goodBlock)):
raise newException(ValidationError, "process block validation") raise newException(ValidationError, "process block validation")
@ -209,17 +197,14 @@ proc importBlock(tester: var Tester, com: CommonRef,
if tester.vmState.generateWitness(): if tester.vmState.generateWitness():
blockWitness(tester.vmState, com.db) blockWitness(tester.vmState, com.db)
discard com.db.persistHeaderToDb(preminedBlock.header, none(DifficultyInt)) discard com.db.persistHeaderToDb(tb.header, none(DifficultyInt))
proc applyFixtureBlockToChain(tester: var Tester, tb: TestBlock, proc applyFixtureBlockToChain(tester: var Tester, tb: var TestBlock,
com: CommonRef, checkSeal, validation: bool): (EthBlock, EthBlock, Blob) = com: CommonRef, checkSeal, validation: bool) =
var rlp = rlpFromBytes(tb.blockRLP)
var tb.header = rlp.read(EthHeader).header
preminedBlock = rlp.decode(tb.blockRLP, EthBlock) tb.body = rlp.readRecordType(BlockBody, false)
minedBlock = tester.importBlock(com, preminedBlock, tb, checkSeal, validation) tester.importBlock(com, tb, checkSeal, validation)
rlpEncodedMinedBlock = rlp.encode(minedBlock)
result = (preminedBlock, minedBlock, rlpEncodedMinedBlock)
func shouldCheckSeal(tester: Tester): bool = func shouldCheckSeal(tester: Tester): bool =
if tester.sealEngine.isSome: if tester.sealEngine.isSome:
@ -244,20 +229,20 @@ proc runTester(tester: var Tester, com: CommonRef, testStatusIMPL: var TestStatu
if tester.debugMode: if tester.debugMode:
tester.debugData = newJArray() tester.debugData = newJArray()
for idx, testBlock in tester.blocks: for idx, tb in tester.blocks:
if testBlock.goodBlock: if tb.goodBlock:
try: try:
let (preminedBlock, _, _) = tester.applyFixtureBlockToChain( tester.applyFixtureBlockToChain(
testBlock, com, checkSeal, validation = false) tester.blocks[idx], com, checkSeal, validation = false)
# manually validating # manually validating
let res = com.validateHeaderAndKinship( let res = com.validateHeaderAndKinship(
preminedBlock, checkSeal, pow) tb.header, tb.body, checkSeal, pow)
check res.isOk check res.isOk
when defined(noisy): when defined(noisy):
if res.isErr: if res.isErr:
debugEcho "blockNumber : ", preminedBlock.header.blockNumber debugEcho "blockNumber : ", tb.header.blockNumber
debugEcho "fork : ", com.toHardFork(preminedBlock.header.blockNumber) debugEcho "fork : ", com.toHardFork(tb.header.blockNumber)
debugEcho "error message: ", res.error debugEcho "error message: ", res.error
debugEcho "consensusType: ", com.consensus debugEcho "consensusType: ", com.consensus
@ -267,11 +252,11 @@ proc runTester(tester: var Tester, com: CommonRef, testStatusIMPL: var TestStatu
else: else:
var noError = true var noError = true
try: try:
let (_, _, _) = tester.applyFixtureBlockToChain(testBlock, tester.applyFixtureBlockToChain(tester.blocks[idx],
com, checkSeal, validation = true) com, checkSeal, validation = true)
except ValueError, ValidationError, BlockNotFound, RlpError: except ValueError, ValidationError, BlockNotFound, RlpError:
# failure is expected on this bad block # failure is expected on this bad block
check (testBlock.hasException or (not testBlock.goodBlock)) check (tb.hasException or (not tb.goodBlock))
noError = false noError = false
if tester.debugMode: if tester.debugMode:
tester.debugData.add %{ tester.debugData.add %{