bump `nim-eth`, extend empty block fallback for EIP4844 (#4425)
Implements `emptyPayloadToBlockHeader` for EIP-4844. https://github.com/status-im/nim-eth/pull/570
This commit is contained in:
parent
c91d9d61e2
commit
2184fd2322
|
@ -459,10 +459,11 @@ OK: 1/1 Fail: 0/1 Skip: 0/1
|
|||
```diff
|
||||
+ build_empty_execution_payload - Bellatrix OK
|
||||
+ build_empty_execution_payload - Capella OK
|
||||
+ build_empty_execution_payload - EIP4844 OK
|
||||
+ build_proof - BeaconState OK
|
||||
+ integer_squareroot OK
|
||||
```
|
||||
OK: 4/4 Fail: 0/4 Skip: 0/4
|
||||
OK: 5/5 Fail: 0/5 Skip: 0/5
|
||||
## Specific field types
|
||||
```diff
|
||||
+ root update OK
|
||||
|
@ -614,4 +615,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
|
|||
OK: 9/9 Fail: 0/9 Skip: 0/9
|
||||
|
||||
---TOTAL---
|
||||
OK: 343/348 Fail: 0/348 Skip: 5/348
|
||||
OK: 344/349 Fail: 0/349 Skip: 5/349
|
||||
|
|
|
@ -77,6 +77,11 @@ type
|
|||
Capella,
|
||||
EIP4844
|
||||
|
||||
ForkyExecutionPayload* =
|
||||
bellatrix.ExecutionPayload |
|
||||
capella.ExecutionPayload |
|
||||
eip4844.ExecutionPayload
|
||||
|
||||
ForkyBeaconBlockBody* =
|
||||
phase0.BeaconBlockBody |
|
||||
altair.BeaconBlockBody |
|
||||
|
@ -444,6 +449,7 @@ template toFork*[T:
|
|||
BeaconBlockFork.Altair
|
||||
|
||||
template toFork*[T:
|
||||
bellatrix.ExecutionPayload |
|
||||
bellatrix.BeaconBlock |
|
||||
bellatrix.SignedBeaconBlock |
|
||||
bellatrix.TrustedBeaconBlock |
|
||||
|
@ -454,6 +460,7 @@ template toFork*[T:
|
|||
BeaconBlockFork.Bellatrix
|
||||
|
||||
template toFork*[T:
|
||||
capella.ExecutionPayload |
|
||||
capella.BeaconBlock |
|
||||
capella.SignedBeaconBlock |
|
||||
capella.TrustedBeaconBlock |
|
||||
|
@ -464,6 +471,7 @@ template toFork*[T:
|
|||
BeaconBlockFork.Capella
|
||||
|
||||
template toFork*[T:
|
||||
eip4844.ExecutionPayload |
|
||||
eip4844.BeaconBlock |
|
||||
eip4844.SignedBeaconBlock |
|
||||
eip4844.TrustedBeaconBlock |
|
||||
|
|
|
@ -19,7 +19,7 @@ import
|
|||
eth/eip1559, eth/common/[eth_types, eth_types_rlp],
|
||||
eth/rlp, eth/trie/[db, hexary],
|
||||
# Internal
|
||||
./datatypes/[phase0, altair, bellatrix, capella],
|
||||
./datatypes/[phase0, altair, bellatrix, capella, eip4844],
|
||||
"."/[eth2_merkleization, forks, ssz_codec]
|
||||
|
||||
# TODO although eth2_merkleization already exports ssz_codec, *sometimes* code
|
||||
|
@ -373,7 +373,7 @@ func compute_timestamp_at_slot*(state: ForkyBeaconState, slot: Slot): uint64 =
|
|||
state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT
|
||||
|
||||
proc computeTransactionsTrieRoot*(
|
||||
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload): Hash256 =
|
||||
payload: ForkyExecutionPayload): Hash256 =
|
||||
if payload.transactions.len == 0:
|
||||
return EMPTY_ROOT_HASH
|
||||
|
||||
|
@ -392,13 +392,13 @@ func toExecutionWithdrawal*(
|
|||
withdrawal: capella.Withdrawal): ExecutionWithdrawal =
|
||||
ExecutionWithdrawal(
|
||||
index: withdrawal.index,
|
||||
validatorIndex: withdrawal.validatorIndex,
|
||||
validatorIndex: withdrawal.validator_index,
|
||||
address: EthAddress withdrawal.address.data,
|
||||
amount: gweiToWei withdrawal.amount)
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-4895
|
||||
proc computeWithdrawalsTrieRoot*(
|
||||
payload: capella.ExecutionPayload): Hash256 =
|
||||
payload: capella.ExecutionPayload | eip4844.ExecutionPayload): Hash256 =
|
||||
if payload.withdrawals.len == 0:
|
||||
return EMPTY_ROOT_HASH
|
||||
|
||||
|
@ -411,8 +411,7 @@ proc computeWithdrawalsTrieRoot*(
|
|||
tr.rootHash()
|
||||
|
||||
proc payloadToBlockHeader*(
|
||||
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload
|
||||
): ExecutionBlockHeader =
|
||||
payload: ForkyExecutionPayload): ExecutionBlockHeader =
|
||||
static: # `GasInt` is signed. We only use it for hashing.
|
||||
doAssert sizeof(GasInt) == sizeof(payload.gas_limit)
|
||||
doAssert sizeof(GasInt) == sizeof(payload.gas_used)
|
||||
|
@ -420,10 +419,15 @@ proc payloadToBlockHeader*(
|
|||
let
|
||||
txRoot = payload.computeTransactionsTrieRoot()
|
||||
withdrawalsRoot =
|
||||
when payload is bellatrix.ExecutionPayload:
|
||||
none(Hash256)
|
||||
else:
|
||||
when typeof(payload).toFork >= BeaconBlockFork.Capella:
|
||||
some payload.computeWithdrawalsTrieRoot()
|
||||
else:
|
||||
none(Hash256)
|
||||
excessDataGas =
|
||||
when typeof(payload).toFork >= BeaconBlockFork.EIP4844:
|
||||
some payload.excess_data_gas
|
||||
else:
|
||||
none(UInt256)
|
||||
|
||||
ExecutionBlockHeader(
|
||||
parentHash : payload.parent_hash,
|
||||
|
@ -442,11 +446,11 @@ proc payloadToBlockHeader*(
|
|||
mixDigest : payload.prev_randao, # EIP-4399 `mixDigest` -> `prevRandao`
|
||||
nonce : default(BlockNonce),
|
||||
fee : some payload.base_fee_per_gas,
|
||||
withdrawalsRoot: withdrawalsRoot)
|
||||
withdrawalsRoot: withdrawalsRoot,
|
||||
excessDataGas : excessDataGas)
|
||||
|
||||
proc compute_execution_block_hash*(
|
||||
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload
|
||||
): Eth2Digest =
|
||||
payload: ForkyExecutionPayload): Eth2Digest =
|
||||
rlpHash payloadToBlockHeader(payload)
|
||||
|
||||
proc build_empty_execution_payload*(
|
||||
|
@ -481,7 +485,8 @@ proc build_empty_execution_payload*(
|
|||
proc build_empty_execution_payload*(
|
||||
state: capella.BeaconState,
|
||||
feeRecipient: Eth1Address,
|
||||
expectedWithdrawals = newSeq[capella.Withdrawal](0)): capella.ExecutionPayload =
|
||||
expectedWithdrawals = newSeq[capella.Withdrawal](0)
|
||||
): capella.ExecutionPayload =
|
||||
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
||||
## without any transactions.
|
||||
let
|
||||
|
@ -509,3 +514,52 @@ proc build_empty_execution_payload*(
|
|||
payload.block_hash = payload.compute_execution_block_hash()
|
||||
|
||||
payload
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-4844#parameters
|
||||
const
|
||||
TARGET_DATA_GAS_PER_BLOCK* = 1.u256 shl 18
|
||||
DATA_GAS_PER_BLOB* = 1.u256 shl 17
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-4844#header-extension
|
||||
func calc_excess_data_gas*(
|
||||
parent: eip4844.ExecutionPayloadHeader, new_blobs: uint): UInt256 =
|
||||
let consumed_data_gas = new_blobs.u256 * DATA_GAS_PER_BLOB
|
||||
return
|
||||
if parent.excess_data_gas + consumed_data_gas < TARGET_DATA_GAS_PER_BLOCK:
|
||||
0.u256
|
||||
else:
|
||||
parent.excess_data_gas + consumed_data_gas - TARGET_DATA_GAS_PER_BLOCK
|
||||
|
||||
proc build_empty_execution_payload*(
|
||||
state: eip4844.BeaconState,
|
||||
feeRecipient: Eth1Address,
|
||||
expectedWithdrawals = newSeq[capella.Withdrawal](0)
|
||||
): eip4844.ExecutionPayload =
|
||||
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
||||
## without any transactions.
|
||||
let
|
||||
latest = state.latest_execution_payload_header
|
||||
timestamp = compute_timestamp_at_slot(state, state.slot)
|
||||
randao_mix = get_randao_mix(state, get_current_epoch(state))
|
||||
base_fee = calcEip1599BaseFee(GasInt.saturate latest.gas_limit,
|
||||
GasInt.saturate latest.gas_used,
|
||||
latest.base_fee_per_gas)
|
||||
|
||||
var payload = eip4844.ExecutionPayload(
|
||||
parent_hash: latest.block_hash,
|
||||
fee_recipient: bellatrix.ExecutionAddress(data: distinctBase(feeRecipient)),
|
||||
state_root: latest.state_root, # no changes to the state
|
||||
receipts_root: EMPTY_ROOT_HASH,
|
||||
block_number: latest.block_number + 1,
|
||||
prev_randao: randao_mix,
|
||||
gas_limit: latest.gas_limit, # retain same limit
|
||||
gas_used: 0, # empty block, 0 gas
|
||||
timestamp: timestamp,
|
||||
base_fee_per_gas: base_fee,
|
||||
excess_data_gas: latest.calc_excess_data_gas(new_blobs = 0))
|
||||
for withdrawal in expectedWithdrawals:
|
||||
doAssert payload.withdrawals.add withdrawal
|
||||
|
||||
payload.block_hash = payload.compute_execution_block_hash()
|
||||
|
||||
payload
|
||||
|
|
|
@ -332,6 +332,7 @@ proc getFeeRecipient(node: BeaconNode,
|
|||
|
||||
from web3/engine_api_types import PayloadExecutionStatus
|
||||
from ../spec/datatypes/capella import BeaconBlock, ExecutionPayload
|
||||
from ../spec/datatypes/eip4844 import BeaconBlock, ExecutionPayload
|
||||
|
||||
proc getExecutionPayload[T](
|
||||
node: BeaconNode, proposalState: ref ForkedHashedBeaconState,
|
||||
|
@ -351,7 +352,9 @@ proc getExecutionPayload[T](
|
|||
# transmit this information through the Forked types, so this has to
|
||||
# be re-proven here.
|
||||
withState(proposalState[]):
|
||||
when (stateFork == BeaconStateFork.Capella and
|
||||
when (stateFork == BeaconStateFork.EIP4844 and
|
||||
T is eip4844.ExecutionPayload) or
|
||||
(stateFork == BeaconStateFork.Capella and
|
||||
T is capella.ExecutionPayload) or
|
||||
(stateFork == BeaconStateFork.Bellatrix and
|
||||
T is bellatrix.ExecutionPayload):
|
||||
|
|
|
@ -126,3 +126,29 @@ suite "Spec helpers":
|
|||
validatorIndex: 2,
|
||||
address: bellatrix.ExecutionAddress(data: distinctBase(recipient)),
|
||||
amount: 2.Gwei)]
|
||||
|
||||
test "build_empty_execution_payload - EIP4844":
|
||||
var cfg = defaultRuntimeConfig
|
||||
cfg.ALTAIR_FORK_EPOCH = GENESIS_EPOCH
|
||||
cfg.BELLATRIX_FORK_EPOCH = GENESIS_EPOCH
|
||||
cfg.CAPELLA_FORK_EPOCH = GENESIS_EPOCH
|
||||
cfg.EIP4844_FORK_EPOCH = GENESIS_EPOCH
|
||||
|
||||
let
|
||||
state = newClone(initGenesisState(cfg = cfg).eip4844Data)
|
||||
recipient = Eth1Address.fromHex(
|
||||
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")
|
||||
withdrawals = @[
|
||||
capella.Withdrawal(
|
||||
index: 42,
|
||||
validatorIndex: 1337,
|
||||
address: bellatrix.ExecutionAddress(data: distinctBase(recipient)),
|
||||
amount: 25.Gwei)]
|
||||
|
||||
payload = build_empty_execution_payload(
|
||||
state[].data, recipient, withdrawals)
|
||||
check:
|
||||
payload.fee_recipient ==
|
||||
bellatrix.ExecutionAddress(data: distinctBase(recipient))
|
||||
payload.withdrawals[0] == withdrawals[0]
|
||||
payload.excess_data_gas == 0.u256
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 571b98d7f77ad58294c4ba7c100b145a466c8fae
|
||||
Subproject commit 2b5f2a27e303b13127bb525b0c7a309eaa7fbed9
|
Loading…
Reference in New Issue