update EF test fixtures and fixes to pass all tests

This commit is contained in:
jangko 2022-09-26 23:14:12 +07:00
parent ae20b92428
commit 16bc2de1cf
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
13 changed files with 252 additions and 63 deletions

View File

@ -8,7 +8,7 @@
# those terms.
import
std/[json, strutils],
std/[json, strutils, options],
stew/byteutils
type
@ -42,6 +42,8 @@ proc processNetwork(network: string): JsonNode =
berlinBlock = 2000
londonBlock = 2000
arrowGlacierBlock = 2000
mergeForkBlock = none(int)
ttd = none(int)
case network
@ -116,6 +118,20 @@ proc processNetwork(network: string): JsonNode =
berlinBlock = 0
londonBlock = 0
arrowGlacierBlock = 0
of "Merge":
homesteadBlock = 0
eip150Block = 0
eip158Block = 0
byzantiumBlock = 0
constantinopleBlock = 0
petersburgBlock = 0
istanbulBlock = 0
muirGlacierBlock = 0
berlinBlock = 0
londonBlock = 0
arrowGlacierBlock = 0
mergeForkBlock = some(0)
ttd = some(0)
# Just the subset of "At5" networks mentioned in the test suite.
of "FrontierToHomesteadAt5":
@ -150,6 +166,19 @@ proc processNetwork(network: string): JsonNode =
muirGlacierBlock = 0
berlinBlock = 0
londonBlock = 5
of "ArrowGlacierToMergeAtDiffC0000":
homesteadBlock = 0
eip150Block = 0
eip158Block = 0
byzantiumBlock = 0
constantinopleBlock = 0
petersburgBlock = 0
istanbulBlock = 0
muirGlacierBlock = 0
berlinBlock = 0
londonBlock = 0
arrowGlacierBlock = 0
ttd = some(0xC0000)
else:
doAssert(false, "unsupported network: " & network)
@ -169,7 +198,11 @@ proc processNetwork(network: string): JsonNode =
n["berlinBlock"] = newJInt(berlinBlock)
n["londonBlock"] = newJInt(londonBlock)
n["arrowGlacierBlock"] = newJInt(arrowGlacierBlock)
if mergeForkBlock.isSome:
n["mergeForkBlock"] = newJInt(mergeForkBlock.get())
n["chainId"] = newJInt(1)
if ttd.isSome:
n["terminalTotalDifficulty"] = newJString("0x" & ttd.get().toHex(8))
result = n
proc optionalField(n: string, genesis, gen: JsonNode) =

View File

