simplify test_blockchain_json a bit
This commit is contained in:
parent
93725bdc02
commit
7bab58731b
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 %{
|
||||||
|
|
Loading…
Reference in New Issue