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
|
/debug*.json
|
||||||
/block*.json
|
/block*.json
|
||||||
/.update.timestamp
|
/.update.timestamp
|
||||||
|
|
||||||
|
*.generated.nim
|
||||||
|
|
|
@ -114,8 +114,8 @@
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "vendor/nim-web3"]
|
[submodule "vendor/nim-web3"]
|
||||||
path = vendor/nim-web3
|
path = vendor/nim-web3
|
||||||
url = https://github.com/status-im/nim-web3.git
|
url = https://github.com/status-im/nim-web3.git
|
||||||
ignore = dirty
|
ignore = dirty
|
||||||
branch = master
|
branch = master
|
||||||
[submodule "vendor/nim-byteutils"]
|
[submodule "vendor/nim-byteutils"]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
# those terms.
|
# those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[os, json, tables],
|
std/[os, json, tables, strutils],
|
||||||
stew/[byteutils, results],
|
stew/[byteutils, results],
|
||||||
eth/[keyfile, common, keys],
|
eth/[keyfile, common, keys],
|
||||||
chronicles
|
chronicles
|
||||||
|
@ -87,7 +87,7 @@ iterator addresses*(am: AccountsManager): EthAddress =
|
||||||
proc importPrivateKey*(am: var AccountsManager, fileName: string): Result[void, string] =
|
proc importPrivateKey*(am: var AccountsManager, fileName: string): Result[void, string] =
|
||||||
try:
|
try:
|
||||||
let pkhex = readFile(fileName)
|
let pkhex = readFile(fileName)
|
||||||
let res = PrivateKey.fromHex(pkhex)
|
let res = PrivateKey.fromHex(pkhex.strip)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
return err("not a valid private key, expect 32 bytes hex")
|
return err("not a valid private key, expect 32 bytes hex")
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ type
|
||||||
londonBlock : Option[BlockNumber]
|
londonBlock : Option[BlockNumber]
|
||||||
arrowGlacierBlock : Option[BlockNumber]
|
arrowGlacierBlock : Option[BlockNumber]
|
||||||
clique : CliqueOptions
|
clique : CliqueOptions
|
||||||
|
terminalTotalDifficulty*: Option[UInt256]
|
||||||
|
|
||||||
ChainConfig* = object
|
ChainConfig* = object
|
||||||
chainId* : ChainId
|
chainId* : ChainId
|
||||||
|
@ -67,6 +68,8 @@ type
|
||||||
cliquePeriod* : int
|
cliquePeriod* : int
|
||||||
cliqueEpoch* : int
|
cliqueEpoch* : int
|
||||||
|
|
||||||
|
terminalTotalDifficulty*: Option[UInt256]
|
||||||
|
|
||||||
Genesis* = object
|
Genesis* = object
|
||||||
nonce* : BlockNonce
|
nonce* : BlockNonce
|
||||||
timestamp* : EthTime
|
timestamp* : EthTime
|
||||||
|
@ -76,6 +79,9 @@ type
|
||||||
mixHash* : Hash256
|
mixHash* : Hash256
|
||||||
coinbase* : EthAddress
|
coinbase* : EthAddress
|
||||||
alloc* : GenesisAlloc
|
alloc* : GenesisAlloc
|
||||||
|
number* : BlockNumber
|
||||||
|
gasUser* : GasInt
|
||||||
|
parentHash* : Hash256
|
||||||
baseFeePerGas*: Option[UInt256]
|
baseFeePerGas*: Option[UInt256]
|
||||||
|
|
||||||
GenesisAlloc* = Table[EthAddress, GenesisAccount]
|
GenesisAlloc* = Table[EthAddress, GenesisAccount]
|
||||||
|
@ -97,6 +103,21 @@ type
|
||||||
config : ChainOptions
|
config : ChainOptions
|
||||||
genesis: Genesis
|
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
|
const
|
||||||
CustomNet* = 0.NetworkId
|
CustomNet* = 0.NetworkId
|
||||||
# these are public network id
|
# these are public network id
|
||||||
|
@ -194,6 +215,8 @@ proc loadNetworkParams*(fileName: string, cg: var NetworkParams):
|
||||||
if cc.config.clique.epoch.isSome:
|
if cc.config.clique.epoch.isSome:
|
||||||
cg.config.cliqueEpoch = cc.config.clique.epoch.get()
|
cg.config.cliqueEpoch = cc.config.clique.epoch.get()
|
||||||
|
|
||||||
|
cg.config.terminalTotalDifficulty = cc.config.terminalTotalDifficulty
|
||||||
|
|
||||||
template validateFork(forkName: untyped, nextBlock: BlockNumber) =
|
template validateFork(forkName: untyped, nextBlock: BlockNumber) =
|
||||||
let fork = astToStr(forkName)
|
let fork = astToStr(forkName)
|
||||||
if cc.config.forkName.isSome:
|
if cc.config.forkName.isSome:
|
||||||
|
|
|
@ -102,6 +102,7 @@ const
|
||||||
defaultEthRpcPort = 8545
|
defaultEthRpcPort = 8545
|
||||||
defaultEthWsPort = 8546
|
defaultEthWsPort = 8546
|
||||||
defaultEthGraphqlPort = 8547
|
defaultEthGraphqlPort = 8547
|
||||||
|
defaultEngineApiPort = 8550
|
||||||
defaultListenAddress = (static ValidIpAddress.init("0.0.0.0"))
|
defaultListenAddress = (static ValidIpAddress.init("0.0.0.0"))
|
||||||
defaultAdminListenAddress = (static ValidIpAddress.init("127.0.0.1"))
|
defaultAdminListenAddress = (static ValidIpAddress.init("127.0.0.1"))
|
||||||
defaultListenAddressDesc = $defaultListenAddress & ", meaning all network interfaces"
|
defaultListenAddressDesc = $defaultListenAddress & ", meaning all network interfaces"
|
||||||
|
@ -306,6 +307,27 @@ type
|
||||||
defaultValueDesc: $DiscoveryType.V4
|
defaultValueDesc: $DiscoveryType.V4
|
||||||
name: "discovery" .}: DiscoveryType
|
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* {.
|
nodeKeyHex* {.
|
||||||
desc: "P2P node private key (as 32 bytes hex string)"
|
desc: "P2P node private key (as 32 bytes hex string)"
|
||||||
defaultValue: ""
|
defaultValue: ""
|
||||||
|
@ -418,13 +440,18 @@ type
|
||||||
defaultValue: ""
|
defaultValue: ""
|
||||||
name: "blocks-file" }: InputFile
|
name: "blocks-file" }: InputFile
|
||||||
|
|
||||||
|
|
||||||
proc parseCmdArg(T: type NetworkId, p: TaintedString): T =
|
proc parseCmdArg(T: type NetworkId, p: TaintedString): T =
|
||||||
parseInt(p.string).T
|
parseInt(p.string).T
|
||||||
|
|
||||||
proc completeCmdArg(T: type NetworkId, val: TaintedString): seq[string] =
|
proc completeCmdArg(T: type NetworkId, val: TaintedString): seq[string] =
|
||||||
return @[]
|
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 =
|
proc parseCmdArg(T: type EthAddress, p: TaintedString): T =
|
||||||
try:
|
try:
|
||||||
result = hexToByteArray(p.string, 20)
|
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 =
|
proc getBlockHeader*(self: BaseChainDB; blockHash: Hash256, output: var BlockHeader): bool =
|
||||||
let data = self.db.get(genericHashKey(blockHash).toOpenArray)
|
let data = self.db.get(genericHashKey(blockHash).toOpenArray)
|
||||||
if data.len != 0:
|
if data.len != 0:
|
||||||
output = rlp.decode(data, BlockHeader)
|
try:
|
||||||
result = true
|
output = rlp.decode(data, BlockHeader)
|
||||||
|
true
|
||||||
|
except RlpError:
|
||||||
|
false
|
||||||
|
else:
|
||||||
|
false
|
||||||
|
|
||||||
proc getBlockHeader*(self: BaseChainDB, blockHash: Hash256): BlockHeader =
|
proc getBlockHeader*(self: BaseChainDB, blockHash: Hash256): BlockHeader =
|
||||||
## Returns the requested block header as specified by block hash.
|
## Returns the requested block header as specified by block hash.
|
||||||
|
@ -273,6 +278,17 @@ proc setAsCanonicalChainHead(self: BaseChainDB; headerHash: Hash256): seq[BlockH
|
||||||
|
|
||||||
return newCanonicalHeaders
|
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) =
|
proc setHead*(self: BaseChainDB, header: BlockHeader, writeHeader = false) =
|
||||||
var headerHash = rlpHash(header)
|
var headerHash = rlpHash(header)
|
||||||
if writeHeader:
|
if writeHeader:
|
||||||
|
@ -280,10 +296,6 @@ proc setHead*(self: BaseChainDB, header: BlockHeader, writeHeader = false) =
|
||||||
self.addBlockNumberToHashLookup(header)
|
self.addBlockNumberToHashLookup(header)
|
||||||
self.db.put(canonicalHeadHashKey().toOpenArray, rlp.encode(headerHash))
|
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 =
|
proc persistReceipts*(self: BaseChainDB, receipts: openArray[Receipt]): Hash256 =
|
||||||
var trie = initHexaryTrie(self.db)
|
var trie = initHexaryTrie(self.db)
|
||||||
for idx, rec in receipts:
|
for idx, rec in receipts:
|
||||||
|
|
|
@ -18,11 +18,12 @@ import
|
||||||
chronos, json_rpc/rpcserver, chronicles,
|
chronos, json_rpc/rpcserver, chronicles,
|
||||||
eth/p2p/rlpx_protocols/les_protocol,
|
eth/p2p/rlpx_protocols/les_protocol,
|
||||||
./p2p/blockchain_sync, eth/net/nat, eth/p2p/peer_pool,
|
./p2p/blockchain_sync, eth/net/nat, eth/p2p/peer_pool,
|
||||||
|
./p2p/clique/[clique_desc, clique_sealer],
|
||||||
./sync/protocol_eth65,
|
./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],
|
eth/trie/db, metrics, metrics/[chronos_httpserver, chronicles_support],
|
||||||
graphql/ethapi, context,
|
graphql/ethapi, context,
|
||||||
"."/[conf_utils, sealer, constants]
|
"."/[conf_utils, sealer, constants, utils]
|
||||||
|
|
||||||
when defined(evmc_enabled):
|
when defined(evmc_enabled):
|
||||||
import transaction/evmc_dynamic_loader
|
import transaction/evmc_dynamic_loader
|
||||||
|
@ -38,6 +39,7 @@ type
|
||||||
|
|
||||||
NimbusNode = ref object
|
NimbusNode = ref object
|
||||||
rpcServer: RpcHttpServer
|
rpcServer: RpcHttpServer
|
||||||
|
engineApiServer: RpcHttpServer
|
||||||
ethNode: EthereumNode
|
ethNode: EthereumNode
|
||||||
state: NimbusState
|
state: NimbusState
|
||||||
graphqlServer: GraphqlHttpServerRef
|
graphqlServer: GraphqlHttpServerRef
|
||||||
|
@ -183,11 +185,38 @@ proc localServices(nimbus: NimbusNode, conf: NimbusConf,
|
||||||
if rs.isErr:
|
if rs.isErr:
|
||||||
echo rs.error
|
echo rs.error
|
||||||
quit(QuitFailure)
|
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.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()
|
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
|
# metrics server
|
||||||
if conf.metricsEnabled:
|
if conf.metricsEnabled:
|
||||||
info "Starting metrics HTTP server", address = conf.metricsAddress, port = conf.metricsPort
|
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"
|
trace "Graceful shutdown"
|
||||||
if conf.rpcEnabled:
|
if conf.rpcEnabled:
|
||||||
await nimbus.rpcServer.stop()
|
await nimbus.rpcServer.stop()
|
||||||
|
if conf.engineApiEnabled:
|
||||||
|
await nimbus.engineAPiServer.stop()
|
||||||
if conf.wsEnabled:
|
if conf.wsEnabled:
|
||||||
nimbus.wsRpcServer.stop()
|
nimbus.wsRpcServer.stop()
|
||||||
if conf.graphqlEnabled:
|
if conf.graphqlEnabled:
|
||||||
|
|
|
@ -63,6 +63,11 @@ type
|
||||||
## For non-PoA networks (when `db.config.poaEngine` is `false`),
|
## For non-PoA networks (when `db.config.poaEngine` is `false`),
|
||||||
## this descriptor is ignored.
|
## 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].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -75,6 +80,9 @@ func toNextFork(n: BlockNumber): uint64 =
|
||||||
else:
|
else:
|
||||||
result = n.truncate(uint64)
|
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 =
|
func getNextFork(c: ChainConfig, fork: ChainFork): uint64 =
|
||||||
let next: array[ChainFork, uint64] = [
|
let next: array[ChainFork, uint64] = [
|
||||||
0'u64,
|
0'u64,
|
||||||
|
@ -165,7 +173,6 @@ proc newChain*(db: BaseChainDB; poa: Clique; extraValidation: bool): Chain
|
||||||
new result
|
new result
|
||||||
result.initChain(db, poa, extraValidation)
|
result.initChain(db, poa, extraValidation)
|
||||||
|
|
||||||
|
|
||||||
proc newChain*(db: BaseChainDB, extraValidation: bool): Chain
|
proc newChain*(db: BaseChainDB, extraValidation: bool): Chain
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
## Constructor for the `Chain` descriptor object with default initialisation
|
## Constructor for the `Chain` descriptor object with default initialisation
|
||||||
|
|
|
@ -90,7 +90,8 @@ proc persistBlocksImpl(c: Chain; headers: openarray[BlockHeader];
|
||||||
header,
|
header,
|
||||||
body,
|
body,
|
||||||
checkSealOK = false, # TODO: how to checkseal from here
|
checkSealOK = false, # TODO: how to checkseal from here
|
||||||
c.pow)
|
ttdReached = c.isBlockAfterTtd(header.blockNumber),
|
||||||
|
pow = c.pow)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
debug "block validation error",
|
debug "block validation error",
|
||||||
msg = res.error
|
msg = res.error
|
||||||
|
|
|
@ -167,7 +167,7 @@ proc verifyUncles*(c: Clique; ethBlock: EthBlock): CliqueOkResult =
|
||||||
|
|
||||||
# clique/clique.go(506): func (c *Clique) Prepare(chain [..]
|
# clique/clique.go(506): func (c *Clique) Prepare(chain [..]
|
||||||
proc prepare*(c: Clique; parent: BlockHeader, header: var BlockHeader): CliqueOkResult
|
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
|
## For the Consensus Engine, `prepare()` initializes the consensus fields
|
||||||
## of a block header according to the rules of a particular engine. The
|
## of a block header according to the rules of a particular engine. The
|
||||||
## changes are executed inline.
|
## 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
|
## This implementation prepares all the consensus fields of the header for
|
||||||
## running the transactions on top.
|
## 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
|
# Assemble the voting snapshot to check which votes make sense
|
||||||
let rc = c.cliqueSnapshot(header.parentHash, @[])
|
let rc = c.cliqueSnapshot(header.parentHash, @[])
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
|
@ -225,7 +221,6 @@ proc authorize*(c: Clique; signer: EthAddress; signFn: CliqueSignerFn) =
|
||||||
c.signer = signer
|
c.signer = signer
|
||||||
c.signFn = signFn
|
c.signFn = signFn
|
||||||
|
|
||||||
|
|
||||||
# clique/clique.go(724): func CliqueRLP(header [..]
|
# clique/clique.go(724): func CliqueRLP(header [..]
|
||||||
proc cliqueRlp*(header: BlockHeader): seq[byte] =
|
proc cliqueRlp*(header: BlockHeader): seq[byte] =
|
||||||
## Returns the rlp bytes which needs to be signed for the proof-of-authority
|
## 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.
|
##hashes for the same header.
|
||||||
header.encodeSealHeader
|
header.encodeSealHeader
|
||||||
|
|
||||||
|
|
||||||
# clique/clique.go(688): func SealHash(header *types.Header) common.Hash {
|
# clique/clique.go(688): func SealHash(header *types.Header) common.Hash {
|
||||||
proc sealHash*(header: BlockHeader): Hash256 =
|
proc sealHash*(header: BlockHeader): Hash256 =
|
||||||
## For the Consensus Engine, `sealHash()` returns the hash of a block prior
|
## For the Consensus Engine, `sealHash()` returns the hash of a block prior
|
||||||
|
|
|
@ -35,7 +35,8 @@ const
|
||||||
# Pre Eip 1559 gas limit validation
|
# 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:
|
let diff = if limit > header.gasLimit:
|
||||||
limit - header.gasLimit
|
limit - header.gasLimit
|
||||||
else:
|
else:
|
||||||
|
@ -44,14 +45,21 @@ proc validateGasLimit(header: BlockHeader; limit: GasInt): Result[void, string]
|
||||||
let upperLimit = limit div GAS_LIMIT_ADJUSTMENT_FACTOR
|
let upperLimit = limit div GAS_LIMIT_ADJUSTMENT_FACTOR
|
||||||
|
|
||||||
if diff >= upperLimit:
|
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:
|
if header.gasLimit < GAS_LIMIT_MINIMUM:
|
||||||
return err("invalid gas limit below 5000")
|
return err("invalid gas limit below 5000")
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc validateGasLimit(c: BaseChainDB; header: BlockHeader): Result[void, string] {.
|
proc validateGasLimit(c: BaseChainDB; header: BlockHeader): Result[void, string]
|
||||||
gcsafe, raises: [Defect,RlpError,BlockNotFound,ValueError].} =
|
{.raises: [Defect].} =
|
||||||
let parent = c.getBlockHeader(header.parentHash)
|
let parent = try:
|
||||||
|
c.getBlockHeader(header.parentHash)
|
||||||
|
except CatchableError:
|
||||||
|
return err "Parent block not in database"
|
||||||
header.validateGasLimit(parent.gasLimit)
|
header.validateGasLimit(parent.gasLimit)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
@ -105,8 +113,8 @@ proc calcEip1599BaseFee*(c: ChainConfig; parent: BlockHeader): UInt256 =
|
||||||
|
|
||||||
# consensus/misc/eip1559.go(32): func VerifyEip1559Header(config [..]
|
# consensus/misc/eip1559.go(32): func VerifyEip1559Header(config [..]
|
||||||
proc verifyEip1559Header(c: ChainConfig;
|
proc verifyEip1559Header(c: ChainConfig;
|
||||||
parent, header: BlockHeader): Result[void, string] {.
|
parent, header: BlockHeader): Result[void, string]
|
||||||
gcsafe, raises: [Defect,ValueError].} =
|
{.raises: [Defect].} =
|
||||||
## Verify that the gas limit remains within allowed bounds
|
## Verify that the gas limit remains within allowed bounds
|
||||||
let limit = if c.isLondonOrLater(parent.blockNumber):
|
let limit = if c.isLondonOrLater(parent.blockNumber):
|
||||||
parent.gasLimit
|
parent.gasLimit
|
||||||
|
@ -124,22 +132,25 @@ proc verifyEip1559Header(c: ChainConfig;
|
||||||
# Verify the baseFee is correct based on the parent header.
|
# Verify the baseFee is correct based on the parent header.
|
||||||
var expectedBaseFee = c.calcEip1599BaseFee(parent)
|
var expectedBaseFee = c.calcEip1599BaseFee(parent)
|
||||||
if headerBaseFee != expectedBaseFee:
|
if headerBaseFee != expectedBaseFee:
|
||||||
return err(&"invalid baseFee: have {expectedBaseFee}, "&
|
try:
|
||||||
&"want {header.baseFee}, " &
|
return err(&"invalid baseFee: have {expectedBaseFee}, "&
|
||||||
&"parent.baseFee {parent.baseFee}, "&
|
&"want {header.baseFee}, " &
|
||||||
&"parent.gasUsed {parent.gasUsed}")
|
&"parent.baseFee {parent.baseFee}, "&
|
||||||
|
&"parent.gasUsed {parent.gasUsed}")
|
||||||
|
except ValueError:
|
||||||
|
# TODO deprecate-strformat
|
||||||
|
raiseAssert "strformat cannot fail"
|
||||||
|
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
proc validateGasLimitOrBaseFee*(c: BaseChainDB;
|
proc validateGasLimitOrBaseFee*(c: BaseChainDB;
|
||||||
header, parent: BlockHeader): Result[void, string] {.
|
header, parent: BlockHeader): Result[void, string]
|
||||||
gcsafe, raises: [Defect,ValueError,CatchableError].} =
|
{.gcsafe, raises: [Defect].} =
|
||||||
|
|
||||||
if not c.config.isLondonOrLater(header.blockNumber):
|
if not c.config.isLondonOrLater(header.blockNumber):
|
||||||
# Verify BaseFee not present before EIP-1559 fork.
|
# Verify BaseFee not present before EIP-1559 fork.
|
||||||
if not header.baseFee.isZero:
|
if not header.baseFee.isZero:
|
||||||
return err("invalid baseFee before London fork: have " &
|
return err("invalid baseFee before London fork: have " & $header.baseFee & ", want <0>")
|
||||||
&"{header.baseFee}, want <0>")
|
|
||||||
let rc = c.validateGasLimit(header)
|
let rc = c.validateGasLimit(header)
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
return rc
|
return rc
|
||||||
|
|
|
@ -13,18 +13,15 @@ import
|
||||||
../constants,
|
../constants,
|
||||||
../db/[db_chain, accounts_cache],
|
../db/[db_chain, accounts_cache],
|
||||||
../transaction,
|
../transaction,
|
||||||
../utils/[difficulty, header],
|
../utils/[difficulty, header, pow],
|
||||||
../vm_state,
|
".."/[vm_state, vm_types, forks, errors],
|
||||||
../vm_types,
|
|
||||||
../forks,
|
|
||||||
./dao,
|
./dao,
|
||||||
../utils/pow,
|
|
||||||
./gaslimit,
|
./gaslimit,
|
||||||
chronicles,
|
chronicles,
|
||||||
eth/[common, rlp],
|
eth/[common, rlp],
|
||||||
nimcrypto,
|
nimcrypto,
|
||||||
options,
|
options,
|
||||||
stew/[results, endians2]
|
stew/[objects, results, endians2]
|
||||||
|
|
||||||
from stew/byteutils
|
from stew/byteutils
|
||||||
import nil
|
import nil
|
||||||
|
@ -52,14 +49,17 @@ func isGenesis(header: BlockHeader): bool =
|
||||||
# Pivate validator functions
|
# Pivate validator functions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string]
|
proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string] =
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
let (expMixDigest, miningValue) = try:
|
||||||
let (expMixDigest,miningValue) = pow.getPowDigest(header)
|
pow.getPowDigest(header)
|
||||||
|
except CatchableError as err:
|
||||||
|
return err("test")
|
||||||
|
|
||||||
if expMixDigest != header.mixDigest:
|
if expMixDigest != header.mixDigest:
|
||||||
let
|
let
|
||||||
miningHash = header.getPowSpecs.miningHash
|
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",
|
debug "mixHash mismatch",
|
||||||
actual = header.mixDigest,
|
actual = header.mixDigest,
|
||||||
expected = expMixDigest,
|
expected = expMixDigest,
|
||||||
|
@ -79,8 +79,7 @@ proc validateSeal(pow: PoWRef; header: BlockHeader): Result[void,string]
|
||||||
|
|
||||||
proc validateHeader(db: BaseChainDB; header, parentHeader: BlockHeader;
|
proc validateHeader(db: BaseChainDB; header, parentHeader: BlockHeader;
|
||||||
numTransactions: int; checkSealOK: bool;
|
numTransactions: int; checkSealOK: bool;
|
||||||
pow: PowRef): Result[void,string]
|
ttdReached: bool; pow: PowRef): Result[void,string] =
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
|
||||||
|
|
||||||
template inDAOExtraRange(blockNumber: BlockNumber): bool =
|
template inDAOExtraRange(blockNumber: BlockNumber): bool =
|
||||||
# EIP-799
|
# EIP-799
|
||||||
|
@ -109,16 +108,28 @@ proc validateHeader(db: BaseChainDB; header, parentHeader: BlockHeader;
|
||||||
if header.extraData != daoForkBlockExtraData:
|
if header.extraData != daoForkBlockExtraData:
|
||||||
return err("header extra data should be marked DAO")
|
return err("header extra data should be marked DAO")
|
||||||
|
|
||||||
let calcDiffc = db.config.calcDifficulty(header.timestamp, parentHeader)
|
if ttdReached:
|
||||||
if header.difficulty < calcDiffc:
|
if not header.mixDigest.isZeroMemory:
|
||||||
return err("provided header difficulty is too low")
|
return err("Non-zero mix hash in a post-merge block")
|
||||||
|
|
||||||
if checkSealOK:
|
if not header.difficulty.isZero:
|
||||||
return pow.validateSeal(header)
|
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()
|
result = ok()
|
||||||
|
|
||||||
|
|
||||||
func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
|
func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
|
||||||
Result[void,string] =
|
Result[void,string] =
|
||||||
if uncle.blockNumber >= currBlock.blockNumber:
|
if uncle.blockNumber >= currBlock.blockNumber:
|
||||||
|
@ -138,8 +149,7 @@ func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
|
||||||
|
|
||||||
proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
|
proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
|
||||||
uncles: seq[BlockHeader]; checkSealOK: bool;
|
uncles: seq[BlockHeader]; checkSealOK: bool;
|
||||||
pow: PowRef): Result[void,string]
|
pow: PowRef): Result[void,string] =
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
|
||||||
let hasUncles = uncles.len > 0
|
let hasUncles = uncles.len > 0
|
||||||
let shouldHaveUncles = header.ommersHash != EMPTY_UNCLE_HASH
|
let shouldHaveUncles = header.ommersHash != EMPTY_UNCLE_HASH
|
||||||
|
|
||||||
|
@ -161,9 +171,16 @@ proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
|
||||||
else:
|
else:
|
||||||
uncleSet.incl uncleHash
|
uncleSet.incl uncleHash
|
||||||
|
|
||||||
let recentAncestorHashes = chainDB.getAncestorsHashes(
|
let recentAncestorHashes = try:
|
||||||
MAX_UNCLE_DEPTH + 1, header)
|
chainDB.getAncestorsHashes(MAX_UNCLE_DEPTH + 1, header)
|
||||||
let recentUncleHashes = chainDB.getUncleHashes(recentAncestorHashes)
|
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
|
let blockHash = header.blockHash
|
||||||
|
|
||||||
for uncle in uncles:
|
for uncle in uncles:
|
||||||
|
@ -199,7 +216,11 @@ proc validateUncles(chainDB: BaseChainDB; header: BlockHeader;
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return
|
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)
|
result = validateUncle(header, uncle, uncleParent)
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return
|
return
|
||||||
|
@ -318,18 +339,26 @@ proc validateTransaction*(
|
||||||
# Public functions, extracted from test_blockchain_json
|
# Public functions, extracted from test_blockchain_json
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc validateHeaderAndKinship*(chainDB: BaseChainDB; header: BlockHeader;
|
proc validateHeaderAndKinship*(
|
||||||
uncles: seq[BlockHeader]; numTransactions: int; checkSealOK: bool;
|
chainDB: BaseChainDB;
|
||||||
pow: PowRef): Result[void,string]
|
header: BlockHeader;
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
uncles: seq[BlockHeader];
|
||||||
|
numTransactions: int;
|
||||||
|
checkSealOK: bool;
|
||||||
|
ttdReached: bool;
|
||||||
|
pow: PowRef): Result[void, string] =
|
||||||
if header.isGenesis:
|
if header.isGenesis:
|
||||||
if header.extraData.len > 32:
|
if header.extraData.len > 32:
|
||||||
return err("BlockHeader.extraData larger than 32 bytes")
|
return err("BlockHeader.extraData larger than 32 bytes")
|
||||||
return ok()
|
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(
|
result = chainDB.validateHeader(
|
||||||
header, parent, numTransactions, checkSealOK, pow)
|
header, parent, numTransactions, checkSealOK, ttdReached, pow)
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -339,24 +368,32 @@ proc validateHeaderAndKinship*(chainDB: BaseChainDB; header: BlockHeader;
|
||||||
if not chainDB.exists(header.stateRoot):
|
if not chainDB.exists(header.stateRoot):
|
||||||
return err("`state_root` was not found in the db.")
|
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:
|
if result.isOk:
|
||||||
result = chainDB.validateGasLimitOrBaseFee(header, parent)
|
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(
|
chainDB.validateHeaderAndKinship(
|
||||||
header, body.uncles, body.transactions.len, checkSealOK, pow)
|
header, body.uncles, body.transactions.len, checkSealOK, ttdReached, pow)
|
||||||
|
|
||||||
|
proc validateHeaderAndKinship*(
|
||||||
proc validateHeaderAndKinship*(chainDB: BaseChainDB; ethBlock: EthBlock;
|
chainDB: BaseChainDB;
|
||||||
checkSealOK: bool; pow: PowRef): Result[void,string]
|
ethBlock: EthBlock;
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
checkSealOK: bool;
|
||||||
|
ttdReached: bool;
|
||||||
|
pow: PowRef): Result[void,string] =
|
||||||
chainDB.validateHeaderAndKinship(
|
chainDB.validateHeaderAndKinship(
|
||||||
ethBlock.header, ethBlock.uncles, ethBlock.txs.len, checkSealOK, pow)
|
ethBlock.header, ethBlock.uncles, ethBlock.txs.len,
|
||||||
|
checkSealOK, ttdReached, pow)
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# 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.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[times, tables],
|
std/[times, tables, typetraits],
|
||||||
pkg/[chronos, eth/common, eth/keys, stew/results, chronicles],
|
pkg/[chronos, stew/results, chronicles, eth/common, eth/keys],
|
||||||
"."/[config, db/db_chain, p2p/chain, constants, utils/header],
|
"."/[config, db/db_chain, p2p/chain, constants, utils/header],
|
||||||
"."/p2p/clique/[clique_defs,
|
"."/p2p/clique/[clique_defs,
|
||||||
clique_desc,
|
clique_desc,
|
||||||
|
@ -19,18 +19,31 @@ import
|
||||||
./p2p/gaslimit,
|
./p2p/gaslimit,
|
||||||
"."/[chain_config, utils, context]
|
"."/[chain_config, utils, context]
|
||||||
|
|
||||||
|
from web3/ethtypes as web3types import nil
|
||||||
|
from web3/engine_api_types import ExecutionPayload, PayloadAttributes
|
||||||
|
|
||||||
type
|
type
|
||||||
EngineState = enum
|
EngineState* = enum
|
||||||
EngineStopped, EngineRunning
|
EngineStopped,
|
||||||
|
EngineRunning,
|
||||||
|
EnginePostMerge
|
||||||
|
|
||||||
|
Web3BlockHash = web3types.BlockHash
|
||||||
|
Web3Address = web3types.Address
|
||||||
|
Web3Bloom = web3types.FixedBytes[256]
|
||||||
|
Web3Quantity = web3types.Quantity
|
||||||
|
|
||||||
SealingEngineRef* = ref SealingEngineObj
|
SealingEngineRef* = ref SealingEngineObj
|
||||||
SealingEngineObj = object of RootObj
|
SealingEngineObj = object of RootObj
|
||||||
state: EngineState
|
state: EngineState
|
||||||
engineLoop: Future[void]
|
engineLoop: Future[void]
|
||||||
chain: Chain
|
chain*: Chain
|
||||||
ctx: EthContext
|
ctx: EthContext
|
||||||
signer: EthAddress
|
signer: EthAddress
|
||||||
|
|
||||||
|
template asEthHash*(hash: Web3BlockHash): Hash256 =
|
||||||
|
Hash256(data: distinctBase(hash))
|
||||||
|
|
||||||
proc validateSealer*(conf: NimbusConf, ctx: EthContext, chain: Chain): Result[void, string] =
|
proc validateSealer*(conf: NimbusConf, ctx: EthContext, chain: Chain): Result[void, string] =
|
||||||
if conf.engineSigner == ZERO_ADDRESS:
|
if conf.engineSigner == ZERO_ADDRESS:
|
||||||
return err("signer address should not zero, use --engine-signer to set signer 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.} =
|
proc isLondon(c: ChainConfig, number: BlockNumber): bool {.inline.} =
|
||||||
number >= c.londonBlock
|
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:
|
let timestamp = if parent.timestamp >= time:
|
||||||
parent.timestamp + 1.seconds
|
parent.timestamp + 1.seconds
|
||||||
else:
|
else:
|
||||||
|
@ -69,6 +85,7 @@ proc prepareHeader(engine: SealingEngineRef, parent: BlockHeader, time: Time): R
|
||||||
gasCeil = DEFAULT_GAS_LIMIT),
|
gasCeil = DEFAULT_GAS_LIMIT),
|
||||||
# TODO: extraData can be configured via cli
|
# TODO: extraData can be configured via cli
|
||||||
#extraData : engine.extra,
|
#extraData : engine.extra,
|
||||||
|
coinbase : coinbase,
|
||||||
timestamp : timestamp,
|
timestamp : timestamp,
|
||||||
ommersHash : EMPTY_UNCLE_HASH,
|
ommersHash : EMPTY_UNCLE_HASH,
|
||||||
stateRoot : parent.stateRoot,
|
stateRoot : parent.stateRoot,
|
||||||
|
@ -87,14 +104,21 @@ proc prepareHeader(engine: SealingEngineRef, parent: BlockHeader, time: Time): R
|
||||||
# TODO: desiredLimit can be configured by user, gasCeil
|
# TODO: desiredLimit can be configured by user, gasCeil
|
||||||
header.gasLimit = calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
|
header.gasLimit = calcGasLimit1559(parentGasLimit, desiredLimit = DEFAULT_GAS_LIMIT)
|
||||||
|
|
||||||
|
# TODO Post merge, clique should not be executing
|
||||||
let clique = engine.chain.clique
|
let clique = engine.chain.clique
|
||||||
let res = clique.prepare(parent, header)
|
let res = clique.prepare(parent, header)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
return err($res.error)
|
return err($res.error)
|
||||||
|
|
||||||
|
if engine.chain.isBlockAfterTtd(header.blockNumber):
|
||||||
|
header.difficulty = DifficultyInt.zero
|
||||||
|
|
||||||
ok(header)
|
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
|
# deviation from standard block generator
|
||||||
# - no local and remote transactions inclusion(need tx pool)
|
# - no local and remote transactions inclusion(need tx pool)
|
||||||
# - no receipts from tx
|
# - no receipts from tx
|
||||||
|
@ -102,23 +126,48 @@ proc generateBlock(engine: SealingEngineRef, ethBlock: var EthBlock): Result[voi
|
||||||
# - no local and remote uncles inclusion
|
# - no local and remote uncles inclusion
|
||||||
|
|
||||||
let clique = engine.chain.clique
|
let clique = engine.chain.clique
|
||||||
let parent = engine.chain.currentBlock()
|
|
||||||
|
|
||||||
let time = getTime()
|
let time = getTime()
|
||||||
let res = prepareHeader(engine, parent, time)
|
let res = prepareHeader(engine, coinbase, parentBlockHeader, time)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
return err("error prepare header")
|
return err("error prepare header")
|
||||||
|
|
||||||
ethBlock = EthBlock(
|
outBlock = EthBlock(
|
||||||
header: res.get()
|
header: res.get()
|
||||||
)
|
)
|
||||||
|
|
||||||
let sealRes = clique.seal(ethBlock)
|
# TODO Post merge, Clique should not be executing
|
||||||
|
let sealRes = clique.seal(outBlock)
|
||||||
if sealRes.isErr:
|
if sealRes.isErr:
|
||||||
return err("error sealing block header: " & $sealRes.error)
|
return err("error sealing block header: " & $sealRes.error)
|
||||||
|
|
||||||
|
debug "generated block",
|
||||||
|
blockNumber = outBlock.header.blockNumber,
|
||||||
|
blockHash = blockHash(outBlock.header)
|
||||||
|
|
||||||
ok()
|
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.} =
|
proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
|
||||||
let clique = engine.chain.clique
|
let clique = engine.chain.clique
|
||||||
|
|
||||||
|
@ -134,6 +183,9 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
|
||||||
|
|
||||||
clique.authorize(engine.signer, signerFunc)
|
clique.authorize(engine.signer, signerFunc)
|
||||||
|
|
||||||
|
# TODO: This should be configurable
|
||||||
|
var coinbase: EthAddress
|
||||||
|
|
||||||
# convert times.Duration to chronos.Duration
|
# convert times.Duration to chronos.Duration
|
||||||
let period = chronos.seconds(clique.cfg.period.inSeconds)
|
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 queue for chain reorgs
|
||||||
# - no async lock/guard against race with sync algo
|
# - no async lock/guard against race with sync algo
|
||||||
var blk: EthBlock
|
var blk: EthBlock
|
||||||
let blkRes = engine.generateBlock(blk)
|
let blkRes = engine.generateBlock(coinbase, blk)
|
||||||
if blkRes.isErr:
|
if blkRes.isErr:
|
||||||
error "sealing engine generateBlock error", msg=blkRes.error
|
error "sealing engine generateBlock error", msg=blkRes.error
|
||||||
break
|
break
|
||||||
|
@ -163,14 +215,50 @@ proc sealingLoop(engine: SealingEngineRef): Future[void] {.async.} =
|
||||||
|
|
||||||
info "block generated", number=blk.header.blockNumber
|
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,
|
proc new*(_: type SealingEngineRef,
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
ctx: EthContext,
|
ctx: EthContext,
|
||||||
signer: EthAddress): SealingEngineRef =
|
signer: EthAddress,
|
||||||
|
initialState: EngineState): SealingEngineRef =
|
||||||
SealingEngineRef(
|
SealingEngineRef(
|
||||||
chain: chain,
|
chain: chain,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
signer: signer
|
signer: signer,
|
||||||
|
state: initialState
|
||||||
)
|
)
|
||||||
|
|
||||||
proc start*(engine: SealingEngineRef) =
|
proc start*(engine: SealingEngineRef) =
|
||||||
|
|
|
@ -227,8 +227,8 @@ proc getPowSpecs*(header: BlockHeader): PowSpecs =
|
||||||
difficulty: header.difficulty)
|
difficulty: header.difficulty)
|
||||||
|
|
||||||
proc getPowCacheLookup*(tm: PowRef;
|
proc getPowCacheLookup*(tm: PowRef;
|
||||||
blockNumber: BlockNumber): (uint64,Hash256)
|
blockNumber: BlockNumber): (uint64, Hash256)
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [KeyError, Defect].} =
|
||||||
## Returns the pair `(size,digest)` derived from the lookup cache for the
|
## Returns the pair `(size,digest)` derived from the lookup cache for the
|
||||||
## `hashimotoLight()` function for the given block number. The `size` is 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
|
## 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
|
## This function is intended for error reporting and might also be useful
|
||||||
## for testing and debugging.
|
## for testing and debugging.
|
||||||
let ds = tm.lightByEpoch.get(blockNumber)
|
let ds = tm.lightByEpoch.get(blockNumber)
|
||||||
|
if ds == nil:
|
||||||
|
raise newException(KeyError, "block not found")
|
||||||
|
|
||||||
result[0] = ds.size
|
result[0] = ds.size
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ proc new*(T: type PowCacheRef; maxItems = nItemsMax): T =
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc get*(pc: var PowCache; bn: BlockNumber): PowCacheItemRef
|
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
|
## Return a cache derived from argument `blockNumber` ready to be used
|
||||||
## for the `hashimotoLight()` method.
|
## for the `hashimotoLight()` method.
|
||||||
let
|
let
|
||||||
|
@ -91,12 +91,10 @@ proc get*(pc: var PowCache; bn: BlockNumber): PowCacheItemRef
|
||||||
|
|
||||||
pc.cache.lruAppend(key, pair, pc.cacheMax)
|
pc.cache.lruAppend(key, pair, pc.cacheMax)
|
||||||
|
|
||||||
proc get*(pcr: PowCacheRef; bn: BlockNumber): PowCacheItemRef
|
proc get*(pcr: PowCacheRef; bn: BlockNumber): PowCacheItemRef =
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
|
||||||
## Variant of `getCache()`
|
## Variant of `getCache()`
|
||||||
pcr[].get(bn)
|
pcr[].get(bn)
|
||||||
|
|
||||||
|
|
||||||
proc hasItem*(pc: var PowCache; bn: BlockNumber): bool
|
proc hasItem*(pc: var PowCache; bn: BlockNumber): bool
|
||||||
{.gcsafe,raises: [Defect,CatchableError].} =
|
{.gcsafe,raises: [Defect,CatchableError].} =
|
||||||
## Returns true if there is a cache entry for argument `bn`.
|
## 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:
|
if validation:
|
||||||
let rc = chainDB.validateHeaderAndKinship(
|
let rc = chainDB.validateHeaderAndKinship(
|
||||||
result.header, body, checkSeal, pow)
|
result.header, body, checkSeal, false, pow)
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
raise newException(
|
raise newException(
|
||||||
ValidationError, "validateHeaderAndKinship: " & rc.error)
|
ValidationError, "validateHeaderAndKinship: " & rc.error)
|
||||||
|
@ -312,7 +312,7 @@ proc runTester(tester: var Tester, chainDB: BaseChainDB, testStatusIMPL: var Tes
|
||||||
|
|
||||||
# manually validating
|
# manually validating
|
||||||
check chainDB.validateHeaderAndKinship(
|
check chainDB.validateHeaderAndKinship(
|
||||||
preminedBlock, checkSeal, pow).isOk
|
preminedBlock, checkSeal, false, pow).isOk
|
||||||
|
|
||||||
except:
|
except:
|
||||||
debugEcho "FATAL ERROR(WE HAVE BUG): ", getCurrentExceptionMsg()
|
debugEcho "FATAL ERROR(WE HAVE BUG): ", getCurrentExceptionMsg()
|
||||||
|
|
|
@ -65,7 +65,7 @@ proc configurationMain*() =
|
||||||
check conf.networkId == 678.NetworkId
|
check conf.networkId == 678.NetworkId
|
||||||
check conf.networkParams == NetworkParams()
|
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])
|
let conf = makeConfig(@["--custom-network:" & genesisFile])
|
||||||
check conf.networkId == 123.NetworkId
|
check conf.networkId == 123.NetworkId
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b464505b4dcbe2ef52d19b2cfca8f2be4ebf2c7e
|
Subproject commit bb705bf17b46d2c8f9bfb106d9cc7437009a2501
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 16ae908e49dad3dd1be1d536798a2b0ae39250df
|
|
@ -1,5 +1,12 @@
|
||||||
witnessBuilderBC
|
witnessBuilderBC
|
||||||
===
|
===
|
||||||
|
## bcBerlinToLondon
|
||||||
|
```diff
|
||||||
|
+ BerlinToLondonTransition.json OK
|
||||||
|
+ initialVal.json OK
|
||||||
|
+ londonUncles.json OK
|
||||||
|
```
|
||||||
|
OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
## bcBlockGasLimitTest
|
## bcBlockGasLimitTest
|
||||||
```diff
|
```diff
|
||||||
+ BlockGasLimit2p63m1.json OK
|
+ BlockGasLimit2p63m1.json OK
|
||||||
|
@ -15,11 +22,39 @@ OK: 6/6 Fail: 0/6 Skip: 0/6
|
||||||
+ ConstantinopleFixTransition.json OK
|
+ ConstantinopleFixTransition.json OK
|
||||||
```
|
```
|
||||||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
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
|
## bcEIP158ToByzantium
|
||||||
```diff
|
```diff
|
||||||
+ ByzantiumTransition.json OK
|
+ ByzantiumTransition.json OK
|
||||||
```
|
```
|
||||||
OK: 1/1 Fail: 0/1 Skip: 0/1
|
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
|
## bcExample
|
||||||
|
```diff
|
||||||
|
+ basefeeExample.json OK
|
||||||
|
```
|
||||||
|
OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
## bcExploitTest
|
## bcExploitTest
|
||||||
```diff
|
```diff
|
||||||
+ DelegateCallSpam.json OK
|
+ DelegateCallSpam.json OK
|
||||||
|
@ -88,6 +123,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ ExtraData33.json OK
|
+ ExtraData33.json OK
|
||||||
+ GasLimitHigherThan2p63m1.json OK
|
+ GasLimitHigherThan2p63m1.json OK
|
||||||
+ GasLimitIsZero.json OK
|
+ GasLimitIsZero.json OK
|
||||||
|
+ badTimestamp.json OK
|
||||||
+ log1_wrongBlockNumber.json OK
|
+ log1_wrongBlockNumber.json OK
|
||||||
+ log1_wrongBloom.json OK
|
+ log1_wrongBloom.json OK
|
||||||
+ timeDiff0.json OK
|
+ timeDiff0.json OK
|
||||||
|
@ -104,7 +140,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ wrongTransactionsTrie.json OK
|
+ wrongTransactionsTrie.json OK
|
||||||
+ wrongUncleHash.json OK
|
+ wrongUncleHash.json OK
|
||||||
```
|
```
|
||||||
OK: 21/21 Fail: 0/21 Skip: 0/21
|
OK: 22/22 Fail: 0/22 Skip: 0/22
|
||||||
## bcMultiChainTest
|
## bcMultiChainTest
|
||||||
```diff
|
```diff
|
||||||
+ CallContractFromNotBestBlock.json OK
|
+ CallContractFromNotBestBlock.json OK
|
||||||
|
@ -288,11 +324,26 @@ OK: 96/96 Fail: 0/96 Skip: 0/96
|
||||||
+ suicideStorageCheckVCreate.json OK
|
+ suicideStorageCheckVCreate.json OK
|
||||||
+ suicideStorageCheckVCreate2.json OK
|
+ suicideStorageCheckVCreate2.json OK
|
||||||
+ suicideThenCheckBalance.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
|
+ transactionFromNotExistingAccount.json OK
|
||||||
+ txCost-sec73.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
|
## bcTotalDifficultyTest
|
||||||
```diff
|
```diff
|
||||||
+ lotsOfBranchesOverrideAtTheEnd.json OK
|
+ lotsOfBranchesOverrideAtTheEnd.json OK
|
||||||
|
@ -320,6 +371,7 @@ OK: 11/11 Fail: 0/11 Skip: 0/11
|
||||||
+ gasLimitTooLow.json OK
|
+ gasLimitTooLow.json OK
|
||||||
+ gasLimitTooLowExactBound.json OK
|
+ gasLimitTooLowExactBound.json OK
|
||||||
+ gasLimitTooLowExactBound2.json OK
|
+ gasLimitTooLowExactBound2.json OK
|
||||||
|
+ gasLimitTooLowExactBoundLondon.json OK
|
||||||
+ incorrectUncleNumber0.json OK
|
+ incorrectUncleNumber0.json OK
|
||||||
+ incorrectUncleNumber1.json OK
|
+ incorrectUncleNumber1.json OK
|
||||||
+ incorrectUncleNumber500.json OK
|
+ incorrectUncleNumber500.json OK
|
||||||
|
@ -335,7 +387,7 @@ OK: 11/11 Fail: 0/11 Skip: 0/11
|
||||||
+ wrongParentHash.json OK
|
+ wrongParentHash.json OK
|
||||||
+ wrongStateRoot.json OK
|
+ wrongStateRoot.json OK
|
||||||
```
|
```
|
||||||
OK: 24/24 Fail: 0/24 Skip: 0/24
|
OK: 25/25 Fail: 0/25 Skip: 0/25
|
||||||
## bcUncleSpecialTests
|
## bcUncleSpecialTests
|
||||||
```diff
|
```diff
|
||||||
+ futureUncleTimestamp2.json OK
|
+ futureUncleTimestamp2.json OK
|
||||||
|
@ -467,17 +519,135 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
+ badOpcodes.json OK
|
+ badOpcodes.json OK
|
||||||
+ eip2315NotRemoved.json OK
|
+ eip2315NotRemoved.json OK
|
||||||
+ invalidAddr.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
|
+ undefinedOpcodeFirstByte.json OK
|
||||||
```
|
```
|
||||||
OK: 4/4 Fail: 0/4 Skip: 0/4
|
OK: 121/121 Fail: 0/121 Skip: 0/121
|
||||||
## stBugs
|
## stBugs
|
||||||
```diff
|
```diff
|
||||||
+ evmBytecode.json OK
|
+ evmBytecode.json OK
|
||||||
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192.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
|
+ returndatacopyPythonBug_Tue_03_48_41-1432.json OK
|
||||||
+ staticcall_createfails.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
|
## stCallCodes
|
||||||
```diff
|
```diff
|
||||||
+ call_OOG_additionalGasCosts1.json OK
|
+ call_OOG_additionalGasCosts1.json OK
|
||||||
|
@ -757,6 +927,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
+ CREATE2_Bounds2.json OK
|
+ CREATE2_Bounds2.json OK
|
||||||
+ CREATE2_Bounds3.json OK
|
+ CREATE2_Bounds3.json OK
|
||||||
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
|
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
|
||||||
|
+ CREATE2_EOF1.json OK
|
||||||
+ CREATE2_FirstByte_loop.json OK
|
+ CREATE2_FirstByte_loop.json OK
|
||||||
+ CREATE2_Suicide.json OK
|
+ CREATE2_Suicide.json OK
|
||||||
+ Create2OOGafterInitCode.json OK
|
+ Create2OOGafterInitCode.json OK
|
||||||
|
@ -801,7 +972,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
+ returndatacopy_following_successful_create.json OK
|
+ returndatacopy_following_successful_create.json OK
|
||||||
+ returndatasize_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
|
## stCreateTest
|
||||||
```diff
|
```diff
|
||||||
+ CREATE_AcreateB_BSuicide_BStore.json OK
|
+ 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_EContractCreateNEContractInInitOOG_Tr.json OK
|
||||||
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
|
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
|
||||||
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
|
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
|
||||||
|
+ CREATE_EOF1.json OK
|
||||||
+ CREATE_EmptyContract.json OK
|
+ CREATE_EmptyContract.json OK
|
||||||
+ CREATE_EmptyContractAndCallIt_0wei.json OK
|
+ CREATE_EmptyContractAndCallIt_0wei.json OK
|
||||||
+ CREATE_EmptyContractAndCallIt_1wei.json OK
|
+ CREATE_EmptyContractAndCallIt_1wei.json OK
|
||||||
|
@ -838,8 +1010,9 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
|
||||||
+ TransactionCollisionToEmpty.json OK
|
+ TransactionCollisionToEmpty.json OK
|
||||||
+ TransactionCollisionToEmptyButCode.json OK
|
+ TransactionCollisionToEmptyButCode.json OK
|
||||||
+ TransactionCollisionToEmptyButNonce.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
|
## stDelegatecallTestHomestead
|
||||||
```diff
|
```diff
|
||||||
+ Call1024BalanceTooLow.json OK
|
+ Call1024BalanceTooLow.json OK
|
||||||
|
@ -933,6 +1106,22 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
|
||||||
+ gasCostReturn.json OK
|
+ gasCostReturn.json OK
|
||||||
```
|
```
|
||||||
OK: 40/40 Fail: 0/40 Skip: 0/40
|
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
|
## stEIP158Specific
|
||||||
```diff
|
```diff
|
||||||
+ CALL_OneVCallSuicide.json OK
|
+ CALL_OneVCallSuicide.json OK
|
||||||
|
@ -947,23 +1136,28 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stEIP2930
|
## stEIP2930
|
||||||
```diff
|
```diff
|
||||||
+ addressOpcodes.json OK
|
+ addressOpcodes.json OK
|
||||||
|
+ coinbaseT01.json OK
|
||||||
|
+ coinbaseT2.json OK
|
||||||
+ manualCreate.json OK
|
+ manualCreate.json OK
|
||||||
+ storageCosts.json OK
|
+ storageCosts.json OK
|
||||||
+ transactionCosts.json OK
|
+ transactionCosts.json OK
|
||||||
+ variedContext.json OK
|
+ variedContext.json OK
|
||||||
```
|
```
|
||||||
OK: 5/5 Fail: 0/5 Skip: 0/5
|
OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stExample
|
## stExample
|
||||||
```diff
|
```diff
|
||||||
+ accessListExample.json OK
|
+ accessListExample.json OK
|
||||||
+ add11.json OK
|
+ add11.json OK
|
||||||
+ add11_yml.json OK
|
+ add11_yml.json OK
|
||||||
|
+ basefeeExample.json OK
|
||||||
|
+ eip1559.json OK
|
||||||
|
+ invalidTr.json OK
|
||||||
+ labelsExample.json OK
|
+ labelsExample.json OK
|
||||||
+ rangesExample.json OK
|
+ rangesExample.json OK
|
||||||
+ solidityExample.json OK
|
+ solidityExample.json OK
|
||||||
+ yulExample.json OK
|
+ yulExample.json OK
|
||||||
```
|
```
|
||||||
OK: 7/7 Fail: 0/7 Skip: 0/7
|
OK: 10/10 Fail: 0/10 Skip: 0/10
|
||||||
## stExtCodeHash
|
## stExtCodeHash
|
||||||
```diff
|
```diff
|
||||||
+ callToNonExistent.json OK
|
+ callToNonExistent.json OK
|
||||||
|
@ -1190,6 +1384,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
||||||
+ mem64kb_singleByte-32.json OK
|
+ mem64kb_singleByte-32.json OK
|
||||||
+ mem64kb_singleByte-33.json OK
|
+ mem64kb_singleByte-33.json OK
|
||||||
+ mem64kb_singleByte.json OK
|
+ mem64kb_singleByte.json OK
|
||||||
|
+ memCopySelf.json OK
|
||||||
+ memReturn.json OK
|
+ memReturn.json OK
|
||||||
+ mload16bitBound.json OK
|
+ mload16bitBound.json OK
|
||||||
+ mload8bitBound.json OK
|
+ mload8bitBound.json OK
|
||||||
|
@ -1208,7 +1403,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
||||||
+ stackLimitPush32_1024.json OK
|
+ stackLimitPush32_1024.json OK
|
||||||
+ stackLimitPush32_1025.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
|
## stNonZeroCallsTest
|
||||||
```diff
|
```diff
|
||||||
+ NonZeroValue_CALL.json OK
|
+ NonZeroValue_CALL.json OK
|
||||||
|
@ -1243,102 +1438,11 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
|
||||||
+ identity_to_bigger.json OK
|
+ identity_to_bigger.json OK
|
||||||
+ identity_to_smaller.json OK
|
+ identity_to_smaller.json OK
|
||||||
+ modexp.json OK
|
+ modexp.json OK
|
||||||
+ modexp_0_0_0_1000000.json OK
|
+ modexpTests.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
|
|
||||||
+ precompsEIP2929.json OK
|
+ precompsEIP2929.json OK
|
||||||
+ sec80.json OK
|
+ sec80.json OK
|
||||||
```
|
```
|
||||||
OK: 98/98 Fail: 0/98 Skip: 0/98
|
OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stPreCompiledContracts2
|
## stPreCompiledContracts2
|
||||||
```diff
|
```diff
|
||||||
+ CALLBlake2f.json OK
|
+ CALLBlake2f.json OK
|
||||||
|
@ -2020,6 +2124,9 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
+ refund50_2.json OK
|
+ refund50_2.json OK
|
||||||
+ refund50percentCap.json OK
|
+ refund50percentCap.json OK
|
||||||
+ refund600.json OK
|
+ refund600.json OK
|
||||||
|
+ refundFF.json OK
|
||||||
|
+ refundMax.json OK
|
||||||
|
+ refundSSTORE.json OK
|
||||||
+ refundSuicide50procentCap.json OK
|
+ refundSuicide50procentCap.json OK
|
||||||
+ refund_CallA.json OK
|
+ refund_CallA.json OK
|
||||||
+ refund_CallA_OOG.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_multimpleSuicide.json OK
|
||||||
+ refund_singleSuicide.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
|
## stReturnDataTest
|
||||||
```diff
|
```diff
|
||||||
+ call_ecrec_success_empty_then_returndatasize.json OK
|
+ call_ecrec_success_empty_then_returndatasize.json OK
|
||||||
|
@ -2140,6 +2247,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ InitCollision.json OK
|
+ InitCollision.json OK
|
||||||
+ InitCollisionNonZeroNonce.json OK
|
+ InitCollisionNonZeroNonce.json OK
|
||||||
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
||||||
|
+ sstoreGas.json OK
|
||||||
+ sstore_0to0.json OK
|
+ sstore_0to0.json OK
|
||||||
+ sstore_0to0to0.json OK
|
+ sstore_0to0to0.json OK
|
||||||
+ sstore_0to0toX.json OK
|
+ sstore_0to0toX.json OK
|
||||||
|
@ -2165,16 +2273,17 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ sstore_changeFromExternalCallInInitCode.json OK
|
+ sstore_changeFromExternalCallInInitCode.json OK
|
||||||
+ sstore_gasLeft.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
|
## stSelfBalance
|
||||||
```diff
|
```diff
|
||||||
|
+ diffPlaces.json OK
|
||||||
+ selfBalance.json OK
|
+ selfBalance.json OK
|
||||||
+ selfBalanceCallTypes.json OK
|
+ selfBalanceCallTypes.json OK
|
||||||
+ selfBalanceEqualsBalance.json OK
|
+ selfBalanceEqualsBalance.json OK
|
||||||
+ selfBalanceGasCost.json OK
|
+ selfBalanceGasCost.json OK
|
||||||
+ selfBalanceUpdate.json OK
|
+ selfBalanceUpdate.json OK
|
||||||
```
|
```
|
||||||
OK: 5/5 Fail: 0/5 Skip: 0/5
|
OK: 6/6 Fail: 0/6 Skip: 0/6
|
||||||
## stShift
|
## stShift
|
||||||
```diff
|
```diff
|
||||||
+ sar00.json OK
|
+ sar00.json OK
|
||||||
|
@ -2675,6 +2784,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
|
||||||
+ ContractStoreClearsSuccess.json OK
|
+ ContractStoreClearsSuccess.json OK
|
||||||
+ CreateMessageReverted.json OK
|
+ CreateMessageReverted.json OK
|
||||||
+ CreateMessageSuccess.json OK
|
+ CreateMessageSuccess.json OK
|
||||||
|
+ CreateTransactionEOF1.json OK
|
||||||
+ CreateTransactionSuccess.json OK
|
+ CreateTransactionSuccess.json OK
|
||||||
+ EmptyTransaction3.json OK
|
+ EmptyTransaction3.json OK
|
||||||
+ HighGasLimit.json OK
|
+ HighGasLimit.json OK
|
||||||
|
@ -2700,7 +2810,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
|
||||||
+ TransactionToAddressh160minusOne.json OK
|
+ TransactionToAddressh160minusOne.json OK
|
||||||
+ TransactionToItself.json OK
|
+ TransactionToItself.json OK
|
||||||
```
|
```
|
||||||
OK: 28/28 Fail: 0/28 Skip: 0/28
|
OK: 29/29 Fail: 0/29 Skip: 0/29
|
||||||
## stTransitionTest
|
## stTransitionTest
|
||||||
```diff
|
```diff
|
||||||
+ createNameRegistratorPerTxsAfter.json OK
|
+ 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
|
OK: 11/11 Fail: 0/11 Skip: 0/11
|
||||||
|
|
||||||
---TOTAL---
|
---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
|
+ badOpcodes.json OK
|
||||||
+ eip2315NotRemoved.json OK
|
+ eip2315NotRemoved.json OK
|
||||||
+ invalidAddr.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
|
+ undefinedOpcodeFirstByte.json OK
|
||||||
```
|
```
|
||||||
OK: 4/4 Fail: 0/4 Skip: 0/4
|
OK: 121/121 Fail: 0/121 Skip: 0/121
|
||||||
## stBugs
|
## stBugs
|
||||||
```diff
|
```diff
|
||||||
+ evmBytecode.json OK
|
+ evmBytecode.json OK
|
||||||
+ randomStatetestDEFAULT-Tue_07_58_41-15153-575192.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
|
+ returndatacopyPythonBug_Tue_03_48_41-1432.json OK
|
||||||
+ staticcall_createfails.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
|
## stCallCodes
|
||||||
```diff
|
```diff
|
||||||
+ call_OOG_additionalGasCosts1.json OK
|
+ call_OOG_additionalGasCosts1.json OK
|
||||||
|
@ -351,6 +469,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
+ CREATE2_Bounds2.json OK
|
+ CREATE2_Bounds2.json OK
|
||||||
+ CREATE2_Bounds3.json OK
|
+ CREATE2_Bounds3.json OK
|
||||||
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
|
+ CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn.json OK
|
||||||
|
+ CREATE2_EOF1.json OK
|
||||||
+ CREATE2_FirstByte_loop.json OK
|
+ CREATE2_FirstByte_loop.json OK
|
||||||
+ CREATE2_Suicide.json OK
|
+ CREATE2_Suicide.json OK
|
||||||
+ Create2OOGafterInitCode.json OK
|
+ Create2OOGafterInitCode.json OK
|
||||||
|
@ -395,7 +514,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
|
||||||
+ returndatacopy_following_successful_create.json OK
|
+ returndatacopy_following_successful_create.json OK
|
||||||
+ returndatasize_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
|
## stCreateTest
|
||||||
```diff
|
```diff
|
||||||
+ CREATE_AcreateB_BSuicide_BStore.json OK
|
+ 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_EContractCreateNEContractInInitOOG_Tr.json OK
|
||||||
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
|
+ CREATE_EContractCreateNEContractInInit_Tr.json OK
|
||||||
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
|
+ CREATE_EContract_ThenCALLToNonExistentAcc.json OK
|
||||||
|
+ CREATE_EOF1.json OK
|
||||||
+ CREATE_EmptyContract.json OK
|
+ CREATE_EmptyContract.json OK
|
||||||
+ CREATE_EmptyContractAndCallIt_0wei.json OK
|
+ CREATE_EmptyContractAndCallIt_0wei.json OK
|
||||||
+ CREATE_EmptyContractAndCallIt_1wei.json OK
|
+ CREATE_EmptyContractAndCallIt_1wei.json OK
|
||||||
|
@ -432,8 +552,9 @@ OK: 47/47 Fail: 0/47 Skip: 0/47
|
||||||
+ TransactionCollisionToEmpty.json OK
|
+ TransactionCollisionToEmpty.json OK
|
||||||
+ TransactionCollisionToEmptyButCode.json OK
|
+ TransactionCollisionToEmptyButCode.json OK
|
||||||
+ TransactionCollisionToEmptyButNonce.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
|
## stDelegatecallTestHomestead
|
||||||
```diff
|
```diff
|
||||||
+ Call1024BalanceTooLow.json OK
|
+ Call1024BalanceTooLow.json OK
|
||||||
|
@ -527,6 +648,22 @@ OK: 13/13 Fail: 0/13 Skip: 0/13
|
||||||
+ gasCostReturn.json OK
|
+ gasCostReturn.json OK
|
||||||
```
|
```
|
||||||
OK: 40/40 Fail: 0/40 Skip: 0/40
|
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
|
## stEIP158Specific
|
||||||
```diff
|
```diff
|
||||||
+ CALL_OneVCallSuicide.json OK
|
+ CALL_OneVCallSuicide.json OK
|
||||||
|
@ -541,23 +678,28 @@ OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stEIP2930
|
## stEIP2930
|
||||||
```diff
|
```diff
|
||||||
+ addressOpcodes.json OK
|
+ addressOpcodes.json OK
|
||||||
|
+ coinbaseT01.json OK
|
||||||
|
+ coinbaseT2.json OK
|
||||||
+ manualCreate.json OK
|
+ manualCreate.json OK
|
||||||
+ storageCosts.json OK
|
+ storageCosts.json OK
|
||||||
+ transactionCosts.json OK
|
+ transactionCosts.json OK
|
||||||
+ variedContext.json OK
|
+ variedContext.json OK
|
||||||
```
|
```
|
||||||
OK: 5/5 Fail: 0/5 Skip: 0/5
|
OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stExample
|
## stExample
|
||||||
```diff
|
```diff
|
||||||
+ accessListExample.json OK
|
+ accessListExample.json OK
|
||||||
+ add11.json OK
|
+ add11.json OK
|
||||||
+ add11_yml.json OK
|
+ add11_yml.json OK
|
||||||
|
+ basefeeExample.json OK
|
||||||
|
+ eip1559.json OK
|
||||||
|
+ invalidTr.json OK
|
||||||
+ labelsExample.json OK
|
+ labelsExample.json OK
|
||||||
+ rangesExample.json OK
|
+ rangesExample.json OK
|
||||||
+ solidityExample.json OK
|
+ solidityExample.json OK
|
||||||
+ yulExample.json OK
|
+ yulExample.json OK
|
||||||
```
|
```
|
||||||
OK: 7/7 Fail: 0/7 Skip: 0/7
|
OK: 10/10 Fail: 0/10 Skip: 0/10
|
||||||
## stExtCodeHash
|
## stExtCodeHash
|
||||||
```diff
|
```diff
|
||||||
+ callToNonExistent.json OK
|
+ callToNonExistent.json OK
|
||||||
|
@ -784,6 +926,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
||||||
+ mem64kb_singleByte-32.json OK
|
+ mem64kb_singleByte-32.json OK
|
||||||
+ mem64kb_singleByte-33.json OK
|
+ mem64kb_singleByte-33.json OK
|
||||||
+ mem64kb_singleByte.json OK
|
+ mem64kb_singleByte.json OK
|
||||||
|
+ memCopySelf.json OK
|
||||||
+ memReturn.json OK
|
+ memReturn.json OK
|
||||||
+ mload16bitBound.json OK
|
+ mload16bitBound.json OK
|
||||||
+ mload8bitBound.json OK
|
+ mload8bitBound.json OK
|
||||||
|
@ -802,7 +945,7 @@ OK: 38/38 Fail: 0/38 Skip: 0/38
|
||||||
+ stackLimitPush32_1024.json OK
|
+ stackLimitPush32_1024.json OK
|
||||||
+ stackLimitPush32_1025.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
|
## stNonZeroCallsTest
|
||||||
```diff
|
```diff
|
||||||
+ NonZeroValue_CALL.json OK
|
+ NonZeroValue_CALL.json OK
|
||||||
|
@ -837,102 +980,11 @@ OK: 24/24 Fail: 0/24 Skip: 0/24
|
||||||
+ identity_to_bigger.json OK
|
+ identity_to_bigger.json OK
|
||||||
+ identity_to_smaller.json OK
|
+ identity_to_smaller.json OK
|
||||||
+ modexp.json OK
|
+ modexp.json OK
|
||||||
+ modexp_0_0_0_1000000.json OK
|
+ modexpTests.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
|
|
||||||
+ precompsEIP2929.json OK
|
+ precompsEIP2929.json OK
|
||||||
+ sec80.json OK
|
+ sec80.json OK
|
||||||
```
|
```
|
||||||
OK: 98/98 Fail: 0/98 Skip: 0/98
|
OK: 7/7 Fail: 0/7 Skip: 0/7
|
||||||
## stPreCompiledContracts2
|
## stPreCompiledContracts2
|
||||||
```diff
|
```diff
|
||||||
+ CALLBlake2f.json OK
|
+ CALLBlake2f.json OK
|
||||||
|
@ -1614,6 +1666,9 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
|
||||||
+ refund50_2.json OK
|
+ refund50_2.json OK
|
||||||
+ refund50percentCap.json OK
|
+ refund50percentCap.json OK
|
||||||
+ refund600.json OK
|
+ refund600.json OK
|
||||||
|
+ refundFF.json OK
|
||||||
|
+ refundMax.json OK
|
||||||
|
+ refundSSTORE.json OK
|
||||||
+ refundSuicide50procentCap.json OK
|
+ refundSuicide50procentCap.json OK
|
||||||
+ refund_CallA.json OK
|
+ refund_CallA.json OK
|
||||||
+ refund_CallA_OOG.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_multimpleSuicide.json OK
|
||||||
+ refund_singleSuicide.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
|
## stReturnDataTest
|
||||||
```diff
|
```diff
|
||||||
+ call_ecrec_success_empty_then_returndatasize.json OK
|
+ call_ecrec_success_empty_then_returndatasize.json OK
|
||||||
|
@ -1734,6 +1789,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ InitCollision.json OK
|
+ InitCollision.json OK
|
||||||
+ InitCollisionNonZeroNonce.json OK
|
+ InitCollisionNonZeroNonce.json OK
|
||||||
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
+ SstoreCallToSelfSubRefundBelowZero.json OK
|
||||||
|
+ sstoreGas.json OK
|
||||||
+ sstore_0to0.json OK
|
+ sstore_0to0.json OK
|
||||||
+ sstore_0to0to0.json OK
|
+ sstore_0to0to0.json OK
|
||||||
+ sstore_0to0toX.json OK
|
+ sstore_0to0toX.json OK
|
||||||
|
@ -1759,16 +1815,17 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
||||||
+ sstore_changeFromExternalCallInInitCode.json OK
|
+ sstore_changeFromExternalCallInInitCode.json OK
|
||||||
+ sstore_gasLeft.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
|
## stSelfBalance
|
||||||
```diff
|
```diff
|
||||||
|
+ diffPlaces.json OK
|
||||||
+ selfBalance.json OK
|
+ selfBalance.json OK
|
||||||
+ selfBalanceCallTypes.json OK
|
+ selfBalanceCallTypes.json OK
|
||||||
+ selfBalanceEqualsBalance.json OK
|
+ selfBalanceEqualsBalance.json OK
|
||||||
+ selfBalanceGasCost.json OK
|
+ selfBalanceGasCost.json OK
|
||||||
+ selfBalanceUpdate.json OK
|
+ selfBalanceUpdate.json OK
|
||||||
```
|
```
|
||||||
OK: 5/5 Fail: 0/5 Skip: 0/5
|
OK: 6/6 Fail: 0/6 Skip: 0/6
|
||||||
## stShift
|
## stShift
|
||||||
```diff
|
```diff
|
||||||
+ sar00.json OK
|
+ sar00.json OK
|
||||||
|
@ -2269,6 +2326,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
|
||||||
+ ContractStoreClearsSuccess.json OK
|
+ ContractStoreClearsSuccess.json OK
|
||||||
+ CreateMessageReverted.json OK
|
+ CreateMessageReverted.json OK
|
||||||
+ CreateMessageSuccess.json OK
|
+ CreateMessageSuccess.json OK
|
||||||
|
+ CreateTransactionEOF1.json OK
|
||||||
+ CreateTransactionSuccess.json OK
|
+ CreateTransactionSuccess.json OK
|
||||||
+ EmptyTransaction3.json OK
|
+ EmptyTransaction3.json OK
|
||||||
+ HighGasLimit.json OK
|
+ HighGasLimit.json OK
|
||||||
|
@ -2294,7 +2352,7 @@ OK: 14/14 Fail: 0/14 Skip: 0/14
|
||||||
+ TransactionToAddressh160minusOne.json OK
|
+ TransactionToAddressh160minusOne.json OK
|
||||||
+ TransactionToItself.json OK
|
+ TransactionToItself.json OK
|
||||||
```
|
```
|
||||||
OK: 28/28 Fail: 0/28 Skip: 0/28
|
OK: 29/29 Fail: 0/29 Skip: 0/29
|
||||||
## stTransitionTest
|
## stTransitionTest
|
||||||
```diff
|
```diff
|
||||||
+ createNameRegistratorPerTxsAfter.json OK
|
+ 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
|
OK: 11/11 Fail: 0/11 Skip: 0/11
|
||||||
|
|
||||||
---TOTAL---
|
---TOTAL---
|
||||||
OK: 2517/2517 Fail: 0/2517 Skip: 0/2517
|
OK: 2571/2571 Fail: 0/2571 Skip: 0/2571
|
||||||
|
|
Loading…
Reference in New Issue