@ -1,5 +1,12 @@
newBlockchainTests
===
## bcArrowGlacierToMerge
```diff
+ difficultyFormula.json OK
+ powToPosBlockRejection.json OK
+ powToPosTest.json OK
```
OK: 3/3 Fail: 0/3 Skip: 0/3
## bcBerlinToLondon
```diff
+ BerlinToLondonTransition.json OK
@ -29,6 +36,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ baseFee.json OK
+ besuBaseFeeBug.json OK
+ burnVerify.json OK
+ burnVerifyLondon.json OK
+ checkGasLimit.json OK
+ feeCap.json OK
+ gasLimit20m.json OK
@ -40,21 +48,29 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ lowDemand.json OK
+ medDemand.json OK
+ tips.json OK
+ tipsLondon.json OK
+ transFail.json OK
+ transType.json OK
+ valCausesOOF.json OK
```
OK: 19/19 Fail: 0/19 Skip: 0/19
OK: 21/21 Fail: 0/21 Skip: 0/21
## bcEIP158ToByzantium
```diff
+ ByzantiumTransition.json OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
## bcEIP3675
```diff
+ timestampPerBlock.json OK
+ tipInsideBlock.json OK
```
OK: 2/2 Fail: 0/2 Skip: 0/2
## bcExample
```diff
+ basefeeExample.json OK
+ mergeExample.json OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
OK: 2/2 Fail: 0/2 Skip: 0/2
## bcExploitTest
```diff
DelegateCallSpam.json Skip
@ -266,6 +282,7 @@ OK: 96/96 Fail: 0/96 Skip: 0/96
+ RefundOverflow.json OK
+ RefundOverflow2.json OK
+ SuicidesMixingCoinbase.json OK
+ SuicidesMixingCoinbase2.json OK
+ TransactionFromCoinbaseHittingBlockGasLimit1.json OK
+ TransactionFromCoinbaseNotEnoughFounds.json OK
+ TransactionNonceCheck.json OK
@ -299,6 +316,7 @@ OK: 96/96 Fail: 0/96 Skip: 0/96
+ extcodehashEmptySuicide.json OK
+ logRevert.json OK
+ multimpleBalanceInstruction.json OK
+ random.json OK
+ randomStatetest123.json OK
+ randomStatetest136.json OK
+ randomStatetest160.json OK
@ -344,7 +362,7 @@ OK: 96/96 Fail: 0/96 Skip: 0/96
+ transactionFromSelfDestructedContract.json OK
+ txCost-sec73.json OK
```
OK: 87/88 Fail: 0/88 Skip: 1/88
OK: 89/90 Fail: 0/90 Skip: 1/90
## bcTotalDifficultyTest
```diff
+ lotsOfBranchesOverrideAtTheEnd.json OK
@ -405,6 +423,7 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
## bcUncleTest
```diff
+ EqualUncleInTwoDifferentBlocks.json OK
+ EqualUncleInTwoDifferentBlocks2.json OK
+ InChainUncle.json OK
+ InChainUncleFather.json OK
+ InChainUncleGrandPa.json OK
@ -427,7 +446,7 @@ OK: 9/9 Fail: 0/9 Skip: 0/9
+ uncleHeaderWithGeneration0.json OK
+ uncleWithSameBlockNumber.json OK
```
OK: 22/22 Fail: 0/22 Skip: 0/22
OK: 23/23 Fail: 0/23 Skip: 0/23
## bcValidBlockTest
```diff
+ ExtraData32.json OK
@ -730,8 +749,9 @@ OK: 5/5 Fail: 0/5 Skip: 0/5
+ callcodecallcodecallcode_111_SuicideEnd.json OK
+ callcodecallcodecallcode_111_SuicideMiddle.json OK
callcodecallcodecallcode_ABCB_RECURSIVE.json Skip
+ touchAndGo.json OK
```
OK: 72/79 Fail: 0/79 Skip: 7/79
OK: 73/80 Fail: 0/80 Skip: 7/80
## stCallCreateCallCodeTest
```diff
Call1024BalanceTooLow.json Skip
@ -1006,6 +1026,7 @@ OK: 51/52 Fail: 0/52 Skip: 1/52
+ CREATE_HighNonceMinus1.json OK
+ CREATE_empty000CreateinInitCode_Transaction.json OK
+ CodeInConstructor.json OK
+ CreateAddressWarmAfterFail.json OK
+ CreateCollisionResults.json OK
+ CreateCollisionToEmpty.json OK
+ CreateOOGFromCallRefunds.json OK
@ -1019,12 +1040,14 @@ OK: 51/52 Fail: 0/52 Skip: 1/52
+ CreateOOGafterInitCodeRevert2.json OK
+ CreateOOGafterMaxCodesize.json OK
+ CreateResults.json OK
+ CreateTransactionHighNonce.json OK
+ TransactionCollisionToEmpty.json OK
+ TransactionCollisionToEmptyButCode.json OK
+ TransactionCollisionToEmptyButNonce.json OK
+ createFailResult.json OK
+ createLargeResult.json OK
```
OK: 41/41 Fail: 0/41 Skip: 0/41
OK: 44/44 Fail: 0/44 Skip: 0/44
## stDelegatecallTestHomestead
```diff
Call1024BalanceTooLow.json Skip
@ -1128,12 +1151,13 @@ OK: 40/40 Fail: 0/40 Skip: 0/40
+ lowGasPriceOldTypes.json OK
+ outOfFunds.json OK
+ outOfFundsOldTypes.json OK
+ senderBalance.json OK
+ tipTooHigh.json OK
+ transactionIntinsicBug.json OK
+ typeTwoBerlin.json OK
+ valCausesOOF.json OK
```
OK: 12/12 Fail: 0/12 Skip: 0/12
OK: 13/13 Fail: 0/13 Skip: 0/13
## stEIP158Specific
```diff
+ CALL_OneVCallSuicide.json OK
@ -1175,11 +1199,12 @@ OK: 5/5 Fail: 0/5 Skip: 0/5
+ indexesOmitExample.json OK
+ invalidTr.json OK
+ labelsExample.json OK
+ mergeTest.json OK
+ rangesExample.json OK
+ solidityExample.json OK
+ yulExample.json OK
```
OK: 11/11 Fail: 0/11 Skip: 0/11
OK: 12/12 Fail: 0/12 Skip: 0/12
## stExtCodeHash
```diff
+ callToNonExistent.json OK
@ -1457,6 +1482,7 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
## stPreCompiledContracts
```diff
+ blake2B.json OK
+ delegatecall09Undefined.json OK
+ idPrecomps.json OK
+ identity_to_bigger.json OK
+ identity_to_smaller.json OK
@ -1465,7 +1491,7 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
+ precompsEIP2929.json OK
+ sec80.json OK
```
OK: 8/8 Fail: 0/8 Skip: 0/8
OK: 9/9 Fail: 0/9 Skip: 0/9
## stPreCompiledContracts2
```diff
+ CALLBlake2f.json OK
@ -1533,6 +1559,7 @@ OK: 8/8 Fail: 0/8 Skip: 0/8
+ CallEcrecoverS_prefixed0.json OK
+ CallEcrecoverUnrecoverableKey.json OK
+ CallEcrecoverV_prefixed0.json OK
+ CallEcrecover_Overflow.json OK
+ CallIdentitiy_0.json OK
+ CallIdentitiy_1.json OK
+ CallIdentity_1_nonzeroValue.json OK
@ -1562,13 +1589,15 @@ OK: 8/8 Fail: 0/8 Skip: 0/8
+ CallSha256_4.json OK
+ CallSha256_4_gas99.json OK
+ CallSha256_5.json OK
+ ecrecoverShortBuff.json OK
+ ecrecoverWeirdV.json OK
+ modexpRandomInput.json OK
+ modexp_0_0_0_20500.json OK
+ modexp_0_0_0_22000.json OK
+ modexp_0_0_0_25000.json OK
+ modexp_0_0_0_35000.json OK
```
OK: 99/99 Fail: 0/99 Skip: 0/99
OK: 102/102 Fail: 0/102 Skip: 0/102
## stQuadraticComplexityTest
```diff
Call1MB1024Calldepth.json Skip
@ -2772,6 +2801,7 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ currentAccountBalance.json OK
+ doubleSelfdestructTest.json OK
+ doubleSelfdestructTest2.json OK
+ doubleSelfdestructTouch.json OK
+ extcodecopy.json OK
+ return0.json OK
+ return1.json OK
@ -2786,7 +2816,7 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ suicideSendEtherToMe.json OK
+ testRandomTest.json OK
```
OK: 56/66 Fail: 0/66 Skip: 10/66
OK: 57/67 Fail: 0/67 Skip: 10/67
## stTimeConsuming
```diff
CALLBlake2f_MaxRounds.json Skip
@ -3306,4 +3336,4 @@ OK: 0/3 Fail: 0/3 Skip: 3/3
OK: 11/11 Fail: 0/11 Skip: 0/11
---TOTAL---
OK: 2859/2964 Fail: 0/2964 Skip: 105/2964
OK: 2881/2986 Fail: 0/2986 Skip: 105/2986

View File

@ -271,8 +271,9 @@ OK: 5/5 Fail: 0/5 Skip: 0/5
+ callcodecallcodecallcode_111_SuicideEnd.json OK
+ callcodecallcodecallcode_111_SuicideMiddle.json OK
callcodecallcodecallcode_ABCB_RECURSIVE.json Skip
+ touchAndGo.json OK
```
OK: 72/79 Fail: 0/79 Skip: 7/79
OK: 73/80 Fail: 0/80 Skip: 7/80
## stCallCreateCallCodeTest
```diff
Call1024BalanceTooLow.json Skip
@ -547,6 +548,7 @@ OK: 51/52 Fail: 0/52 Skip: 1/52
+ CREATE_HighNonceMinus1.json OK
+ CREATE_empty000CreateinInitCode_Transaction.json OK
+ CodeInConstructor.json OK
+ CreateAddressWarmAfterFail.json OK
+ CreateCollisionResults.json OK
+ CreateCollisionToEmpty.json OK
+ CreateOOGFromCallRefunds.json OK
@ -560,12 +562,14 @@ OK: 51/52 Fail: 0/52 Skip: 1/52
+ CreateOOGafterInitCodeRevert2.json OK
+ CreateOOGafterMaxCodesize.json OK
+ CreateResults.json OK
+ CreateTransactionHighNonce.json OK
+ TransactionCollisionToEmpty.json OK
+ TransactionCollisionToEmptyButCode.json OK
+ TransactionCollisionToEmptyButNonce.json OK
+ createFailResult.json OK
+ createLargeResult.json OK
```
OK: 41/41 Fail: 0/41 Skip: 0/41
OK: 44/44 Fail: 0/44 Skip: 0/44
## stDelegatecallTestHomestead
```diff
Call1024BalanceTooLow.json Skip
@ -669,12 +673,13 @@ OK: 40/40 Fail: 0/40 Skip: 0/40
+ lowGasPriceOldTypes.json OK
+ outOfFunds.json OK
+ outOfFundsOldTypes.json OK
+ senderBalance.json OK
+ tipTooHigh.json OK
+ transactionIntinsicBug.json OK
+ typeTwoBerlin.json OK
+ valCausesOOF.json OK
```
OK: 12/12 Fail: 0/12 Skip: 0/12
OK: 13/13 Fail: 0/13 Skip: 0/13
## stEIP158Specific
```diff
+ CALL_OneVCallSuicide.json OK
@ -716,11 +721,12 @@ OK: 5/5 Fail: 0/5 Skip: 0/5
+ indexesOmitExample.json OK
+ invalidTr.json OK
+ labelsExample.json OK
+ mergeTest.json OK
+ rangesExample.json OK
+ solidityExample.json OK
+ yulExample.json OK
```
OK: 11/11 Fail: 0/11 Skip: 0/11
OK: 12/12 Fail: 0/12 Skip: 0/12
## stExtCodeHash
```diff
+ callToNonExistent.json OK
@ -998,6 +1004,7 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
## stPreCompiledContracts
```diff
+ blake2B.json OK
+ delegatecall09Undefined.json OK
+ idPrecomps.json OK
+ identity_to_bigger.json OK
+ identity_to_smaller.json OK
@ -1006,7 +1013,7 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
+ precompsEIP2929.json OK
+ sec80.json OK
```
OK: 8/8 Fail: 0/8 Skip: 0/8
OK: 9/9 Fail: 0/9 Skip: 0/9
## stPreCompiledContracts2
```diff
+ CALLBlake2f.json OK
@ -1074,6 +1081,7 @@ OK: 8/8 Fail: 0/8 Skip: 0/8
+ CallEcrecoverS_prefixed0.json OK
+ CallEcrecoverUnrecoverableKey.json OK
+ CallEcrecoverV_prefixed0.json OK
+ CallEcrecover_Overflow.json OK
+ CallIdentitiy_0.json OK
+ CallIdentitiy_1.json OK
+ CallIdentity_1_nonzeroValue.json OK
@ -1103,13 +1111,15 @@ OK: 8/8 Fail: 0/8 Skip: 0/8
+ CallSha256_4.json OK
+ CallSha256_4_gas99.json OK
+ CallSha256_5.json OK
+ ecrecoverShortBuff.json OK
+ ecrecoverWeirdV.json OK
+ modexpRandomInput.json OK
+ modexp_0_0_0_20500.json OK
+ modexp_0_0_0_22000.json OK
+ modexp_0_0_0_25000.json OK
+ modexp_0_0_0_35000.json OK
```
OK: 99/99 Fail: 0/99 Skip: 0/99
OK: 102/102 Fail: 0/102 Skip: 0/102
## stQuadraticComplexityTest
```diff
Call1MB1024Calldepth.json Skip
@ -2313,6 +2323,7 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ currentAccountBalance.json OK
+ doubleSelfdestructTest.json OK
+ doubleSelfdestructTest2.json OK
+ doubleSelfdestructTouch.json OK
+ extcodecopy.json OK
+ return0.json OK
+ return1.json OK
@ -2327,7 +2338,7 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ suicideSendEtherToMe.json OK
+ testRandomTest.json OK
```
OK: 56/66 Fail: 0/66 Skip: 10/66
OK: 57/67 Fail: 0/67 Skip: 10/67
## stTimeConsuming
```diff
CALLBlake2f_MaxRounds.json Skip
@ -2847,4 +2858,4 @@ OK: 1/3 Fail: 0/3 Skip: 2/3
OK: 11/11 Fail: 0/11 Skip: 0/11
---TOTAL---
OK: 2495/2597 Fail: 0/2597 Skip: 102/2597
OK: 2506/2608 Fail: 0/2608 Skip: 102/2608

