Skip to content

Commit

Permalink
adds message signatures for epbs
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomi-3-0 committed Jan 13, 2025
1 parent c63862c commit 4ad721b
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 3 deletions.
4 changes: 4 additions & 0 deletions beacon_chain/spec/datatypes/constants.nim
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.0/specs/capella/beacon-chain.md#domain-types
DOMAIN_BLS_TO_EXECUTION_CHANGE* = DomainType([byte 0x0a, 0x00, 0x00, 0x00])

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/beacon-chain.md#domain-types
DOMAIN_BEACON_BUILDER* = DomainType([byte 0x1B, 0x00, 0x00, 0x00])
DOMAIN_PTC_ATTESTER* = DomainType([byte 0x0C, 0x00, 0x00, 0x00])

# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.5/specs/phase0/fork-choice.md#configuration
PROPOSER_SCORE_BOOST*: uint64 = 40
REORG_HEAD_WEIGHT_THRESHOLD*: uint64 = 20
Expand Down
62 changes: 61 additions & 1 deletion beacon_chain/spec/datatypes/fulu.nim
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ from ./deneb import Blobs, BlobsBundle, KzgCommitments, KzgProofs

export json_serialization, base

type
PTCStatus* = distinct uint64

const
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.0/specs/fulu/polynomial-commitments-sampling.md#cells
FIELD_ELEMENTS_PER_EXT_BLOB* = 2 * kzg_abi.FIELD_ELEMENTS_PER_BLOB
Expand Down Expand Up @@ -67,6 +70,18 @@ const
# Number of columns in the network per custody group
COLUMNS_PER_GROUP* = NUMBER_OF_COLUMNS div NUMBER_OF_CUSTODY_GROUPS

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/beacon-chain.md#misc
PTC_SIZE* = 512

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/beacon-chain.md#max-operations-per-block
MAX_PAYLOAD_ATTESTATIONS* = 4

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#payload-status
PAYLOAD_ABSENT* = PTCStatus(0)
PAYLOAD_PRESENT* = PTCStatus(1)
PAYLOAD_WITHHELD* = PTCStatus(2)
PAYLOAD_INVALID_STATUS* = PTCStatus(3)

type
# https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.0/specs/fulu/polynomial-commitments-sampling.md#custom-types
BLSFieldElement* = KzgBytes32
Expand All @@ -84,7 +99,6 @@ type
CellIndex* = uint64
CustodyIndex* = uint64


type
DataColumn* = List[KzgCell, Limit(MAX_BLOB_COMMITMENTS_PER_BLOCK)]

Expand Down Expand Up @@ -124,6 +138,32 @@ type
syncnets*: SyncnetBits
custody_group_count*: uint64

type

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#payloadattestationdata
PayloadAttestationData* = object
beacon_block_root*: Eth2Digest
slot*: Slot
payload_status*: uint8

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#payloadattestation
PayloadAttestation* = object
aggregation_bits*: ElectraCommitteeValidatorsBits
data*: PayloadAttestationData
signature*: ValidatorSig

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#payloadattestationmessage
PayloadAttestationMessage* = object
validatorIndex*: ValidatorIndex
data*: PayloadAttestationData
signature*: ValidatorSig

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#indexedpayloadattestation
IndexedPayloadAttestation* = object
attesting_indices*: List[ValidatorIndex, Limit PTC_SIZE]
data*: PayloadAttestationData
signature*: ValidatorSig

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.10/specs/deneb/beacon-chain.md#executionpayload
ExecutionPayload* = object
# Execution block header fields
Expand Down Expand Up @@ -180,6 +220,26 @@ type
blob_gas_used*: uint64
excess_blob_gas*: uint64

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#executionpayloadenvelope
SignedExecutionPayloadHeader* = object
message*: ExecutionPayloadHeader
signature*: ValidatorSig

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#signedexecutionpayloadenvelope
ExecutionPayloadEnvelope* = object
payload*: ExecutionPayload
execution_requests*: ExecutionRequests
builder_index*: uint64
beacon_block_root*: Eth2Digest
blob_kzg_commitments*: List[KzgCommitment, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK]
payload_withheld*: bool
state_root*: Eth2Digest

# https://github.com/ethereum/consensus-specs/blob/dev/specs/_features/eip7732/beacon-chain.md#signedexecutionpayloadenvelope
SignedExecutionPayloadEnvelope* = object
message*: ExecutionPayloadEnvelope
signature*: ValidatorSig

ExecutePayload* = proc(
execution_payload: ExecutionPayload): bool {.gcsafe, raises: [].}

Expand Down
90 changes: 90 additions & 0 deletions beacon_chain/spec/signatures.nim
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,93 @@ proc verify_bls_to_execution_change_signature*(
let signing_root = compute_bls_to_execution_change_signing_root(
genesisFork, genesis_validators_root, msg.message)
blsVerify(pubkey, signing_root.data, signature)

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/beacon-chain.md#new-verify_execution_payload_header_signature
func compute_execution_payload_header_signing_root*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: fulu.SignedExecutionPayloadHeader,
state: fulu.BeaconState): Eth2Digest =

let
epoch = get_current_epoch(state)
domain = get_domain(
fork, DOMAIN_BEACON_BUILDER, epoch, genesis_validators_root)
compute_signing_root(msg.message, domain)

func get_execution_payload_header_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: SignedExecutionPayloadHeader, state: fulu.BeaconState,
privkey: ValidatorPrivKey): CookedSig =
let signing_root = compute_execution_payload_header_signing_root(
fork, genesis_validators_root, msg, state)
blsSign(privkey, signing_root.data)

