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:
parent
e7adc609f4
commit
137eb97766
|
@ -27,3 +27,5 @@ nimcache
|
|||
/debug*.json
|
||||
/block*.json
|
||||
/.update.timestamp
|
||||
|
||||
*.generated.nim
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
|
@ -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) =
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
hacknet/
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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"
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit b464505b4dcbe2ef52d19b2cfca8f2be4ebf2c7e
|
||||
Subproject commit bb705bf17b46d2c8f9bfb106d9cc7437009a2501
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 16ae908e49dad3dd1be1d536798a2b0ae39250df
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue