mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-08 12:44:34 +00:00
validate EL block hash in EL simulation (#4420)
When simulating EL with `--optimistic` flag, perform block hash check.
This commit is contained in:
parent
07d4160e00
commit
c91d9d61e2
@ -374,7 +374,8 @@ proc storeBlock*(
|
|||||||
self.consensusManager.quarantine[].addUnviable(signedBlock.root)
|
self.consensusManager.quarantine[].addUnviable(signedBlock.root)
|
||||||
return err((VerifierError.UnviableFork, ProcessingStatus.completed))
|
return err((VerifierError.UnviableFork, ProcessingStatus.completed))
|
||||||
|
|
||||||
if NewPayloadStatus.noResponse == payloadStatus and not self[].optimistic:
|
if NewPayloadStatus.noResponse == payloadStatus:
|
||||||
|
if not self[].optimistic:
|
||||||
# Disallow the `MissingParent` from leaking to the sync/request managers
|
# Disallow the `MissingParent` from leaking to the sync/request managers
|
||||||
# as it will be descored. However sync and request managers interact via
|
# as it will be descored. However sync and request managers interact via
|
||||||
# `processBlock` (indirectly). `validator_duties` does call `storeBlock`
|
# `processBlock` (indirectly). `validator_duties` does call `storeBlock`
|
||||||
@ -383,6 +384,19 @@ proc storeBlock*(
|
|||||||
return err((
|
return err((
|
||||||
VerifierError.MissingParent, ProcessingStatus.notCompleted))
|
VerifierError.MissingParent, ProcessingStatus.notCompleted))
|
||||||
|
|
||||||
|
# Client software MUST validate blockHash value as being equivalent to
|
||||||
|
# Keccak256(RLP(ExecutionBlockHeader))
|
||||||
|
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.1/src/engine/specification.md#specification
|
||||||
|
when typeof(signedBlock).toFork() >= BeaconBlockFork.Bellatrix:
|
||||||
|
template payload(): auto = signedBlock.message.body.execution_payload
|
||||||
|
if payload.block_hash != payload.compute_execution_block_hash():
|
||||||
|
debug "EL block hash validation failed", execution_payload = payload
|
||||||
|
doAssert strictVerification notin dag.updateFlags
|
||||||
|
self.consensusManager.quarantine[].addUnviable(signedBlock.root)
|
||||||
|
return err((VerifierError.UnviableFork, ProcessingStatus.completed))
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
# We'll also remove the block as an orphan: it's unlikely the parent is
|
# We'll also remove the block as an orphan: it's unlikely the parent is
|
||||||
# missing if we get this far - should that be the case, the block will
|
# missing if we get this far - should that be the case, the block will
|
||||||
# be re-added later
|
# be re-added later
|
||||||
|
@ -372,6 +372,19 @@ 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
|
||||||
|
|
||||||
|
proc computeTransactionsTrieRoot*(
|
||||||
|
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload): Hash256 =
|
||||||
|
if payload.transactions.len == 0:
|
||||||
|
return EMPTY_ROOT_HASH
|
||||||
|
|
||||||
|
var tr = initHexaryTrie(newMemoryDB())
|
||||||
|
for i, transaction in payload.transactions:
|
||||||
|
try:
|
||||||
|
tr.put(rlp.encode(i), distinctBase(transaction)) # Already RLP encoded
|
||||||
|
except RlpError as exc:
|
||||||
|
doAssert false, "HexaryTrie.put failed: " & $exc.msg
|
||||||
|
tr.rootHash()
|
||||||
|
|
||||||
func gweiToWei*(gwei: Gwei): UInt256 =
|
func gweiToWei*(gwei: Gwei): UInt256 =
|
||||||
gwei.u256 * 1_000_000_000.u256
|
gwei.u256 * 1_000_000_000.u256
|
||||||
|
|
||||||
@ -397,18 +410,15 @@ proc computeWithdrawalsTrieRoot*(
|
|||||||
doAssert false, "HexaryTrie.put failed: " & $exc.msg
|
doAssert false, "HexaryTrie.put failed: " & $exc.msg
|
||||||
tr.rootHash()
|
tr.rootHash()
|
||||||
|
|
||||||
proc emptyPayloadToBlockHeader*(
|
proc payloadToBlockHeader*(
|
||||||
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload
|
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload
|
||||||
): ExecutionBlockHeader =
|
): ExecutionBlockHeader =
|
||||||
static: # `GasInt` is signed. We only use it for hashing.
|
static: # `GasInt` is signed. We only use it for hashing.
|
||||||
doAssert sizeof(GasInt) == sizeof(payload.gas_limit)
|
doAssert sizeof(GasInt) == sizeof(payload.gas_limit)
|
||||||
doAssert sizeof(GasInt) == sizeof(payload.gas_used)
|
doAssert sizeof(GasInt) == sizeof(payload.gas_used)
|
||||||
|
|
||||||
## This function assumes that the payload is empty!
|
|
||||||
doAssert payload.transactions.len == 0
|
|
||||||
|
|
||||||
let
|
let
|
||||||
txRoot = EMPTY_ROOT_HASH
|
txRoot = payload.computeTransactionsTrieRoot()
|
||||||
withdrawalsRoot =
|
withdrawalsRoot =
|
||||||
when payload is bellatrix.ExecutionPayload:
|
when payload is bellatrix.ExecutionPayload:
|
||||||
none(Hash256)
|
none(Hash256)
|
||||||
@ -434,7 +444,12 @@ proc emptyPayloadToBlockHeader*(
|
|||||||
fee : some payload.base_fee_per_gas,
|
fee : some payload.base_fee_per_gas,
|
||||||
withdrawalsRoot: withdrawalsRoot)
|
withdrawalsRoot: withdrawalsRoot)
|
||||||
|
|
||||||
func build_empty_execution_payload*(
|
proc compute_execution_block_hash*(
|
||||||
|
payload: bellatrix.ExecutionPayload | capella.ExecutionPayload
|
||||||
|
): Eth2Digest =
|
||||||
|
rlpHash payloadToBlockHeader(payload)
|
||||||
|
|
||||||
|
proc build_empty_execution_payload*(
|
||||||
state: bellatrix.BeaconState,
|
state: bellatrix.BeaconState,
|
||||||
feeRecipient: Eth1Address): bellatrix.ExecutionPayload =
|
feeRecipient: Eth1Address): bellatrix.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
|
||||||
@ -459,7 +474,7 @@ func build_empty_execution_payload*(
|
|||||||
timestamp: timestamp,
|
timestamp: timestamp,
|
||||||
base_fee_per_gas: base_fee)
|
base_fee_per_gas: base_fee)
|
||||||
|
|
||||||
payload.block_hash = rlpHash emptyPayloadToBlockHeader(payload)
|
payload.block_hash = payload.compute_execution_block_hash()
|
||||||
|
|
||||||
payload
|
payload
|
||||||
|
|
||||||
@ -491,6 +506,6 @@ proc build_empty_execution_payload*(
|
|||||||
for withdrawal in expectedWithdrawals:
|
for withdrawal in expectedWithdrawals:
|
||||||
doAssert payload.withdrawals.add withdrawal
|
doAssert payload.withdrawals.add withdrawal
|
||||||
|
|
||||||
payload.block_hash = rlpHash emptyPayloadToBlockHeader(payload)
|
payload.block_hash = payload.compute_execution_block_hash()
|
||||||
|
|
||||||
payload
|
payload
|
||||||
|
@ -96,7 +96,7 @@ suite "Spec helpers":
|
|||||||
for i, withdrawal in withdrawals:
|
for i, withdrawal in withdrawals:
|
||||||
check payload.withdrawals[i] == withdrawal
|
check payload.withdrawals[i] == withdrawal
|
||||||
|
|
||||||
let elHeader = emptyPayloadToBlockHeader(payload)
|
let elHeader = payloadToBlockHeader(payload)
|
||||||
check elHeader.withdrawalsRoot.isSome
|
check elHeader.withdrawalsRoot.isSome
|
||||||
if withdrawals.len == 0:
|
if withdrawals.len == 0:
|
||||||
check elHeader.withdrawalsRoot.get == EMPTY_ROOT_HASH
|
check elHeader.withdrawalsRoot.get == EMPTY_ROOT_HASH
|
||||||
|
@ -81,7 +81,7 @@ func signBlock(
|
|||||||
from ../beacon_chain/spec/datatypes/capella import
|
from ../beacon_chain/spec/datatypes/capella import
|
||||||
BeaconState, ExecutionPayload, SignedBLSToExecutionChangeList
|
BeaconState, ExecutionPayload, SignedBLSToExecutionChangeList
|
||||||
|
|
||||||
func build_empty_merge_execution_payload(state: bellatrix.BeaconState):
|
proc build_empty_merge_execution_payload(state: bellatrix.BeaconState):
|
||||||
bellatrix.ExecutionPayload =
|
bellatrix.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 from a non-merged block.
|
## without any transactions from a non-merged block.
|
||||||
@ -104,7 +104,7 @@ func build_empty_merge_execution_payload(state: bellatrix.BeaconState):
|
|||||||
timestamp: timestamp,
|
timestamp: timestamp,
|
||||||
base_fee_per_gas: EIP1559_INITIAL_BASE_FEE)
|
base_fee_per_gas: EIP1559_INITIAL_BASE_FEE)
|
||||||
|
|
||||||
payload.block_hash = rlpHash emptyPayloadToBlockHeader(payload)
|
payload.block_hash = rlpHash payloadToBlockHeader(payload)
|
||||||
|
|
||||||
payload
|
payload
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ proc build_empty_merge_execution_payload(state: capella.BeaconState):
|
|||||||
timestamp: timestamp,
|
timestamp: timestamp,
|
||||||
base_fee_per_gas: EIP1559_INITIAL_BASE_FEE)
|
base_fee_per_gas: EIP1559_INITIAL_BASE_FEE)
|
||||||
|
|
||||||
payload.block_hash = rlpHash emptyPayloadToBlockHeader(payload)
|
payload.block_hash = rlpHash payloadToBlockHeader(payload)
|
||||||
|
|
||||||
payload
|
payload
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user