Fix the block header computation when proposing an empty execution payload (#3991)
* Fix the block header computation when proposing an empty execution payload * Spec compliant base fee calculation when producing empty payloads
This commit is contained in:
parent
b5b93e90c0
commit
a7192f5d6c
|
@ -14,10 +14,11 @@ else:
|
||||||
|
|
||||||
import
|
import
|
||||||
# Standard lib
|
# Standard lib
|
||||||
std/[algorithm, math, sets, tables],
|
std/[algorithm, math, sets, tables, times],
|
||||||
# Status libraries
|
# Status libraries
|
||||||
stew/[bitops2, byteutils, endians2, objects],
|
stew/[bitops2, byteutils, endians2, objects, saturation_arith],
|
||||||
chronicles,
|
chronicles,
|
||||||
|
eth/eip1559, eth/common/eth_types,
|
||||||
# Internal
|
# Internal
|
||||||
./datatypes/[phase0, altair, bellatrix],
|
./datatypes/[phase0, altair, bellatrix],
|
||||||
"."/[eth2_merkleization, forks, ssz_codec]
|
"."/[eth2_merkleization, forks, ssz_codec]
|
||||||
|
@ -27,9 +28,12 @@ import
|
||||||
export
|
export
|
||||||
forks, eth2_merkleization, ssz_codec
|
forks, eth2_merkleization, ssz_codec
|
||||||
|
|
||||||
type FinalityCheckpoints* = object
|
type
|
||||||
justified*: Checkpoint
|
ExecutionBlockHeader = eth_types.BlockHeader
|
||||||
finalized*: Checkpoint
|
|
||||||
|
FinalityCheckpoints* = object
|
||||||
|
justified*: Checkpoint
|
||||||
|
finalized*: Checkpoint
|
||||||
|
|
||||||
func shortLog*(v: FinalityCheckpoints): auto =
|
func shortLog*(v: FinalityCheckpoints): auto =
|
||||||
(
|
(
|
||||||
|
@ -340,7 +344,29 @@ func compute_timestamp_at_slot*(state: ForkyBeaconState, slot: Slot): uint64 =
|
||||||
let slots_since_genesis = slot - GENESIS_SLOT
|
let slots_since_genesis = slot - GENESIS_SLOT
|
||||||
state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT
|
state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT
|
||||||
|
|
||||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.10/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py#L1-L31
|
proc emptyPayloadToBlockHeader*(payload: ExecutionPayload): ExecutionBlockHeader =
|
||||||
|
## This function assumes that the payload is empty!
|
||||||
|
doAssert payload.transactions.len == 0
|
||||||
|
|
||||||
|
ExecutionBlockHeader(
|
||||||
|
parentHash : payload.parent_hash,
|
||||||
|
ommersHash : EMPTY_UNCLE_HASH,
|
||||||
|
coinbase : EthAddress payload.fee_recipient.data,
|
||||||
|
stateRoot : payload.state_root,
|
||||||
|
txRoot : BLANK_ROOT_HASH,
|
||||||
|
receiptRoot : payload.receipts_root,
|
||||||
|
bloom : payload.logs_bloom.data,
|
||||||
|
difficulty : default(DifficultyInt),
|
||||||
|
blockNumber : payload.block_number.u256,
|
||||||
|
gasLimit : GasInt payload.gas_limit,
|
||||||
|
gasUsed : GasInt payload.gas_used,
|
||||||
|
timestamp : fromUnix(int64.saturate payload.timestamp),
|
||||||
|
extraData : payload.extra_data.asSeq,
|
||||||
|
mixDigest : payload.prev_randao, # EIP-4399 redefine `mixDigest` -> `prevRandao`
|
||||||
|
nonce : default(BlockNonce),
|
||||||
|
fee : some payload.base_fee_per_gas
|
||||||
|
)
|
||||||
|
|
||||||
func build_empty_execution_payload*(state: bellatrix.BeaconState): ExecutionPayload =
|
func build_empty_execution_payload*(state: bellatrix.BeaconState): ExecutionPayload =
|
||||||
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
||||||
## without any transactions.
|
## without any transactions.
|
||||||
|
@ -348,21 +374,21 @@ func build_empty_execution_payload*(state: bellatrix.BeaconState): ExecutionPayl
|
||||||
latest = state.latest_execution_payload_header
|
latest = state.latest_execution_payload_header
|
||||||
timestamp = compute_timestamp_at_slot(state, state.slot)
|
timestamp = compute_timestamp_at_slot(state, state.slot)
|
||||||
randao_mix = get_randao_mix(state, get_current_epoch(state))
|
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 = ExecutionPayload(
|
var payload = ExecutionPayload(
|
||||||
parent_hash: latest.block_hash,
|
parent_hash: latest.block_hash,
|
||||||
state_root: latest.state_root, # no changes to the state
|
state_root: latest.state_root, # no changes to the state
|
||||||
receipts_root: static(Eth2Digest.fromHex(
|
receipts_root: BLANK_ROOT_HASH,
|
||||||
"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")),
|
|
||||||
block_number: latest.block_number + 1,
|
block_number: latest.block_number + 1,
|
||||||
prev_randao: randao_mix,
|
prev_randao: randao_mix,
|
||||||
gas_limit: latest.gas_limit, # retain same limit
|
gas_limit: latest.gas_limit, # retain same limit
|
||||||
gas_used: 0, # empty block, 0 gas
|
gas_used: 0, # empty block, 0 gas
|
||||||
timestamp: timestamp,
|
timestamp: timestamp,
|
||||||
base_fee_per_gas: latest.base_fee_per_gas) # retain same base_fee
|
base_fee_per_gas: base_fee)
|
||||||
|
|
||||||
payload.block_hash = withEth2Hash:
|
payload.block_hash = rlpHash emptyPayloadToBlockHeader(payload)
|
||||||
h.update payload.hash_tree_root().data
|
|
||||||
h.update cast[array[13, uint8]]("FAKE RLP HASH")
|
|
||||||
|
|
||||||
payload
|
payload
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3e7da146671a6b56939c379d4ac780963bdd1c85
|
Subproject commit 4c702938834d492a96593ea97ec2c813b4a80044
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0476bcad1b580a627af056ae78e872c790029958
|
Subproject commit 018760954a1530b7336aed7133393908875d860f
|
Loading…
Reference in New Issue