validate EL block hash in Electra when no EL is connected (#6407)
When no EL is connected, it is still required to validate the block hash of `ExecutionPayload` to prevent attacks that trick us into attesting to a circular chain with invalid in-between block hashes. This is already done through Deneb but was still missing in Electra to be rectified now.
This commit is contained in:
parent
c59bb71916
commit
7f59e80aaa
|
@ -555,8 +555,7 @@ proc storeBlock(
|
|||
# This should simulate an unsynced EL, which still must perform these
|
||||
# checks. This means it must be able to do so without context, beyond
|
||||
# whatever data the block itself contains.
|
||||
when typeof(signedBlock).kind >= ConsensusFork.Bellatrix and typeof(signedBlock).kind <= ConsensusFork.Deneb:
|
||||
debugComment "electra can do this in principle"
|
||||
when typeof(signedBlock).kind >= ConsensusFork.Bellatrix:
|
||||
template payload(): auto = signedBlock.message.body.execution_payload
|
||||
if signedBlock.message.is_execution_block and
|
||||
payload.block_hash !=
|
||||
|
|
|
@ -39,6 +39,9 @@ type
|
|||
ExecutionTransaction* = eth_types.Transaction
|
||||
ExecutionReceipt* = eth_types.Receipt
|
||||
ExecutionWithdrawal* = eth_types.Withdrawal
|
||||
ExecutionDepositRequest* = eth_types.DepositRequest
|
||||
ExecutionWithdrawalRequest* = eth_types.WithdrawalRequest
|
||||
ExecutionConsolidationRequest* = eth_types.ConsolidationRequest
|
||||
ExecutionBlockHeader* = eth_types.BlockHeader
|
||||
|
||||
FinalityCheckpoints* = object
|
||||
|
@ -474,6 +477,74 @@ proc computeWithdrawalsTrieRoot*(
|
|||
raiseAssert "HexaryTrie.put failed: " & $exc.msg
|
||||
tr.rootHash()
|
||||
|
||||
func toExecutionDepositRequest*(
|
||||
request: electra.DepositRequest): ExecutionDepositRequest =
|
||||
ExecutionDepositRequest(
|
||||
pubkey: request.pubkey.blob,
|
||||
withdrawalCredentials: request.withdrawal_credentials.data,
|
||||
amount: distinctBase(request.amount),
|
||||
signature: request.signature.blob,
|
||||
index: request.index)
|
||||
|
||||
func toExecutionWithdrawalRequest*(
|
||||
request: electra.WithdrawalRequest): ExecutionWithdrawalRequest =
|
||||
ExecutionWithdrawalRequest(
|
||||
sourceAddress: request.source_address.data,
|
||||
validatorPubkey: request.validator_pubkey.blob,
|
||||
amount: distinctBase(request.amount))
|
||||
|
||||
func toExecutionConsolidationRequest*(
|
||||
request: electra.ConsolidationRequest): ExecutionConsolidationRequest =
|
||||
ExecutionConsolidationRequest(
|
||||
sourceAddress: request.source_address.data,
|
||||
sourcePubkey: request.source_pubkey.blob,
|
||||
targetPubkey: request.target_pubkey.blob)
|
||||
|
||||
# https://eips.ethereum.org/EIPS/eip-7685
|
||||
proc computeRequestsTrieRoot*(
|
||||
payload: electra.ExecutionPayload): ExecutionHash256 =
|
||||
if payload.deposit_requests.len == 0 and
|
||||
payload.withdrawal_requests.len == 0 and
|
||||
payload.consolidation_requests.len == 0:
|
||||
return EMPTY_ROOT_HASH
|
||||
|
||||
var
|
||||
tr = initHexaryTrie(newMemoryDB())
|
||||
i = 0'u64
|
||||
|
||||
static:
|
||||
doAssert DEPOSIT_REQUEST_TYPE < WITHDRAWAL_REQUEST_TYPE
|
||||
doAssert WITHDRAWAL_REQUEST_TYPE < CONSOLIDATION_REQUEST_TYPE
|
||||
|
||||
# EIP-6110
|
||||
for request in payload.deposit_requests:
|
||||
try:
|
||||
tr.put(rlp.encode(i.uint), rlp.encode(
|
||||
toExecutionDepositRequest(request)))
|
||||
except RlpError as exc:
|
||||
raiseAssert "HexaryTree.put failed: " & $exc.msg
|
||||
inc i
|
||||
|
||||
# EIP-7002
|
||||
for request in payload.withdrawal_requests:
|
||||
try:
|
||||
tr.put(rlp.encode(i.uint), rlp.encode(
|
||||
toExecutionWithdrawalRequest(request)))
|
||||
except RlpError as exc:
|
||||
raiseAssert "HexaryTree.put failed: " & $exc.msg
|
||||
inc i
|
||||
|
||||
# EIP-7251
|
||||
for request in payload.consolidation_requests:
|
||||
try:
|
||||
tr.put(rlp.encode(i.uint), rlp.encode(
|
||||
toExecutionConsolidationRequest(request)))
|
||||
except RlpError as exc:
|
||||
raiseAssert "HexaryTree.put failed: " & $exc.msg
|
||||
inc i
|
||||
|
||||
tr.rootHash()
|
||||
|
||||
proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
|
||||
template payload: auto = blck.body.execution_payload
|
||||
|
||||
|
@ -503,6 +574,11 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
|
|||
Opt.some ExecutionHash256(data: blck.parent_root.data)
|
||||
else:
|
||||
Opt.none(ExecutionHash256)
|
||||
requestsRoot =
|
||||
when typeof(payload).kind >= ConsensusFork.Electra:
|
||||
Opt.some payload.computeRequestsTrieRoot()
|
||||
else:
|
||||
Opt.none(ExecutionHash256)
|
||||
|
||||
ExecutionBlockHeader(
|
||||
parentHash : payload.parent_hash,
|
||||
|
@ -524,7 +600,8 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): ExecutionBlockHeader =
|
|||
withdrawalsRoot : withdrawalsRoot,
|
||||
blobGasUsed : blobGasUsed, # EIP-4844
|
||||
excessBlobGas : excessBlobGas, # EIP-4844
|
||||
parentBeaconBlockRoot : parentBeaconBlockRoot) # EIP-4788
|
||||
parentBeaconBlockRoot : parentBeaconBlockRoot, # EIP-4788
|
||||
requestsRoot : requestsRoot) # EIP-7685
|
||||
|
||||
proc compute_execution_block_hash*(blck: ForkyBeaconBlock): Eth2Digest =
|
||||
rlpHash blockToBlockHeader(blck)
|
||||
|
|
Loading…
Reference in New Issue