Initial implementation of the merge spec

Includes a simple test harness for the merge interop M1 milestone

This aims to enable connecting nimbus-eth2 to nimbus-eth1 within
the testing protocol described here:

https://github.com/status-im/nimbus-eth2/blob/amphora-merge-interop/docs/interop_merge.md

To execute the work-in-progress test, please run:

In terminal 1:
tests/amphora/launch-nimbus.sh

In terminal 2:
tests/amphora/check-merge-test-vectors.sh
This commit is contained in:
Zahary Karadjov 2021-10-06 01:31:35 +02:00 committed by zah
parent e7adc609f4
commit 137eb97766
28 changed files with 960 additions and 319 deletions

2
.gitignore vendored
View File

@ -27,3 +27,5 @@ nimcache
/debug*.json
/block*.json
/.update.timestamp
*.generated.nim

4
.gitmodules vendored
View File

@ -114,8 +114,8 @@
ignore = dirty
branch = master
[submodule "vendor/nim-web3"]
path = vendor/nim-web3
url = https://github.com/status-im/nim-web3.git
path = vendor/nim-web3
url = https://github.com/status-im/nim-web3.git
ignore = dirty
branch = master
[submodule "vendor/nim-byteutils"]

View File

@ -8,7 +8,7 @@
# those terms.
import
std/[os, json, tables],
std/[os, json, tables, strutils],
stew/[byteutils, results],
eth/[keyfile, common, keys],
chronicles
@ -87,7 +87,7 @@ iterator addresses*(am: AccountsManager): EthAddress =
proc importPrivateKey*(am: var AccountsManager, fileName: string): Result[void, string] =
try:
let pkhex = readFile(fileName)
let res = PrivateKey.fromHex(pkhex)
let res = PrivateKey.fromHex(pkhex.strip)
if res.isErr:
return err("not a valid private key, expect 32 bytes hex")

View File

@ -40,6 +40,7 @@ type
londonBlock : Option[BlockNumber]
arrowGlacierBlock : Option[BlockNumber]
clique : CliqueOptions
terminalTotalDifficulty*: Option[UInt256]
ChainConfig* = object
chainId* : ChainId
@ -67,6 +68,8 @@ type
cliquePeriod* : int
cliqueEpoch* : int
terminalTotalDifficulty*: Option[UInt256]
Genesis* = object
nonce* : BlockNonce
timestamp* : EthTime
@ -76,6 +79,9 @@ type
mixHash* : Hash256
coinbase* : EthAddress
alloc* : GenesisAlloc
number* : BlockNumber
gasUser* : GasInt
parentHash* : Hash256
baseFeePerGas*: Option[UInt256]
GenesisAlloc* = Table[EthAddress, GenesisAccount]
@ -97,6 +103,21 @@ type
config : ChainOptions
genesis: Genesis
GenesisFile* = object
config : ChainOptions
nonce* : BlockNonce
timestamp* : EthTime
extraData* : seq[byte]
gasLimit* : GasInt
difficulty* : DifficultyInt
mixHash* : Hash256
coinbase* : EthAddress
alloc* : GenesisAlloc
number* : BlockNumber
gasUser* : GasInt
parentHash* : Hash256
baseFeePerGas*: Option[UInt256]
const
CustomNet* = 0.NetworkId
# these are public network id
@ -194,6 +215,8 @@ proc loadNetworkParams*(fileName: string, cg: var NetworkParams):
if cc.config.clique.epoch.isSome:
cg.config.cliqueEpoch = cc.config.clique.epoch.get()
cg.config.terminalTotalDifficulty = cc.config.terminalTotalDifficulty
template validateFork(forkName: untyped, nextBlock: BlockNumber) =
let fork = astToStr(forkName)
if cc.config.forkName.isSome:

View File