View File

@ -357,6 +357,9 @@ proc parseGenesisAlloc*(data: string, ga: var GenesisAlloc): bool
proc toFork*(c: ChainConfig, number: BlockNumber): Fork =
## Map to EVM fork, which doesn't include the DAO or Glacier forks.
if c.mergeForkBlock.isSome and number >= c.mergeForkBlock.get:
return FkParis
if number >= c.londonBlock: FkLondon
elif number >= c.berlinBlock: FkBerlin
elif number >= c.istanbulBlock: FkIstanbul

View File

@ -463,6 +463,24 @@ proc persist*(ac: AccountsCache, clearCache: bool = true) =
ac.isDirty = false
iterator addresses*(ac: AccountsCache): EthAddress =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavepoint.isNil)
for address, _ in ac.savePoint.cache:
yield address
iterator accounts*(ac: AccountsCache): Account =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavepoint.isNil)
for _, account in ac.savePoint.cache:
yield account.account
iterator pairs*(ac: AccountsCache): (EthAddress, Account) =
# make sure all savepoint already committed
doAssert(ac.savePoint.parentSavepoint.isNil)
for address, account in ac.savePoint.cache:
yield (address, account.account)
iterator storage*(ac: AccountsCache, address: EthAddress): (UInt256, UInt256) =
# beware that if the account not persisted,
# the storage root will not be updated

