capella test vector support (#4261)
This commit is contained in:
parent
69ed3a2fd6
commit
06ccf5b80c
|
@ -19,6 +19,8 @@ import
|
|||
./datatypes/[phase0, altair, bellatrix],
|
||||
"."/[eth2_merkleization, forks, signatures, validator]
|
||||
|
||||
from ./datatypes/capella import BeaconState, ExecutionPayloadHeader, Withdrawal
|
||||
|
||||
export extras, forks, validator
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#increase_balance
|
||||
|
@ -143,6 +145,8 @@ func get_slashing_penalty*(state: ForkyBeaconState,
|
|||
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR
|
||||
elif state is bellatrix.BeaconState:
|
||||
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
|
||||
elif state is capella.BeaconState:
|
||||
validator_effective_balance div MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
|
||||
else:
|
||||
{.fatal: "invalid BeaconState type".}
|
||||
|
||||
|
@ -158,7 +162,8 @@ func get_whistleblower_reward*(validator_effective_balance: Gwei): Gwei =
|
|||
func get_proposer_reward(state: ForkyBeaconState, whistleblower_reward: Gwei): Gwei =
|
||||
when state is phase0.BeaconState:
|
||||
whistleblower_reward div PROPOSER_REWARD_QUOTIENT
|
||||
elif state is altair.BeaconState or state is bellatrix.BeaconState:
|
||||
elif state is altair.BeaconState or state is bellatrix.BeaconState or
|
||||
state is capella.BeaconState:
|
||||
whistleblower_reward * PROPOSER_WEIGHT div WEIGHT_DENOMINATOR
|
||||
else:
|
||||
{.fatal: "invalid BeaconState type".}
|
||||
|
@ -563,9 +568,9 @@ func check_attestation_index*(
|
|||
check_attestation_index(data.index, committees_per_slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices
|
||||
func get_attestation_participation_flag_indices(state: altair.BeaconState | bellatrix.BeaconState,
|
||||
data: AttestationData,
|
||||
inclusion_delay: uint64): seq[int] =
|
||||
func get_attestation_participation_flag_indices(
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
data: AttestationData, inclusion_delay: uint64): seq[int] =
|
||||
## Return the flag indices that are satisfied by an attestation.
|
||||
let justified_checkpoint =
|
||||
if data.target.epoch == get_current_epoch(state):
|
||||
|
@ -618,8 +623,8 @@ func get_base_reward_per_increment*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_base_reward
|
||||
func get_base_reward(
|
||||
state: altair.BeaconState | bellatrix.BeaconState, index: ValidatorIndex,
|
||||
base_reward_per_increment: Gwei): Gwei =
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei =
|
||||
## Return the base reward for the validator defined by ``index`` with respect
|
||||
## to the current ``state``.
|
||||
let increments =
|
||||
|
@ -717,7 +722,7 @@ proc process_attestation*(
|
|||
pa[].inclusion_delay = state.slot - attestation.data.slot
|
||||
pa[].proposer_index = proposer_index.get().uint64
|
||||
|
||||
# Altair and Bellatrix
|
||||
# Altair, Bellatrix, and Capella
|
||||
template updateParticipationFlags(epoch_participation: untyped) =
|
||||
let proposer_reward = get_proposer_reward(
|
||||
state, attestation, base_reward_per_increment, cache, epoch_participation)
|
||||
|
@ -729,7 +734,8 @@ proc process_attestation*(
|
|||
addPendingAttestation(state.current_epoch_attestations)
|
||||
else:
|
||||
addPendingAttestation(state.previous_epoch_attestations)
|
||||
elif state is altair.BeaconState or state is bellatrix.BeaconState:
|
||||
elif state is altair.BeaconState or state is bellatrix.BeaconState or
|
||||
state is capella.BeaconState:
|
||||
doAssert base_reward_per_increment > 0.Gwei
|
||||
if attestation.data.target.epoch == get_current_epoch(state):
|
||||
updateParticipationFlags(state.current_epoch_participation)
|
||||
|
@ -741,7 +747,8 @@ proc process_attestation*(
|
|||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_next_sync_committee_indices
|
||||
func get_next_sync_committee_keys(state: altair.BeaconState | bellatrix.BeaconState):
|
||||
func get_next_sync_committee_keys(
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState):
|
||||
array[SYNC_COMMITTEE_SIZE, ValidatorPubKey] =
|
||||
## Return the sequence of sync committee indices, with possible duplicates,
|
||||
## for the next sync committee.
|
||||
|
@ -777,7 +784,8 @@ func get_next_sync_committee_keys(state: altair.BeaconState | bellatrix.BeaconSt
|
|||
res
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_next_sync_committee
|
||||
func get_next_sync_committee*(state: altair.BeaconState | bellatrix.BeaconState):
|
||||
func get_next_sync_committee*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState):
|
||||
SyncCommittee =
|
||||
## Return the *next* sync committee for a given ``state``.
|
||||
var res: SyncCommittee
|
||||
|
@ -934,7 +942,88 @@ func upgrade_to_bellatrix*(cfg: RuntimeConfig, pre: altair.BeaconState):
|
|||
next_sync_committee: pre.next_sync_committee,
|
||||
|
||||
# Execution-layer
|
||||
latest_execution_payload_header: ExecutionPayloadHeader()
|
||||
latest_execution_payload_header: default(bellatrix.ExecutionPayloadHeader)
|
||||
)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/b90436c98837924c3a929652b57b07ac9d3c2254/specs/capella/fork.md#upgrading-the-state
|
||||
func upgrade_to_capella*(cfg: RuntimeConfig, pre: bellatrix.BeaconState):
|
||||
ref capella.BeaconState =
|
||||
let
|
||||
epoch = get_current_epoch(pre)
|
||||
latest_execution_payload_header = capella.ExecutionPayloadHeader(
|
||||
parent_hash: pre.latest_execution_payload_header.parent_hash,
|
||||
fee_recipient: pre.latest_execution_payload_header.fee_recipient,
|
||||
state_root: pre.latest_execution_payload_header.state_root,
|
||||
receipts_root: pre.latest_execution_payload_header.receipts_root,
|
||||
logs_bloom: pre.latest_execution_payload_header.logs_bloom,
|
||||
prev_randao: pre.latest_execution_payload_header.prev_randao,
|
||||
block_number: pre.latest_execution_payload_header.block_number,
|
||||
gas_limit: pre.latest_execution_payload_header.gas_limit,
|
||||
gas_used: pre.latest_execution_payload_header.gas_used,
|
||||
timestamp: pre.latest_execution_payload_header.timestamp,
|
||||
extra_data: pre.latest_execution_payload_header.extra_data,
|
||||
base_fee_per_gas: pre.latest_execution_payload_header.base_fee_per_gas,
|
||||
block_hash: pre.latest_execution_payload_header.block_hash,
|
||||
transactions_root: pre.latest_execution_payload_header.transactions_root,
|
||||
withdrawals_root: Eth2Digest() # [New in Capella]
|
||||
)
|
||||
|
||||
(ref capella.BeaconState)(
|
||||
# Versioning
|
||||
genesis_time: pre.genesis_time,
|
||||
genesis_validators_root: pre.genesis_validators_root,
|
||||
slot: pre.slot,
|
||||
fork: Fork(
|
||||
previous_version: pre.fork.current_version,
|
||||
current_version: cfg.CAPELLA_FORK_VERSION,
|
||||
epoch: epoch,
|
||||
),
|
||||
|
||||
# History
|
||||
latest_block_header: pre.latest_block_header,
|
||||
block_roots: pre.block_roots,
|
||||
state_roots: pre.state_roots,
|
||||
historical_roots: pre.historical_roots,
|
||||
|
||||
# Eth1
|
||||
eth1_data: pre.eth1_data,
|
||||
eth1_data_votes: pre.eth1_data_votes,
|
||||
eth1_deposit_index: pre.eth1_deposit_index,
|
||||
|
||||
# Registry
|
||||
validators: pre.validators,
|
||||
balances: pre.balances,
|
||||
|
||||
# Randomness
|
||||
randao_mixes: pre.randao_mixes,
|
||||
|
||||
# Slashings
|
||||
slashings: pre.slashings,
|
||||
|
||||
# Participation
|
||||
previous_epoch_participation: pre.previous_epoch_participation,
|
||||
current_epoch_participation: pre.current_epoch_participation,
|
||||
|
||||
# Finality
|
||||
justification_bits: pre.justification_bits,
|
||||
previous_justified_checkpoint: pre.previous_justified_checkpoint,
|
||||
current_justified_checkpoint: pre.current_justified_checkpoint,
|
||||
finalized_checkpoint: pre.finalized_checkpoint,
|
||||
|
||||
# Inactivity
|
||||
inactivity_scores: pre.inactivity_scores,
|
||||
|
||||
# Sync
|
||||
current_sync_committee: pre.current_sync_committee,
|
||||
next_sync_committee: pre.next_sync_committee,
|
||||
|
||||
# Execution-layer
|
||||
latest_execution_payload_header: latest_execution_payload_header,
|
||||
|
||||
# Withdrawals
|
||||
withdrawal_queue: HashList[Withdrawal, Limit WITHDRAWAL_QUEUE_LIMIT](),
|
||||
next_withdrawal_index: 0,
|
||||
next_partial_withdrawal_validator_index: 0
|
||||
)
|
||||
|
||||
template isValidInState*(idx: ValidatorIndex, state: ForkyBeaconState): bool =
|
||||
|
@ -969,8 +1058,8 @@ func latest_block_root*(state: ForkedHashedBeaconState): Eth2Digest =
|
|||
withState(state): latest_block_root(forkyState)
|
||||
|
||||
func get_sync_committee_cache*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState, cache: var StateCache):
|
||||
SyncCommitteeCache =
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
cache: var StateCache): SyncCommitteeCache =
|
||||
let period = state.slot.sync_committee_period()
|
||||
|
||||
cache.sync_committees.withValue(period, v) do:
|
||||
|
|
|
@ -0,0 +1,439 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
# Types specific to capella (ie known to have changed across hard forks) - see
|
||||
# `base` for types and guidelines common across forks
|
||||
|
||||
# TODO Careful, not nil analysis is broken / incomplete and the semantics will
|
||||
# likely change in future versions of the language:
|
||||
# https://github.com/nim-lang/RFCs/issues/250
|
||||
{.experimental: "notnil".}
|
||||
|
||||
when (NimMajor, NimMinor) < (1, 4):
|
||||
{.push raises: [Defect].}
|
||||
else:
|
||||
{.push raises: [].}
|
||||
|
||||
import
|
||||
stew/byteutils,
|
||||
json_serialization,
|
||||
ssz_serialization/types as sszTypes,
|
||||
../digest,
|
||||
"."/[base, phase0, altair, bellatrix]
|
||||
|
||||
export json_serialization, base
|
||||
|
||||
type
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#custom-types
|
||||
WithdrawalIndex = uint64
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#withdrawal
|
||||
Withdrawal* = object
|
||||
index*: WithdrawalIndex
|
||||
validator_index*: uint64
|
||||
address*: ExecutionAddress
|
||||
amount*: Gwei
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#blstoexecutionchange
|
||||
BLSToExecutionChange* = object
|
||||
validator_index*: uint64
|
||||
from_bls_pubkey*: ValidatorPubKey
|
||||
to_execution_address*: ExecutionAddress
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#signedblstoexecutionchange
|
||||
SignedBLSToExecutionChange* = object
|
||||
message*: BLSToExecutionChange
|
||||
signature*: ValidatorSig
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#executionpayload
|
||||
ExecutionPayload* = object
|
||||
parent_hash*: Eth2Digest
|
||||
fee_recipient*: ExecutionAddress # 'beneficiary' in the yellow paper
|
||||
state_root*: Eth2Digest
|
||||
receipts_root*: Eth2Digest # 'receipts root' in the yellow paper
|
||||
logs_bloom*: BloomLogs
|
||||
prev_randao*: Eth2Digest # 'difficulty' in the yellow paper
|
||||
block_number*: uint64 # 'number' in the yellow paper
|
||||
gas_limit*: uint64
|
||||
gas_used*: uint64
|
||||
timestamp*: uint64
|
||||
extra_data*: List[byte, MAX_EXTRA_DATA_BYTES]
|
||||
base_fee_per_gas*: UInt256
|
||||
|
||||
# Extra payload fields
|
||||
block_hash*: Eth2Digest # Hash of execution block
|
||||
transactions*: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
|
||||
withdrawals*: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD] # [New in Capella]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#executionpayloadheader
|
||||
ExecutionPayloadHeader* = object
|
||||
parent_hash*: Eth2Digest
|
||||
fee_recipient*: ExecutionAddress
|
||||
state_root*: Eth2Digest
|
||||
receipts_root*: Eth2Digest
|
||||
logs_bloom*: BloomLogs
|
||||
prev_randao*: Eth2Digest
|
||||
block_number*: uint64
|
||||
gas_limit*: uint64
|
||||
gas_used*: uint64
|
||||
timestamp*: uint64
|
||||
extra_data*: List[byte, MAX_EXTRA_DATA_BYTES]
|
||||
base_fee_per_gas*: UInt256
|
||||
|
||||
# Extra payload fields
|
||||
block_hash*: Eth2Digest # Hash of execution block
|
||||
transactions_root*: Eth2Digest
|
||||
withdrawals_root*: Eth2Digest # [New in Capella]
|
||||
|
||||
ExecutePayload* = proc(
|
||||
execution_payload: ExecutionPayload): bool {.gcsafe, raises: [Defect].}
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#beaconstate
|
||||
BeaconState* = object
|
||||
# Versioning
|
||||
genesis_time*: uint64
|
||||
genesis_validators_root*: Eth2Digest
|
||||
slot*: Slot
|
||||
fork*: Fork
|
||||
|
||||
# History
|
||||
latest_block_header*: BeaconBlockHeader
|
||||
## `latest_block_header.state_root == ZERO_HASH` temporarily
|
||||
|
||||
block_roots*: HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]
|
||||
## Needed to process attestations, older to newer
|
||||
|
||||
state_roots*: HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest]
|
||||
historical_roots*: HashList[Eth2Digest, Limit HISTORICAL_ROOTS_LIMIT]
|
||||
|
||||
# Eth1
|
||||
eth1_data*: Eth1Data
|
||||
eth1_data_votes*:
|
||||
HashList[Eth1Data, Limit(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH)]
|
||||
eth1_deposit_index*: uint64
|
||||
|
||||
# Registry
|
||||
validators*: HashList[Validator, Limit VALIDATOR_REGISTRY_LIMIT]
|
||||
balances*: HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT]
|
||||
|
||||
# Randomness
|
||||
randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
|
||||
|
||||
# Slashings
|
||||
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei]
|
||||
## Per-epoch sums of slashed effective balances
|
||||
|
||||
# Participation
|
||||
previous_epoch_participation*: EpochParticipationFlags
|
||||
current_epoch_participation*: EpochParticipationFlags
|
||||
|
||||
# Finality
|
||||
justification_bits*: JustificationBits
|
||||
|
||||
previous_justified_checkpoint*: Checkpoint
|
||||
## Previous epoch snapshot
|
||||
|
||||
current_justified_checkpoint*: Checkpoint
|
||||
finalized_checkpoint*: Checkpoint
|
||||
|
||||
# Inactivity
|
||||
inactivity_scores*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] # [New in Altair]
|
||||
|
||||
# Light client sync committees
|
||||
current_sync_committee*: SyncCommittee # [New in Altair]
|
||||
next_sync_committee*: SyncCommittee # [New in Altair]
|
||||
|
||||
# Execution
|
||||
latest_execution_payload_header*: ExecutionPayloadHeader
|
||||
|
||||
# Withdrawals
|
||||
withdrawal_queue*: HashList[Withdrawal, WITHDRAWAL_QUEUE_LIMIT] # [New in Capella]
|
||||
next_withdrawal_index*: WithdrawalIndex # [New in Capella]
|
||||
next_partial_withdrawal_validator_index*: uint64 # [New in Capella]
|
||||
|
||||
# TODO Careful, not nil analysis is broken / incomplete and the semantics will
|
||||
# likely change in future versions of the language:
|
||||
# https://github.com/nim-lang/RFCs/issues/250
|
||||
BeaconStateRef* = ref BeaconState not nil
|
||||
NilableBeaconStateRef* = ref BeaconState
|
||||
|
||||
HashedBeaconState* = object
|
||||
data*: BeaconState
|
||||
root*: Eth2Digest # hash_tree_root(data)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#beaconblock
|
||||
BeaconBlock* = object
|
||||
## For each slot, a proposer is chosen from the validator pool to propose
|
||||
## a new block. Once the block as been proposed, it is transmitted to
|
||||
## validators that will have a chance to vote on it through attestations.
|
||||
## Each block collects attestations, or votes, on past blocks, thus a chain
|
||||
## is formed.
|
||||
|
||||
slot*: Slot
|
||||
proposer_index*: uint64 # `ValidatorIndex` after validation
|
||||
|
||||
parent_root*: Eth2Digest
|
||||
## Root hash of the previous block
|
||||
|
||||
state_root*: Eth2Digest
|
||||
## The state root, _after_ this block has been processed
|
||||
|
||||
body*: BeaconBlockBody
|
||||
|
||||
SigVerifiedBeaconBlock* = object
|
||||
## A BeaconBlock that contains verified signatures
|
||||
## but that has not been verified for state transition
|
||||
|
||||
slot*: Slot
|
||||
proposer_index*: uint64 # `ValidatorIndex` after validation
|
||||
|
||||
parent_root*: Eth2Digest
|
||||
## Root hash of the previous block
|
||||
|
||||
state_root*: Eth2Digest
|
||||
## The state root, _after_ this block has been processed
|
||||
|
||||
body*: SigVerifiedBeaconBlockBody
|
||||
|
||||
TrustedBeaconBlock* = object
|
||||
## When we receive blocks from outside sources, they are untrusted and go
|
||||
## through several layers of validation. Blocks that have gone through
|
||||
## validations can be trusted to be well-formed, with a correct signature,
|
||||
## having a parent and applying cleanly to the state that their parent
|
||||
## left them with.
|
||||
##
|
||||
## When loading such blocks from the database, to rewind states for example,
|
||||
## it is expensive to redo the validations (in particular, the signature
|
||||
## checks), thus `TrustedBlock` uses a `TrustedSig` type to mark that these
|
||||
## checks can be skipped.
|
||||
##
|
||||
## TODO this could probably be solved with some type trickery, but there
|
||||
## too many bugs in nim around generics handling, and we've used up
|
||||
## the trickery budget in the serialization library already. Until
|
||||
## then, the type must be manually kept compatible with its untrusted
|
||||
## cousin.
|
||||
slot*: Slot
|
||||
proposer_index*: uint64 # `ValidatorIndex` after validation
|
||||
parent_root*: Eth2Digest
|
||||
state_root*: Eth2Digest
|
||||
body*: TrustedBeaconBlockBody
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#beaconblockbody
|
||||
BeaconBlockBody* = object
|
||||
randao_reveal*: ValidatorSig
|
||||
eth1_data*: Eth1Data
|
||||
## Eth1 data vote
|
||||
|
||||
graffiti*: GraffitiBytes
|
||||
## Arbitrary data
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
||||
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
||||
attestations*: List[Attestation, Limit MAX_ATTESTATIONS]
|
||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
||||
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
||||
|
||||
sync_aggregate*: SyncAggregate
|
||||
|
||||
# Execution
|
||||
execution_payload*: ExecutionPayload
|
||||
|
||||
# Capella operations
|
||||
bls_to_execution_changes*: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella]
|
||||
|
||||
SigVerifiedBeaconBlockBody* = object
|
||||
## A BeaconBlock body with signatures verified
|
||||
## including:
|
||||
## - Randao reveal
|
||||
## - Attestations
|
||||
## - ProposerSlashing (SignedBeaconBlockHeader)
|
||||
## - AttesterSlashing (IndexedAttestation)
|
||||
## - SignedVoluntaryExits
|
||||
## - SyncAggregate
|
||||
##
|
||||
## However:
|
||||
## - ETH1Data (Deposits) can contain invalid BLS signatures
|
||||
##
|
||||
## The block state transition has NOT been verified
|
||||
randao_reveal*: TrustedSig
|
||||
eth1_data*: Eth1Data
|
||||
## Eth1 data vote
|
||||
|
||||
graffiti*: GraffitiBytes
|
||||
## Arbitrary data
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[TrustedProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
||||
attester_slashings*: List[TrustedAttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
||||
attestations*: List[TrustedAttestation, Limit MAX_ATTESTATIONS]
|
||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
||||
voluntary_exits*: List[TrustedSignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
||||
|
||||
sync_aggregate*: TrustedSyncAggregate
|
||||
|
||||
# Execution
|
||||
execution_payload*: ExecutionPayload
|
||||
|
||||
# Capella operations
|
||||
bls_to_execution_changes*: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella]
|
||||
|
||||
TrustedBeaconBlockBody* = object
|
||||
## A full verified block
|
||||
randao_reveal*: TrustedSig
|
||||
eth1_data*: Eth1Data
|
||||
## Eth1 data vote
|
||||
|
||||
graffiti*: GraffitiBytes
|
||||
## Arbitrary data
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[TrustedProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
||||
attester_slashings*: List[TrustedAttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
||||
attestations*: List[TrustedAttestation, Limit MAX_ATTESTATIONS]
|
||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
||||
voluntary_exits*: List[TrustedSignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
||||
|
||||
sync_aggregate*: TrustedSyncAggregate
|
||||
|
||||
# Execution
|
||||
execution_payload*: ExecutionPayload
|
||||
|
||||
# Capella operations
|
||||
bls_to_execution_changes*: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella]
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#signedbeaconblock
|
||||
SignedBeaconBlock* = object
|
||||
message*: BeaconBlock
|
||||
signature*: ValidatorSig
|
||||
|
||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||
|
||||
SigVerifiedSignedBeaconBlock* = object
|
||||
## A SignedBeaconBlock with signatures verified
|
||||
## including:
|
||||
## - Block signature
|
||||
## - BeaconBlockBody
|
||||
## - Randao reveal
|
||||
## - Attestations
|
||||
## - ProposerSlashing (SignedBeaconBlockHeader)
|
||||
## - AttesterSlashing (IndexedAttestation)
|
||||
## - SignedVoluntaryExits
|
||||
##
|
||||
## - ETH1Data (Deposits) can contain invalid BLS signatures
|
||||
##
|
||||
## The block state transition has NOT been verified
|
||||
message*: SigVerifiedBeaconBlock
|
||||
signature*: TrustedSig
|
||||
|
||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||
|
||||
MsgTrustedSignedBeaconBlock* = object
|
||||
message*: TrustedBeaconBlock
|
||||
signature*: ValidatorSig
|
||||
|
||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||
|
||||
TrustedSignedBeaconBlock* = object
|
||||
message*: TrustedBeaconBlock
|
||||
signature*: TrustedSig
|
||||
|
||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||
|
||||
SomeSignedBeaconBlock* =
|
||||
SignedBeaconBlock |
|
||||
SigVerifiedSignedBeaconBlock |
|
||||
MsgTrustedSignedBeaconBlock |
|
||||
TrustedSignedBeaconBlock
|
||||
SomeBeaconBlock* =
|
||||
BeaconBlock |
|
||||
SigVerifiedBeaconBlock |
|
||||
TrustedBeaconBlock
|
||||
SomeBeaconBlockBody* =
|
||||
BeaconBlockBody |
|
||||
SigVerifiedBeaconBlockBody |
|
||||
TrustedBeaconBlockBody
|
||||
|
||||
BlockParams = object
|
||||
parentHash*: string
|
||||
timestamp*: string
|
||||
|
||||
BoolReturnValidRPC = object
|
||||
valid*: bool
|
||||
|
||||
BoolReturnSuccessRPC = object
|
||||
success*: bool
|
||||
|
||||
func fromHex*(T: typedesc[BloomLogs], s: string): T {.
|
||||
raises: [Defect, ValueError].} =
|
||||
hexToByteArray(s, result.data)
|
||||
|
||||
func fromHex*(T: typedesc[ExecutionAddress], s: string): T {.
|
||||
raises: [Defect, ValueError].} =
|
||||
hexToByteArray(s, result.data)
|
||||
|
||||
proc writeValue*(writer: var JsonWriter, value: ExecutionAddress) {.
|
||||
raises: [Defect, IOError].} =
|
||||
writer.writeValue to0xHex(value.data)
|
||||
|
||||
proc readValue*(reader: var JsonReader, value: var ExecutionAddress) {.
|
||||
raises: [Defect, IOError, SerializationError].} =
|
||||
try:
|
||||
hexToByteArray(reader.readValue(string), value.data)
|
||||
except ValueError:
|
||||
raiseUnexpectedValue(reader,
|
||||
"ExecutionAddress value should be a valid hex string")
|
||||
|
||||
func shortLog*(v: SomeBeaconBlock): auto =
|
||||
(
|
||||
slot: shortLog(v.slot),
|
||||
proposer_index: v.proposer_index,
|
||||
parent_root: shortLog(v.parent_root),
|
||||
state_root: shortLog(v.state_root),
|
||||
eth1data: v.body.eth1_data,
|
||||
graffiti: $v.body.graffiti,
|
||||
proposer_slashings_len: v.body.proposer_slashings.len(),
|
||||
attester_slashings_len: v.body.attester_slashings.len(),
|
||||
attestations_len: v.body.attestations.len(),
|
||||
deposits_len: v.body.deposits.len(),
|
||||
voluntary_exits_len: v.body.voluntary_exits.len(),
|
||||
sync_committee_participants: countOnes(v.body.sync_aggregate.sync_committee_bits)
|
||||
)
|
||||
|
||||
func shortLog*(v: SomeSignedBeaconBlock): auto =
|
||||
(
|
||||
blck: shortLog(v.message),
|
||||
signature: shortLog(v.signature)
|
||||
)
|
||||
|
||||
template asSigned*(
|
||||
x: SigVerifiedSignedBeaconBlock |
|
||||
MsgTrustedSignedBeaconBlock |
|
||||
TrustedSignedBeaconBlock): SignedBeaconBlock =
|
||||
isomorphicCast[SignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified*(
|
||||
x: SignedBeaconBlock |
|
||||
MsgTrustedSignedBeaconBlock |
|
||||
TrustedSignedBeaconBlock): SigVerifiedSignedBeaconBlock =
|
||||
isomorphicCast[SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified*(
|
||||
x: BeaconBlock | TrustedBeaconBlock): SigVerifiedBeaconBlock =
|
||||
isomorphicCast[SigVerifiedBeaconBlock](x)
|
||||
|
||||
template asMsgTrusted*(
|
||||
x: SignedBeaconBlock |
|
||||
SigVerifiedSignedBeaconBlock |
|
||||
TrustedSignedBeaconBlock): MsgTrustedSignedBeaconBlock =
|
||||
isomorphicCast[MsgTrustedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(
|
||||
x: SignedBeaconBlock |
|
||||
SigVerifiedSignedBeaconBlock |
|
||||
MsgTrustedSignedBeaconBlock): TrustedSignedBeaconBlock =
|
||||
isomorphicCast[TrustedSignedBeaconBlock](x)
|
|
@ -33,6 +33,9 @@ const
|
|||
DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF* = DomainType([byte 0x08, 0x00, 0x00, 0x00])
|
||||
DOMAIN_CONTRIBUTION_AND_PROOF* = DomainType([byte 0x09, 0x00, 0x00, 0x00])
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/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.2.0/specs/bellatrix/beacon-chain.md#transition-settings
|
||||
TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH* = FAR_FUTURE_EPOCH
|
||||
|
||||
|
|
|
@ -14,18 +14,28 @@ else:
|
|||
|
||||
import
|
||||
ssz_serialization/[merkleization, proofs],
|
||||
./ssz_codec,
|
||||
./datatypes/[phase0, altair]
|
||||
./ssz_codec
|
||||
|
||||
from ./datatypes/phase0 import HashedBeaconState, SignedBeaconBlock
|
||||
from ./datatypes/altair import HashedBeaconState, SignedBeaconBlock
|
||||
from ./datatypes/bellatrix import HashedBeaconState, SignedBeaconBlock
|
||||
from ./datatypes/capella import HashedBeaconState, SignedBeaconBlock
|
||||
|
||||
export ssz_codec, merkleization, proofs
|
||||
|
||||
type
|
||||
DepositsMerkleizer* = SszMerkleizer[DEPOSIT_CONTRACT_LIMIT]
|
||||
|
||||
func hash_tree_root*(x: phase0.HashedBeaconState | altair.HashedBeaconState) {.
|
||||
# Can't use `ForkyHashedBeaconState`/`ForkyHashedSignedBeaconBlock` without
|
||||
# creating recursive module dependency through `forks`.
|
||||
func hash_tree_root*(
|
||||
x: phase0.HashedBeaconState | altair.HashedBeaconState |
|
||||
bellatrix.HashedBeaconState | capella.HashedBeaconState) {.
|
||||
error: "HashedBeaconState should not be hashed".}
|
||||
|
||||
func hash_tree_root*(x: phase0.SomeSignedBeaconBlock | altair.SomeSignedBeaconBlock) {.
|
||||
func hash_tree_root*(
|
||||
x: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
bellatrix.SignedBeaconBlock | capella.SignedBeaconBlock) {.
|
||||
error: "SignedBeaconBlock should not be hashed".}
|
||||
|
||||
func depositCountU64(s: DepositContractState): uint64 =
|
||||
|
|
|
@ -16,7 +16,7 @@ else:
|
|||
import
|
||||
ssz_serialization,
|
||||
./ssz_codec,
|
||||
./datatypes/[phase0, altair, bellatrix],
|
||||
./datatypes/[phase0, altair, bellatrix, capella],
|
||||
./eth2_merkleization
|
||||
|
||||
export phase0, altair, ssz_codec, ssz_serialization, eth2_merkleization
|
||||
|
@ -48,6 +48,12 @@ template readSszBytes*(
|
|||
template readSszBytes*(
|
||||
data: openArray[byte], val: var bellatrix.TrustedSignedBeaconBlock, updateRoot = true) =
|
||||
readAndUpdateRoot(data, val, updateRoot)
|
||||
template readSszBytes*(
|
||||
data: openArray[byte], val: var capella.SignedBeaconBlock, updateRoot = true) =
|
||||
readAndUpdateRoot(data, val, updateRoot)
|
||||
template readSszBytes*(
|
||||
data: openArray[byte], val: var capella.TrustedSignedBeaconBlock, updateRoot = true) =
|
||||
readAndUpdateRoot(data, val, updateRoot)
|
||||
|
||||
template readSszBytes*(
|
||||
data: openArray[byte], val: var auto, updateRoot: bool) =
|
||||
|
|
|
@ -15,7 +15,7 @@ import
|
|||
chronicles,
|
||||
../extras,
|
||||
"."/[block_id, eth2_merkleization, eth2_ssz_serialization, presets],
|
||||
./datatypes/[phase0, altair, bellatrix],
|
||||
./datatypes/[phase0, altair, bellatrix, capella],
|
||||
./mev/bellatrix_mev
|
||||
|
||||
export
|
||||
|
@ -47,7 +47,8 @@ type
|
|||
ForkyBeaconState* =
|
||||
phase0.BeaconState |
|
||||
altair.BeaconState |
|
||||
bellatrix.BeaconState
|
||||
bellatrix.BeaconState |
|
||||
capella.BeaconState
|
||||
|
||||
ForkyHashedBeaconState* =
|
||||
phase0.HashedBeaconState |
|
||||
|
@ -88,7 +89,8 @@ type
|
|||
ForkyBeaconBlock* =
|
||||
phase0.BeaconBlock |
|
||||
altair.BeaconBlock |
|
||||
bellatrix.BeaconBlock
|
||||
bellatrix.BeaconBlock |
|
||||
capella.BeaconBlock
|
||||
|
||||
ForkySigVerifiedBeaconBlock* =
|
||||
phase0.SigVerifiedBeaconBlock |
|
||||
|
|
|
@ -20,7 +20,7 @@ import
|
|||
chronicles,
|
||||
eth/eip1559, eth/common/[eth_types, eth_types_rlp],
|
||||
# Internal
|
||||
./datatypes/[phase0, altair, bellatrix],
|
||||
./datatypes/[phase0, altair, bellatrix, capella],
|
||||
"."/[eth2_merkleization, forks, ssz_codec]
|
||||
|
||||
# TODO although eth2_merkleization already exports ssz_codec, *sometimes* code
|
||||
|
@ -319,8 +319,10 @@ func contextEpoch*(update: SomeLightClientUpdate): Epoch =
|
|||
update.attested_header.slot.epoch
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/bellatrix/beacon-chain.md#is_merge_transition_complete
|
||||
func is_merge_transition_complete*(state: bellatrix.BeaconState): bool =
|
||||
const defaultExecutionPayloadHeader = default(ExecutionPayloadHeader)
|
||||
func is_merge_transition_complete*(
|
||||
state: bellatrix.BeaconState | capella.BeaconState): bool =
|
||||
const defaultExecutionPayloadHeader =
|
||||
default(typeof(state.latest_execution_payload_header))
|
||||
state.latest_execution_payload_header != defaultExecutionPayloadHeader
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/sync/optimistic.md#helpers
|
||||
|
@ -354,7 +356,8 @@ func compute_timestamp_at_slot*(state: ForkyBeaconState, slot: Slot): uint64 =
|
|||
let slots_since_genesis = slot - GENESIS_SLOT
|
||||
state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT
|
||||
|
||||
proc emptyPayloadToBlockHeader*(payload: ExecutionPayload): ExecutionBlockHeader =
|
||||
proc emptyPayloadToBlockHeader*(
|
||||
payload: bellatrix.ExecutionPayload): ExecutionBlockHeader =
|
||||
## This function assumes that the payload is empty!
|
||||
doAssert payload.transactions.len == 0
|
||||
|
||||
|
@ -377,7 +380,8 @@ proc emptyPayloadToBlockHeader*(payload: ExecutionPayload): ExecutionBlockHeader
|
|||
fee : some payload.base_fee_per_gas
|
||||
)
|
||||
|
||||
func build_empty_execution_payload*(state: bellatrix.BeaconState): ExecutionPayload =
|
||||
func build_empty_execution_payload*(
|
||||
state: bellatrix.BeaconState): bellatrix.ExecutionPayload =
|
||||
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
||||
## without any transactions.
|
||||
let
|
||||
|
@ -388,7 +392,7 @@ func build_empty_execution_payload*(state: bellatrix.BeaconState): ExecutionPayl
|
|||
GasInt.saturate latest.gas_used,
|
||||
latest.base_fee_per_gas)
|
||||
|
||||
var payload = ExecutionPayload(
|
||||
var payload = bellatrix.ExecutionPayload(
|
||||
parent_hash: latest.block_hash,
|
||||
state_root: latest.state_root, # no changes to the state
|
||||
receipts_root: EMPTY_ROOT_HASH,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import
|
||||
./mainnet/[altair_preset, bellatrix_preset, phase0_preset]
|
||||
./mainnet/[altair_preset, bellatrix_preset, capella_preset, phase0_preset]
|
||||
|
||||
export altair_preset, bellatrix_preset, phase0_preset
|
||||
export altair_preset, bellatrix_preset, capella_preset, phase0_preset
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# Mainnet preset - Capella
|
||||
# https://github.com/ethereum/consensus-specs/blob/86e2f8fd7de25a7478c240f0cf5ba3c5264e96bf/presets/mainnet/capella.yaml
|
||||
const
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# 2**8 (= 256) withdrawals
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_EPOCH* = 256
|
||||
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
# 2**40 (= 1,099,511,627,776) withdrawals
|
||||
WITHDRAWAL_QUEUE_LIMIT* = 1099511627776
|
||||
|
||||
|
||||
# Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
# 2**4 (= 16)
|
||||
MAX_BLS_TO_EXECUTION_CHANGES* = 16
|
||||
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
# 2**4 (= 16) withdrawals
|
||||
MAX_WITHDRAWALS_PER_PAYLOAD* = 16
|
|
@ -1,4 +1,4 @@
|
|||
import
|
||||
./minimal/[altair_preset, bellatrix_preset, phase0_preset]
|
||||
./minimal/[altair_preset, bellatrix_preset, capella_preset, phase0_preset]
|
||||
|
||||
export altair_preset, bellatrix_preset, phase0_preset
|
||||
export altair_preset, bellatrix_preset, capella_preset, phase0_preset
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# Minimal preset - Capella
|
||||
# https://github.com/ethereum/consensus-specs/blob/86e2f8fd7de25a7478c240f0cf5ba3c5264e96bf/presets/minimal/capella.yaml
|
||||
const
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# # [customized] 16 for more interesting tests at low validator count
|
||||
MAX_PARTIAL_WITHDRAWALS_PER_EPOCH* = 16
|
||||
|
||||
|
||||
# State list lengths
|
||||
# ---------------------------------------------------------------
|
||||
# 2**40 (= 1,099,511,627,776) withdrawals
|
||||
WITHDRAWAL_QUEUE_LIMIT* = 1099511627776
|
||||
|
||||
|
||||
# Max operations per block
|
||||
# ---------------------------------------------------------------
|
||||
# 2**4 (= 16)
|
||||
MAX_BLS_TO_EXECUTION_CHANGES* = 16
|
||||
|
||||
|
||||
# Execution
|
||||
# ---------------------------------------------------------------
|
||||
# [customized] Lower than MAX_PARTIAL_WITHDRAWALS_PER_EPOCH so not all
|
||||
# processed in one block
|
||||
MAX_WITHDRAWALS_PER_PAYLOAD* = 8
|
|
@ -23,6 +23,8 @@ import
|
|||
./datatypes/[phase0, altair, bellatrix], ./mev/bellatrix_mev, ./helpers,
|
||||
./eth2_merkleization
|
||||
|
||||
from ./datatypes/capella import BLSToExecutionChange, SignedBLSToExecutionChange
|
||||
|
||||
export phase0, altair
|
||||
|
||||
template withTrust(sig: SomeSig, body: untyped): bool =
|
||||
|
@ -368,3 +370,19 @@ proc verify_builder_signature*(
|
|||
pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool =
|
||||
let signing_root = compute_builder_signing_root(fork, msg)
|
||||
blsVerify(pubkey, signing_root.data, signature)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
|
||||
func compute_bls_to_execution_change_signing_root(
|
||||
fork: Fork, genesis_validators_root: Eth2Digest,
|
||||
epoch: Epoch, msg: BLSToExecutionChange): Eth2Digest =
|
||||
let domain = get_domain(
|
||||
fork, DOMAIN_BLS_TO_EXECUTION_CHANGE, epoch, genesis_validators_root)
|
||||
compute_signing_root(msg, domain)
|
||||
|
||||
proc verify_bls_to_execution_change_signature*(
|
||||
fork: Fork, genesis_validators_root: Eth2Digest, epoch: Epoch,
|
||||
msg: SignedBLSToExecutionChange,
|
||||
pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool =
|
||||
let signing_root = compute_bls_to_execution_change_signing_root(
|
||||
fork, genesis_validators_root, epoch, msg.message)
|
||||
blsVerify(pubkey, signing_root.data, signature)
|
||||
|
|
|
@ -29,6 +29,9 @@ import
|
|||
./datatypes/[phase0, altair, bellatrix],
|
||||
"."/[beaconstate, eth2_merkleization, helpers, validator, signatures]
|
||||
|
||||
from ./datatypes/capella import
|
||||
BeaconState, MAX_WITHDRAWALS_PER_PAYLOAD, SignedBLSToExecutionChange
|
||||
|
||||
export extras, phase0, altair
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#block-header
|
||||
|
@ -311,7 +314,7 @@ proc process_deposit*(cfg: RuntimeConfig,
|
|||
static: doAssert state.balances.maxLen == state.validators.maxLen
|
||||
raiseAssert "adding validator succeeded, so should balances"
|
||||
|
||||
when state is altair.BeaconState or state is bellatrix.BeaconState:
|
||||
when state is altair.BeaconState or state is bellatrix.BeaconState or state is capella.BeaconState:
|
||||
if not state.previous_epoch_participation.add(ParticipationFlags(0)):
|
||||
return err("process_deposit: too many validators (previous_epoch_participation)")
|
||||
if not state.current_epoch_participation.add(ParticipationFlags(0)):
|
||||
|
@ -437,7 +440,7 @@ func get_proposer_reward*(participant_reward: Gwei): Gwei =
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#sync-committee-processing
|
||||
proc process_sync_aggregate*(
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState),
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState),
|
||||
sync_aggregate: SomeSyncAggregate, total_active_balance: Gwei,
|
||||
cache: var StateCache):
|
||||
Result[void, cstring] =
|
||||
|
@ -493,8 +496,8 @@ proc process_sync_aggregate*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/bellatrix/beacon-chain.md#process_execution_payload
|
||||
proc process_execution_payload*(
|
||||
state: var bellatrix.BeaconState, payload: ExecutionPayload,
|
||||
notify_new_payload: ExecutePayload): Result[void, cstring] =
|
||||
state: var bellatrix.BeaconState, payload: bellatrix.ExecutionPayload,
|
||||
notify_new_payload: bellatrix.ExecutePayload): Result[void, cstring] =
|
||||
## Verify consistency of the parent hash with respect to the previous
|
||||
## execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
|
@ -515,7 +518,7 @@ proc process_execution_payload*(
|
|||
return err("process_execution_payload: execution payload invalid")
|
||||
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = ExecutionPayloadHeader(
|
||||
state.latest_execution_payload_header = bellatrix.ExecutionPayloadHeader(
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
|
@ -533,6 +536,107 @@ proc process_execution_payload*(
|
|||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#modified-process_execution_payload
|
||||
proc process_execution_payload*(
|
||||
state: var capella.BeaconState, payload: capella.ExecutionPayload,
|
||||
notify_new_payload: capella.ExecutePayload): Result[void, cstring] =
|
||||
## Verify consistency of the parent hash with respect to the previous
|
||||
## execution payload header
|
||||
if is_merge_transition_complete(state):
|
||||
if not (payload.parent_hash ==
|
||||
state.latest_execution_payload_header.block_hash):
|
||||
return err("process_execution_payload: payload and state parent hash mismatch")
|
||||
|
||||
# Verify prev_randao
|
||||
if not (payload.prev_randao == get_randao_mix(state, get_current_epoch(state))):
|
||||
return err("process_execution_payload: payload and state randomness mismatch")
|
||||
|
||||
# Verify timestamp
|
||||
if not (payload.timestamp == compute_timestamp_at_slot(state, state.slot)):
|
||||
return err("process_execution_payload: invalid timestamp")
|
||||
|
||||
# Verify the execution payload is valid
|
||||
if not notify_new_payload(payload):
|
||||
return err("process_execution_payload: execution payload invalid")
|
||||
|
||||
# Cache execution payload header
|
||||
state.latest_execution_payload_header = capella.ExecutionPayloadHeader(
|
||||
parent_hash: payload.parent_hash,
|
||||
fee_recipient: payload.fee_recipient,
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom,
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
timestamp: payload.timestamp,
|
||||
base_fee_per_gas: payload.base_fee_per_gas,
|
||||
block_hash: payload.block_hash,
|
||||
extra_data: payload.extra_data,
|
||||
transactions_root: hash_tree_root(payload.transactions),
|
||||
withdrawals_root: hash_tree_root(payload.withdrawals)) # [New in Capella]
|
||||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#new-process_bls_to_execution_change
|
||||
proc process_bls_to_execution_change*(
|
||||
state: var capella.BeaconState,
|
||||
signed_address_change: SignedBLSToExecutionChange): Result[void, cstring] =
|
||||
let address_change = signed_address_change.message
|
||||
|
||||
if not (address_change.validator_index < state.validators.lenu64):
|
||||
return err("process_bls_to_execution_change: invalid validator index")
|
||||
|
||||
var withdrawal_credentials =
|
||||
state.validators.item(address_change.validator_index).withdrawal_credentials
|
||||
|
||||
if not (withdrawal_credentials.data[0] == BLS_WITHDRAWAL_PREFIX):
|
||||
return err("process_bls_to_execution_change: invalid withdrawal prefix")
|
||||
|
||||
# TODO what's usual convention here re 32 hardcoded constant?
|
||||
if not (withdrawal_credentials.data.toOpenArray(1, 31) ==
|
||||
eth2digest(address_change.from_bls_pubkey.blob).data.toOpenArray(1, 31)):
|
||||
return err("process_bls_to_execution_change: invalid withdrawal credentials")
|
||||
|
||||
if not verify_bls_to_execution_change_signature(
|
||||
state.fork, state.genesis_validators_root, state.get_current_epoch,
|
||||
signed_address_change, address_change.from_bls_pubkey,
|
||||
signed_address_change.signature):
|
||||
return err("process_bls_to_execution_change: invalid signature")
|
||||
|
||||
withdrawal_credentials.data[0] = ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
||||
withdrawal_credentials.data.fill(1, 11, 0)
|
||||
withdrawal_credentials.data[12..31] =
|
||||
address_change.to_execution_address.data
|
||||
state.validators.mitem(address_change.validator_index).withdrawal_credentials =
|
||||
withdrawal_credentials
|
||||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/53b63cedc586c3e1cc2ff737e85c1ed8a3eb45c6/specs/capella/beacon-chain.md#new-process_withdrawals
|
||||
func process_withdrawals*(
|
||||
state: var capella.BeaconState, payload: capella.ExecutionPayload):
|
||||
Result[void, cstring] =
|
||||
let
|
||||
num_withdrawals =
|
||||
min(MAX_WITHDRAWALS_PER_PAYLOAD, len(state.withdrawal_queue))
|
||||
dequeued_withdrawals = state.withdrawal_queue.asSeq[0 ..< num_withdrawals]
|
||||
|
||||
if not (len(dequeued_withdrawals) == len(payload.withdrawals)):
|
||||
return err("process_withdrawals: different numbers of dequeued and payload withdrawals")
|
||||
|
||||
for i in 0 ..< len(dequeued_withdrawals):
|
||||
if not (dequeued_withdrawals[i] == payload.withdrawals[i]):
|
||||
return err("process_withdrawals: mismatched queued and payload withdrawals")
|
||||
|
||||
# Remove dequeued withdrawals from state
|
||||
if num_withdrawals > 0:
|
||||
state.withdrawal_queue.asSeq.delete(0, num_withdrawals - 1)
|
||||
state.withdrawal_queue.resetCache()
|
||||
|
||||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#block-processing
|
||||
# TODO workaround for https://github.com/nim-lang/Nim/issues/18095
|
||||
# copy of datatypes/phase0.nim
|
||||
|
@ -597,7 +701,6 @@ proc process_block*(
|
|||
if is_execution_enabled(state, blck.body):
|
||||
? process_execution_payload(
|
||||
state, blck.body.execution_payload,
|
||||
# TODO this is enough to pass consensus spec tests
|
||||
func(_: ExecutionPayload): bool = true)
|
||||
? process_randao(state, blck.body, flags, cache)
|
||||
? process_eth1_data(state, blck.body)
|
||||
|
|
|
@ -30,6 +30,8 @@ import
|
|||
./datatypes/[phase0, altair, bellatrix],
|
||||
"."/[beaconstate, eth2_merkleization, helpers, validator]
|
||||
|
||||
from ./datatypes/capella import BeaconState
|
||||
|
||||
export extras, phase0, altair
|
||||
|
||||
# Logging utilities
|
||||
|
@ -173,7 +175,7 @@ func is_eligible_validator*(validator: ParticipationInfo): bool =
|
|||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_unslashed_participating_indices
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/phase0/beacon-chain.md#get_total_balance
|
||||
func get_unslashed_participating_balances*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState
|
||||
): UnslashedParticipatingBalances =
|
||||
let
|
||||
previous_epoch = get_previous_epoch(state)
|
||||
|
@ -224,8 +226,8 @@ func get_unslashed_participating_balances*(
|
|||
res
|
||||
|
||||
func is_unslashed_participating_index(
|
||||
state: altair.BeaconState | bellatrix.BeaconState, flag_index: int, epoch: Epoch,
|
||||
validator_index: ValidatorIndex): bool =
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
flag_index: int, epoch: Epoch, validator_index: ValidatorIndex): bool =
|
||||
doAssert epoch in [get_previous_epoch(state), get_current_epoch(state)]
|
||||
# TODO hoist this conditional
|
||||
let epoch_participation =
|
||||
|
@ -420,7 +422,7 @@ proc compute_unrealized_finality*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#justification-and-finalization
|
||||
proc process_justification_and_finalization*(
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState),
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState),
|
||||
balances: UnslashedParticipatingBalances,
|
||||
flags: UpdateFlags = {}) =
|
||||
# Initial FFG checkpoint values have a `0x00` stub for `root`.
|
||||
|
@ -624,8 +626,8 @@ func get_attestation_deltas(state: phase0.BeaconState, info: var phase0.EpochInf
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_base_reward
|
||||
func get_base_reward_increment*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState, index: ValidatorIndex,
|
||||
base_reward_per_increment: Gwei): Gwei =
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
index: ValidatorIndex, base_reward_per_increment: Gwei): Gwei =
|
||||
## Return the base reward for the validator defined by ``index`` with respect
|
||||
## to the current ``state``.
|
||||
let increments =
|
||||
|
@ -633,10 +635,11 @@ func get_base_reward_increment*(
|
|||
increments * base_reward_per_increment
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_flag_index_deltas
|
||||
func get_flag_index_reward*(state: altair.BeaconState | bellatrix.BeaconState,
|
||||
base_reward: Gwei, active_increments: Gwei,
|
||||
unslashed_participating_increments: Gwei,
|
||||
weight, finality_delay: uint64): Gwei =
|
||||
func get_flag_index_reward*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
base_reward: Gwei, active_increments: Gwei,
|
||||
unslashed_participating_increments: Gwei,
|
||||
weight, finality_delay: uint64): Gwei =
|
||||
if not is_in_inactivity_leak(finality_delay):
|
||||
let reward_numerator =
|
||||
base_reward * weight * unslashed_participating_increments
|
||||
|
@ -655,10 +658,9 @@ func get_active_increments*(info: altair.EpochInfo | bellatrix.BeaconState): Gwe
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#get_flag_index_deltas
|
||||
iterator get_flag_index_deltas*(
|
||||
state: altair.BeaconState | bellatrix.BeaconState, flag_index: int,
|
||||
base_reward_per_increment: Gwei,
|
||||
info: var altair.EpochInfo,
|
||||
finality_delay: uint64):
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState,
|
||||
flag_index: int, base_reward_per_increment: Gwei,
|
||||
info: var altair.EpochInfo, finality_delay: uint64):
|
||||
(ValidatorIndex, RewardDelta) =
|
||||
## Return the deltas for a given ``flag_index`` by scanning through the
|
||||
## participation flags.
|
||||
|
@ -722,8 +724,8 @@ iterator get_inactivity_penalty_deltas*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/bellatrix/beacon-chain.md#modified-get_inactivity_penalty_deltas
|
||||
iterator get_inactivity_penalty_deltas*(
|
||||
cfg: RuntimeConfig, state: bellatrix.BeaconState, info: altair.EpochInfo):
|
||||
(ValidatorIndex, Gwei) =
|
||||
cfg: RuntimeConfig, state: bellatrix.BeaconState | capella.BeaconState,
|
||||
info: altair.EpochInfo): (ValidatorIndex, Gwei) =
|
||||
## Return the inactivity penalty deltas by considering timely target
|
||||
## participation flags and inactivity scores.
|
||||
let
|
||||
|
@ -768,7 +770,7 @@ func process_rewards_and_penalties(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#rewards-and-penalties
|
||||
func process_rewards_and_penalties(
|
||||
cfg: RuntimeConfig, state: var (altair.BeaconState | bellatrix.BeaconState),
|
||||
cfg: RuntimeConfig, state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState),
|
||||
info: var altair.EpochInfo)
|
||||
=
|
||||
if get_current_epoch(state) == GENESIS_EPOCH:
|
||||
|
@ -868,6 +870,8 @@ func get_adjusted_total_slashing_balance*(
|
|||
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR
|
||||
elif state is bellatrix.BeaconState:
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX
|
||||
elif state is capella.BeaconState:
|
||||
PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX
|
||||
else:
|
||||
{.fatal: "process_slashings: incorrect BeaconState type".}
|
||||
min(sum(state.slashings.data) * multiplier, total_balance)
|
||||
|
@ -983,7 +987,8 @@ func process_participation_record_updates*(state: var phase0.BeaconState) =
|
|||
swap(state.previous_epoch_attestations, state.current_epoch_attestations)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#participation-flags-updates
|
||||
func process_participation_flag_updates*(state: var (altair.BeaconState | bellatrix.BeaconState)) =
|
||||
func process_participation_flag_updates*(
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState)) =
|
||||
state.previous_epoch_participation = state.current_epoch_participation
|
||||
|
||||
const zero = 0.ParticipationFlags
|
||||
|
@ -998,7 +1003,7 @@ func process_participation_flag_updates*(state: var (altair.BeaconState | bellat
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#sync-committee-updates
|
||||
func process_sync_committee_updates*(
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState)) =
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState)) =
|
||||
let next_epoch = get_current_epoch(state) + 1
|
||||
if next_epoch.is_sync_committee_period():
|
||||
state.current_sync_committee = state.next_sync_committee
|
||||
|
@ -1006,7 +1011,8 @@ func process_sync_committee_updates*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#inactivity-scores
|
||||
func process_inactivity_updates*(
|
||||
cfg: RuntimeConfig, state: var (altair.BeaconState | bellatrix.BeaconState),
|
||||
cfg: RuntimeConfig,
|
||||
state: var (altair.BeaconState | bellatrix.BeaconState | capella.BeaconState),
|
||||
info: altair.EpochInfo) =
|
||||
# Score updates based on previous epoch participation, skip genesis epoch
|
||||
if get_current_epoch(state) == GENESIS_EPOCH:
|
||||
|
@ -1076,7 +1082,7 @@ proc process_epoch*(
|
|||
|
||||
func init*(
|
||||
info: var altair.EpochInfo,
|
||||
state: altair.BeaconState | bellatrix.BeaconState) =
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState) =
|
||||
# init participation, overwriting the full structure
|
||||
info.balances = get_unslashed_participating_balances(state)
|
||||
info.validators.setLen(state.validators.len())
|
||||
|
@ -1092,7 +1098,8 @@ func init*(
|
|||
)
|
||||
|
||||
func init*(
|
||||
T: type altair.EpochInfo, state: altair.BeaconState | bellatrix.BeaconState): T =
|
||||
T: type altair.EpochInfo,
|
||||
state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState): T =
|
||||
init(result, state)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/beacon-chain.md#epoch-processing
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
./test_fixture_fork,
|
||||
./test_fixture_operations,
|
||||
#./test_fixture_sanity_blocks, # TODO needs forked
|
||||
#./test_fixture_sanity_slots, # TODO needs forked
|
||||
./test_fixture_ssz_consensus_objects,
|
||||
./test_fixture_state_transition_epoch
|
||||
#./test_fixture_transition # TODO needs forked
|
|
@ -0,0 +1,44 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2021-2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
# Standard library
|
||||
os,
|
||||
# Beacon chain internals
|
||||
../../../beacon_chain/spec/[beaconstate, helpers],
|
||||
../../../beacon_chain/spec/datatypes/[bellatrix, capella],
|
||||
# Test utilities
|
||||
../../testutil,
|
||||
../fixtures_utils,
|
||||
../../helpers/debug_state
|
||||
|
||||
const OpForkDir = SszTestsDir/const_preset/"capella"/"fork"/"fork"/"pyspec_tests"
|
||||
|
||||
proc runTest(identifier: string) =
|
||||
let testDir = OpForkDir / identifier
|
||||
|
||||
proc `testImpl _ fork _ identifier`() =
|
||||
test identifier:
|
||||
let
|
||||
preState = newClone(
|
||||
parseTest(testDir/"pre.ssz_snappy", SSZ, bellatrix.BeaconState))
|
||||
postState = newClone(
|
||||
parseTest(testDir/"post.ssz_snappy", SSZ, capella.BeaconState))
|
||||
|
||||
let cfg = defaultRuntimeConfig
|
||||
|
||||
let upgradedState = upgrade_to_capella(cfg, preState[])
|
||||
check: upgradedState[].hash_tree_root() == postState[].hash_tree_root()
|
||||
reportDiff(upgradedState, postState)
|
||||
|
||||
`testImpl _ fork _ identifier`()
|
||||
|
||||
suite "EF - Capella - Fork " & preset():
|
||||
for kind, path in walkDir(OpForkDir, relative = true, checkDir = true):
|
||||
runTest(path)
|
|
@ -0,0 +1,207 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
# Standard library
|
||||
std/[os, sequtils, sets, strutils],
|
||||
# Utilities
|
||||
chronicles,
|
||||
unittest2,
|
||||
stew/results,
|
||||
# Beacon chain internals
|
||||
../../../beacon_chain/spec/[beaconstate, state_transition_block],
|
||||
../../../beacon_chain/spec/datatypes/capella,
|
||||
# Test utilities
|
||||
../../testutil,
|
||||
../fixtures_utils,
|
||||
../../helpers/debug_state
|
||||
|
||||
const
|
||||
OpDir = SszTestsDir/const_preset/"capella"/"operations"
|
||||
OpAttestationsDir = OpDir/"attestation"
|
||||
OpAttSlashingDir = OpDir/"attester_slashing"
|
||||
OpBlockHeaderDir = OpDir/"block_header"
|
||||
OpBlsToExecutionChangeDir = OpDir/"bls_to_execution_change"
|
||||
OpDepositsDir = OpDir/"deposit"
|
||||
OpExecutionPayloadDir = OpDir/"execution_payload"
|
||||
OpProposerSlashingDir = OpDir/"proposer_slashing"
|
||||
OpSyncAggregateDir = OpDir/"sync_aggregate"
|
||||
OpVoluntaryExitDir = OpDir/"voluntary_exit"
|
||||
OpWithdrawalsDir = OpDir/"withdrawals"
|
||||
|
||||
baseDescription = "EF - Capella - Operations - "
|
||||
|
||||
doAssert toHashSet(mapIt(toSeq(walkDir(OpDir, relative = false)), it.path)) ==
|
||||
toHashSet([
|
||||
OpAttestationsDir, OpAttSlashingDir, OpBlockHeaderDir,
|
||||
OpBlsToExecutionChangeDir, OpDepositsDir, OpExecutionPayloadDir,
|
||||
OpProposerSlashingDir, OpSyncAggregateDir, OpVoluntaryExitDir,
|
||||
OpWithdrawalsDir])
|
||||
|
||||
proc runTest[T, U](
|
||||
testSuiteDir: string, testSuiteName: string, applyFile: string,
|
||||
applyProc: U, identifier: string) =
|
||||
let testDir = testSuiteDir / "pyspec_tests" / identifier
|
||||
|
||||
proc testImpl() =
|
||||
let prefix =
|
||||
if fileExists(testDir/"post.ssz_snappy"):
|
||||
"[Valid] "
|
||||
else:
|
||||
"[Invalid] "
|
||||
|
||||
test prefix & baseDescription & testSuiteName & " - " & identifier:
|
||||
let preState = newClone(
|
||||
parseTest(testDir/"pre.ssz_snappy", SSZ, capella.BeaconState))
|
||||
let done = applyProc(
|
||||
preState[], parseTest(testDir/(applyFile & ".ssz_snappy"), SSZ, T))
|
||||
|
||||
if fileExists(testDir/"post.ssz_snappy"):
|
||||
let postState =
|
||||
newClone(parseTest(
|
||||
testDir/"post.ssz_snappy", SSZ, capella.BeaconState))
|
||||
|
||||
reportDiff(preState, postState)
|
||||
check:
|
||||
done.isOk()
|
||||
preState[].hash_tree_root() == postState[].hash_tree_root()
|
||||
else:
|
||||
check: done.isErr() # No post state = processing should fail
|
||||
|
||||
testImpl()
|
||||
|
||||
suite baseDescription & "Attestation " & preset():
|
||||
proc applyAttestation(
|
||||
preState: var capella.BeaconState, attestation: Attestation):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
let
|
||||
total_active_balance = get_total_active_balance(preState, cache)
|
||||
base_reward_per_increment =
|
||||
get_base_reward_per_increment(total_active_balance)
|
||||
|
||||
process_attestation(
|
||||
preState, attestation, {}, base_reward_per_increment, cache)
|
||||
|
||||
for path in walkTests(OpAttestationsDir):
|
||||
runTest[Attestation, typeof applyAttestation](
|
||||
OpAttestationsDir, "Attestation", "attestation", applyAttestation, path)
|
||||
|
||||
suite baseDescription & "Attester Slashing " & preset():
|
||||
proc applyAttesterSlashing(
|
||||
preState: var capella.BeaconState, attesterSlashing: AttesterSlashing):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
process_attester_slashing(
|
||||
defaultRuntimeConfig, preState, attesterSlashing, {}, cache)
|
||||
|
||||
for path in walkTests(OpAttSlashingDir):
|
||||
runTest[AttesterSlashing, typeof applyAttesterSlashing](
|
||||
OpAttSlashingDir, "Attester Slashing", "attester_slashing",
|
||||
applyAttesterSlashing, path)
|
||||
|
||||
suite baseDescription & "Block Header " & preset():
|
||||
func applyBlockHeader(
|
||||
preState: var capella.BeaconState, blck: capella.BeaconBlock):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
process_block_header(preState, blck, {}, cache)
|
||||
|
||||
for path in walkTests(OpBlockHeaderDir):
|
||||
runTest[capella.BeaconBlock, typeof applyBlockHeader](
|
||||
OpBlockHeaderDir, "Block Header", "block", applyBlockHeader, path)
|
||||
|
||||
suite baseDescription & "BLS to execution change " & preset():
|
||||
proc applyBlsToExecutionChange(
|
||||
preState: var capella.BeaconState,
|
||||
signed_address_change: SignedBLSToExecutionChange):
|
||||
Result[void, cstring] =
|
||||
process_bls_to_execution_change(preState, signed_address_change)
|
||||
|
||||
for path in walkTests(OpBlsToExecutionChangeDir):
|
||||
runTest[SignedBLSToExecutionChange, typeof applyBlsToExecutionChange](
|
||||
OpBlsToExecutionChangeDir, "BLS to execution change", "address_change",
|
||||
applyBlsToExecutionChange, path)
|
||||
|
||||
suite baseDescription & "Deposit " & preset():
|
||||
proc applyDeposit(
|
||||
preState: var capella.BeaconState, deposit: Deposit):
|
||||
Result[void, cstring] =
|
||||
process_deposit(defaultRuntimeConfig, preState, deposit, {})
|
||||
|
||||
for path in walkTests(OpDepositsDir):
|
||||
runTest[Deposit, typeof applyDeposit](
|
||||
OpDepositsDir, "Deposit", "deposit", applyDeposit, path)
|
||||
|
||||
suite baseDescription & "Execution Payload " & preset():
|
||||
for path in walkTests(OpExecutionPayloadDir):
|
||||
proc applyExecutionPayload(
|
||||
preState: var capella.BeaconState,
|
||||
executionPayload: capella.ExecutionPayload):
|
||||
Result[void, cstring] =
|
||||
let payloadValid =
|
||||
readFile(OpExecutionPayloadDir/"pyspec_tests"/path/"execution.yaml").
|
||||
contains("execution_valid: true")
|
||||
func executePayload(_: capella.ExecutionPayload): bool = payloadValid
|
||||
process_execution_payload(
|
||||
preState, executionPayload, executePayload)
|
||||
|
||||
runTest[capella.ExecutionPayload, typeof applyExecutionPayload](
|
||||
OpExecutionPayloadDir, "Execution Payload", "execution_payload",
|
||||
applyExecutionPayload, path)
|
||||
|
||||
suite baseDescription & "Proposer Slashing " & preset():
|
||||
proc applyProposerSlashing(
|
||||
preState: var capella.BeaconState, proposerSlashing: ProposerSlashing):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
process_proposer_slashing(
|
||||
defaultRuntimeConfig, preState, proposerSlashing, {}, cache)
|
||||
|
||||
for path in walkTests(OpProposerSlashingDir):
|
||||
runTest[ProposerSlashing, typeof applyProposerSlashing](
|
||||
OpProposerSlashingDir, "Proposer Slashing", "proposer_slashing",
|
||||
applyProposerSlashing, path)
|
||||
|
||||
suite baseDescription & "Sync Aggregate " & preset():
|
||||
proc applySyncAggregate(
|
||||
preState: var capella.BeaconState, syncAggregate: SyncAggregate):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
process_sync_aggregate(
|
||||
preState, syncAggregate, get_total_active_balance(preState, cache), cache)
|
||||
|
||||
for path in walkTests(OpSyncAggregateDir):
|
||||
runTest[SyncAggregate, typeof applySyncAggregate](
|
||||
OpSyncAggregateDir, "Sync Aggregate", "sync_aggregate",
|
||||
applySyncAggregate, path)
|
||||
|
||||
suite baseDescription & "Voluntary Exit " & preset():
|
||||
proc applyVoluntaryExit(
|
||||
preState: var capella.BeaconState, voluntaryExit: SignedVoluntaryExit):
|
||||
Result[void, cstring] =
|
||||
var cache = StateCache()
|
||||
process_voluntary_exit(
|
||||
defaultRuntimeConfig, preState, voluntaryExit, {}, cache)
|
||||
|
||||
for path in walkTests(OpVoluntaryExitDir):
|
||||
runTest[SignedVoluntaryExit, typeof applyVoluntaryExit](
|
||||
OpVoluntaryExitDir, "Voluntary Exit", "voluntary_exit",
|
||||
applyVoluntaryExit, path)
|
||||
|
||||
suite baseDescription & "Withdrawals " & preset():
|
||||
proc applyWithdrawals(
|
||||
preState: var capella.BeaconState,
|
||||
executionPayload: capella.ExecutionPayload): Result[void, cstring] =
|
||||
process_withdrawals(preState, executionPayload)
|
||||
|
||||
for path in walkTests(OpWithdrawalsDir):
|
||||
runTest[capella.ExecutionPayload, typeof applyWithdrawals](
|
||||
OpWithdrawalsDir, "Withdrawals", "execution_payload",
|
||||
applyWithdrawals, path)
|
|
@ -0,0 +1,85 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2020-2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
# Standard library
|
||||
std/os,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/[beaconstate, validator, helpers, state_transition_epoch],
|
||||
../../beacon_chain/spec/datatypes/[altair, capella],
|
||||
# Test utilities
|
||||
../../testutil,
|
||||
../fixtures_utils
|
||||
|
||||
const
|
||||
RewardsDirBase = SszTestsDir/const_preset/"capella"/"rewards"
|
||||
RewardsDirBasic = RewardsDirBase/"basic"/"pyspec_tests"
|
||||
RewardsDirLeak = RewardsDirBase/"leak"/"pyspec_tests"
|
||||
RewardsDirRandom = RewardsDirBase/"random"/"pyspec_tests"
|
||||
|
||||
func init(T: type Deltas, len: int): T =
|
||||
if not result.rewards.setLen(len):
|
||||
raiseAssert "setLen"
|
||||
if not result.penalties.setLen(len):
|
||||
raiseAssert "setLen"
|
||||
|
||||
proc runTest(rewardsDir, identifier: string) =
|
||||
let testDir = rewardsDir / identifier
|
||||
|
||||
proc `testImpl _ rewards _ identifier`() =
|
||||
test "EF - Capella - Rewards - " & identifier & preset():
|
||||
var info: altair.EpochInfo
|
||||
|
||||
let
|
||||
state = newClone(
|
||||
parseTest(testDir/"pre.ssz_snappy", SSZ, capella.BeaconState))
|
||||
flagDeltas = [
|
||||
parseTest(testDir/"source_deltas.ssz_snappy", SSZ, Deltas),
|
||||
parseTest(testDir/"target_deltas.ssz_snappy", SSZ, Deltas),
|
||||
parseTest(testDir/"head_deltas.ssz_snappy", SSZ, Deltas)]
|
||||
inactivityPenaltyDeltas =
|
||||
parseTest(testDir/"inactivity_penalty_deltas.ssz_snappy", SSZ, Deltas)
|
||||
|
||||
info.init(state[])
|
||||
let
|
||||
total_balance = info.balances.current_epoch
|
||||
base_reward_per_increment = get_base_reward_per_increment(total_balance)
|
||||
|
||||
static: doAssert PARTICIPATION_FLAG_WEIGHTS.len == 3
|
||||
var
|
||||
flagDeltas2 = [
|
||||
Deltas.init(state[].validators.len),
|
||||
Deltas.init(state[].validators.len),
|
||||
Deltas.init(state[].validators.len)]
|
||||
inactivityPenaltyDeltas2 = Deltas.init(state[].validators.len)
|
||||
|
||||
let finality_delay = get_finality_delay(state[])
|
||||
|
||||
for flag_index in 0 ..< PARTICIPATION_FLAG_WEIGHTS.len:
|
||||
for validator_index, delta in get_flag_index_deltas(
|
||||
state[], flag_index, base_reward_per_increment, info, finality_delay):
|
||||
if not is_eligible_validator(info.validators[validator_index]):
|
||||
continue
|
||||
flagDeltas2[flag_index].rewards[validator_index] = delta.rewards
|
||||
flagDeltas2[flag_index].penalties[validator_index] = delta.penalties
|
||||
|
||||
for validator_index, delta in get_inactivity_penalty_deltas(
|
||||
defaultRuntimeConfig, state[], info):
|
||||
inactivityPenaltyDeltas2.penalties[validator_index] = delta
|
||||
|
||||
check:
|
||||
flagDeltas == flagDeltas2
|
||||
inactivityPenaltyDeltas == inactivityPenaltyDeltas2
|
||||
|
||||
`testImpl _ rewards _ identifier`()
|
||||
|
||||
suite "EF - Capella - Rewards " & preset():
|
||||
for rewardsDir in [RewardsDirBasic, RewardsDirLeak, RewardsDirRandom]:
|
||||
for kind, path in walkDir(rewardsDir, relative = true, checkDir = true):
|
||||
runTest(rewardsDir, path)
|
|
@ -0,0 +1,157 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
# Standard library
|
||||
os, strutils, streams, strformat,
|
||||
macros, sets,
|
||||
# Third-party
|
||||
yaml,
|
||||
# Beacon chain internals
|
||||
../../beacon_chain/spec/datatypes/capella,
|
||||
# Status libraries
|
||||
snappy,
|
||||
# Test utilities
|
||||
../../testutil, ../fixtures_utils
|
||||
|
||||
from ../../beacon_chain/spec/datatypes/bellatrix import PowBlock
|
||||
|
||||
# SSZ tests of consensus objects (minimal/mainnet preset specific)
|
||||
|
||||
# Parsing definitions
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
const
|
||||
SSZDir = SszTestsDir/const_preset/"capella"/"ssz_static"
|
||||
|
||||
type
|
||||
SSZHashTreeRoot = object
|
||||
# The test files have the values at the "root"
|
||||
# so we **must** use "root" as a field name
|
||||
root: string
|
||||
# Some have a signing_root field
|
||||
signing_root {.defaultVal: "".}: string
|
||||
|
||||
# Note this only tracks HashTreeRoot
|
||||
# Checking the values against the yaml file is TODO (require more flexible Yaml parser)
|
||||
|
||||
proc checkSSZ(T: type capella.SignedBeaconBlock, dir: string, expectedHash: SSZHashTreeRoot) =
|
||||
# Deserialize into a ref object to not fill Nim stack
|
||||
let encoded = snappy.decode(
|
||||
readFileBytes(dir/"serialized.ssz_snappy"), MaxObjectSize)
|
||||
let deserialized = newClone(sszDecodeEntireInput(encoded, T))
|
||||
|
||||
# SignedBeaconBlocks usually not hashed because they're identified by
|
||||
# htr(BeaconBlock), so do it manually
|
||||
check: expectedHash.root == "0x" & toLowerAscii($hash_tree_root(
|
||||
[hash_tree_root(deserialized.message),
|
||||
hash_tree_root(deserialized.signature)]))
|
||||
|
||||
check deserialized.root == hash_tree_root(deserialized.message)
|
||||
check SSZ.encode(deserialized[]) == encoded
|
||||
check sszSize(deserialized[]) == encoded.len
|
||||
|
||||
# TODO check the value (requires YAML loader)
|
||||
|
||||
proc checkSSZ(T: type, dir: string, expectedHash: SSZHashTreeRoot) =
|
||||
# Deserialize into a ref object to not fill Nim stack
|
||||
let encoded = snappy.decode(
|
||||
readFileBytes(dir/"serialized.ssz_snappy"), MaxObjectSize)
|
||||
let deserialized = newClone(sszDecodeEntireInput(encoded, T))
|
||||
|
||||
check: expectedHash.root == "0x" & toLowerAscii($hash_tree_root(deserialized[]))
|
||||
|
||||
check SSZ.encode(deserialized[]) == encoded
|
||||
check sszSize(deserialized[]) == encoded.len
|
||||
|
||||
# TODO check the value (requires YAML loader)
|
||||
|
||||
proc loadExpectedHashTreeRoot(dir: string): SSZHashTreeRoot =
|
||||
let s = openFileStream(dir/"roots.yaml")
|
||||
yaml.load(s, result)
|
||||
s.close()
|
||||
|
||||
# Test runner
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
suite "EF - Capella - SSZ consensus objects " & preset():
|
||||
doAssert dirExists(SSZDir), "You need to run the \"download_test_vectors.sh\" script to retrieve the consensus spec test vectors."
|
||||
for pathKind, sszType in walkDir(SSZDir, relative = true, checkDir = true):
|
||||
doAssert pathKind == pcDir
|
||||
|
||||
test &" Testing {sszType}":
|
||||
let path = SSZDir/sszType
|
||||
for pathKind, sszTestKind in walkDir(
|
||||
path, relative = true, checkDir = true):
|
||||
doAssert pathKind == pcDir
|
||||
let path = SSZDir/sszType/sszTestKind
|
||||
for pathKind, sszTestCase in walkDir(
|
||||
path, relative = true, checkDir = true):
|
||||
let path = SSZDir/sszType/sszTestKind/sszTestCase
|
||||
let hash = loadExpectedHashTreeRoot(path)
|
||||
|
||||
case sszType:
|
||||
of "AggregateAndProof": checkSSZ(AggregateAndProof, path, hash)
|
||||
of "Attestation": checkSSZ(Attestation, path, hash)
|
||||
of "AttestationData": checkSSZ(AttestationData, path, hash)
|
||||
of "AttesterSlashing": checkSSZ(AttesterSlashing, path, hash)
|
||||
of "BeaconBlock": checkSSZ(capella.BeaconBlock, path, hash)
|
||||
of "BeaconBlockBody": checkSSZ(capella.BeaconBlockBody, path, hash)
|
||||
of "BeaconBlockHeader": checkSSZ(BeaconBlockHeader, path, hash)
|
||||
of "BeaconState": checkSSZ(capella.BeaconState, path, hash)
|
||||
of "BLSToExecutionChange": checkSSZ(BLSToExecutionChange, path, hash)
|
||||
of "Checkpoint": checkSSZ(Checkpoint, path, hash)
|
||||
of "ContributionAndProof": checkSSZ(ContributionAndProof, path, hash)
|
||||
of "Deposit": checkSSZ(Deposit, path, hash)
|
||||
of "DepositData": checkSSZ(DepositData, path, hash)
|
||||
of "DepositMessage": checkSSZ(DepositMessage, path, hash)
|
||||
of "Eth1Block": checkSSZ(Eth1Block, path, hash)
|
||||
of "Eth1Data": checkSSZ(Eth1Data, path, hash)
|
||||
of "ExecutionPayload": checkSSZ(ExecutionPayload, path, hash)
|
||||
of "ExecutionPayloadHeader":
|
||||
checkSSZ(ExecutionPayloadHeader, path, hash)
|
||||
of "Fork": checkSSZ(Fork, path, hash)
|
||||
of "ForkData": checkSSZ(ForkData, path, hash)
|
||||
of "HistoricalBatch": checkSSZ(HistoricalBatch, path, hash)
|
||||
of "IndexedAttestation": checkSSZ(IndexedAttestation, path, hash)
|
||||
of "LightClientBootstrap":
|
||||
checkSSZ(LightClientBootstrap, path, hash)
|
||||
of "LightClientUpdate":
|
||||
checkSSZ(LightClientUpdate, path, hash)
|
||||
of "LightClientFinalityUpdate":
|
||||
checkSSZ(LightClientFinalityUpdate, path, hash)
|
||||
of "LightClientOptimisticUpdate":
|
||||
checkSSZ(LightClientOptimisticUpdate, path, hash)
|
||||
of "PendingAttestation": checkSSZ(PendingAttestation, path, hash)
|
||||
of "PowBlock": checkSSZ(PowBlock, path, hash)
|
||||
of "ProposerSlashing": checkSSZ(ProposerSlashing, path, hash)
|
||||
of "SignedAggregateAndProof":
|
||||
checkSSZ(SignedAggregateAndProof, path, hash)
|
||||
of "SignedBeaconBlock":
|
||||
checkSSZ(capella.SignedBeaconBlock, path, hash)
|
||||
of "SignedBeaconBlockHeader":
|
||||
checkSSZ(SignedBeaconBlockHeader, path, hash)
|
||||
of "SignedBLSToExecutionChange":
|
||||
checkSSZ(SignedBLSToExecutionChange, path, hash)
|
||||
of "SignedContributionAndProof":
|
||||
checkSSZ(SignedContributionAndProof, path, hash)
|
||||
of "SignedVoluntaryExit": checkSSZ(SignedVoluntaryExit, path, hash)
|
||||
of "SigningData": checkSSZ(SigningData, path, hash)
|
||||
of "SyncAggregate": checkSSZ(SyncAggregate, path, hash)
|
||||
of "SyncAggregatorSelectionData":
|
||||
checkSSZ(SyncAggregatorSelectionData, path, hash)
|
||||
of "SyncCommittee": checkSSZ(SyncCommittee, path, hash)
|
||||
of "SyncCommitteeContribution":
|
||||
checkSSZ(SyncCommitteeContribution, path, hash)
|
||||
of "SyncCommitteeMessage": checkSSZ(SyncCommitteeMessage, path, hash)
|
||||
of "Withdrawal": checkSSZ(Withdrawal, path, hash)
|
||||
of "Validator": checkSSZ(Validator, path, hash)
|
||||
of "VoluntaryExit": checkSSZ(VoluntaryExit, path, hash)
|
||||
else:
|
||||
raise newException(ValueError, "Unsupported test: " & sszType)
|
|
@ -0,0 +1,141 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2022 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).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
{.used.}
|
||||
|
||||
import
|
||||
# Standard library
|
||||
std/[os, strutils],
|
||||
# Status internals
|
||||
chronicles,
|
||||
# Beacon chain internals
|
||||
../../../beacon_chain/spec/[beaconstate, presets, state_transition_epoch],
|
||||
../../../beacon_chain/spec/datatypes/[altair, capella],
|
||||
# Test utilities
|
||||
../../testutil,
|
||||
../fixtures_utils,
|
||||
./test_fixture_rewards,
|
||||
../../helpers/debug_state
|
||||
|
||||
const RootDir = SszTestsDir/const_preset/"capella"/"epoch_processing"
|
||||
|
||||
template runSuite(
|
||||
suiteDir, testName: string, transitionProc: untyped): untyped =
|
||||
suite "EF - Capella - Epoch Processing - " & testName & preset():
|
||||
for testDir in walkDirRec(suiteDir, yieldFilter = {pcDir}, checkDir = true):
|
||||
let unitTestName = testDir.rsplit(DirSep, 1)[1]
|
||||
test testName & " - " & unitTestName & preset():
|
||||
# BeaconState objects are stored on the heap to avoid stack overflow
|
||||
type T = capella.BeaconState
|
||||
let preState {.inject.} = newClone(parseTest(testDir/"pre.ssz_snappy", SSZ, T))
|
||||
var cache {.inject, used.} = StateCache()
|
||||
template state: untyped {.inject, used.} = preState[]
|
||||
template cfg: untyped {.inject, used.} = defaultRuntimeConfig
|
||||
|
||||
if transitionProc.isOk:
|
||||
let postState =
|
||||
newClone(parseTest(testDir/"post.ssz_snappy", SSZ, T))
|
||||
check: hash_tree_root(preState[]) == hash_tree_root(postState[])
|
||||
reportDiff(preState, postState)
|
||||
else:
|
||||
check: not fileExists(testDir/"post.ssz_snappy")
|
||||
|
||||
# Justification & Finalization
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const JustificationFinalizationDir = RootDir/"justification_and_finalization"/"pyspec_tests"
|
||||
runSuite(JustificationFinalizationDir, "Justification & Finalization"):
|
||||
let info = altair.EpochInfo.init(state)
|
||||
process_justification_and_finalization(state, info.balances)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Inactivity updates
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const InactivityDir = RootDir/"inactivity_updates"/"pyspec_tests"
|
||||
runSuite(InactivityDir, "Inactivity"):
|
||||
let info = altair.EpochInfo.init(state)
|
||||
process_inactivity_updates(cfg, state, info)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Rewards & Penalties
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
# in test_fixture_rewards
|
||||
|
||||
# Registry updates
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const RegistryUpdatesDir = RootDir/"registry_updates"/"pyspec_tests"
|
||||
runSuite(RegistryUpdatesDir, "Registry updates"):
|
||||
process_registry_updates(cfg, state, cache)
|
||||
|
||||
# Slashings
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const SlashingsDir = RootDir/"slashings"/"pyspec_tests"
|
||||
runSuite(SlashingsDir, "Slashings"):
|
||||
let info = altair.EpochInfo.init(state)
|
||||
process_slashings(state, info.balances.current_epoch)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Eth1 data reset
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const Eth1DataResetDir = RootDir/"eth1_data_reset/"/"pyspec_tests"
|
||||
runSuite(Eth1DataResetDir, "Eth1 data reset"):
|
||||
process_eth1_data_reset(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Effective balance updates
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const EffectiveBalanceUpdatesDir = RootDir/"effective_balance_updates"/"pyspec_tests"
|
||||
runSuite(EffectiveBalanceUpdatesDir, "Effective balance updates"):
|
||||
process_effective_balance_updates(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Slashings reset
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const SlashingsResetDir = RootDir/"slashings_reset"/"pyspec_tests"
|
||||
runSuite(SlashingsResetDir, "Slashings reset"):
|
||||
process_slashings_reset(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# RANDAO mixes reset
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const RandaoMixesResetDir = RootDir/"randao_mixes_reset"/"pyspec_tests"
|
||||
runSuite(RandaoMixesResetDir, "RANDAO mixes reset"):
|
||||
process_randao_mixes_reset(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Historical roots update
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const HistoricalRootsUpdateDir = RootDir/"historical_roots_update"/"pyspec_tests"
|
||||
runSuite(HistoricalRootsUpdateDir, "Historical roots update"):
|
||||
process_historical_roots_update(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Participation flag updates
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
const ParticipationFlagDir = RootDir/"participation_flag_updates"/"pyspec_tests"
|
||||
runSuite(ParticipationFlagDir, "Participation flag updates"):
|
||||
process_participation_flag_updates(state)
|
||||
Result[void, cstring].ok()
|
||||
|
||||
# Sync committee updates
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
# These are only for minimal, not mainnet
|
||||
const SyncCommitteeDir = RootDir/"sync_committee_updates"/"pyspec_tests"
|
||||
runSuite(SyncCommitteeDir, "Sync committee updates"):
|
||||
process_sync_committee_updates(state)
|
||||
Result[void, cstring].ok()
|
Loading…
Reference in New Issue