@ -102,6 +102,7 @@ const
defaultEthRpcPort = 8545
defaultEthWsPort = 8546
defaultEthGraphqlPort = 8547
defaultEngineApiPort = 8550
defaultListenAddress = (static ValidIpAddress.init("0.0.0.0"))
defaultAdminListenAddress = (static ValidIpAddress.init("127.0.0.1"))
defaultListenAddressDesc = $defaultListenAddress & ", meaning all network interfaces"
@ -306,6 +307,27 @@ type
defaultValueDesc: $DiscoveryType.V4
name: "discovery" .}: DiscoveryType
terminalTotalDifficulty* {.
desc: "The terminal total difficulty of the eth2 merge transition block"
name: "terminal-total-difficulty" .}: Option[UInt256]
engineApiEnabled* {.
desc: "Enable the Engine API"
defaultValue: false
name: "engine-api" .}: bool
engineApiPort* {.
desc: "Listening port for the Engine API"
defaultValue: defaultEngineApiPort
defaultValueDesc: $defaultEngineApiPort
name: "engine-api-port" .}: Port
engineApiAddress* {.
desc: "Listening address for the Engine API"
defaultValue: defaultAdminListenAddress
defaultValueDesc: defaultAdminListenAddressDesc
name: "engine-api-address" .}: ValidIpAddress
nodeKeyHex* {.
desc: "P2P node private key (as 32 bytes hex string)"
defaultValue: ""
@ -418,13 +440,18 @@ type
defaultValue: ""
name: "blocks-file" }: InputFile
proc parseCmdArg(T: type NetworkId, p: TaintedString): T =
parseInt(p.string).T
proc completeCmdArg(T: type NetworkId, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg(T: type UInt256, p: TaintedString): T =
parse(string p, T)
proc completeCmdArg(T: type UInt256, val: TaintedString): seq[string] =
return @[]
proc parseCmdArg(T: type EthAddress, p: TaintedString): T =
try:
result = hexToByteArray(p.string, 20)

View File

@ -55,8 +55,13 @@ proc exists*(self: BaseChainDB, hash: Hash256): bool =
proc getBlockHeader*(self: BaseChainDB; blockHash: Hash256, output: var BlockHeader): bool =
let data = self.db.get(genericHashKey(blockHash).toOpenArray)
if data.len != 0:
output = rlp.decode(data, BlockHeader)
result = true
try:
output = rlp.decode(data, BlockHeader)
true
except RlpError:
false
else:
false
proc getBlockHeader*(self: BaseChainDB, blockHash: Hash256): BlockHeader =
## Returns the requested block header as specified by block hash.
@ -273,6 +278,17 @@ proc setAsCanonicalChainHead(self: BaseChainDB; headerHash: Hash256): seq[BlockH
return newCanonicalHeaders
proc headerExists*(self: BaseChainDB; blockHash: Hash256): bool =
## Returns True if the header with the given block hash is in our DB.
self.db.contains(genericHashKey(blockHash).toOpenArray)
proc setHead*(self: BaseChainDB, blockHash: Hash256): bool =
if self.headerExists(blockHash):
self.db.put(canonicalHeadHashKey().toOpenArray, rlp.encode(blockHash))
return true
else:
return false
proc setHead*(self: BaseChainDB, header: BlockHeader, writeHeader = false) =
var headerHash = rlpHash(header)
if writeHeader:
@ -280,10 +296,6 @@ proc setHead*(self: BaseChainDB, header: BlockHeader, writeHeader = false) =
self.addBlockNumberToHashLookup(header)
self.db.put(canonicalHeadHashKey().toOpenArray, rlp.encode(headerHash))
proc headerExists*(self: BaseChainDB; blockHash: Hash256): bool =
## Returns True if the header with the given block hash is in our DB.
self.db.contains(genericHashKey(blockHash).toOpenArray)
proc persistReceipts*(self: BaseChainDB, receipts: openArray[Receipt]): Hash256 =
var trie = initHexaryTrie(self.db)
for idx, rec in receipts:

View File

@ -18,11 +18,12 @@ import
chronos, json_rpc/rpcserver, chronicles,
eth/p2p/rlpx_protocols/les_protocol,
./p2p/blockchain_sync, eth/net/nat, eth/p2p/peer_pool,
./p2p/clique/[clique_desc, clique_sealer],
./sync/protocol_eth65,
config, genesis, rpc/[common, p2p, debug], p2p/chain,
config, genesis, rpc/[common, p2p, debug, engine_api], p2p/chain,
eth/trie/db, metrics, metrics/[chronos_httpserver, chronicles_support],
graphql/ethapi, context,
"."/[conf_utils, sealer, constants]
"."/[conf_utils, sealer, constants, utils]
when defined(evmc_enabled):
import transaction/evmc_dynamic_loader
@ -38,6 +39,7 @@ type
NimbusNode = ref object
rpcServer: RpcHttpServer
engineApiServer: RpcHttpServer
ethNode: EthereumNode
state: NimbusState
graphqlServer: GraphqlHttpServerRef
@ -183,11 +185,38 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
if rs.isErr:
echo rs.error
quit(QuitFailure)
proc signFunc(signer: EthAddress, message: openArray[byte]): Result[RawSignature, cstring] {.gcsafe.} =
let
hashData = keccakHash(message)
acc = nimbus.ctx.am.getAccount(signer).tryGet()
rawSign = sign(acc.privateKey, SkMessage(hashData.data)).toRaw
ok(rawSign)
# TODO: There should be a better place to initialize this
nimbus.chainRef.clique.authorize(conf.engineSigner, signFunc)
let initialSealingEngineState =
if conf.networkParams.config.terminalTotalDifficulty.isSome and
conf.networkParams.config.terminalTotalDifficulty.get.isZero:
nimbus.chainRef.ttdReachedAt = some(BlockNumber.zero)
EnginePostMerge
else:
EngineStopped
nimbus.sealingEngine = SealingEngineRef.new(
nimbus.chainRef, nimbus.ctx, conf.engineSigner
)
# TODO: Implement the initial state correctly
nimbus.chainRef, nimbus.ctx, conf.engineSigner, initialSealingEngineState)
nimbus.sealingEngine.start()
if conf.engineApiEnabled:
nimbus.engineApiServer = newRpcHttpServer([
initTAddress(conf.engineApiAddress, conf.engineApiPort)
])
setupEngineAPI(nimbus.sealingEngine, nimbus.engineApiServer)
nimbus.engineAPiServer.start()
info "Starting engine API server", port = conf.engineApiPort
# metrics server
if conf.metricsEnabled:
info "Starting metrics HTTP server", address = conf.metricsAddress, port = conf.metricsPort
@ -241,6 +270,8 @@ proc stop*(nimbus: NimbusNode, conf: NimbusConf) {.async, gcsafe.} =
trace "Graceful shutdown"
if conf.rpcEnabled:
await nimbus.rpcServer.stop()
if conf.engineApiEnabled:
await nimbus.engineAPiServer.stop()
if conf.wsEnabled:
nimbus.wsRpcServer.stop()
if conf.graphqlEnabled:

View File

@ -63,6 +63,11 @@ type
## For non-PoA networks (when `db.config.poaEngine` is `false`),
## this descriptor is ignored.
ttdReachedAt*: Option[BlockNumber]
## The first block which difficulty was above the terminal
## total difficulty. In networks with TTD=0, this would be
## the very first block.
{.push raises: [Defect].}
# ------------------------------------------------------------------------------
@ -75,6 +80,9 @@ func toNextFork(n: BlockNumber): uint64 =
else:
result = n.truncate(uint64)
func isBlockAfterTtd*(c: Chain, blockNum: BlockNumber): bool =
c.ttdReachedAt.isSome and blockNum > c.ttdReachedAt.get
func getNextFork(c: ChainConfig, fork: ChainFork): uint64 =
let next: array[ChainFork, uint64] = [
0'u64,
@ -165,7 +173,6 @@ proc newChain*(db: BaseChainDB; poa: Clique; extraValidation: bool): Chain
new result
result.initChain(db, poa, extraValidation)
proc newChain*(db: BaseChainDB, extraValidation: bool): Chain
{.gcsafe, raises: [Defect,CatchableError].} =
## Constructor for the `Chain` descriptor object with default initialisation

View File

@ -90,7 +90,8 @@ proc persistBlocksImpl(c: Chain; headers: openarray[BlockHeader];
header,
body,
checkSealOK = false, # TODO: how to checkseal from here
c.pow)
ttdReached = c.isBlockAfterTtd(header.blockNumber),
pow = c.pow)
if res.isErr:
debug "block validation error",
msg = res.error

View File

@ -167,7 +167,7 @@ proc verifyUncles*(c: Clique; ethBlock: EthBlock): CliqueOkResult =
# clique/clique.go(506): func (c *Clique) Prepare(chain [..]
proc prepare*(c: Clique; parent: BlockHeader, header: var BlockHeader): CliqueOkResult
{.gcsafe, raises: [Defect,CatchableError].} =
{.gcsafe, raises: [Defect, CatchableError].} =
## For the Consensus Engine, `prepare()` initializes the consensus fields
## of a block header according to the rules of a particular engine. The
## changes are executed inline.
@ -175,10 +175,6 @@ proc prepare*(c: Clique; parent: BlockHeader, header: var BlockHeader): CliqueOk
## This implementation prepares all the consensus fields of the header for
## running the transactions on top.
# If the block isn't a checkpoint, cast a random vote (good enough for now)
header.coinbase.reset
header.nonce.reset
# Assemble the voting snapshot to check which votes make sense
let rc = c.cliqueSnapshot(header.parentHash, @[])
if rc.isErr:
@ -225,7 +221,6 @@ proc authorize*(c: Clique; signer: EthAddress; signFn: CliqueSignerFn) =
c.signer = signer
c.signFn = signFn
# clique/clique.go(724): func CliqueRLP(header [..]
proc cliqueRlp*(header: BlockHeader): seq[byte] =
## Returns the rlp bytes which needs to be signed for the proof-of-authority
@ -238,7 +233,6 @@ proc cliqueRlp*(header: BlockHeader): seq[byte] =
##hashes for the same header.
header.encodeSealHeader
# clique/clique.go(688): func SealHash(header *types.Header) common.Hash {
proc sealHash*(header: BlockHeader): Hash256 =
## For the Consensus Engine, `sealHash()` returns the hash of a block prior

View File

@ -35,7 +35,8 @@ const
# Pre Eip 1559 gas limit validation
# ------------------------------------------------------------------------------
proc validateGasLimit(header: BlockHeader; limit: GasInt): Result[void, string] =
proc validateGasLimit(header: BlockHeader; limit: GasInt): Result[void, string]
{.raises: [Defect].} =
let diff = if limit > header.gasLimit:
limit - header.gasLimit
else:
@ -44,14 +45,21 @@ proc validateGasLimit(header: BlockHeader; limit: GasInt): Result[void, string]
let upperLimit = limit div GAS_LIMIT_ADJUSTMENT_FACTOR
if diff >= upperLimit:
return err(&"invalid gas limit: have {header.gasLimit}, want {limit} +-= {upperLimit-1}")
try:
return err(&"invalid gas limit: have {header.gasLimit}, want {limit} +-= {upperLimit-1}")
except ValueError:
# TODO deprecate-strformat
raiseAssert "strformat cannot fail"
if header.gasLimit < GAS_LIMIT_MINIMUM:
return err("invalid gas limit below 5000")
ok()
proc validateGasLimit(c: BaseChainDB; header: BlockHeader): Result[void, string] {.
gcsafe, raises: [Defect,RlpError,BlockNotFound,ValueError].} =
let parent = c.getBlockHeader(header.parentHash)
proc validateGasLimit(c: BaseChainDB; header: BlockHeader): Result[void, string]
{.raises: [Defect].} =
let parent = try:
c.getBlockHeader(header.parentHash)
except CatchableError:
return err "Parent block not in database"
header.validateGasLimit(parent.gasLimit)
# ------------------------------------------------------------------------------
@ -105,8 +113,8 @@ proc calcEip1599BaseFee*(c: ChainConfig; parent: BlockHeader): UInt256 =
# consensus/misc/eip1559.go(32): func VerifyEip1559Header(config [..]
proc verifyEip1559Header(c: ChainConfig;
parent, header: BlockHeader): Result[void, string] {.
gcsafe, raises: [Defect,ValueError].} =
parent, header: BlockHeader): Result[void, string]
{.raises: [Defect].} =
## Verify that the gas limit remains within allowed bounds
let limit = if c.isLondonOrLater(parent.blockNumber):
parent.gasLimit
@ -124,22 +132,25 @@ proc verifyEip1559Header(c: ChainConfig;
# Verify the baseFee is correct based on the parent header.
var expectedBaseFee = c.calcEip1599BaseFee(parent)
if headerBaseFee != expectedBaseFee:
return err(&"invalid baseFee: have {expectedBaseFee}, "&
&"want {header.baseFee}, " &
&"parent.baseFee {parent.baseFee}, "&
&"parent.gasUsed {parent.gasUsed}")
try:
return err(&"invalid baseFee: have {expectedBaseFee}, "&
&"want {header.baseFee}, " &
&"parent.baseFee {parent.baseFee}, "&
&"parent.gasUsed {parent.gasUsed}")
except ValueError:
# TODO deprecate-strformat
raiseAssert "strformat cannot fail"
return ok()
proc validateGasLimitOrBaseFee*(c: BaseChainDB;
header, parent: BlockHeader): Result[void, string] {.
gcsafe, raises: [Defect,ValueError,CatchableError].} =
header, parent: BlockHeader): Result[void, string]
{.gcsafe, raises: [Defect].} =
if not c.config.isLondonOrLater(header.blockNumber):
# Verify BaseFee not present before EIP-1559 fork.
if not header.baseFee.isZero:
return err("invalid baseFee before London fork: have " &
&"{header.baseFee}, want <0>")
return err("invalid baseFee before London fork: have " & $header.baseFee & ", want <0>")
let rc = c.validateGasLimit(header)
if rc.isErr:
return rc

View File