View File

@ -144,6 +144,10 @@ proc getBlockHeader*(self: BaseChainDB; n: BlockNumber): BlockHeader =
proc getScore*(self: BaseChainDB; blockHash: Hash256): UInt256 =
rlp.decode(self.db.get(blockHashToScoreKey(blockHash).toOpenArray), UInt256)
proc setScore*(self: BaseChainDB; blockHash: Hash256, score: UInt256) =
## for testing purpose
self.db.put(blockHashToScoreKey(blockHash).toOpenArray, rlp.encode(score))
proc getTd*(self: BaseChainDB; blockHash: Hash256, td: var UInt256): bool =
let bytes = self.db.get(blockHashToScoreKey(blockHash).toOpenArray)
if bytes.len == 0: return false
@ -162,7 +166,14 @@ proc headTotalDifficulty*(self: BaseChainDB): UInt256 =
let blockHash = rlp.decode(data, Hash256)
rlp.decode(self.db.get(blockHashToScoreKey(blockHash).toOpenArray), UInt256)
proc isBlockAfterTtd*(self: BaseChainDB, header: BlockHeader): bool =
let
ttd = self.ttd
ptd = self.getScore(header.parentHash)
td = ptd + header.difficulty
ptd >= ttd and td >= ttd
proc getAncestorsHashes*(self: BaseChainDB, limit: UInt256, header: BlockHeader): seq[Hash256] =
var ancestorCount = min(header.blockNumber, limit).truncate(int)
var h = header
@ -465,7 +476,7 @@ proc persistHeaderToDb*(self: BaseChainDB; header: BlockHeader): seq[BlockHeader
if headScore < ttd and score >= ttd:
self.writeTerminalHash(headerHash)
if score > headScore:
if score > headScore or score >= ttd:
result = self.setAsCanonicalChainHead(headerHash)
proc persistHeaderToDbWithoutSetHead*(self: BaseChainDB; header: BlockHeader) =

View File

@ -13,6 +13,8 @@ import
proc newStateDB*(db: TrieDatabaseRef, pruneTrie: bool): AccountStateDB =
newAccountStateDB(db, emptyRlpHash, pruneTrie)
import debug
proc toGenesisHeader*(db: BaseChainDB, sdb: AccountStateDB): BlockHeader
{.raises: [Defect, RlpError].} =
## Initialise block chain DB accounts derived from the `genesis.alloc` table
@ -76,15 +78,16 @@ proc toGenesisHeader*(db: BaseChainDB, sdb: AccountStateDB): BlockHeader
ommersHash: EMPTY_UNCLE_HASH
)
let fork = db.config.toFork(0.toBlockNumber)
if g.baseFeePerGas.isSome:
result.baseFee = g.baseFeePerGas.get()
elif db.config.toFork(0.toBlockNumber) >= FkLondon:
elif fork >= FkLondon:
result.baseFee = EIP1559_INITIAL_BASE_FEE.u256
if g.gasLimit.isZero:
result.gasLimit = GENESIS_GAS_LIMIT
if g.difficulty.isZero:
if g.difficulty.isZero and fork <= FkLondon:
result.difficulty = GENESIS_DIFFICULTY
proc toGenesisHeader*(params: NetworkParams): BlockHeader

