Implement EIP-4788: Beacon block root in the EVM (#1722)

* Implement EIP-4788: Beacon block root in the EVM

* EIP-4788: Fix genesis.parentBeaconBlockRoot initialization
This commit is contained in:
andri lim 2023-08-30 23:29:48 +07:00 committed by GitHub
parent 57a22bbfab
commit 96fb355efe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 357 additions and 21 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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)

View File

@ -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 =

View File

@ -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.} =

View File

@ -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.

View File

@ -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

View File

@ -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].} =

View File

@ -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 =

View File

@ -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)

View File

@ -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() =

View File

@ -15,5 +15,6 @@
}
],
"parentBlobGasUsed": "0x100",
"parentExcessBlobGas": "0x100"
"parentExcessBlobGas": "0x100",
"parentBeaconBlockRoot" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
}

View File

@ -16,7 +16,7 @@
"gasUsed": "0x0",
"currentBaseFee": "0x500",
"withdrawalsRoot": "0x4921c0162c359755b2ae714a0978a1dad2eb8edce7ff9b38b9b6fc4cbc547eb5",
"blobGasUsed": "0x0",
"excessBlobGas": "0x0"
"currentBlobGasUsed": "0x0",
"currentExcessBlobGas": "0x0"
}
}

View File

@ -8,6 +8,6 @@
"currentTimestamp" : "0x03e8",
"parentBlobGasUsed" : "0x2000",
"parentExcessBlobGas" : "0x1000",
"previousHash" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"parentBeaconBlockRoot" : "0x5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
"withdrawals": []
}

16
tools/t8n/testdata/28/alloc.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x016345785d8a0000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x016345785d8a0000",
"code" : "0x60004960015500",
"nonce" : "0x00",
"storage" : {
}
}
}

23
tools/t8n/testdata/28/env.json vendored Normal file
View File

@ -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"
}

46
tools/t8n/testdata/28/exp.json vendored Normal file
View File

@ -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"
}
}

1
tools/t8n/testdata/28/txs.rlp vendored Normal file
View File

@ -0,0 +1 @@
"0xf88bb88903f8860180026483061a8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b8080c00ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d801a025e16bb498552165016751911c3608d79000ab89dc3100776e729e6ea13091c7a03acacff7fc0cff6eda8a927dec93ca17765e1ee6cbc06c5954ce102e097c01d2"

16
tools/t8n/testdata/29/alloc.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x016345785d8a0000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xbEac00dDB15f3B6d645C48263dC93862413A222D" : {
"balance" : "0x1",
"code" : "0x3373fffffffffffffffffffffffffffffffffffffffe14604457602036146024575f5ffd5b620180005f350680545f35146037575f5ffd5b6201800001545f5260205ff35b6201800042064281555f359062018000015500",
"nonce" : "0x00",
"storage" : {
}
}
}

20
tools/t8n/testdata/29/env.json vendored Normal file
View File

@ -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"
}

44
tools/t8n/testdata/29/exp.json vendored Normal file
View File

@ -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"
}
}

29
tools/t8n/testdata/29/readme.md vendored Normal file
View File

@ -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
}
}
}
```

19
tools/t8n/testdata/29/txs.json vendored Normal file
View File

@ -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" : [
]
}
]

View File

@ -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:

View File

@ -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