@ -13,18 +13,15 @@ import
../constants,
../db/[db_chain, accounts_cache],
../transaction,
../utils/[difficulty, header],
../vm_state,
../vm_types,
../forks,
../utils/[difficulty, header, pow],
".."/[vm_state, vm_types, forks, errors],
./dao,
../utils/pow,
./gaslimit,
chronicles,
eth/[common, rlp],
nimcrypto,
options,
stew/[results, endians2]
stew/[objects, results, endians2]
from stew/byteutils
import nil
@ -52,14 +49,17 @@ func isGenesis(header: BlockHeader): bool =
# Pivate validator functions
# ------------------------------------------------------------------------------
proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
let (expMixDigest,miningValue) = pow.getPowDigest(header)
proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string] =
let (expMixDigest, miningValue) = try:
pow.getPowDigest(header)
except CatchableError as err:
return err("test")
if expMixDigest != header.mixDigest:
let
miningHash = header.getPowSpecs.miningHash
(size, cachedHash) = pow.getPowCacheLookup(header.blockNumber)
(size, cachedHash) = try: pow.getPowCacheLookup(header.blockNumber)
except KeyError: return err("Unknown block")
debug "mixHash mismatch",
actual = header.mixDigest,
expected = expMixDigest,
@ -79,8 +79,7 @@ proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string]
proc validateHeader(db: BaseChainDB; header, parentHeader: BlockHeader;
numTransactions: int; checkSealOK: bool;
pow: PowRef): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
ttdReached: bool; pow: PowRef): Result[void,string] =
template inDAOExtraRange(blockNumber: BlockNumber): bool =
# EIP-799
@ -109,16 +108,28 @@ proc validateHeader(db: BaseChainDB; header, parentHeader: BlockHeader;
if header.extraData != daoForkBlockExtraData:
return err("header extra data should be marked DAO")
let calcDiffc = db.config.calcDifficulty(header.timestamp, parentHeader)
if header.difficulty < calcDiffc:
return err("provided header difficulty is too low")
if ttdReached:
if not header.mixDigest.isZeroMemory:
return err("Non-zero mix hash in a post-merge block")
if checkSealOK:
return pow.validateSeal(header)
if not header.difficulty.isZero:
return err("Non-zero difficulty in a post-merge block")
if not header.nonce.isZeroMemory:
return err("Non-zero nonce in a post-merge block")
if header.ommersHash != EMPTY_UNCLE_HASH:
return err("Invalid ommers hash in a post-merge block")
else:
let calcDiffc = db.config.calcDifficulty(header.timestamp, parentHeader)
if header.difficulty < calcDiffc:
return err("provided header difficulty is too low")
if checkSealOK:
return pow.validateSeal(header)
result = ok()
func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
Result[void,string] =
if uncle.blockNumber >= currBlock.blockNumber:
@ -138,8 +149,7 @@ func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
uncles: seq[BlockHeader]; checkSealOK: bool;
pow: PowRef): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
pow: PowRef): Result[void,string] =
let hasUncles = uncles.len > 0
let shouldHaveUncles = header.ommersHash != EMPTY_UNCLE_HASH
@ -161,9 +171,16 @@ proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
else:
uncleSet.incl uncleHash
let recentAncestorHashes = chainDB.getAncestorsHashes(
MAX_UNCLE_DEPTH + 1, header)
let recentUncleHashes = chainDB.getUncleHashes(recentAncestorHashes)
let recentAncestorHashes = try:
chainDB.getAncestorsHashes(MAX_UNCLE_DEPTH + 1, header)
except CatchableError as err:
return err("Block not present in database")
let recentUncleHashes = try:
chainDB.getUncleHashes(recentAncestorHashes)
except CatchableError as err:
return err("Ancenstors not present in database")
let blockHash = header.blockHash
for uncle in uncles:
@ -199,7 +216,11 @@ proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
if result.isErr:
return
let uncleParent = chainDB.getBlockHeader(uncle.parentHash)
let uncleParent = try:
chainDB.getBlockHeader(uncle.parentHash)
except BlockNotFound:
return err("Uncle parent not found")
result = validateUncle(header, uncle, uncleParent)
if result.isErr:
return
@ -318,18 +339,26 @@ proc validateTransaction*(
# Public functions, extracted from test_blockchain_json
# ------------------------------------------------------------------------------
proc validateHeaderAndKinship*(chainDB: BaseChainDB; header: BlockHeader;
uncles: seq[BlockHeader]; numTransactions: int; checkSealOK: bool;
pow: PowRef): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
proc validateHeaderAndKinship*(
chainDB: BaseChainDB;
header: BlockHeader;
uncles: seq[BlockHeader];
numTransactions: int;
checkSealOK: bool;
ttdReached: bool;
pow: PowRef): Result[void, string] =
if header.isGenesis:
if header.extraData.len > 32:
return err("BlockHeader.extraData larger than 32 bytes")
return ok()
let parent = chainDB.getBlockHeader(header.parentHash)
let parent = try:
chainDB.getBlockHeader(header.parentHash)
except CatchableError as err:
return err("Failed to load block header from DB")
result = chainDB.validateHeader(
header, parent, numTransactions, checkSealOK, pow)
header, parent, numTransactions, checkSealOK, ttdReached, pow)
if result.isErr:
return
@ -339,24 +368,32 @@ proc validateHeaderAndKinship*(chainDB: BaseChainDB; header: BlockHeader;
if not chainDB.exists(header.stateRoot):
return err("`state_root` was not found in the db.")
result = chainDB.validateUncles(header, uncles, checkSealOK, pow)
if not ttdReached:
result = chainDB.validateUncles(header, uncles, checkSealOK, pow)
if result.isOk:
result = chainDB.validateGasLimitOrBaseFee(header, parent)
proc validateHeaderAndKinship*(
chainDB: BaseChainDB;
header: BlockHeader;
body: BlockBody;
checkSealOK: bool;
ttdReached: bool;
pow: PowRef): Result[void, string] {.gcsafe,raises: [CatchableError, Defect].} =
proc validateHeaderAndKinship*(chainDB: BaseChainDB;
header: BlockHeader; body: BlockBody; checkSealOK: bool;
pow: PowRef): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
chainDB.validateHeaderAndKinship(
header, body.uncles, body.transactions.len, checkSealOK, pow)
header, body.uncles, body.transactions.len, checkSealOK, ttdReached, pow)
proc validateHeaderAndKinship*(chainDB: BaseChainDB; ethBlock: EthBlock;
checkSealOK: bool; pow: PowRef): Result[void,string]
{.gcsafe,raises: [Defect,CatchableError].} =
proc validateHeaderAndKinship*(
chainDB: BaseChainDB;
ethBlock: EthBlock;
checkSealOK: bool;
ttdReached: bool;
pow: PowRef): Result[void,string] =
chainDB.validateHeaderAndKinship(
ethBlock.header, ethBlock.uncles, ethBlock.txs.len, checkSealOK, pow)
ethBlock.header, ethBlock.uncles, ethBlock.txs.len,
checkSealOK, ttdReached, pow)
# ------------------------------------------------------------------------------
# End

111
nimbus/rpc/engine_api.nim Normal file
View File

@ -0,0 +1,111 @@
# Nimbus
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
# at your option.
# This file may not be copied, modified, or distributed except according to
# those terms.
import
std/[typetraits, times],
stew/[objects, results],
json_rpc/[rpcserver, errors],
web3/[conversions, engine_api_types],
eth/[trie, rlp, common, trie/db],
".."/db/db_chain,
".."/p2p/chain/[chain_desc, persist_blocks],
".."/[sealer, utils, constants]
import eth/common/eth_types except BlockHeader
type EthBlockHeader = eth_types.BlockHeader
# TODO move this to stew/objects
template newClone*[T: not ref](x: T): ref T =
# TODO not nil in return type: https://github.com/nim-lang/Nim/issues/14146
# TODO use only when x is a function call that returns a new instance!
let res = new typeof(x) # TODO safe to do noinit here?
res[] = x
res
template asEthHash*(hash: engine_api_types.BlockHash): Hash256 =
Hash256(data: distinctBase(hash))
template unsafeQuantityToInt64(q: Quantity): int64 =
int64 q
proc calcRootHashRlp*(items: openArray[seq[byte]]): Hash256 =
var tr = initHexaryTrie(newMemoryDB())
for i, t in items:
tr.put(rlp.encode(i), t)
return tr.rootHash()
proc toBlockHeader(payload: ExecutionPayload): eth_types.BlockHeader =
discard payload.random # TODO: What should this be used for?
let transactions = seq[seq[byte]](payload.transactions)
let txRoot = calcRootHashRlp(transactions)
EthBlockHeader(
parentHash : payload.parentHash.asEthHash,
ommersHash : EMPTY_UNCLE_HASH,
coinbase : EthAddress payload.coinbase,
stateRoot : payload.stateRoot.asEthHash,
txRoot : txRoot,
receiptRoot : payload.receiptRoot.asEthHash,
bloom : distinctBase(payload.logsBloom),
difficulty : default(DifficultyInt),
blockNumber : payload.blockNumber.distinctBase.u256,
gasLimit : payload.gasLimit.unsafeQuantityToInt64,
gasUsed : payload.gasUsed.unsafeQuantityToInt64,
timestamp : fromUnix payload.timestamp.unsafeQuantityToInt64,
extraData : distinctBase payload.extraData,
mixDigest : default(Hash256),
nonce : default(BlockNonce),
fee : some payload.baseFeePerGas
)
proc toBlockBody(payload: ExecutionPayload): BlockBody =
# TODO the transactions from the payload have to be converted here
discard payload.transactions
proc setupEngineAPI*(sealingEngine: SealingEngineRef, server: RpcServer) =
var payloadsInstance = newClone(newSeq[ExecutionPayload]())
template payloads: auto = payloadsInstance[]
server.rpc("engine_getPayload") do(payloadId: Quantity) -> ExecutionPayload:
if payloadId.uint64 > high(int).uint64 or
int(payloadId) >= payloads.len:
raise (ref InvalidRequest)(code: UNKNOWN_PAYLOAD, msg: "Unknown payload")
return payloads[int payloadId]
server.rpc("engine_executePayload") do(payload: ExecutionPayload) -> ExecutePayloadResponse:
# TODO
if payload.transactions.len > 0:
# Give us a break, a block with transcations? instructions to execute?
# Nah, we are syncing!
return ExecutePayloadResponse(status: $PayloadExecutionStatus.syncing)
let
headers = [payload.toBlockHeader]
bodies = [payload.toBlockBody]
if rlpHash(headers[0]) != payload.blockHash.asEthHash:
return ExecutePayloadResponse(status: $PayloadExecutionStatus.invalid)
if sealingEngine.chain.persistBlocks(headers, bodies) != ValidationResult.OK:
return ExecutePayloadResponse(status: $PayloadExecutionStatus.invalid)
return ExecutePayloadResponse(status: $PayloadExecutionStatus.valid)
server.rpc("engine_forkchoiceUpdated") do(update: ForkChoiceUpdate):
let
db = sealingEngine.chain.db
newHead = update.headBlockHash.asEthHash
# TODO Use the finalized block information to prune any alterantive
# histories that are no longer relevant
discard update.finalizedBlockHash
if not db.setHead(newHead):
raise (ref InvalidRequest)(code: UNKNOWN_HEADER, msg: "Uknown head block hash")

View File