proc verify_execution_payload_header_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: fulu.SignedExecutionPayloadHeader, state: fulu.BeaconState,
pubkey: ValidatorPubKey | CookedPubKey,
signature: SomeSig): bool =
let signing_root = compute_execution_payload_header_signing_root(
fork, genesis_validators_root, msg, state)
blsVerify(pubkey, signing_root.data, signature)

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/beacon-chain.md#new-verify_execution_payload_envelope_signature
func compute_execution_payload_envelope_signing_root*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: fulu.SignedExecutionPayloadEnvelope,
state: fulu.BeaconState): Eth2Digest =

let
epoch = get_current_epoch(state)
domain = get_domain(
fork, DOMAIN_BEACON_BUILDER, epoch, genesis_validators_root)
compute_signing_root(msg.message, domain)

func get_execution_payload_envelope_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: SignedExecutionPayloadEnvelope, state: fulu.BeaconState,
privkey: ValidatorPrivKey): CookedSig =
let signing_root = compute_execution_payload_envelope_signing_root(
fork, genesis_validators_root, msg, state)
blsSign(privkey, signing_root.data)

proc verify_execution_payload_envelope_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
msg: fulu.SignedExecutionPayloadEnvelope,
state: fulu.BeaconState, pubkey: ValidatorPubKey | CookedPubKey,
signature: SomeSig): bool =
let signing_root = compute_execution_payload_envelope_signing_root(
fork, genesis_validators_root, msg, state)
blsVerify(pubkey, signing_root.data, signature)

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.4/specs/_features/eip7732/validator.md#payload-timeliness-attestation
func compute_payload_attestation_message_signing_root*(
fork: Fork, genesis_validators_root: Eth2Digest,
attestation: PayloadAttestationMessage,
state: fulu.BeaconState): Eth2Digest =

let
epoch = get_current_epoch(state)
domain = get_domain(
fork, DOMAIN_BEACON_BUILDER, epoch, genesis_validators_root)
compute_signing_root(attestation.data, domain)

func get_payload_attestation_message_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
attestation: PayloadAttestationMessage,
state: fulu.BeaconState,
privkey: ValidatorPrivKey): CookedSig =
let signing_root = compute_payload_attestation_message_signing_root(
fork, genesis_validators_root, attestation, state)
blsSign(privkey, signing_root.data)

proc verify_payload_attestation_message_signature*(
fork: Fork, genesis_validators_root: Eth2Digest,
attestation: PayloadAttestationMessage,
state: fulu.BeaconState,
pubkey: ValidatorPubKey | CookedPubKey,
signature: SomeSig,
): bool =
let signing_root = compute_payload_attestation_message_signing_root(
fork, genesis_validators_root, attestation, state)
blsVerify(pubkey, signing_root.data, signature)
103 changes: 101 additions & 2 deletions tests/test_message_signatures.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
Expand Down Expand Up @@ -272,4 +272,103 @@ suite "Message signatures":
fork0, genesis_validators_root0, slot, subcommittee_index,
load(pubkey0).get, get_sync_committee_selection_proof(
fork0, genesis_validators_root1, slot,
subcommittee_index, privkey0).toValidatorSig)
subcommittee_index, privkey0).toValidatorSig)

let testState = default(fulu.BeaconState)

test "execution payload header signatures":
let msg = default(fulu.SignedExecutionPayloadHeader)

check:
# Matching public/private keys and genesis validator roots
verify_execution_payload_header_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_header_signature(
fork0, genesis_validators_root0, msg,
testState, privkey0).toValidatorSig)

# Mismatched public/private keys
not verify_execution_payload_header_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_header_signature(
fork0, genesis_validators_root0, msg,
testState, privkey1).toValidatorSig)

# Mismatched forks
not verify_execution_payload_header_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_header_signature(
fork1, genesis_validators_root0, msg,
testState, privkey0).toValidatorSig)

# Mismatched genesis validator roots
not verify_execution_payload_header_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_header_signature(
fork0, genesis_validators_root1, msg,
testState, privkey0).toValidatorSig)

test "execution payload envelope signatures":
let msg = default(fulu.SignedExecutionPayloadEnvelope)

check:
# Matching public/private keys and genesis validator roots
verify_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg,
testState, privkey0).toValidatorSig)

# Mismatched public/private keys
not verify_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg,
testState, privkey1).toValidatorSig)

# Mismatched forks
not verify_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_envelope_signature(
fork1, genesis_validators_root0, msg,
testState, privkey0).toValidatorSig)

# Mismatched genesis validator roots
not verify_execution_payload_envelope_signature(
fork0, genesis_validators_root0, msg, testState,
load(pubkey0).get, get_execution_payload_envelope_signature(
fork0, genesis_validators_root1, msg,
testState, privkey0).toValidatorSig)

test "execution payload attestation signatures":
let attestation = default(fulu.PayloadAttestationMessage)

check:
# Matching public/private keys and genesis validator roots
verify_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation, testState,
load(pubkey0).get, get_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation,
testState, privkey0).toValidatorSig)

# Mismatched public/private keys
not verify_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation, testState,
load(pubkey0).get, get_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation,
testState, privkey1).toValidatorSig)

# Mismatched forks
not verify_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation, testState,
load(pubkey0).get, get_payload_attestation_message_signature(
fork1, genesis_validators_root0, attestation,
testState, privkey0).toValidatorSig)

# Mismatched genesis validator roots
not verify_payload_attestation_message_signature(
fork0, genesis_validators_root0, attestation, testState,
load(pubkey0).get, get_payload_attestation_message_signature(
fork0, genesis_validators_root1, attestation,
testState, privkey0).toValidatorSig)

0 comments on commit 4ad721b

Please sign in to comment.