diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 25a0f08e81..37b42fbc04 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -18,7 +18,7 @@ import helpers, network, signatures, peerdas_helpers], ../consensus_object_pools/[ attestation_pool, blockchain_dag, blob_quarantine, block_quarantine, - spec_cache, light_client_pool, sync_committee_msg_pool, + light_client_pool, spec_cache, sync_committee_msg_pool, validator_change_pool], ".."/[beacon_clock], ./batch_validation @@ -973,6 +973,78 @@ proc validateBeaconBlock*( ok() +# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/gloas/p2p-interface.md#execution_payload +proc validateExecutionPayload*( + dag: ChainDAGRef, quarantine: ref Quarantine, + signed_execution_payload_envelope: SignedExecutionPayloadEnvelope): + Result[void, ValidationError] = + template envelope: untyped = signed_execution_payload_envelope.message + + # [IGNORE] The envelope's block root envelope.block_root has been seen (via + # gossip or non-gossip sources) (a client MAY queue payload for processing + # once the block is retrieved). + let blockSeen = + block: + var seen = + envelope.beacon_block_root in quarantine.unviable or + envelope.beacon_block_root in quarantine.missing or + dag.getBlockRef(envelope.beacon_block_root).isSome() + if not seen: + for k, _ in quarantine.orphans: + if k[0] == envelope.beacon_block_root: + seen = true + break + seen + if not blockSeen: + return errIgnore("ExecutionPayload: block not found") + + # [IGNORE] The node has not seen another valid SignedExecutionPayloadEnvelope + # for this block root from this builder. + debugGloasComment("") + + # [REJECT] block passes validation. + let blck = + block: + let forkedBlock = dag.getForkedBlock(signed_execution_payload_envelope.toBlockId()).valueOr: + return errReject("ExecutionPayload: invalid block") + withBlck(forkedBlock): + when consensusFork >= ConsensusFork.Gloas: + forkyBlck.asSigned().message + else: + return errReject("ExecutionPayload: invalid fork") + + # [REJECT] block.slot equals envelope.slot. + if blck.slot != envelope.slot: + return errReject("ExecutionPayload: slot mismatch") + + # TODO: check if it needs fallback to `state.latest_execution_payload_bid` + template bid: untyped = blck.body.signed_execution_payload_bid.message + debug "Validating execution payload", bid = shortLog(bid) + + # [REJECT] envelope.builder_index == bid.builder_index + if envelope.builder_index != bid.builder_index: + return errReject("ExecutionPayload: builder index mismatch") + + # [REJECT] payload.block_hash == bid.block_hash + if envelope.payload.block_hash != bid.block_hash: + return errReject("ExecutionPayload: block hash mismatch") + + # [REJECT] signed_execution_payload_envelope.signature is valid with respect + # to the builder's public key. + withState(dag.headState): + when consensusFork >= ConsensusFork.Gloas: + if not verify_execution_payload_envelope_signature( + dag.forkAtEpoch(envelope.slot.epoch), + getStateField(dag.headState, genesis_validators_root), + signed_execution_payload_envelope, forkyState.data, + dag.validatorKey(envelope.builder_index).get(), + signed_execution_payload_envelope.signature): + return dag.checkedReject("ExecutionPayload: invalid builder signature") + else: + return dag.checkedReject("ExecutionPayload: invalid fork") + + ok() + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/deneb/p2p-interface.md#beacon_aggregate_and_proof proc validateAttestation*( diff --git a/beacon_chain/spec/datatypes/gloas.nim b/beacon_chain/spec/datatypes/gloas.nim index c6fd70a3f9..2d93504197 100644 --- a/beacon_chain/spec/datatypes/gloas.nim +++ b/beacon_chain/spec/datatypes/gloas.nim @@ -22,7 +22,7 @@ import json_serialization, ssz_serialization/[merkleization, proofs], ssz_serialization/types as sszTypes, - ../digest, + ../[block_id, digest], kzg4844/[kzg, kzg_abi] from ./altair import @@ -115,7 +115,7 @@ type # https://github.com/ethereum/consensus-specs/blob/v1.6.0-alpha.6/specs/gloas/beacon-chain.md#payloadattestationmessage PayloadAttestationMessage* = object - validatorIndex*: uint64 + validator_index*: uint64 data*: PayloadAttestationData signature*: ValidatorSig @@ -626,3 +626,6 @@ template asTrusted*( x: SignedBeaconBlock | SigVerifiedSignedBeaconBlock): TrustedSignedBeaconBlock = isomorphicCast[TrustedSignedBeaconBlock](x) + +func toBlockId*(v: SignedExecutionPayloadEnvelope): BlockId = + BlockId(root: v.message.beacon_block_root, slot: v.message.slot)