@ -9,8 +9,8 @@
# according to those terms.
import
std/[times, tables],
pkg/[chronos, eth/common, eth/keys, stew/results, chronicles],
std/[times, tables, typetraits],
pkg/[chronos, stew/results, chronicles, eth/common, eth/keys],
"."/[config, db/db_chain, p2p/chain, constants, utils/header],
"."/p2p/clique/[clique_defs,
clique_desc,
@ -19,18 +19,31 @@ import
./p2p/gaslimit,
"."/[chain_config, utils, context]
from web3/ethtypes as web3types import nil
from web3/engine_api_types import ExecutionPayload, PayloadAttributes
type
EngineState = enum
EngineStopped, EngineRunning
EngineState* = enum
EngineStopped,
EngineRunning,
EnginePostMerge
Web3BlockHash = web3types.BlockHash
Web3Address = web3types.Address
Web3Bloom = web3types.FixedBytes[256]
Web3Quantity = web3types.Quantity
SealingEngineRef* = ref SealingEngineObj
SealingEngineObj = object of RootObj
state: EngineState
engineLoop: Future[void]
chain: Chain
chain*: Chain
ctx: EthContext
signer: EthAddress
template asEthHash*(hash: Web3BlockHash): Hash256 =
Hash256(data: distinctBase(hash))
proc validateSealer*(conf: NimbusConf, ctx: EthContext, chain: Chain): Result[void, string] =
if conf.engineSigner == ZERO_ADDRESS:
return err("signer address should not zero, use --engine-signer to set signer address")
@ -52,7 +65,10 @@ proc validateSealer*(conf: NimbusConf, ctx: EthContext, chain: Chain): Result[vo
proc isLondon(c: ChainConfig, number: BlockNumber): bool {.inline.} =
number >= c.londonBlock
proc prepareHeader(engine: SealingEngineRef, parent: BlockHeader, time: Time): Result[BlockHeader, string] =
proc prepareHeader(engine: SealingEngineRef,
coinbase: EthAddress,
parent: BlockHeader,
time: Time): Result[BlockHeader, string] =
let timestamp = if parent.timestamp >= time:
parent.timestamp + 1.seconds
else:
@ -69,6 +85,7 @@ proc prepareHeader(engine: SealingEngineRef, parent: BlockHeader, time: Time): R
gasCeil = DEFAULT_GAS_LIMIT),
# TODO: extraData can be configured via cli
#extraData : engine.extra,
coinbase : coinbase,
timestamp : timestamp,
ommersHash : EMPTY_UNCLE_HASH,
stateRoot : parent.stateRoot,
@ -87,14 +104,21 @@ proc prepareHeader(engine: SealingEngineRef, parent: BlockHeader, time: Time): R
# TODO: desiredLimit can be configured by user, gasCeil
header.gasLimit = calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
# TODO Post merge, clique should not be executing
let clique = engine.chain.clique
let res = clique.prepare(parent, header)
if res.isErr:
return err($res.error)
if engine.chain.isBlockAfterTtd(header.blockNumber):
header.difficulty = DifficultyInt.zero
ok(header)
proc generateBlock(engine: SealingEngineRef, ethBlock: var EthBlock): Result[void,string] =
proc generateBlock(engine: SealingEngineRef,
coinbase: EthAddress,
parentBlockHeader: BlockHeader,
outBlock: var EthBlock): Result[void, string] =
# deviation from standard block generator
# - no local and remote transactions inclusion(need tx pool)
# - no receipts from tx
@ -102,23 +126,48 @@ proc generateBlock(engine: SealingEngineRef, ethBlock: var EthBlock): Result[voi
# - no local and remote uncles inclusion
let clique = engine.chain.clique
let parent = engine.chain.currentBlock()
let time = getTime()
let res = prepareHeader(engine, parent, time)
let res = prepareHeader(engine, coinbase, parentBlockHeader, time)
if res.isErr:
return err("error prepare header")
ethBlock = EthBlock(
outBlock = EthBlock(
header: res.get()
)
let sealRes = clique.seal(ethBlock)
# TODO Post merge, Clique should not be executing
let sealRes = clique.seal(outBlock)
if sealRes.isErr:
return err("error sealing block header: " & $sealRes.error)
debug "generated block",
blockNumber = outBlock.header.blockNumber,
blockHash = blockHash(outBlock.header)
ok()
proc generateBlock(engine: SealingEngineRef,
coinbase: EthAddress,
parentHash: Hash256,
outBlock: var EthBlock): Result[void, string] =
var parentBlockHeader: BlockHeader
if engine.chain.db.getBlockHeader(parentHash, parentBlockHeader):
generateBlock(engine, coinbase, parentBlockHeader, outBlock)
else:
# TODO:
# This hack shouldn't be necessary if the database can find
# the genesis block hash in `getBlockHeader`.
let maybeGenesisBlock = engine.chain.currentBlock()
if parentHash == maybeGenesisBlock.blockHash:
generateBlock(engine, coinbase, maybeGenesisBlock, outBlock)
else:
return err "parent block not found"
proc generateBlock(engine: SealingEngineRef,
coinbase: EthAddress,
outBlock: var EthBlock): Result[void, string] =
generateBlock(engine, coinbase, engine.chain.currentBlock(), outBlock)
proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
let clique = engine.chain.clique
@ -134,6 +183,9 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
clique.authorize(engine.signer, signerFunc)
# TODO: This should be configurable
var coinbase: EthAddress
# convert times.Duration to chronos.Duration
let period = chronos.seconds(clique.cfg.period.inSeconds)
@ -148,7 +200,7 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
# - no queue for chain reorgs
# - no async lock/guard against race with sync algo
var blk: EthBlock
let blkRes = engine.generateBlock(blk)
let blkRes = engine.generateBlock(coinbase, blk)
if blkRes.isErr:
error "sealing engine generateBlock error", msg=blkRes.error
break
@ -163,14 +215,50 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
info "block generated", number=blk.header.blockNumber
proc generateExecutionPayload*(engine: SealingEngineRef,
payloadAttrs: PayloadAttributes,
payloadRes: var ExecutionPayload): Result[void, string] =
var blk: EthBlock
let blkRes = engine.generateBlock(EthAddress payloadAttrs.feeRecipient,
payloadAttrs.parentHash.asEthHash,
blk)
if blkRes.isErr:
error "sealing engine generateBlock error", msg = blkRes.error
return blkRes
let res = engine.chain.persistBlocks([blk.header], [
BlockBody(transactions: blk.txs, uncles: blk.uncles)
])
payloadRes.parentHash = Web3BlockHash blk.header.parentHash.data
payloadRes.coinbase = Web3Address blk.header.coinbase
payloadRes.stateRoot = Web3BlockHash blk.header.stateRoot.data
payloadRes.receiptRoot = Web3BlockHash blk.header.receiptRoot.data
payloadRes.logsBloom = Web3Bloom blk.header.bloom
payloadRes.random = web3types.FixedBytes[32](payloadAttrs.random)
payloadRes.blockNumber = Web3Quantity blk.header.blockNumber.truncate(uint64)
payloadRes.gasLimit = Web3Quantity blk.header.gasLimit
payloadRes.gasUsed = Web3Quantity blk.header.gasUsed
payloadRes.timestamp = payloadAttrs.timestamp
# TODO
# res.extraData
payloadRes.baseFeePerGas = blk.header.fee.get(UInt256.zero)
payloadRes.blockHash = Web3BlockHash rlpHash(blk.header).data
# TODO
# res.transactions*: seq[TypedTransaction]
return ok()
proc new*(_: type SealingEngineRef,
chain: Chain,
ctx: EthContext,
signer: EthAddress): SealingEngineRef =
signer: EthAddress,
initialState: EngineState): SealingEngineRef =
SealingEngineRef(
chain: chain,
ctx: ctx,
signer: signer
signer: signer,
state: initialState
)
proc start*(engine: SealingEngineRef) =

View File

@ -227,8 +227,8 @@ proc getPowSpecs*(header: BlockHeader): PowSpecs =
difficulty: header.difficulty)
proc getPowCacheLookup*(tm: PowRef;
blockNumber: BlockNumber): (uint64,Hash256)
{.gcsafe,raises: [Defect,CatchableError].} =
blockNumber: BlockNumber): (uint64, Hash256)
{.gcsafe, raises: [KeyError, Defect].} =
## Returns the pair `(size,digest)` derived from the lookup cache for the
## `hashimotoLight()` function for the given block number. The `size` is the
## full size of the dataset (the cache represents) as passed on to the
@ -238,6 +238,8 @@ proc getPowCacheLookup*(tm: PowRef;
## This function is intended for error reporting and might also be useful
## for testing and debugging.
let ds = tm.lightByEpoch.get(blockNumber)
if ds == nil:
raise newException(KeyError, "block not found")
result[0] = ds.size

View File

@ -71,7 +71,7 @@ proc new*(T: type PowCacheRef; maxItems = nItemsMax): T =
# ------------------------------------------------------------------------------
proc get*(pc: var PowCache; bn: BlockNumber): PowCacheItemRef
{.gcsafe,raises: [Defect,CatchableError].} =
{.gcsafe, raises: [Defect].} =
## Return a cache derived from argument `blockNumber` ready to be used
## for the `hashimotoLight()` method.
let
@ -91,12 +91,10 @@ proc get*(pc: var PowCache; bn: BlockNumber): PowCacheItemRef
pc.cache.lruAppend(key, pair, pc.cacheMax)
proc get*(pcr: PowCacheRef; bn: BlockNumber): PowCacheItemRef
{.gcsafe,raises: [Defect,CatchableError].} =
proc get*(pcr: PowCacheRef; bn: BlockNumber): PowCacheItemRef =
## Variant of `getCache()`
pcr[].get(bn)
proc hasItem*(pc: var PowCache; bn: BlockNumber): bool
{.gcsafe,raises: [Defect,CatchableError].} =
## Returns true if there is a cache entry for argument `bn`.

1
tests/amphora/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
hacknet/

View File

@ -0,0 +1,41 @@
{
"config": {
"chainId": 1,
"homesteadBlock": 0,
"daoForkBlock": 0,
"daoForkSupport": true,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"muirGlacierBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"clique": {
"period": 5,
"epoch": 30000
},
"terminalTotalDifficulty": 0
},
"genesis": {
"nonce": "0x42",
"timestamp": "0x0",
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0x1C9C380",
"difficulty": "0x400000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
"balance": "0x6d6172697573766477000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": "0x7"
}
}

View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -Eeuo pipefail
# https://notes.ethereum.org/@9AeMAlpyQYaAAyuj47BzRw/rkwW3ceVY
#
# git clone --branch merge-interop-spec https://github.com/MariusVanDerWijden/go-ethereum.git
#
# Last checked against geth as of
# commit d6b04900423634d27be1178edf46622394085bb9 (HEAD -> merge-interop-spec, origin/merge-interop-spec)
# Author: Marius van der Wijden <m.vanderwijden@live.de>
# Date: Wed Sep 29 19:24:56 2021 +0200
#
# eth/catalyst: fix random in payload, payloadid as hexutil
# Get the payload
resp_get_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_getPayload","params":["0x0"],"id":67}' http://localhost:8550)
echo "engine_getPayload response: ${resp_get_payload}"
expected_resp_get_payload='{"jsonrpc":"2.0","id":67,"result":{"blockHash":"0xb084c10440f05f5a23a55d1d7ebcb1b3892935fb56f23cdc9a7f42c348eed174","parentHash":"0xa0513a503d5bd6e89a144c3268e5b7e9da9dbf63df125a360e3950a7d0d67131","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x989680","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x0","transactions":[]}}'
empirical_resp_get_payload='{"jsonrpc":"2.0","id":67,"result":{"blockHash":"0x7a694c5e6e372e6f865b073c101c2fba01f899f16480eb13f7e333a3b7e015bc","parentHash":"0xa0513a503d5bd6e89a144c3268e5b7e9da9dbf63df125a360e3950a7d0d67131","coinbase":"0x0000000000000000000000000000000000000000","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x989680","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x0","transactions":[]}}'
[[ ${resp_get_payload} == ${expected_resp_get_payload} ]] || [[ ${resp_get_payload} == ${empirical_resp_get_payload} ]] || (echo "Unexpected response to engine_getPayload"; false)
# Execute the payload
# Needed two tweaks vs upstream note: (a) add blockNumber field and (b) switch receiptRoots to receiptRoot
resp_execute_payload=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_executePayload","params":[{"blockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858","parentHash":"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a","coinbase":"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","stateRoot":"0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45","receiptRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","random":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x5","extraData":"0x","baseFeePerGas":"0x7","transactions":[]}],"id":67}' http://localhost:8550)
[[ ${resp_execute_payload} == '{"jsonrpc":"2.0","id":67,"result":{"status":"VALID"}}' ]] || (echo "Unexpected response to engine_executePayload"; false)
# Update the fork choice
resp_fork_choice_updated=$(curl -sX POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdated","params":[{"headBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "finalizedBlockHash":"0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858"}],"id":67}' http://localhost:8550)
[[ ${resp_consensus_validated} == '{"jsonrpc":"2.0","id":67,"result":null}' ]] || (echo "Unexpected response to engine_forkChoiceUpdated"; false)
echo "Execution test vectors for Merge passed"