View File

@ -91,17 +91,7 @@ func toNextFork(n: Option[BlockNumber]): uint64 =
proc isBlockAfterTtd*(c: Chain, header: BlockHeader): bool
{.gcsafe, raises: [Defect,CatchableError].} =
let
ttd = c.db.ttd
ptd = c.db.getScore(header.parentHash)
td = ptd + header.difficulty
# c.db.totalDifficulty is parent.totalDifficulty
# TerminalBlock is defined as header.totalDifficulty >= TTD
# and parent.totalDifficulty < TTD
# So blockAfterTTD must be both header.totalDifficulty >= TTD
# and parent.totalDifficulty >= TTD
ptd >= ttd and td >= ttd
isBlockAfterTtd(c.db, header)
func getNextFork(c: ChainConfig, fork: ChainFork): uint64 =
let next: array[ChainFork, uint64] = [

View File

@ -321,6 +321,10 @@ proc validateTransaction*(
accountNonce=nonce
return false
if tx.nonce == high(uint64):
debug "invalid tx: nonce at maximum"
return false
# EIP-3607 Reject transactions from senders with deployed code
# The EIP spec claims this attack never happened before
# Clients might choose to disable this rule for RPC calls like

View File

@ -142,6 +142,7 @@ when isMainModule and isChatty:
echo ">>> frontier[sstore]: ", FkFrontier.opHandlersInfo(Sstore)
echo ">>> constantinople[sstore]: ", FkConstantinople.opHandlersInfo(Sstore)
echo ">>> berlin[sstore]: ", FkBerlin.opHandlersInfo(Sstore)
echo ">>> paris[sstore]: ", FkParis.opHandlersInfo(Sstore)
# ------------------------------------------------------------------------------
# End

View File

@ -9,7 +9,7 @@ import
unittest2, json, os, tables, strutils, sets,
options,
eth/[common, rlp], eth/trie/[db, trie_defs],
stew/endians2,
stew/[endians2, byteutils],
./test_helpers, ./test_allowed_to_fail,
../premix/parser, test_config,
../nimbus/[vm_state, utils, vm_types, errors, constants, forks],
@ -39,6 +39,7 @@ type
vmState : BaseVMState
debugData : JsonNode
network : string
postStateHash: Hash256
var pow = PowRef.new
@ -146,7 +147,9 @@ func vmConfiguration(network: string, c: var ChainConfig) =
c.berlinBlock = number[FkBerlin]
c.londonBlock = number[FkLondon]
c.arrowGlacierBlock = number[FkLondon]
c.mergeForkBlock = some(number[FkParis])
c.terminalTotalDifficulty = none(UInt256)
case network
of "EIP150":
c.assignNumber(FkTangerine, Zero)
@ -183,6 +186,12 @@ func vmConfiguration(network: string, c: var ChainConfig) =
c.assignNumber(FkLondon, Zero)
of "BerlinToLondonAt5":
c.assignNumber(FkLondon, Five)
of "Merge":
c.assignNumber(FkParis, Zero)
c.terminalTotalDifficulty = some(0.u256)
of "ArrowGlacierToMergeAtDiffC0000":
c.assignNumber(FkParis, H)
c.terminalTotalDifficulty = some(0xC0000.u256)
else:
raise newException(ValueError, "unsupported network " & network)
@ -205,6 +214,10 @@ proc parseTester(fixture: JsonNode, testStatusIMPL: var TestStatus): Tester =
if "sealEngine" in fixture:
result.sealEngine = some(parseEnum[SealEngine](fixture["sealEngine"].getStr))
if "postStateHash" in fixture:
result.postStateHash.data = hexToByteArray[32](fixture["postStateHash"].getStr)
result.network = fixture["network"].getStr
proc blockWitness(vmState: BaseVMState, chainDB: BaseChainDB) =
@ -230,7 +243,7 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB,
preminedBlock: EthBlock, tb: TestBlock, checkSeal, validation: bool): EthBlock =
let parentHeader = chainDB.getBlockHeader(preminedBlock.header.parentHash)
let baseHeaderForImport = generateHeaderFromParentHeader(chainDB.config,
var baseHeaderForImport = generateHeaderFromParentHeader(chainDB.config,
parentHeader,
preminedBlock.header.coinbase,
some(preminedBlock.header.timestamp),
@ -240,6 +253,12 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB,
)
deepCopy(result, preminedBlock)
let ttdReached = chainDB.isBlockAfterTtd(preminedBlock.header)
if ttdReached and chainDB.config.mergeForkBlock.isNone:
chainDB.config.mergeForkBlock = some(preminedBlock.header.blockNumber)
if ttdReached:
baseHeaderForImport.prevRandao = preminedBlock.header.prevRandao
tester.vmState = BaseVMState.new(
parentHeader,
@ -252,6 +271,14 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB,
transactions: result.txs,
uncles: result.uncles
)
if validation:
let rc = chainDB.validateHeaderAndKinship(
result.header, body, checkSeal, ttdReached, pow)
if rc.isErr:
raise newException(
ValidationError, "validateHeaderAndKinship: " & rc.error)
let res = tester.vmState.processBlockNotPoA(result.header, body)
if res == ValidationResult.Error:
if not (tb.hasException or (not tb.goodBlock)):
@ -260,13 +287,6 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB,
if tester.vmState.generateWitness():
blockWitness(tester.vmState, chainDB)
if validation:
let rc = chainDB.validateHeaderAndKinship(
result.header, body, checkSeal, false, pow)
if rc.isErr:
raise newException(
ValidationError, "validateHeaderAndKinship: " & rc.error)
discard chainDB.persistHeaderToDb(preminedBlock.header)
proc applyFixtureBlockToChain(tester: var Tester, tb: TestBlock,
@ -279,6 +299,7 @@ proc applyFixtureBlockToChain(tester: var Tester, tb: TestBlock,
preminedBlock = rlp.decode(tb.blockRLP, EthBlock)
minedBlock = tester.importBlock(chainDB, preminedBlock, tb, checkSeal, validation)
rlpEncodedMinedBlock = rlp.encode(minedBlock)
result = (preminedBlock, minedBlock, rlpEncodedMinedBlock)
func shouldCheckSeal(tester: Tester): bool =
@ -310,9 +331,20 @@ proc runTester(tester: var Tester, chainDB: BaseChainDB, testStatusIMPL: var Tes
let (preminedBlock, _, _) = tester.applyFixtureBlockToChain(
testBlock, chainDB, checkSeal, validation = false)
let ttdReached = chainDB.isBlockAfterTtd(preminedBlock.header)
if ttdReached and chainDB.config.mergeForkBlock.isNone:
chainDB.config.mergeForkBlock = some(preminedBlock.header.blockNumber)
# manually validating
check chainDB.validateHeaderAndKinship(
preminedBlock, checkSeal, false, pow).isOk
let res = chainDB.validateHeaderAndKinship(
preminedBlock, checkSeal, ttdReached, pow)
check res.isOk
when defined(noisy):
if res.isErr:
debugEcho "blockNumber: ", preminedBlock.header.blockNumber
debugEcho "fork: ", chainDB.config.toFork(preminedBlock.header.blockNumber)
debugEcho "error message: ", res.error
debugEcho "ttdReached: ", ttdReached
except:
debugEcho "FATAL ERROR(WE HAVE BUG): ", getCurrentExceptionMsg()
@ -361,13 +393,45 @@ proc dumpDebugData(tester: Tester, vmState: BaseVMState, accountList: JsonNode):
"accounts": accounts
}
proc dumpDebugData(tester: Tester, fixture: JsonNode, fixtureName: string, fixtureIndex: int, success: bool) =
let accountList = if fixture["postState"].kind == JObject: fixture["postState"] else: fixture["pre"]
proc accountList(fixture: JsonNode): JsonNode =
if fixture["postState"].kind == JObject:
fixture["postState"]
else:
fixture["pre"]
proc debugDataFromAccountList(tester: Tester, fixture: JsonNode): JsonNode =
let accountList = fixture.accountList
let vmState = tester.vmState
let debugData = if vmState.isNil:
%{"debugData": tester.debugData}
if vmState.isNil:
%{"debugData": tester.debugData}
else:
dumpDebugData(tester, vmState, accountList)
proc debugDataFromPostStateHash(tester: Tester): JsonNode =
var
accounts = newJObject()
accountList = newSeq[EthAddress]()
vmState = tester.vmState
for address in vmState.stateDB.addresses:
accountList.add address
for i, ac in accountList:
accounts[ac.toHex] = dumpAccount(vmState.readOnlyStateDB, ac, "acc" & $i)
%{
"debugData": tester.debugData,
"postStateHash": %($vmState.readOnlyStateDB.rootHash),
"expectedStateHash": %($tester.postStateHash),
"accounts": accounts
}
proc dumpDebugData(tester: Tester, fixture: JsonNode, fixtureName: string, fixtureIndex: int, success: bool) =
let debugData = if tester.postStateHash != Hash256():
debugDataFromPostStateHash(tester)
else:
dumpDebugData(tester, vmState, accountList)
debugDataFromAccountList(tester, fixture)
let status = if success: "_success" else: "_failed"
writeFile("debug_" & fixtureName & "_" & $fixtureIndex & status & ".json", debugData.pretty())
@ -411,7 +475,15 @@ proc testFixture(node: JsonNode, testStatusIMPL: var TestStatus, debugMode = fal
tester.runTester(chainDB, testStatusIMPL)
let latestBlockHash = chainDB.getCanonicalHead().blockHash
if latestBlockHash != tester.lastBlockHash:
verifyStateDB(fixture["postState"], tester.vmState.readOnlyStateDB)
if tester.postStateHash != Hash256():
let rootHash = tester.vmState.stateDB.rootHash
if tester.postStateHash != rootHash:
raise newException(ValidationError, "incorrect postStateHash, expect=" &
$rootHash & ", get=" &
$tester.postStateHash
)
else:
verifyStateDB(fixture["postState"], tester.vmState.readOnlyStateDB)
except ValidationError as E:
echo fixtureName, " ERROR: ", E.msg
success = false

View File

@ -17,7 +17,7 @@ import
eth/[rlp, common],
eth/trie/[db, trie_defs],
unittest2,
stew/results
stew/[results, byteutils]
type
Tester = object
@ -89,8 +89,16 @@ let chainParams = networkParams(MainNet)
proc testFixtureIndexes(tester: Tester, testStatusIMPL: var TestStatus) =
let
chainDB = newBaseChainDB(newMemoryDB(), getConfiguration().pruning, params = chainParams)
vmState = BaseVMState.new(
parent = BlockHeader(stateRoot: emptyRlpHash),
parent = BlockHeader(stateRoot: emptyRlpHash)
# can't be assigned to
# tester.header.parentHash = parent.blockHash
chainDB.setScore(parent.blockHash, 0.u256)
if tester.fork >= FkParis:
chainDB.config.terminalTotalDifficulty = some(0.u256)
let vmState = BaseVMState.new(
parent = parent,
header = tester.header,
chainDB = chainDB,
tracerFlags = (if tester.trace: {TracerFlags.EnableTracing} else: {}),
@ -157,17 +165,20 @@ proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus,
let fenv = fixture["env"]
tester.header = BlockHeader(
coinbase: fenv["currentCoinbase"].getStr.ethAddressFromHex,
difficulty: fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
coinbase : fenv["currentCoinbase"].getStr.ethAddressFromHex,
difficulty : fromHex(UInt256, fenv{"currentDifficulty"}.getStr),
blockNumber: fenv{"currentNumber"}.getHexadecimalInt.u256,
gasLimit: fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
timestamp: fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
stateRoot: emptyRlpHash
gasLimit : fenv{"currentGasLimit"}.getHexadecimalInt.GasInt,
timestamp : fenv{"currentTimestamp"}.getHexadecimalInt.int64.fromUnix,
stateRoot : emptyRlpHash
)
if "currentBaseFee" in fenv:
tester.header.baseFee = fromHex(UInt256, fenv{"currentBaseFee"}.getStr)
if "currentRandom" in fenv:
tester.header.prevRandao.data = hexToByteArray[32](fenv{"currentRandom"}.getStr)
let specifyIndex = getConfiguration().index
tester.trace = trace
tester.debugMode = debugMode

View File

@ -30,7 +30,8 @@ const
FkPetersburg: "ConstantinopleFix",
FkIstanbul: "Istanbul",
FkBerlin: "Berlin",
FkLondon: "London"
FkLondon: "London",
FkParis: "Merge"
}.toTable
supportedForks* = {
@ -43,7 +44,8 @@ const
FkPetersburg,
FkIstanbul,
FkBerlin,
FkLondon}
FkLondon,
FkParis}
nameToFork* = revmap(forkNames)