diff --git a/nimbus/beacon/beacon_engine.nim b/nimbus/beacon/beacon_engine.nim index 69118cd2d..69096740b 100644 --- a/nimbus/beacon/beacon_engine.nim +++ b/nimbus/beacon/beacon_engine.nim @@ -155,6 +155,9 @@ proc generatePayload*(ben: BeaconEngineRef, pos.prevRandao = ethHash attrs.prevRandao pos.timestamp = ethTime attrs.timestamp pos.feeRecipient = ethAddr attrs.suggestedFeeRecipient + + if attrs.parentBeaconBlockRoot.isSome: + pos.parentBeaconBlockRoot = ethHash attrs.parentBeaconBlockRoot.get xp.setWithdrawals(attrs) diff --git a/nimbus/common/chain_config.nim b/nimbus/common/chain_config.nim index f808d3c54..ec6ecdd55 100644 --- a/nimbus/common/chain_config.nim +++ b/nimbus/common/chain_config.nim @@ -37,6 +37,7 @@ type baseFeePerGas*: Option[UInt256] blobGasUsed* : Option[uint64] # EIP-4844 excessBlobGas*: Option[uint64] # EIP-4844 + parentBeaconBlockRoot*: Option[Hash256] # EIP-4788 GenesisAlloc* = Table[EthAddress, GenesisAccount] GenesisAccount* = object @@ -69,6 +70,7 @@ type baseFeePerGas*: Option[UInt256] blobGasUsed* : Option[uint64] # EIP-4844 excessBlobGas*: Option[uint64] # EIP-4844 + parentBeaconBlockRoot*: Option[Hash256] # EIP-4788 const CustomNet* = 0.NetworkId diff --git a/nimbus/common/genesis.nim b/nimbus/common/genesis.nim index 94b91498c..bdbad14a0 100644 --- a/nimbus/common/genesis.nim +++ b/nimbus/common/genesis.nim @@ -83,6 +83,7 @@ proc toGenesisHeader*( if fork >= Cancun: result.blobGasUsed = g.blobGasUsed result.excessBlobGas = g.excessBlobGas + result.parentBeaconBlockRoot = g.parentBeaconBlockRoot proc toGenesisHeader*( genesis: Genesis; diff --git a/nimbus/constants.nim b/nimbus/constants.nim index 6d95322c4..305cd7465 100644 --- a/nimbus/constants.nim +++ b/nimbus/constants.nim @@ -1,6 +1,7 @@ {.used.} import + stew/byteutils, eth/common/eth_types # proc default(t: typedesc): t = discard -- notused @@ -85,4 +86,10 @@ const MAX_BLOB_GAS_PER_BLOCK* = 786432 MAX_ALLOWED_BLOB* = MAX_BLOB_GAS_PER_BLOCK div GAS_PER_BLOB + # EIP-4788 addresses + # BeaconRootsStorageAddress is the address where historical beacon roots are stored as per EIP-4788 + BeaconRootsStorageAddress* = hexToByteArray[20]("0xbEac00dDB15f3B6d645C48263dC93862413A222D") + # SystemAddress is where the system-transaction is sent from as per EIP-4788 + SystemAddress* = hexToByteArray[20]("0xfffffffffffffffffffffffffffffffffffffffe") + # End diff --git a/nimbus/core/casper.nim b/nimbus/core/casper.nim index 01e0e412e..fe8df6d01 100644 --- a/nimbus/core/casper.nim +++ b/nimbus/core/casper.nim @@ -14,6 +14,7 @@ type feeRecipient : EthAddress timestamp : EthTime prevRandao : Hash256 + parentBeaconBlockRoot: Hash256 proc prepare*(ctx: CasperRef, header: var BlockHeader) = header.coinbase = ctx.feeRecipient @@ -40,6 +41,9 @@ func timestamp*(ctx: CasperRef): EthTime = func prevRandao*(ctx: CasperRef): Hash256 = ctx.prevRandao +func parentBeaconBlockRoot*(ctx: CasperRef): Hash256 = + ctx.parentBeaconBlockRoot + # ------------------------------------------------------------------------------ # Setters # ------------------------------------------------------------------------------ @@ -52,3 +56,6 @@ proc `timestamp=`*(ctx: CasperRef, val: EthTime) = proc `prevRandao=`*(ctx: CasperRef, val: Hash256) = ctx.prevRandao = val + +proc `parentBeaconBlockRoot=`*(ctx: CasperRef, val: Hash256) = + ctx.parentBeaconBlockRoot = val diff --git a/nimbus/core/executor/process_block.nim b/nimbus/core/executor/process_block.nim index 1763ce2c2..40d59a5ff 100644 --- a/nimbus/core/executor/process_block.nim +++ b/nimbus/core/executor/process_block.nim @@ -34,6 +34,11 @@ proc processTransactions*(vmState: BaseVMState; {.gcsafe, raises: [CatchableError].} = vmState.receipts = newSeq[Receipt](transactions.len) vmState.cumulativeGasUsed = 0 + + if header.parentBeaconBlockRoot.isSome: + vmState.processBeaconBlockRoot(header.parentBeaconBlockRoot.get).isOkOr: + return err(error) + for txIndex, tx in transactions: var sender: EthAddress if not tx.getSender(sender): @@ -58,6 +63,13 @@ proc procBlkPreamble(vmState: BaseVMState; blockNumber = header.blockNumber return false + if vmState.determineFork >= FkCancun: + if header.parentBeaconBlockRoot.isNone: + raise ValidationError.newException("Post-Cancun block header must have parentBeaconBlockRoot") + else: + if header.parentBeaconBlockRoot.isSome: + raise ValidationError.newException("Pre-Cancun block header must not have parentBeaconBlockRoot") + if header.txRoot != EMPTY_ROOT_HASH: if body.transactions.len == 0: debug "No transactions in body", diff --git a/nimbus/core/executor/process_transaction.nim b/nimbus/core/executor/process_transaction.nim index 66c734a86..2b68e1ada 100644 --- a/nimbus/core/executor/process_transaction.nim +++ b/nimbus/core/executor/process_transaction.nim @@ -15,10 +15,12 @@ import ../../common/common, ../../db/accounts_cache, ../../transaction/call_evm, + ../../transaction/call_common, ../../transaction, ../../vm_state, ../../vm_types, ../../evm/async/operations, + ../../constants, ../validate, chronos, stew/results @@ -129,6 +131,43 @@ proc asyncProcessTransactionImpl( # Public functions # ------------------------------------------------------------------------------ +proc processBeaconBlockRoot*(vmState: BaseVMState, beaconRoot: Hash256): + Result[void, string] {.raises: [CatchableError].} = + ## processBeaconBlockRoot applies the EIP-4788 system call to the + ## beacon block root contract. This method is exported to be used in tests. + ## If EIP-4788 is enabled, we need to invoke the beaconroot storage + ## contract with the new root. + let + statedb = vmState.stateDB + call = CallParams( + vmState: vmState, + sender: SystemAddress, + gasLimit: 30_000_000.GasInt, + gasPrice: 0.GasInt, + to: BeaconRootsStorageAddress, + input: @(beaconRoot.data), + ) + + # runComputation a.k.a syscall/evm.call + if call.runComputation().isError: + return err("processBeaconBlockRoot: syscall error") + + # We can choose to set SystemAddress nonce to 0 + # like erigon or geth(their EVM have explicit nonce set) + # or we delete the account manually instead of let it deleted + # by AccountsCache.persist. + statedb.deleteAccount(SystemAddress) + + when false: + # nimbus EVM automatically increase sender nonce by one + # for each call/create. + statedb.setNonce(SystemAddress, 0) + # statedb.persist probably not needed as each processTransaction + # will call it. + statedb.persist(clearEmptyAccount = true, clearCache = false) + + ok() + proc asyncProcessTransaction*( vmState: BaseVMState; ## Parent accounts environment for transaction tx: Transaction; ## Transaction to validate diff --git a/nimbus/core/tx_pool/tx_chain.nim b/nimbus/core/tx_pool/tx_chain.nim index eeaa5cc8f..19da288aa 100644 --- a/nimbus/core/tx_pool/tx_chain.nim +++ b/nimbus/core/tx_pool/tx_chain.nim @@ -230,6 +230,9 @@ proc getHeader*(dh: TxChainRef): BlockHeader if dh.com.forkGTE(Shanghai): result.withdrawalsRoot = some(calcWithdrawalsRoot(dh.withdrawals)) + if dh.com.forkGTE(Cancun): + result.parentBeaconBlockRoot = some(dh.com.pos.parentBeaconBlockRoot) + dh.prepareForSeal(result) proc clearAccounts*(dh: TxChainRef) diff --git a/nimbus/db/accounts_cache.nim b/nimbus/db/accounts_cache.nim index 67bbc5fd3..43b45f9b6 100644 --- a/nimbus/db/accounts_cache.nim +++ b/nimbus/db/accounts_cache.nim @@ -670,7 +670,7 @@ func witnessData(acc: RefAccount): WitnessData = result.storageKeys = initHashSet[UInt256]() update(result, acc) -proc collectWitnessData*(ac: var AccountsCache) = +proc collectWitnessData*(ac: AccountsCache) = # make sure all savepoint already committed doAssert(ac.savePoint.parentSavepoint.isNil) # usually witness data is collected before we call persist() @@ -694,10 +694,10 @@ proc makeMultiKeys*(ac: AccountsCache): MultikeysRef = result.add(k, v.codeTouched, multiKeys(v.storageKeys)) result.sort() -proc accessList*(ac: var AccountsCache, address: EthAddress) {.inline.} = +proc accessList*(ac: AccountsCache, address: EthAddress) {.inline.} = ac.savePoint.accessList.add(address) -proc accessList*(ac: var AccountsCache, address: EthAddress, slot: UInt256) {.inline.} = +proc accessList*(ac: AccountsCache, address: EthAddress, slot: UInt256) {.inline.} = ac.savePoint.accessList.add(address, slot) func inAccessList*(ac: AccountsCache, address: EthAddress): bool = diff --git a/nimbus/graphql/ethapi.nim b/nimbus/graphql/ethapi.nim index 43efceefa..00c00250a 100644 --- a/nimbus/graphql/ethapi.nim +++ b/nimbus/graphql/ethapi.nim @@ -1158,6 +1158,14 @@ proc blockexcessBlobGas(ud: RootRef, params: Args, parent: Node): RespResult {.a else: ok(respNull()) +proc blockParentBeaconBlockRoot(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} = + let h = HeaderNode(parent) + if h.header.parentBeaconBlockRoot.isSome: + resp(h.header.parentBeaconBlockRoot.get) + else: + ok(respNull()) + + const blockProcs = { "parent": blockParent, "number": blockNumberImpl, @@ -1190,7 +1198,8 @@ const blockProcs = { "withdrawalsRoot": blockWithdrawalsRoot, "withdrawals": blockWithdrawals, "blobGasUsed": blockBlobGasUsed, - "excessBlobGas": blockExcessBlobGas + "excessBlobGas": blockExcessBlobGas, + "parentBeaconBlockRoot": blockParentBeaconBlockRoot, } proc callResultData(ud: RootRef, params: Args, parent: Node): RespResult {.apiPragma.} = diff --git a/nimbus/graphql/ethapi.ql b/nimbus/graphql/ethapi.ql index 5329209c4..517f7a22d 100644 --- a/nimbus/graphql/ethapi.ql +++ b/nimbus/graphql/ethapi.ql @@ -339,6 +339,10 @@ type Block { # (bounded at 0). excessBlobGas: Long + # EIP-4788: This root consumes 32 bytes and is exactly the hash tree root + # of the parent beacon block for the given execution block. + parentBeaconBlockRoot: Bytes32 + #--------------------------Extensions------------------------------- # RawHeader is the RLP encoding of the block's header. diff --git a/nimbus/rpc/rpc_types.nim b/nimbus/rpc/rpc_types.nim index 1a021d89b..8be2b0595 100644 --- a/nimbus/rpc/rpc_types.nim +++ b/nimbus/rpc/rpc_types.nim @@ -66,7 +66,7 @@ type difficulty*: HexQuantityStr # integer of the difficulty for this block. totalDifficulty*: HexQuantityStr # integer of the total difficulty of the chain until this block. extraData*: HexDataStr # the "extra data" field of this block. - mixHash*: Hash256 + mixHash*: Hash256 size*: HexQuantityStr # integer the size of this block in bytes. gasLimit*: HexQuantityStr # the maximum gas allowed in this block. gasUsed*: HexQuantityStr # the total used gas by all transactions in this block. @@ -78,6 +78,7 @@ type withdrawalsRoot*: Option[Hash256] # EIP-4895 blobGasUsed*: Option[HexQuantityStr] # EIP-4844 excessBlobGas*: Option[HexQuantityStr] # EIP-4844 + parentBeaconBlockRoot*: Option[Hash256] # EIP-4788 TransactionObject* = object # A transaction object, or null when no transaction was found: # Returned to user @@ -97,7 +98,7 @@ type value*: HexQuantityStr # value transferred in Wei. v*: HexQuantityStr # ECDSA recovery id r*: HexQuantityStr # 32 Bytes - ECDSA signature r - s*: HexQuantityStr # 32 Bytes - ECDSA signature s + s*: HexQuantityStr # 32 Bytes - ECDSA signature s chainId*: Option[HexQuantityStr] # EIP-159 accessList*: Option[seq[AccessTuple]] # EIP-2930 maxFeePerBlobGas*: Option[HexQuantityStr] # EIP-4844 diff --git a/nimbus/rpc/rpc_utils.nim b/nimbus/rpc/rpc_utils.nim index 2b0400e0a..d92082741 100644 --- a/nimbus/rpc/rpc_utils.nim +++ b/nimbus/rpc/rpc_utils.nim @@ -244,6 +244,8 @@ proc populateBlockObject*(header: BlockHeader, chain: CoreDbRef, fullTx: bool, i if header.excessBlobGas.isSome: result.excessBlobGas = some(encodeQuantity(header.excessBlobGas.get)) + result.parentBeaconBlockRoot = header.parentBeaconBlockRoot + proc populateReceipt*(receipt: Receipt, gasUsed: GasInt, tx: Transaction, txIndex: int, header: BlockHeader): ReceiptObject {.gcsafe, raises: [ValidationError].} = diff --git a/tools/evmstate/helpers.nim b/tools/evmstate/helpers.nim index d26052a08..ffc9a27e0 100644 --- a/tools/evmstate/helpers.nim +++ b/tools/evmstate/helpers.nim @@ -115,7 +115,8 @@ proc parseHeader*(n: JsonNode): BlockHeader = mixDigest : omitZero(Hash256, "currentRandom"), fee : optional(UInt256, "currentBaseFee"), excessBlobGas: optional(uint64, "excessBlobGas"), - blobGasUsed: optional(uint64, "blobGasUsed") + blobGasUsed: optional(uint64, "blobGasUsed"), + parentBeaconBlockRoot: optional(Hash256, "parentBeaconBlockRoot"), ) proc parseTx*(n: JsonNode, dataIndex, gasIndex, valueIndex: int): Transaction = diff --git a/tools/t8n/helpers.nim b/tools/t8n/helpers.nim index 7eb82eafd..9f7c1b5af 100644 --- a/tools/t8n/helpers.nim +++ b/tools/t8n/helpers.nim @@ -183,6 +183,7 @@ proc parseEnv*(ctx: var TransContext, n: JsonNode) = optional(ctx.env, uint64, currentExcessBlobGas) optional(ctx.env, uint64, parentBlobGasUsed) optional(ctx.env, uint64, parentExcessBlobGas) + optional(ctx.env, Hash256, parentBeaconBlockRoot) if n.hasKey("blockHashes"): let w = n["blockHashes"] @@ -442,7 +443,7 @@ proc `@@`*(x: ExecutionResult): JsonNode = result["currentBaseFee"] = @@(x.currentBaseFee) if x.withdrawalsRoot.isSome: result["withdrawalsRoot"] = @@(x.withdrawalsRoot) - if x.blobGasUsed.isSome: - result["blobGasUsed"] = @@(x.blobGasUsed) - if x.excessBlobGas.isSome: - result["excessBlobGas"] = @@(x.excessBlobGas) + if x.currentBlobGasUsed.isSome: + result["currentBlobGasUsed"] = @@(x.currentBlobGasUsed) + if x.currentExcessBlobGas.isSome: + result["currentExcessBlobGas"] = @@(x.currentExcessBlobGas) diff --git a/tools/t8n/t8n_test.nim b/tools/t8n/t8n_test.nim index feff82447..d19d93dfe 100644 --- a/tools/t8n/t8n_test.nim +++ b/tools/t8n/t8n_test.nim @@ -524,6 +524,24 @@ const output: T8nOutput(trace: true, result: true), expOut: "exp.txt", ), + TestSpec( + name : "Cancun tests", + base : "testdata/28", + input : t8nInput( + "alloc.json", "txs.rlp", "env.json", "Cancun", "", + ), + output: T8nOutput(alloc: true, result: true), + expOut: "exp.json", + ), + TestSpec( + name : "More cancun tests", + base : "/testdata/29", + input : t8nInput( + "alloc.json", "txs.json", "env.json", "Cancun", "", + ), + output: T8nOutput(alloc: true, result: true), + expOut: "exp.json", + ), ] proc main() = diff --git a/tools/t8n/testdata/00-517/env.json b/tools/t8n/testdata/00-517/env.json index b07d44f70..363463a94 100644 --- a/tools/t8n/testdata/00-517/env.json +++ b/tools/t8n/testdata/00-517/env.json @@ -15,5 +15,6 @@ } ], "parentBlobGasUsed": "0x100", - "parentExcessBlobGas": "0x100" + "parentExcessBlobGas": "0x100", + "parentBeaconBlockRoot" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", } diff --git a/tools/t8n/testdata/00-517/exp.json b/tools/t8n/testdata/00-517/exp.json index b27eabd64..7d99d6a6e 100644 --- a/tools/t8n/testdata/00-517/exp.json +++ b/tools/t8n/testdata/00-517/exp.json @@ -16,7 +16,7 @@ "gasUsed": "0x0", "currentBaseFee": "0x500", "withdrawalsRoot": "0x4921c0162c359755b2ae714a0978a1dad2eb8edce7ff9b38b9b6fc4cbc547eb5", - "blobGasUsed": "0x0", - "excessBlobGas": "0x0" + "currentBlobGasUsed": "0x0", + "currentExcessBlobGas": "0x0" } } diff --git a/tools/t8n/testdata/00-518/env.json b/tools/t8n/testdata/00-518/env.json index acb30c5ad..0b5a0cc8d 100644 --- a/tools/t8n/testdata/00-518/env.json +++ b/tools/t8n/testdata/00-518/env.json @@ -8,6 +8,6 @@ "currentTimestamp" : "0x03e8", "parentBlobGasUsed" : "0x2000", "parentExcessBlobGas" : "0x1000", - "previousHash" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", + "parentBeaconBlockRoot" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", "withdrawals": [] } diff --git a/tools/t8n/testdata/28/alloc.json b/tools/t8n/testdata/28/alloc.json new file mode 100644 index 000000000..680a89f4e --- /dev/null +++ b/tools/t8n/testdata/28/alloc.json @@ -0,0 +1,16 @@ +{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x016345785d8a0000", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + }, + "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x016345785d8a0000", + "code" : "0x60004960015500", + "nonce" : "0x00", + "storage" : { + } + } +} \ No newline at end of file diff --git a/tools/t8n/testdata/28/env.json b/tools/t8n/testdata/28/env.json new file mode 100644 index 000000000..5056fe29a --- /dev/null +++ b/tools/t8n/testdata/28/env.json @@ -0,0 +1,23 @@ +{ + "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentNumber" : "0x01", + "currentTimestamp" : "0x079e", + "currentGasLimit" : "0x7fffffffffffffff", + "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6", + "currentBlobGasUsed" : "0x00", + "parentTimestamp" : "0x03b6", + "parentDifficulty" : "0x00", + "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "withdrawals" : [ + ], + "parentBaseFee" : "0x0a", + "parentGasUsed" : "0x00", + "parentGasLimit" : "0x7fffffffffffffff", + "parentExcessBlobGas" : "0x00", + "parentBlobGasUsed" : "0x00", + "blockHashes" : { + "0" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6" + }, + "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" +} \ No newline at end of file diff --git a/tools/t8n/testdata/28/exp.json b/tools/t8n/testdata/28/exp.json new file mode 100644 index 000000000..f0e7e7fa8 --- /dev/null +++ b/tools/t8n/testdata/28/exp.json @@ -0,0 +1,46 @@ +{ + "alloc": { + "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba": { + "balance": "0x150ca" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x16345785d80c3a9", + "nonce": "0x1" + }, + "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "code": "0x60004960015500", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x01a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8" + }, + "balance": "0x16345785d8a0000" + } + }, + "result": { + "stateRoot": "0xa40cb3fab01848e922a48bd24191815df9f721ad4b60376edac75161517663e8", + "txRoot": "0x4409cc4b699384ba5f8248d92b784713610c5ff9c1de51e9239da0dac76de9ce", + "receiptsRoot": "0xbff643da765981266133094092d98c81d2ac8e9a83a7bbda46c3d736f1f874ac", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [ + { + "type": "0x3", + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0xa865", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x7508d7139d002a4b3a26a4f12dec0d87cb46075c78bf77a38b569a133b509262", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0xa865", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + } + ], + "currentDifficulty": null, + "gasUsed": "0xa865", + "currentBaseFee": "0x9", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "currentExcessBlobGas": "0x0", + "currentBlobGasUsed": "0x20000" + } +} \ No newline at end of file diff --git a/tools/t8n/testdata/28/txs.rlp b/tools/t8n/testdata/28/txs.rlp new file mode 100644 index 000000000..8df20e3aa --- /dev/null +++ b/tools/t8n/testdata/28/txs.rlp @@ -0,0 +1 @@ +"0xf88bb88903f8860180026483061a8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b8080c00ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d801a025e16bb498552165016751911c3608d79000ab89dc3100776e729e6ea13091c7a03acacff7fc0cff6eda8a927dec93ca17765e1ee6cbc06c5954ce102e097c01d2" \ No newline at end of file diff --git a/tools/t8n/testdata/29/alloc.json b/tools/t8n/testdata/29/alloc.json new file mode 100644 index 000000000..70d47862a --- /dev/null +++ b/tools/t8n/testdata/29/alloc.json @@ -0,0 +1,16 @@ +{ + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "0x016345785d8a0000", + "code" : "0x", + "nonce" : "0x00", + "storage" : { + } + }, + "0xbEac00dDB15f3B6d645C48263dC93862413A222D" : { + "balance" : "0x1", + "code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "nonce" : "0x00", + "storage" : { + } + } +} \ No newline at end of file diff --git a/tools/t8n/testdata/29/env.json b/tools/t8n/testdata/29/env.json new file mode 100644 index 000000000..e752a909a --- /dev/null +++ b/tools/t8n/testdata/29/env.json @@ -0,0 +1,20 @@ +{ + "currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", + "currentNumber" : "0x01", + "currentTimestamp" : "0x079e", + "currentGasLimit" : "0x7fffffffffffffff", + "previousHash" : "0x3a9b485972e7353edd9152712492f0c58d89ef80623686b6bf947a4a6dce6cb6", + "currentBlobGasUsed" : "0x00", + "parentTimestamp" : "0x03b6", + "parentDifficulty" : "0x00", + "parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "currentRandom" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "withdrawals" : [ + ], + "parentBaseFee" : "0x0a", + "parentGasUsed" : "0x00", + "parentGasLimit" : "0x7fffffffffffffff", + "parentExcessBlobGas" : "0x00", + "parentBlobGasUsed" : "0x00", + "parentBeaconBlockRoot": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" +} \ No newline at end of file diff --git a/tools/t8n/testdata/29/exp.json b/tools/t8n/testdata/29/exp.json new file mode 100644 index 000000000..ddff4e879 --- /dev/null +++ b/tools/t8n/testdata/29/exp.json @@ -0,0 +1,44 @@ +{ + "alloc": { + "0xbeac00ddb15f3b6d645c48263dc93862413a222d": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", + "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" + }, + "balance": "0x1" + }, + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x16345785d871db8", + "nonce": "0x1" + } + }, + "result": { + "stateRoot": "0x2db9f6bc233e8fd0af2d8023404493a19b37d9d69ace71f4e73158851fced574", + "txRoot": "0x248074fabe112f7d93917f292b64932394f835bb98da91f21501574d58ec92ab", + "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", + "logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receipts": [ + { + "type": "0x2", + "root": "0x", + "status": "0x1", + "cumulativeGasUsed": "0x5208", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logs": null, + "transactionHash": "0x84f70aba406a55628a0620f26d260f90aeb6ccc55fed6ec2ac13dd4f727032ed", + "contractAddress": "0x0000000000000000000000000000000000000000", + "gasUsed": "0x5208", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionIndex": "0x0" + } + ], + "currentDifficulty": null, + "gasUsed": "0x5208", + "currentBaseFee": "0x9", + "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "currentExcessBlobGas": "0x0", + "currentBlobGasUsed": "0x0" + } +} \ No newline at end of file diff --git a/tools/t8n/testdata/29/readme.md b/tools/t8n/testdata/29/readme.md new file mode 100644 index 000000000..4383e328e --- /dev/null +++ b/tools/t8n/testdata/29/readme.md @@ -0,0 +1,29 @@ +## EIP 4788 + +This test contains testcases for EIP-4788. The 4788-contract is +located at address `0xbeac00ddb15f3b6d645c48263dc93862413a222d`, and this test executes a simple transaction. It also +implicitly invokes the system tx, which sets calls the contract and sets the +storage values +``` +$ dir=./testdata/29/ && go run . t8n --state.fork=Cancun --input.alloc=$dir/alloc.json --input.txs=$dir/txs.json --input.env=$dir/env.json --output.alloc=stdout +INFO [08-15|20:07:56.335] Trie dumping started root=ecde45..2af8a7 +INFO [08-15|20:07:56.335] Trie dumping complete accounts=2 elapsed="225.848µs" +INFO [08-15|20:07:56.335] Wrote file file=result.json +{ + "alloc": { + "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0x16345785d871db8", + "nonce": "0x1" + }, + "0xbeac00541d49391ed88abf392bfc1f4dea8c4143": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500", + "storage": { + "0x000000000000000000000000000000000000000000000000000000000000079e": "0x000000000000000000000000000000000000000000000000000000000000079e", + "0x000000000000000000000000000000000000000000000000000000000001879e": "0x0000beac00beac00beac00beac00beac00beac00beac00beac00beac00beac00" + }, + "balance": "0x + } + } +} + +``` diff --git a/tools/t8n/testdata/29/txs.json b/tools/t8n/testdata/29/txs.json new file mode 100644 index 000000000..d6743cc4d --- /dev/null +++ b/tools/t8n/testdata/29/txs.json @@ -0,0 +1,19 @@ +[ + { + "input" : "0x", + "gas" : "0x10000000", + "nonce" : "0x0", + "to" : "0x1111111111111111111111111111111111111111", + "value" : "0x0", + "secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "chainId" : "0x1", + "type" : "0x2", + "v": "0x0", + "r": "0x0", + "s": "0x0", + "maxFeePerGas" : "0xfa0", + "maxPriorityFeePerGas" : "0x0", + "accessList" : [ + ] + } +] \ No newline at end of file diff --git a/tools/t8n/transition.nim b/tools/t8n/transition.nim index 430d1e91b..9945bba65 100644 --- a/tools/t8n/transition.nim +++ b/tools/t8n/transition.nim @@ -101,7 +101,7 @@ proc envToHeader(env: EnvStruct): BlockHeader = fee : env.currentBaseFee, withdrawalsRoot: env.withdrawals.calcWithdrawalsRoot(), blobGasUsed: env.currentBlobGasUsed, - excessBlobGas: env.currentExcessBlobGas + excessBlobGas: env.currentExcessBlobGas, ) proc postState(db: AccountsCache, alloc: var GenesisAlloc) = @@ -217,6 +217,10 @@ proc exec(ctx: var TransContext, vmState.receipts = newSeqOfCap[Receipt](txList.len) vmState.cumulativeGasUsed = 0 + if ctx.env.parentBeaconBlockRoot.isSome: + vmState.processBeaconBlockRoot(ctx.env.parentBeaconBlockRoot.get).isOkOr: + raise newError(ErrorConfig, error) + var blobGasUsed = 0'u64 for txIndex, txRes in txList: if txRes.isErr: @@ -306,8 +310,8 @@ proc exec(ctx: var TransContext, ) if fork >= FkCancun: - result.result.blobGasUsed = some blobGasUsed - result.result.excessBlobGas = some calcExcessBlobGas(vmState.parent) + result.result.currentBlobGasUsed = some blobGasUsed + result.result.currentExcessBlobGas = some calcExcessBlobGas(vmState.parent) template wrapException(body: untyped) = when wrapExceptionEnabled: @@ -413,7 +417,7 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) = ommersHash: uncleHash, blockNumber: ctx.env.currentNumber - 1.toBlockNumber, blobGasUsed: ctx.env.parentBlobGasUsed, - excessBlobGas: ctx.env.parentExcessBlobGas + excessBlobGas: ctx.env.parentExcessBlobGas, ) # Sanity check, to not `panic` in state_transition @@ -436,9 +440,15 @@ proc transitionAction*(ctx: var TransContext, conf: T8NConf) = if ctx.env.parentExcessBlobGas.isNone: raise newError(ErrorConfig, "Cancun config but missing 'parentExcessBlobGas' in env section") + if ctx.env.parentBeaconBlockRoot.isNone: + raise newError(ErrorConfig, "Cancun config but missing 'parentBeaconBlockRoot' in env section") + let res = loadKzgTrustedSetup() if res.isErr: raise newError(ErrorConfig, res.error) + else: + # un-set it if it has been set too early + ctx.env.parentBeaconBlockRoot = none(Hash256) if com.forkGTE(MergeFork): if ctx.env.currentRandom.isNone: diff --git a/tools/t8n/types.nim b/tools/t8n/types.nim index 48a127024..700d5c428 100644 --- a/tools/t8n/types.nim +++ b/tools/t8n/types.nim @@ -48,6 +48,7 @@ type currentExcessBlobGas*: Option[uint64] parentBlobGasUsed*: Option[uint64] parentExcessBlobGas*: Option[uint64] + parentBeaconBlockRoot*: Option[Hash256] TxsType* = enum TxsNone @@ -96,8 +97,8 @@ type gasUsed*: GasInt currentBaseFee*: Option[UInt256] withdrawalsRoot*: Option[Hash256] - blobGasUsed*: Option[uint64] - excessBlobGas*: Option[uint64] + currentBlobGasUsed*: Option[uint64] + currentExcessBlobGas*: Option[uint64] const ErrorEVM* = 2.T8NExitCode