View File

@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -eu
SCRIPT_DIR=$(cd $(dirname "$0") && pwd)
cd "$SCRIPT_DIR"
if [[ ! -d hacknet ]]; then
git clone https://github.com/karalabe/hacknet/
fi
DATA_DIR=hacknet/data/nimbus-eth1
mkdir -p $DATA_DIR
BOOT_NODE=enode://e95870e55cf62fd3d7091d7e0254d10ead007a1ac64ea071296a603d94694b8d92b49f9a3d3851d9aa95ee1452de8b854e0d5e095ef58cc25e7291e7588f4dfc@35.178.114.73:30303
$SCRIPT_DIR/../../build/nimbus \
--log-level:DEBUG \
--data-dir:"$SCRIPT_DIR/$DATA_DIR" \
--custom-network:"$SCRIPT_DIR/hacknet/v2/genesis.json" \
--bootstrap-node:$BOOT_NODE \
--network:1337002 \
--engine-api \
--rpc

27
tests/amphora/launch-nimbus.sh Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
# set -Eeuo pipefail
# https://notes.ethereum.org/@9AeMAlpyQYaAAyuj47BzRw/rkwW3ceVY
# To increase verbosity: debug.verbosity(4)
# MetaMask seed phrase for address with balance is:
# lecture manual soon title cloth uncle gesture cereal common fruit tooth crater
set -eu
SCRIPT_DIR=$(cd $(dirname "$0") && pwd)
DATA_DIR=$(mktemp -d)
echo Using data dir ${DATA_DIR}
$SCRIPT_DIR/../../build/nimbus \
--log-level:TRACE \
--data-dir:"${DATA_DIR}" \
--custom-network:"$SCRIPT_DIR/amphora-interop-genesis-m1.json" \
--network:0 \
--engine-api \
--rpc \
--nat:none --discovery:none \
--import-key:"$SCRIPT_DIR/signer-key.txt" \
--engine-signer:0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b

View File

@ -0,0 +1 @@
0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8

View File

@ -262,7 +262,7 @@ proc importBlock(tester: var Tester, chainDB: BaseChainDB,
if validation:
let rc = chainDB.validateHeaderAndKinship(
result.header, body, checkSeal, pow)
result.header, body, checkSeal, false, pow)
if rc.isErr:
raise newException(
ValidationError, "validateHeaderAndKinship: " & rc.error)
@ -312,7 +312,7 @@ proc runTester(tester: var Tester, chainDB: BaseChainDB, testStatusIMPL: var Tes
# manually validating
check chainDB.validateHeaderAndKinship(
preminedBlock, checkSeal, pow).isOk
preminedBlock, checkSeal, false, pow).isOk
except:
debugEcho "FATAL ERROR(WE HAVE BUG): ", getCurrentExceptionMsg()

View File

@ -65,7 +65,7 @@ proc configurationMain*() =
check conf.networkId == 678.NetworkId
check conf.networkParams == NetworkParams()
test "network-id not set, copy from chainId of customnetwork":
test "network-id not set, copy from chainId of custom network":
let conf = makeConfig(@["--custom-network:" & genesisFile])
check conf.networkId == 123.NetworkId

2
vendor/nim-stew vendored

@ -1 +1 @@
Subproject commit b464505b4dcbe2ef52d19b2cfca8f2be4ebf2c7e
Subproject commit bb705bf17b46d2c8f9bfb106d9cc7437009a2501

1
vendor/nim-web3 vendored Submodule

@ -0,0 +1 @@
Subproject commit 16ae908e49dad3dd1be1d536798a2b0ae39250df

View File

@ -1,5 +1,12 @@
witnessBuilderBC
===
## bcBerlinToLondon
```diff
+ BerlinToLondonTransition.json OK
+ initialVal.json OK
+ londonUncles.json OK
```
OK: 3/3 Fail: 0/3 Skip: 0/3
## bcBlockGasLimitTest
```diff
+ BlockGasLimit2p63m1.json OK
@ -15,11 +22,39 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
+ ConstantinopleFixTransition.json OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
## bcEIP1559
```diff
+ badBlocks.json OK
+ badUncles.json OK
+ baseFee.json OK
+ besuBaseFeeBug.json OK
+ burnVerify.json OK
+ checkGasLimit.json OK
+ feeCap.json OK
+ gasLimit20m.json OK
+ gasLimit40m.json OK
+ highDemand.json OK
+ intrinsic.json OK
+ intrinsicOrFail.json OK
+ intrinsicTip.json OK
+ lowDemand.json OK
+ medDemand.json OK
+ tips.json OK
+ transFail.json OK
+ transType.json OK
+ valCausesOOF.json OK
```
OK: 19/19 Fail: 0/19 Skip: 0/19
## bcEIP158ToByzantium
```diff
+ ByzantiumTransition.json OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
## bcExample
```diff
+ basefeeExample.json OK
```
OK: 1/1 Fail: 0/1 Skip: 0/1
## bcExploitTest
```diff
+ DelegateCallSpam.json OK
@ -88,6 +123,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ ExtraData33.json OK
+ GasLimitHigherThan2p63m1.json OK
+ GasLimitIsZero.json OK
+ badTimestamp.json OK
+ log1_wrongBlockNumber.json OK
+ log1_wrongBloom.json OK
+ timeDiff0.json OK
@ -104,7 +140,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ wrongTransactionsTrie.json OK
+ wrongUncleHash.json OK
```
OK: 21/21 Fail: 0/21 Skip: 0/21
OK: 22/22 Fail: 0/22 Skip: 0/22
## bcMultiChainTest
```diff
+ CallContractFromNotBestBlock.json OK
@ -288,11 +324,26 @@ OK: 96/96 Fail: 0/96 Skip: 0/96
+ suicideStorageCheckVCreate.json OK
+ suicideStorageCheckVCreate2.json OK
+ suicideThenCheckBalance.json OK
+ testOpcodes.json OK
+ testOpcode_00.json OK
+ testOpcode_10.json OK
+ testOpcode_20.json OK
+ testOpcode_30.json OK
+ testOpcode_40.json OK
+ testOpcode_50.json OK
+ testOpcode_60.json OK
+ testOpcode_70.json OK
+ testOpcode_80.json OK
+ testOpcode_90.json OK
+ testOpcode_A0.json OK
+ testOpcode_B0.json OK
+ testOpcode_C0.json OK
+ testOpcode_D0.json OK
+ testOpcode_E0.json OK
+ testOpcode_F0.json OK
+ transactionFromNotExistingAccount.json OK
+ txCost-sec73.json OK
```
OK: 72/72 Fail: 0/72 Skip: 0/72
OK: 87/87 Fail: 0/87 Skip: 0/87
## bcTotalDifficultyTest
```diff
+ lotsOfBranchesOverrideAtTheEnd.json OK
@ -320,6 +371,7 @@ OK: 11/11 Fail: 0/11 Skip: 0/11
+ gasLimitTooLow.json OK
+ gasLimitTooLowExactBound.json OK
+ gasLimitTooLowExactBound2.json OK
+ gasLimitTooLowExactBoundLondon.json OK
+ incorrectUncleNumber0.json OK
+ incorrectUncleNumber1.json OK
+ incorrectUncleNumber500.json OK
@ -335,7 +387,7 @@ OK: 11/11 Fail: 0/11 Skip: 0/11
+ wrongParentHash.json OK
+ wrongStateRoot.json OK
```
OK: 24/24 Fail: 0/24 Skip: 0/24
OK: 25/25 Fail: 0/25 Skip: 0/25
## bcUncleSpecialTests
```diff
+ futureUncleTimestamp2.json OK
@ -467,17 +519,135 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ badOpcodes.json OK
+ eip2315NotRemoved.json OK
+ invalidAddr.json OK
+ invalidDiffPlaces.json OK
+ measureGas.json OK
+ opc0CDiffPlaces.json OK
+ opc0DDiffPlaces.json OK
+ opc0EDiffPlaces.json OK
+ opc0FDiffPlaces.json OK
+ opc1EDiffPlaces.json OK
+ opc1FDiffPlaces.json OK
+ opc21DiffPlaces.json OK
+ opc22DiffPlaces.json OK
+ opc23DiffPlaces.json OK
+ opc24DiffPlaces.json OK
+ opc25DiffPlaces.json OK
+ opc26DiffPlaces.json OK
+ opc27DiffPlaces.json OK
+ opc28DiffPlaces.json OK
+ opc29DiffPlaces.json OK
+ opc2ADiffPlaces.json OK
+ opc2BDiffPlaces.json OK
+ opc2CDiffPlaces.json OK
+ opc2DDiffPlaces.json OK
+ opc2EDiffPlaces.json OK
+ opc2FDiffPlaces.json OK
+ opc49DiffPlaces.json OK
+ opc4ADiffPlaces.json OK
+ opc4BDiffPlaces.json OK
+ opc4CDiffPlaces.json OK
+ opc4DDiffPlaces.json OK
+ opc4EDiffPlaces.json OK
+ opc4FDiffPlaces.json OK
+ opc5CDiffPlaces.json OK
+ opc5DDiffPlaces.json OK
+ opc5EDiffPlaces.json OK
+ opc5FDiffPlaces.json OK
+ opcA5DiffPlaces.json OK
+ opcA6DiffPlaces.json OK
+ opcA7DiffPlaces.json OK
+ opcA8DiffPlaces.json OK
+ opcA9DiffPlaces.json OK
+ opcAADiffPlaces.json OK
+ opcABDiffPlaces.json OK
+ opcACDiffPlaces.json OK
+ opcADDiffPlaces.json OK
+ opcAEDiffPlaces.json OK
+ opcAFDiffPlaces.json OK
+ opcB0DiffPlaces.json OK
+ opcB1DiffPlaces.json OK
+ opcB2DiffPlaces.json OK
+ opcB3DiffPlaces.json OK
+ opcB4DiffPlaces.json OK
+ opcB5DiffPlaces.json OK
+ opcB6DiffPlaces.json OK
+ opcB7DiffPlaces.json OK
+ opcB8DiffPlaces.json OK
+ opcB9DiffPlaces.json OK
+ opcBADiffPlaces.json OK
+ opcBBDiffPlaces.json OK
+ opcBCDiffPlaces.json OK
+ opcBDDiffPlaces.json OK
+ opcBEDiffPlaces.json OK
+ opcBFDiffPlaces.json OK
+ opcC0DiffPlaces.json OK
+ opcC1DiffPlaces.json OK
+ opcC2DiffPlaces.json OK
+ opcC3DiffPlaces.json OK
+ opcC4DiffPlaces.json OK
+ opcC5DiffPlaces.json OK
+ opcC6DiffPlaces.json OK
+ opcC7DiffPlaces.json OK
+ opcC8DiffPlaces.json OK
+ opcC9DiffPlaces.json OK
+ opcCADiffPlaces.json OK
+ opcCBDiffPlaces.json OK
+ opcCCDiffPlaces.json OK
+ opcCDDiffPlaces.json OK
+ opcCEDiffPlaces.json OK
+ opcCFDiffPlaces.json OK
+ opcD0DiffPlaces.json OK
+ opcD1DiffPlaces.json OK
+ opcD2DiffPlaces.json OK
+ opcD3DiffPlaces.json OK
+ opcD4DiffPlaces.json OK
+ opcD5DiffPlaces.json OK
+ opcD6DiffPlaces.json OK
+ opcD7DiffPlaces.json OK
+ opcD8DiffPlaces.json OK
+ opcD9DiffPlaces.json OK
+ opcDADiffPlaces.json OK
+ opcDBDiffPlaces.json OK
+ opcDCDiffPlaces.json OK
+ opcDDDiffPlaces.json OK
+ opcDEDiffPlaces.json OK
+ opcDFDiffPlaces.json OK
+ opcE0DiffPlaces.json OK
+ opcE1DiffPlaces.json OK
+ opcE2DiffPlaces.json OK
+ opcE3DiffPlaces.json OK
+ opcE4DiffPlaces.json OK
+ opcE5DiffPlaces.json OK
+ opcE6DiffPlaces.json OK
+ opcE7DiffPlaces.json OK
+ opcE8DiffPlaces.json OK
+ opcE9DiffPlaces.json OK
+ opcEADiffPlaces.json OK
+ opcEBDiffPlaces.json OK
+ opcECDiffPlaces.json OK
+ opcEDDiffPlaces.json OK
+ opcEEDiffPlaces.json OK
+ opcEFDiffPlaces.json OK
+ opcF6DiffPlaces.json OK
+ opcF7DiffPlaces.json OK
+ opcF8DiffPlaces.json OK
+ opcF9DiffPlaces.json OK
+ opcFBDiffPlaces.json OK
+ opcFCDiffPlaces.json OK
+ opcFEDiffPlaces.json OK
+ operationDiffGas.json OK
+ undefinedOpcodeFirstByte.json OK
```
OK: 4/4 Fail: 0/4 Skip: 0/4
OK: 121/121 Fail: 0/121 Skip: 0/121
## stBugs
```diff
+ evmBytecode.json OK
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192.json OK
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192_london.json OK
+ returndatacopyPythonBug_Tue_03_48_41-1432.json OK
+ staticcall_createfails.json OK
```
OK: 4/4 Fail: 0/4 Skip: 0/4
OK: 5/5 Fail: 0/5 Skip: 0/5
## stCallCodes
```diff
+ call_OOG_additionalGasCosts1.json OK
@ -757,6 +927,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
+ CREATE2_Bounds2.json OK
+ CREATE2_Bounds3.json OK
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
+ CREATE2_EOF1.json OK
+ CREATE2_FirstByte_loop.json OK
+ CREATE2_Suicide.json OK
+ Create2OOGafterInitCode.json OK
@ -801,7 +972,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
+ returndatacopy_following_successful_create.json OK
+ returndatasize_following_successful_create.json OK
```
OK: 47/47 Fail: 0/47 Skip: 0/47
OK: 48/48 Fail: 0/48 Skip: 0/48
## stCreateTest
```diff
+ CREATE_AcreateB_BSuicide_BStore.json OK
@ -815,6 +986,7 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
+ CREATE_EContractCreateNEContractInInitOOG_Tr.json OK
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
+ CREATE_EOF1.json OK
+ CREATE_EmptyContract.json OK
+ CREATE_EmptyContractAndCallIt_0wei.json OK
+ CREATE_EmptyContractAndCallIt_1wei.json OK
@ -838,8 +1010,9 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
+ TransactionCollisionToEmpty.json OK
+ TransactionCollisionToEmptyButCode.json OK
+ TransactionCollisionToEmptyButNonce.json OK
+ createFailResult.json OK
```
OK: 34/34 Fail: 0/34 Skip: 0/34
OK: 36/36 Fail: 0/36 Skip: 0/36
## stDelegatecallTestHomestead
```diff
+ Call1024BalanceTooLow.json OK
@ -933,6 +1106,22 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ gasCostReturn.json OK
```
OK: 40/40 Fail: 0/40 Skip: 0/40
## stEIP1559
```diff
+ baseFeeDiffPlaces.json OK
+ gasPriceDiffPlaces.json OK
+ intrinsic.json OK
+ lowFeeCap.json OK
+ lowGasLimit.json OK
+ lowGasPriceOldTypes.json OK
+ outOfFunds.json OK
+ outOfFundsOldTypes.json OK
+ tipTooHigh.json OK
+ transactionIntinsicBug.json OK
+ typeTwoBerlin.json OK
+ valCausesOOF.json OK
```
OK: 12/12 Fail: 0/12 Skip: 0/12
## stEIP158Specific
```diff
+ CALL_OneVCallSuicide.json OK
@ -947,23 +1136,28 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
## stEIP2930
```diff
+ addressOpcodes.json OK
+ coinbaseT01.json OK
+ coinbaseT2.json OK
+ manualCreate.json OK
+ storageCosts.json OK
+ transactionCosts.json OK
+ variedContext.json OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 7/7 Fail: 0/7 Skip: 0/7
## stExample
```diff
+ accessListExample.json OK
+ add11.json OK
+ add11_yml.json OK
+ basefeeExample.json OK
+ eip1559.json OK
+ invalidTr.json OK
+ labelsExample.json OK
+ rangesExample.json OK
+ solidityExample.json OK
+ yulExample.json OK
```
OK: 7/7 Fail: 0/7 Skip: 0/7
OK: 10/10 Fail: 0/10 Skip: 0/10
## stExtCodeHash
```diff
+ callToNonExistent.json OK
@ -1190,6 +1384,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
+ mem64kb_singleByte-32.json OK
+ mem64kb_singleByte-33.json OK
+ mem64kb_singleByte.json OK
+ memCopySelf.json OK
+ memReturn.json OK
+ mload16bitBound.json OK
+ mload8bitBound.json OK
@ -1208,7 +1403,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
+ stackLimitPush32_1024.json OK
+ stackLimitPush32_1025.json OK
```
OK: 70/70 Fail: 0/70 Skip: 0/70
OK: 71/71 Fail: 0/71 Skip: 0/71
## stNonZeroCallsTest
```diff
+ NonZeroValue_CALL.json OK
@ -1243,102 +1438,11 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
+ identity_to_bigger.json OK
+ identity_to_smaller.json OK
+ modexp.json OK
+ modexp_0_0_0_1000000.json OK
+ modexp_0_0_0_155000.json OK
+ modexp_0_1_0_1000000.json OK
+ modexp_0_1_0_155000.json OK
+ modexp_0_1_0_20500.json OK
+ modexp_0_1_0_22000.json OK
+ modexp_0_1_0_25000.json OK
+ modexp_0_1_0_35000.json OK
+ modexp_0_3_100_1000000.json OK
+ modexp_0_3_100_155000.json OK
+ modexp_0_3_100_20500.json OK
+ modexp_0_3_100_22000.json OK
+ modexp_0_3_100_25000.json OK
+ modexp_0_3_100_35000.json OK
+ modexp_1_0_0_1000000.json OK
+ modexp_1_0_0_155000.json OK
+ modexp_1_0_0_20500.json OK
+ modexp_1_0_0_22000.json OK
+ modexp_1_0_0_25000.json OK
+ modexp_1_0_0_35000.json OK
+ modexp_1_0_1_1000000.json OK
+ modexp_1_0_1_155000.json OK
+ modexp_1_0_1_20500.json OK
+ modexp_1_0_1_22000.json OK
+ modexp_1_0_1_25000.json OK
+ modexp_1_0_1_35000.json OK
+ modexp_1_1_1_1000000.json OK
+ modexp_1_1_1_155000.json OK
+ modexp_1_1_1_20500.json OK
+ modexp_1_1_1_22000.json OK
+ modexp_1_1_1_25000.json OK
+ modexp_1_1_1_35000.json OK
+ modexp_37120_22411_22000.json OK
+ modexp_37120_37111_0_1000000.json OK
+ modexp_37120_37111_0_155000.json OK
+ modexp_37120_37111_0_20500.json OK
+ modexp_37120_37111_0_22000.json OK
+ modexp_37120_37111_0_25000.json OK
+ modexp_37120_37111_0_35000.json OK
+ modexp_37120_37111_1_1000000.json OK
+ modexp_37120_37111_1_155000.json OK
+ modexp_37120_37111_1_20500.json OK
+ modexp_37120_37111_1_25000.json OK
+ modexp_37120_37111_1_35000.json OK
+ modexp_37120_37111_37111_1000000.json OK
+ modexp_37120_37111_37111_155000.json OK
+ modexp_37120_37111_37111_20500.json OK
+ modexp_37120_37111_37111_22000.json OK
+ modexp_37120_37111_37111_25000.json OK
+ modexp_37120_37111_37111_35000.json OK
+ modexp_37120_37111_97_1000000.json OK
+ modexp_37120_37111_97_155000.json OK
+ modexp_37120_37111_97_20500.json OK
+ modexp_37120_37111_97_22000.json OK
+ modexp_37120_37111_97_25000.json OK
+ modexp_37120_37111_97_35000.json OK
+ modexp_39936_1_55201_1000000.json OK
+ modexp_39936_1_55201_155000.json OK
+ modexp_39936_1_55201_20500.json OK
+ modexp_39936_1_55201_22000.json OK
+ modexp_39936_1_55201_25000.json OK
+ modexp_39936_1_55201_35000.json OK
+ modexp_3_09984_39936_1000000.json OK
+ modexp_3_09984_39936_155000.json OK
+ modexp_3_09984_39936_22000.json OK
+ modexp_3_09984_39936_25000.json OK
+ modexp_3_09984_39936_35000.json OK
+ modexp_3_28948_11579_20500.json OK
+ modexp_3_5_100_1000000.json OK
+ modexp_3_5_100_155000.json OK
+ modexp_3_5_100_20500.json OK
+ modexp_3_5_100_22000.json OK
+ modexp_3_5_100_25000.json OK
+ modexp_3_5_100_35000.json OK
+ modexp_49_2401_2401_1000000.json OK
+ modexp_49_2401_2401_155000.json OK
+ modexp_49_2401_2401_20500.json OK
+ modexp_49_2401_2401_22000.json OK
+ modexp_49_2401_2401_25000.json OK
+ modexp_49_2401_2401_35000.json OK
+ modexp_55190_55190_42965_1000000.json OK
+ modexp_55190_55190_42965_155000.json OK
+ modexp_55190_55190_42965_20500.json OK
+ modexp_55190_55190_42965_22000.json OK
+ modexp_55190_55190_42965_25000.json OK
+ modexp_55190_55190_42965_35000.json OK
+ modexp_9_37111_37111_1000000.json OK
+ modexp_9_37111_37111_155000.json OK
+ modexp_9_37111_37111_20500.json OK
+ modexp_9_37111_37111_22000.json OK
+ modexp_9_37111_37111_35000.json OK
+ modexp_9_3711_37111_25000.json OK
+ modexpTests.json OK
+ precompsEIP2929.json OK
+ sec80.json OK
```
OK: 98/98 Fail: 0/98 Skip: 0/98
OK: 7/7 Fail: 0/7 Skip: 0/7
## stPreCompiledContracts2
```diff
+ CALLBlake2f.json OK
@ -2020,6 +2124,9 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ refund50_2.json OK
+ refund50percentCap.json OK
+ refund600.json OK
+ refundFF.json OK
+ refundMax.json OK
+ refundSSTORE.json OK
+ refundSuicide50procentCap.json OK
+ refund_CallA.json OK
+ refund_CallA_OOG.json OK
@ -2036,7 +2143,7 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ refund_multimpleSuicide.json OK
+ refund_singleSuicide.json OK
```
OK: 19/19 Fail: 0/19 Skip: 0/19
OK: 22/22 Fail: 0/22 Skip: 0/22
## stReturnDataTest
```diff
+ call_ecrec_success_empty_then_returndatasize.json OK
@ -2140,6 +2247,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ InitCollision.json OK
+ InitCollisionNonZeroNonce.json OK
+ SstoreCallToSelfSubRefundBelowZero.json OK
+ sstoreGas.json OK
+ sstore_0to0.json OK
+ sstore_0to0to0.json OK
+ sstore_0to0toX.json OK
@ -2165,16 +2273,17 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ sstore_changeFromExternalCallInInitCode.json OK
+ sstore_gasLeft.json OK
```
OK: 27/27 Fail: 0/27 Skip: 0/27
OK: 28/28 Fail: 0/28 Skip: 0/28
## stSelfBalance
```diff
+ diffPlaces.json OK
+ selfBalance.json OK
+ selfBalanceCallTypes.json OK
+ selfBalanceEqualsBalance.json OK
+ selfBalanceGasCost.json OK
+ selfBalanceUpdate.json OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 6/6 Fail: 0/6 Skip: 0/6
## stShift
```diff
+ sar00.json OK
@ -2675,6 +2784,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
+ ContractStoreClearsSuccess.json OK
+ CreateMessageReverted.json OK
+ CreateMessageSuccess.json OK
+ CreateTransactionEOF1.json OK
+ CreateTransactionSuccess.json OK
+ EmptyTransaction3.json OK
+ HighGasLimit.json OK
@ -2700,7 +2810,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
+ TransactionToAddressh160minusOne.json OK
+ TransactionToItself.json OK
```
OK: 28/28 Fail: 0/28 Skip: 0/28
OK: 29/29 Fail: 0/29 Skip: 0/29
## stTransitionTest
```diff
+ createNameRegistratorPerTxsAfter.json OK
@ -3165,4 +3275,4 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
OK: 11/11 Fail: 0/11 Skip: 0/11
---TOTAL---
OK: 2843/2843 Fail: 0/2843 Skip: 0/2843
OK: 2937/2937 Fail: 0/2937 Skip: 0/2937

View File

@ -61,17 +61,135 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ badOpcodes.json OK
+ eip2315NotRemoved.json OK
+ invalidAddr.json OK
+ invalidDiffPlaces.json OK
+ measureGas.json OK
+ opc0CDiffPlaces.json OK
+ opc0DDiffPlaces.json OK
+ opc0EDiffPlaces.json OK
+ opc0FDiffPlaces.json OK
+ opc1EDiffPlaces.json OK
+ opc1FDiffPlaces.json OK
+ opc21DiffPlaces.json OK
+ opc22DiffPlaces.json OK
+ opc23DiffPlaces.json OK
+ opc24DiffPlaces.json OK
+ opc25DiffPlaces.json OK
+ opc26DiffPlaces.json OK
+ opc27DiffPlaces.json OK
+ opc28DiffPlaces.json OK
+ opc29DiffPlaces.json OK
+ opc2ADiffPlaces.json OK
+ opc2BDiffPlaces.json OK
+ opc2CDiffPlaces.json OK
+ opc2DDiffPlaces.json OK
+ opc2EDiffPlaces.json OK
+ opc2FDiffPlaces.json OK
+ opc49DiffPlaces.json OK
+ opc4ADiffPlaces.json OK
+ opc4BDiffPlaces.json OK
+ opc4CDiffPlaces.json OK
+ opc4DDiffPlaces.json OK
+ opc4EDiffPlaces.json OK
+ opc4FDiffPlaces.json OK
+ opc5CDiffPlaces.json OK
+ opc5DDiffPlaces.json OK
+ opc5EDiffPlaces.json OK
+ opc5FDiffPlaces.json OK
+ opcA5DiffPlaces.json OK
+ opcA6DiffPlaces.json OK
+ opcA7DiffPlaces.json OK
+ opcA8DiffPlaces.json OK
+ opcA9DiffPlaces.json OK
+ opcAADiffPlaces.json OK
+ opcABDiffPlaces.json OK
+ opcACDiffPlaces.json OK
+ opcADDiffPlaces.json OK
+ opcAEDiffPlaces.json OK
+ opcAFDiffPlaces.json OK
+ opcB0DiffPlaces.json OK
+ opcB1DiffPlaces.json OK
+ opcB2DiffPlaces.json OK
+ opcB3DiffPlaces.json OK
+ opcB4DiffPlaces.json OK
+ opcB5DiffPlaces.json OK
+ opcB6DiffPlaces.json OK
+ opcB7DiffPlaces.json OK
+ opcB8DiffPlaces.json OK
+ opcB9DiffPlaces.json OK
+ opcBADiffPlaces.json OK
+ opcBBDiffPlaces.json OK
+ opcBCDiffPlaces.json OK
+ opcBDDiffPlaces.json OK
+ opcBEDiffPlaces.json OK
+ opcBFDiffPlaces.json OK
+ opcC0DiffPlaces.json OK
+ opcC1DiffPlaces.json OK
+ opcC2DiffPlaces.json OK
+ opcC3DiffPlaces.json OK
+ opcC4DiffPlaces.json OK
+ opcC5DiffPlaces.json OK
+ opcC6DiffPlaces.json OK
+ opcC7DiffPlaces.json OK
+ opcC8DiffPlaces.json OK
+ opcC9DiffPlaces.json OK
+ opcCADiffPlaces.json OK
+ opcCBDiffPlaces.json OK
+ opcCCDiffPlaces.json OK
+ opcCDDiffPlaces.json OK
+ opcCEDiffPlaces.json OK
+ opcCFDiffPlaces.json OK
+ opcD0DiffPlaces.json OK
+ opcD1DiffPlaces.json OK
+ opcD2DiffPlaces.json OK
+ opcD3DiffPlaces.json OK
+ opcD4DiffPlaces.json OK
+ opcD5DiffPlaces.json OK
+ opcD6DiffPlaces.json OK
+ opcD7DiffPlaces.json OK
+ opcD8DiffPlaces.json OK
+ opcD9DiffPlaces.json OK
+ opcDADiffPlaces.json OK
+ opcDBDiffPlaces.json OK
+ opcDCDiffPlaces.json OK
+ opcDDDiffPlaces.json OK
+ opcDEDiffPlaces.json OK
+ opcDFDiffPlaces.json OK
+ opcE0DiffPlaces.json OK
+ opcE1DiffPlaces.json OK
+ opcE2DiffPlaces.json OK
+ opcE3DiffPlaces.json OK
+ opcE4DiffPlaces.json OK
+ opcE5DiffPlaces.json OK
+ opcE6DiffPlaces.json OK
+ opcE7DiffPlaces.json OK
+ opcE8DiffPlaces.json OK
+ opcE9DiffPlaces.json OK
+ opcEADiffPlaces.json OK
+ opcEBDiffPlaces.json OK
+ opcECDiffPlaces.json OK
+ opcEDDiffPlaces.json OK
+ opcEEDiffPlaces.json OK
+ opcEFDiffPlaces.json OK
+ opcF6DiffPlaces.json OK
+ opcF7DiffPlaces.json OK
+ opcF8DiffPlaces.json OK
+ opcF9DiffPlaces.json OK
+ opcFBDiffPlaces.json OK
+ opcFCDiffPlaces.json OK
+ opcFEDiffPlaces.json OK
+ operationDiffGas.json OK
+ undefinedOpcodeFirstByte.json OK
```
OK: 4/4 Fail: 0/4 Skip: 0/4
OK: 121/121 Fail: 0/121 Skip: 0/121
## stBugs
```diff
+ evmBytecode.json OK
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192.json OK
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192_london.json OK
+ returndatacopyPythonBug_Tue_03_48_41-1432.json OK
+ staticcall_createfails.json OK
```
OK: 4/4 Fail: 0/4 Skip: 0/4
OK: 5/5 Fail: 0/5 Skip: 0/5
## stCallCodes
```diff
+ call_OOG_additionalGasCosts1.json OK
@ -351,6 +469,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
+ CREATE2_Bounds2.json OK
+ CREATE2_Bounds3.json OK
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
+ CREATE2_EOF1.json OK
+ CREATE2_FirstByte_loop.json OK
+ CREATE2_Suicide.json OK
+ Create2OOGafterInitCode.json OK
@ -395,7 +514,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
+ returndatacopy_following_successful_create.json OK
+ returndatasize_following_successful_create.json OK
```
OK: 47/47 Fail: 0/47 Skip: 0/47
OK: 48/48 Fail: 0/48 Skip: 0/48
## stCreateTest
```diff
+ CREATE_AcreateB_BSuicide_BStore.json OK
@ -409,6 +528,7 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
+ CREATE_EContractCreateNEContractInInitOOG_Tr.json OK
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
+ CREATE_EOF1.json OK
+ CREATE_EmptyContract.json OK
+ CREATE_EmptyContractAndCallIt_0wei.json OK
+ CREATE_EmptyContractAndCallIt_1wei.json OK
@ -432,8 +552,9 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
+ TransactionCollisionToEmpty.json OK
+ TransactionCollisionToEmptyButCode.json OK
+ TransactionCollisionToEmptyButNonce.json OK
+ createFailResult.json OK
```
OK: 34/34 Fail: 0/34 Skip: 0/34
OK: 36/36 Fail: 0/36 Skip: 0/36
## stDelegatecallTestHomestead
```diff
+ Call1024BalanceTooLow.json OK
@ -527,6 +648,22 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
+ gasCostReturn.json OK
```
OK: 40/40 Fail: 0/40 Skip: 0/40
## stEIP1559
```diff
+ baseFeeDiffPlaces.json OK
+ gasPriceDiffPlaces.json OK
+ intrinsic.json OK
+ lowFeeCap.json OK
+ lowGasLimit.json OK
+ lowGasPriceOldTypes.json OK
+ outOfFunds.json OK
+ outOfFundsOldTypes.json OK
+ tipTooHigh.json OK
+ transactionIntinsicBug.json OK
+ typeTwoBerlin.json OK
+ valCausesOOF.json OK
```
OK: 12/12 Fail: 0/12 Skip: 0/12
## stEIP158Specific
```diff
+ CALL_OneVCallSuicide.json OK
@ -541,23 +678,28 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
## stEIP2930
```diff
+ addressOpcodes.json OK
+ coinbaseT01.json OK
+ coinbaseT2.json OK
+ manualCreate.json OK
+ storageCosts.json OK
+ transactionCosts.json OK
+ variedContext.json OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 7/7 Fail: 0/7 Skip: 0/7
## stExample
```diff
+ accessListExample.json OK
+ add11.json OK
+ add11_yml.json OK
+ basefeeExample.json OK
+ eip1559.json OK
+ invalidTr.json OK
+ labelsExample.json OK
+ rangesExample.json OK
+ solidityExample.json OK
+ yulExample.json OK
```
OK: 7/7 Fail: 0/7 Skip: 0/7
OK: 10/10 Fail: 0/10 Skip: 0/10
## stExtCodeHash
```diff
+ callToNonExistent.json OK
@ -784,6 +926,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
+ mem64kb_singleByte-32.json OK
+ mem64kb_singleByte-33.json OK
+ mem64kb_singleByte.json OK
+ memCopySelf.json OK
+ memReturn.json OK
+ mload16bitBound.json OK
+ mload8bitBound.json OK
@ -802,7 +945,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
+ stackLimitPush32_1024.json OK
+ stackLimitPush32_1025.json OK
```
OK: 70/70 Fail: 0/70 Skip: 0/70
OK: 71/71 Fail: 0/71 Skip: 0/71
## stNonZeroCallsTest
```diff
+ NonZeroValue_CALL.json OK
@ -837,102 +980,11 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
+ identity_to_bigger.json OK
+ identity_to_smaller.json OK
+ modexp.json OK
+ modexp_0_0_0_1000000.json OK
+ modexp_0_0_0_155000.json OK
+ modexp_0_1_0_1000000.json OK
+ modexp_0_1_0_155000.json OK
+ modexp_0_1_0_20500.json OK
+ modexp_0_1_0_22000.json OK
+ modexp_0_1_0_25000.json OK
+ modexp_0_1_0_35000.json OK
+ modexp_0_3_100_1000000.json OK
+ modexp_0_3_100_155000.json OK
+ modexp_0_3_100_20500.json OK
+ modexp_0_3_100_22000.json OK
+ modexp_0_3_100_25000.json OK
+ modexp_0_3_100_35000.json OK
+ modexp_1_0_0_1000000.json OK
+ modexp_1_0_0_155000.json OK
+ modexp_1_0_0_20500.json OK
+ modexp_1_0_0_22000.json OK
+ modexp_1_0_0_25000.json OK
+ modexp_1_0_0_35000.json OK
+ modexp_1_0_1_1000000.json OK
+ modexp_1_0_1_155000.json OK
+ modexp_1_0_1_20500.json OK
+ modexp_1_0_1_22000.json OK
+ modexp_1_0_1_25000.json OK
+ modexp_1_0_1_35000.json OK
+ modexp_1_1_1_1000000.json OK
+ modexp_1_1_1_155000.json OK
+ modexp_1_1_1_20500.json OK
+ modexp_1_1_1_22000.json OK
+ modexp_1_1_1_25000.json OK
+ modexp_1_1_1_35000.json OK
+ modexp_37120_22411_22000.json OK
+ modexp_37120_37111_0_1000000.json OK
+ modexp_37120_37111_0_155000.json OK
+ modexp_37120_37111_0_20500.json OK
+ modexp_37120_37111_0_22000.json OK
+ modexp_37120_37111_0_25000.json OK
+ modexp_37120_37111_0_35000.json OK
+ modexp_37120_37111_1_1000000.json OK
+ modexp_37120_37111_1_155000.json OK
+ modexp_37120_37111_1_20500.json OK
+ modexp_37120_37111_1_25000.json OK
+ modexp_37120_37111_1_35000.json OK
+ modexp_37120_37111_37111_1000000.json OK
+ modexp_37120_37111_37111_155000.json OK
+ modexp_37120_37111_37111_20500.json OK
+ modexp_37120_37111_37111_22000.json OK
+ modexp_37120_37111_37111_25000.json OK
+ modexp_37120_37111_37111_35000.json OK
+ modexp_37120_37111_97_1000000.json OK
+ modexp_37120_37111_97_155000.json OK
+ modexp_37120_37111_97_20500.json OK
+ modexp_37120_37111_97_22000.json OK
+ modexp_37120_37111_97_25000.json OK
+ modexp_37120_37111_97_35000.json OK
+ modexp_39936_1_55201_1000000.json OK
+ modexp_39936_1_55201_155000.json OK
+ modexp_39936_1_55201_20500.json OK
+ modexp_39936_1_55201_22000.json OK
+ modexp_39936_1_55201_25000.json OK
+ modexp_39936_1_55201_35000.json OK
+ modexp_3_09984_39936_1000000.json OK
+ modexp_3_09984_39936_155000.json OK
+ modexp_3_09984_39936_22000.json OK
+ modexp_3_09984_39936_25000.json OK
+ modexp_3_09984_39936_35000.json OK
+ modexp_3_28948_11579_20500.json OK
+ modexp_3_5_100_1000000.json OK
+ modexp_3_5_100_155000.json OK
+ modexp_3_5_100_20500.json OK
+ modexp_3_5_100_22000.json OK
+ modexp_3_5_100_25000.json OK
+ modexp_3_5_100_35000.json OK
+ modexp_49_2401_2401_1000000.json OK
+ modexp_49_2401_2401_155000.json OK
+ modexp_49_2401_2401_20500.json OK
+ modexp_49_2401_2401_22000.json OK
+ modexp_49_2401_2401_25000.json OK
+ modexp_49_2401_2401_35000.json OK
+ modexp_55190_55190_42965_1000000.json OK
+ modexp_55190_55190_42965_155000.json OK
+ modexp_55190_55190_42965_20500.json OK
+ modexp_55190_55190_42965_22000.json OK
+ modexp_55190_55190_42965_25000.json OK
+ modexp_55190_55190_42965_35000.json OK
+ modexp_9_37111_37111_1000000.json OK
+ modexp_9_37111_37111_155000.json OK
+ modexp_9_37111_37111_20500.json OK
+ modexp_9_37111_37111_22000.json OK
+ modexp_9_37111_37111_35000.json OK
+ modexp_9_3711_37111_25000.json OK
+ modexpTests.json OK
+ precompsEIP2929.json OK
+ sec80.json OK
```
OK: 98/98 Fail: 0/98 Skip: 0/98
OK: 7/7 Fail: 0/7 Skip: 0/7
## stPreCompiledContracts2
```diff
+ CALLBlake2f.json OK
@ -1614,6 +1666,9 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ refund50_2.json OK
+ refund50percentCap.json OK
+ refund600.json OK
+ refundFF.json OK
+ refundMax.json OK
+ refundSSTORE.json OK
+ refundSuicide50procentCap.json OK
+ refund_CallA.json OK
+ refund_CallA_OOG.json OK
@ -1630,7 +1685,7 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
+ refund_multimpleSuicide.json OK
+ refund_singleSuicide.json OK
```
OK: 19/19 Fail: 0/19 Skip: 0/19
OK: 22/22 Fail: 0/22 Skip: 0/22
## stReturnDataTest
```diff
+ call_ecrec_success_empty_then_returndatasize.json OK
@ -1734,6 +1789,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ InitCollision.json OK
+ InitCollisionNonZeroNonce.json OK
+ SstoreCallToSelfSubRefundBelowZero.json OK
+ sstoreGas.json OK
+ sstore_0to0.json OK
+ sstore_0to0to0.json OK
+ sstore_0to0toX.json OK
@ -1759,16 +1815,17 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
+ sstore_changeFromExternalCallInInitCode.json OK
+ sstore_gasLeft.json OK
```
OK: 27/27 Fail: 0/27 Skip: 0/27
OK: 28/28 Fail: 0/28 Skip: 0/28
## stSelfBalance
```diff
+ diffPlaces.json OK
+ selfBalance.json OK
+ selfBalanceCallTypes.json OK
+ selfBalanceEqualsBalance.json OK
+ selfBalanceGasCost.json OK
+ selfBalanceUpdate.json OK
```
OK: 5/5 Fail: 0/5 Skip: 0/5
OK: 6/6 Fail: 0/6 Skip: 0/6
## stShift
```diff
+ sar00.json OK
@ -2269,6 +2326,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
+ ContractStoreClearsSuccess.json OK
+ CreateMessageReverted.json OK
+ CreateMessageSuccess.json OK
+ CreateTransactionEOF1.json OK
+ CreateTransactionSuccess.json OK
+ EmptyTransaction3.json OK
+ HighGasLimit.json OK
@ -2294,7 +2352,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
+ TransactionToAddressh160minusOne.json OK
+ TransactionToItself.json OK
```
OK: 28/28 Fail: 0/28 Skip: 0/28
OK: 29/29 Fail: 0/29 Skip: 0/29
## stTransitionTest
```diff
+ createNameRegistratorPerTxsAfter.json OK
@ -2759,4 +2817,4 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
OK: 11/11 Fail: 0/11 Skip: 0/11
---TOTAL---
OK: 2517/2517 Fail: 0/2517 Skip: 0/2517
OK: 2571/2571 Fail: 0/2571 Skip: 0/2571