Update spec types, use generics instead of static enums. TODO SSZ [skip CI]
This commit is contained in:
parent
7fde0a87d4
commit
0a0a304e8e
|
@ -250,7 +250,7 @@ proc initialize_beacon_state_from_eth1*(
|
||||||
Eth1Data(block_hash: eth1_block_hash, deposit_count: uint64(len(deposits))),
|
Eth1Data(block_hash: eth1_block_hash, deposit_count: uint64(len(deposits))),
|
||||||
latest_block_header:
|
latest_block_header:
|
||||||
BeaconBlockHeader(
|
BeaconBlockHeader(
|
||||||
body_root: hash_tree_root(BeaconBlockBody(
|
body_root: hash_tree_root(BeaconBlockBody[Unchecked](
|
||||||
# This differs from the spec intentionally.
|
# This differs from the spec intentionally.
|
||||||
# We must specify the default value for `ValidatorSig`
|
# We must specify the default value for `ValidatorSig`
|
||||||
# in order to get a correct `hash_tree_root`.
|
# in order to get a correct `hash_tree_root`.
|
||||||
|
@ -321,19 +321,19 @@ proc initialize_hashed_beacon_state_from_eth1*(
|
||||||
preset, eth1_block_hash, eth1_timestamp, deposits, flags)
|
preset, eth1_block_hash, eth1_timestamp, deposits, flags)
|
||||||
HashedBeaconState(data: genesisState[], root: hash_tree_root(genesisState[]))
|
HashedBeaconState(data: genesisState[], root: hash_tree_root(genesisState[]))
|
||||||
|
|
||||||
func emptyBeaconBlockBody(): BeaconBlockBody =
|
func emptyBeaconBlockBody(): BeaconBlockBody[Unchecked] =
|
||||||
# TODO: This shouldn't be necessary if OpaqueBlob is the default
|
# TODO: This shouldn't be necessary if OpaqueBlob is the default
|
||||||
BeaconBlockBody(randao_reveal: ValidatorSig(kind: OpaqueBlob))
|
BeaconBlockBody[Unchecked](randao_reveal: ValidatorSig(kind: OpaqueBlob))
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#genesis-block
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#genesis-block
|
||||||
func get_initial_beacon_block*(state: BeaconState): SignedBeaconBlock =
|
func get_initial_beacon_block*(state: BeaconState): SignedBeaconBlock[Unchecked] =
|
||||||
let message = BeaconBlock(
|
let message = BeaconBlock[Unchecked](
|
||||||
slot: state.slot,
|
slot: state.slot,
|
||||||
state_root: hash_tree_root(state),
|
state_root: hash_tree_root(state),
|
||||||
body: emptyBeaconBlockBody())
|
body: emptyBeaconBlockBody())
|
||||||
# parent_root, randao_reveal, eth1_data, signature, and body automatically
|
# parent_root, randao_reveal, eth1_data, signature, and body automatically
|
||||||
# initialized to default values.
|
# initialized to default values.
|
||||||
SignedBeaconBlock(message: message, root: hash_tree_root(message))
|
SignedBeaconBlock[Unchecked](message: message, root: hash_tree_root(message))
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
||||||
func get_block_root_at_slot*(state: BeaconState,
|
func get_block_root_at_slot*(state: BeaconState,
|
||||||
|
@ -430,7 +430,8 @@ proc process_registry_updates*(state: var BeaconState,
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
|
||||||
proc is_valid_indexed_attestation*(
|
proc is_valid_indexed_attestation*(
|
||||||
state: BeaconState, indexed_attestation: SomeIndexedAttestation,
|
state: BeaconState,
|
||||||
|
indexed_attestation: IndexedAttestation[Unchecked],
|
||||||
flags: UpdateFlags): Result[void, cstring] =
|
flags: UpdateFlags): Result[void, cstring] =
|
||||||
## Check if ``indexed_attestation`` is not empty, has sorted and unique
|
## Check if ``indexed_attestation`` is not empty, has sorted and unique
|
||||||
## indices and has a valid aggregate signature.
|
## indices and has a valid aggregate signature.
|
||||||
|
@ -516,31 +517,15 @@ func get_attesting_indices*(state: BeaconState,
|
||||||
result.incl index
|
result.incl index
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_indexed_attestation
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_indexed_attestation
|
||||||
func get_indexed_attestation(state: BeaconState, attestation: Attestation,
|
func get_indexed_attestation[Trust](state: BeaconState, attestation: Attestation[Trust],
|
||||||
cache: var StateCache): IndexedAttestation =
|
cache: var StateCache): IndexedAttestation[Trust] =
|
||||||
## Return the indexed attestation corresponding to ``attestation``.
|
## Return the indexed attestation corresponding to ``attestation``.
|
||||||
let
|
let
|
||||||
attesting_indices =
|
attesting_indices =
|
||||||
get_attesting_indices(
|
get_attesting_indices(
|
||||||
state, attestation.data, attestation.aggregation_bits, cache)
|
state, attestation.data, attestation.aggregation_bits, cache)
|
||||||
|
|
||||||
IndexedAttestation(
|
IndexedAttestation[Trust](
|
||||||
attesting_indices:
|
|
||||||
List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init(
|
|
||||||
sorted(mapIt(attesting_indices.toSeq, it.uint64), system.cmp)),
|
|
||||||
data: attestation.data,
|
|
||||||
signature: attestation.signature
|
|
||||||
)
|
|
||||||
|
|
||||||
func get_indexed_attestation(state: BeaconState, attestation: TrustedAttestation,
|
|
||||||
cache: var StateCache): TrustedIndexedAttestation =
|
|
||||||
## Return the indexed attestation corresponding to ``attestation``.
|
|
||||||
let
|
|
||||||
attesting_indices =
|
|
||||||
get_attesting_indices(
|
|
||||||
state, attestation.data, attestation.aggregation_bits, cache)
|
|
||||||
|
|
||||||
TrustedIndexedAttestation(
|
|
||||||
attesting_indices:
|
attesting_indices:
|
||||||
List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init(
|
List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init(
|
||||||
sorted(mapIt(attesting_indices.toSeq, it.uint64), system.cmp)),
|
sorted(mapIt(attesting_indices.toSeq, it.uint64), system.cmp)),
|
||||||
|
@ -592,7 +577,7 @@ func check_attestation_index(
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestations
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestations
|
||||||
proc check_attestation*(
|
proc check_attestation*(
|
||||||
state: BeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
state: BeaconState, attestation: Attestation, flags: UpdateFlags,
|
||||||
cache: var StateCache): Result[void, cstring] =
|
cache: var StateCache): Result[void, cstring] =
|
||||||
## Check that an attestation follows the rules of being included in the state
|
## Check that an attestation follows the rules of being included in the state
|
||||||
## at the current slot. When acting as a proposer, the same rules need to
|
## at the current slot. When acting as a proposer, the same rules need to
|
||||||
|
@ -621,13 +606,13 @@ proc check_attestation*(
|
||||||
if not (data.source == state.previous_justified_checkpoint):
|
if not (data.source == state.previous_justified_checkpoint):
|
||||||
return err("FFG data not matching previous justified epoch")
|
return err("FFG data not matching previous justified epoch")
|
||||||
|
|
||||||
? is_valid_indexed_attestation(
|
let idx_att = get_indexed_attestation(state, attestation, cache)
|
||||||
state, get_indexed_attestation(state, attestation, cache), flags)
|
? is_valid_indexed_attestation(state, idx_att, flags)
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc process_attestation*(
|
proc process_attestation*(
|
||||||
state: var BeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
state: var BeaconState, attestation: Attestation, flags: UpdateFlags,
|
||||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||||
# In the spec, attestation validation is mixed with state mutation, so here
|
# In the spec, attestation validation is mixed with state mutation, so here
|
||||||
# we've split it into two functions so that the validation logic can be
|
# we've split it into two functions so that the validation logic can be
|
||||||
|
|
|
@ -78,6 +78,55 @@ const
|
||||||
template maxSize*(n: int) {.pragma.}
|
template maxSize*(n: int) {.pragma.}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
# The trust level of a block, attestation or signature
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# docs/block_validation_flow.md
|
||||||
|
|
||||||
|
Unchecked* = object # Object hasn't gone through any verification
|
||||||
|
SigVerified* = object # Object cryptographic signature has been verified
|
||||||
|
TransitionVerified* = object # Object is valid according to the protocol state transition logic
|
||||||
|
Trusted* = object # Object is fully verified both cryptographically and logically
|
||||||
|
|
||||||
|
# We use dummy objects instead of static enum as static enum
|
||||||
|
# have cause issues with shortLog:
|
||||||
|
# - cannot use `auto`, need to use `tuple` as return value
|
||||||
|
# - overloading on Eth2Digest needed to be prefixed with the module digest.shortLog(_)
|
||||||
|
# They also required to reorder the type section.
|
||||||
|
# Generics are also better tested than static enums.
|
||||||
|
|
||||||
|
# TODO: we might want to compile with deduplication on
|
||||||
|
# as the C code will be the same but we will have 1 duplicate per trust level
|
||||||
|
# https://stackoverflow.com/questions/15168924/gcc-clang-merging-functions-with-identical-instructions-comdat-folding
|
||||||
|
# linker: --icf (identical COMDAT folding)
|
||||||
|
# GCC: -ffunction-sections
|
||||||
|
|
||||||
|
# Trust level aliases
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
TrustedSignedBeaconBlock* = SignedBeaconBlock[Trusted]
|
||||||
|
UntrustedSignedBeaconBlock* = SignedBeaconBlock[Unchecked] or
|
||||||
|
SignedBeaconBlock[SigVerified] or
|
||||||
|
SignedBeaconBlock[TransitionVerified]
|
||||||
|
TrustedBeaconBlock* = BeaconBlock[Trusted]
|
||||||
|
UntrustedBeaconBlock* = BeaconBlock[Unchecked] or
|
||||||
|
BeaconBlock[SigVerified] or
|
||||||
|
BeaconBlock[TransitionVerified]
|
||||||
|
|
||||||
|
TrustedIndexedAttestation* = IndexedAttestation[Trusted]
|
||||||
|
UntrustedIndexedAttestation* = IndexedAttestation[Unchecked] or
|
||||||
|
IndexedAttestation[SigVerified] or
|
||||||
|
IndexedAttestation[TransitionVerified]
|
||||||
|
|
||||||
# Domains
|
# Domains
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#domain-types
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#domain-types
|
||||||
|
@ -120,33 +169,29 @@ type
|
||||||
signed_header_2*: SignedBeaconBlockHeader
|
signed_header_2*: SignedBeaconBlockHeader
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attesterslashing
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attesterslashing
|
||||||
AttesterSlashing* = object
|
AttesterSlashing*[Trust] = object
|
||||||
attestation_1*: IndexedAttestation
|
attestation_1*: IndexedAttestation[Trust]
|
||||||
attestation_2*: IndexedAttestation
|
attestation_2*: IndexedAttestation[Trust]
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#indexedattestation
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#indexedattestation
|
||||||
IndexedAttestation* = object
|
IndexedAttestation*[Trust] = object
|
||||||
attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE]
|
|
||||||
data*: AttestationData
|
|
||||||
signature*: ValidatorSig
|
|
||||||
|
|
||||||
TrustedIndexedAttestation* = object
|
|
||||||
attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE]
|
attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE]
|
||||||
data*: AttestationData
|
data*: AttestationData
|
||||||
|
when Trust is SigVerified|Trusted:
|
||||||
signature*: TrustedSig
|
signature*: TrustedSig
|
||||||
|
else:
|
||||||
|
signature*: ValidatorSig
|
||||||
|
|
||||||
CommitteeValidatorsBits* = BitList[Limit MAX_VALIDATORS_PER_COMMITTEE]
|
CommitteeValidatorsBits* = BitList[Limit MAX_VALIDATORS_PER_COMMITTEE]
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestation
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestation
|
||||||
Attestation* = object
|
Attestation*[Trust] = object
|
||||||
aggregation_bits*: CommitteeValidatorsBits
|
|
||||||
data*: AttestationData
|
|
||||||
signature*: ValidatorSig
|
|
||||||
|
|
||||||
TrustedAttestation* = object
|
|
||||||
aggregation_bits*: CommitteeValidatorsBits
|
aggregation_bits*: CommitteeValidatorsBits
|
||||||
data*: AttestationData
|
data*: AttestationData
|
||||||
|
when Trust is SigVerified|Trusted:
|
||||||
signature*: TrustedSig
|
signature*: TrustedSig
|
||||||
|
else:
|
||||||
|
signature*: ValidatorSig
|
||||||
|
|
||||||
ForkDigest* = distinct array[4, byte]
|
ForkDigest* = distinct array[4, byte]
|
||||||
|
|
||||||
|
@ -203,7 +248,7 @@ type
|
||||||
validator_index*: uint64
|
validator_index*: uint64
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblock
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblock
|
||||||
BeaconBlock* = object
|
BeaconBlock*[Trust] = object
|
||||||
## For each slot, a proposer is chosen from the validator pool to propose
|
## 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
|
## 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.
|
## validators that will have a chance to vote on it through attestations.
|
||||||
|
@ -219,30 +264,7 @@ type
|
||||||
state_root*: Eth2Digest ##\
|
state_root*: Eth2Digest ##\
|
||||||
## The state root, _after_ this block has been processed
|
## The state root, _after_ this block has been processed
|
||||||
|
|
||||||
body*: BeaconBlockBody
|
body*: BeaconBlockBody[Trust]
|
||||||
|
|
||||||
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
|
|
||||||
parent_root*: Eth2Digest ##\
|
|
||||||
state_root*: Eth2Digest ##\
|
|
||||||
body*: TrustedBeaconBlockBody
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblockheader
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblockheader
|
||||||
BeaconBlockHeader* = object
|
BeaconBlockHeader* = object
|
||||||
|
@ -260,35 +282,20 @@ type
|
||||||
GraffitiBytes* = distinct array[MAX_GRAFFITI_SIZE, byte]
|
GraffitiBytes* = distinct array[MAX_GRAFFITI_SIZE, byte]
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblockbody
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblockbody
|
||||||
BeaconBlockBody* = object
|
BeaconBlockBody*[Trust] = object
|
||||||
|
when Trust is SigVerified|Trusted:
|
||||||
|
randao_reveal*: TrustedSig
|
||||||
|
else:
|
||||||
randao_reveal*: ValidatorSig
|
randao_reveal*: ValidatorSig
|
||||||
eth1_data*: Eth1Data
|
eth1_data*: Eth1Data
|
||||||
graffiti*: GraffitiBytes
|
graffiti*: GraffitiBytes
|
||||||
|
|
||||||
# Operations
|
# Operations
|
||||||
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
||||||
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
attester_slashings*: List[AttesterSlashing[Trust], Limit MAX_ATTESTER_SLASHINGS]
|
||||||
attestations*: List[Attestation, Limit MAX_ATTESTATIONS]
|
attestations*: List[Attestation[Trust], Limit MAX_ATTESTATIONS]
|
||||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
||||||
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS] # TODO: trust system?
|
||||||
|
|
||||||
TrustedBeaconBlockBody* = object
|
|
||||||
randao_reveal*: TrustedSig
|
|
||||||
eth1_data*: Eth1Data
|
|
||||||
graffiti*: GraffitiBytes
|
|
||||||
|
|
||||||
# Operations
|
|
||||||
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
|
||||||
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
|
||||||
attestations*: List[TrustedAttestation, Limit MAX_ATTESTATIONS]
|
|
||||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
|
||||||
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
|
||||||
|
|
||||||
SomeSignedBeaconBlock* = SignedBeaconBlock | TrustedSignedBeaconBlock
|
|
||||||
SomeBeaconBlock* = BeaconBlock | TrustedBeaconBlock
|
|
||||||
SomeBeaconBlockBody* = BeaconBlockBody | TrustedBeaconBlockBody
|
|
||||||
SomeAttestation* = Attestation | TrustedAttestation
|
|
||||||
SomeIndexedAttestation* = IndexedAttestation | TrustedIndexedAttestation
|
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconstate
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconstate
|
||||||
BeaconState* = object
|
BeaconState* = object
|
||||||
|
@ -417,15 +424,12 @@ type
|
||||||
signature*: ValidatorSig
|
signature*: ValidatorSig
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#signedbeaconblock
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#signedbeaconblock
|
||||||
SignedBeaconBlock* = object
|
SignedBeaconBlock*[Trust] = object
|
||||||
message*: BeaconBlock
|
message*: BeaconBlock[Trust]
|
||||||
signature*: ValidatorSig
|
when Trust is SigVerified|Trusted:
|
||||||
|
|
||||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
|
||||||
|
|
||||||
TrustedSignedBeaconBlock* = object
|
|
||||||
message*: TrustedBeaconBlock
|
|
||||||
signature*: TrustedSig
|
signature*: TrustedSig
|
||||||
|
else:
|
||||||
|
signature*: ValidatorSig
|
||||||
|
|
||||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||||
|
|
||||||
|
@ -437,7 +441,7 @@ type
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#aggregateandproof
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#aggregateandproof
|
||||||
AggregateAndProof* = object
|
AggregateAndProof* = object
|
||||||
aggregator_index*: uint64
|
aggregator_index*: uint64
|
||||||
aggregate*: Attestation
|
aggregate*: Attestation[Trusted]
|
||||||
selection_proof*: ValidatorSig
|
selection_proof*: ValidatorSig
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#signedaggregateandproof
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#signedaggregateandproof
|
||||||
|
@ -667,7 +671,7 @@ func shortLog*(s: Slot): uint64 =
|
||||||
func shortLog*(e: Epoch): uint64 =
|
func shortLog*(e: Epoch): uint64 =
|
||||||
e - GENESIS_EPOCH
|
e - GENESIS_EPOCH
|
||||||
|
|
||||||
func shortLog*(v: SomeBeaconBlock): auto =
|
func shortLog*(v: BeaconBlock): auto =
|
||||||
(
|
(
|
||||||
slot: shortLog(v.slot),
|
slot: shortLog(v.slot),
|
||||||
proposer_index: v.proposer_index,
|
proposer_index: v.proposer_index,
|
||||||
|
@ -682,7 +686,7 @@ func shortLog*(v: SomeBeaconBlock): auto =
|
||||||
voluntary_exits_len: v.body.voluntary_exits.len(),
|
voluntary_exits_len: v.body.voluntary_exits.len(),
|
||||||
)
|
)
|
||||||
|
|
||||||
func shortLog*(v: SomeSignedBeaconBlock): auto =
|
func shortLog*(v: SignedBeaconBlock): auto =
|
||||||
(
|
(
|
||||||
blck: shortLog(v.message),
|
blck: shortLog(v.message),
|
||||||
signature: shortLog(v.signature)
|
signature: shortLog(v.signature)
|
||||||
|
@ -733,14 +737,14 @@ func shortLog*(v: PendingAttestation): auto =
|
||||||
proposer_index: v.proposer_index
|
proposer_index: v.proposer_index
|
||||||
)
|
)
|
||||||
|
|
||||||
func shortLog*(v: SomeAttestation): auto =
|
func shortLog*(v: Attestation): auto =
|
||||||
(
|
(
|
||||||
aggregation_bits: v.aggregation_bits,
|
aggregation_bits: v.aggregation_bits,
|
||||||
data: shortLog(v.data),
|
data: shortLog(v.data),
|
||||||
signature: shortLog(v.signature)
|
signature: shortLog(v.signature)
|
||||||
)
|
)
|
||||||
|
|
||||||
func shortLog*(v: SomeIndexedAttestation): auto =
|
func shortLog*(v: IndexedAttestation): auto =
|
||||||
(
|
(
|
||||||
attestating_indices: v.attesting_indices,
|
attestating_indices: v.attesting_indices,
|
||||||
data: shortLog(v.data),
|
data: shortLog(v.data),
|
||||||
|
@ -773,9 +777,15 @@ func shortLog*(v: SignedVoluntaryExit): auto =
|
||||||
|
|
||||||
chronicles.formatIt Slot: it.shortLog
|
chronicles.formatIt Slot: it.shortLog
|
||||||
chronicles.formatIt Epoch: it.shortLog
|
chronicles.formatIt Epoch: it.shortLog
|
||||||
chronicles.formatIt BeaconBlock: it.shortLog
|
chronicles.formatIt BeaconBlock[Unchecked]: it.shortLog
|
||||||
|
chronicles.formatIt BeaconBlock[SigVerified]: it.shortLog
|
||||||
|
chronicles.formatIt BeaconBlock[TransitionVerified]: it.shortLog
|
||||||
|
chronicles.formatIt BeaconBlock[Trusted]: it.shortLog
|
||||||
chronicles.formatIt AttestationData: it.shortLog
|
chronicles.formatIt AttestationData: it.shortLog
|
||||||
chronicles.formatIt Attestation: it.shortLog
|
chronicles.formatIt Attestation[Unchecked]: it.shortLog
|
||||||
|
chronicles.formatIt Attestation[SigVerified]: it.shortLog
|
||||||
|
chronicles.formatIt Attestation[TransitionVerified]: it.shortLog
|
||||||
|
chronicles.formatIt Attestation[Trusted]: it.shortLog
|
||||||
chronicles.formatIt Checkpoint: it.shortLog
|
chronicles.formatIt Checkpoint: it.shortLog
|
||||||
|
|
||||||
import json_serialization
|
import json_serialization
|
||||||
|
|
|
@ -90,7 +90,7 @@ func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
|
||||||
raiseAssert e.msg
|
raiseAssert e.msg
|
||||||
|
|
||||||
func getAttestationTopic*(forkDigest: ForkDigest,
|
func getAttestationTopic*(forkDigest: ForkDigest,
|
||||||
attestation: Attestation,
|
attestation: Attestation[Unchecked],
|
||||||
num_active_validators: uint64): string =
|
num_active_validators: uint64): string =
|
||||||
getAttestationTopic(
|
getAttestationTopic(
|
||||||
forkDigest,
|
forkDigest,
|
||||||
|
|
|
@ -84,7 +84,7 @@ func get_block_signature*(
|
||||||
|
|
||||||
proc verify_block_signature*(
|
proc verify_block_signature*(
|
||||||
fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot,
|
fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot,
|
||||||
blck: Eth2Digest | SomeBeaconBlock | BeaconBlockHeader,
|
blck: Eth2Digest | BeaconBlock | BeaconBlockHeader,
|
||||||
pubkey: ValidatorPubKey,
|
pubkey: ValidatorPubKey,
|
||||||
signature: SomeSig): bool =
|
signature: SomeSig): bool =
|
||||||
withTrust(signature):
|
withTrust(signature):
|
||||||
|
|
|
@ -30,7 +30,7 @@ import
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||||
proc verify_block_signature*(
|
proc verify_block_signature*(
|
||||||
state: BeaconState, signed_block: SomeSignedBeaconBlock): bool {.nbench.} =
|
state: BeaconState, signed_block: SignedBeaconBlock): bool {.nbench.} =
|
||||||
let
|
let
|
||||||
proposer_index = signed_block.message.proposer_index
|
proposer_index = signed_block.message.proposer_index
|
||||||
if proposer_index >= state.validators.lenu64:
|
if proposer_index >= state.validators.lenu64:
|
||||||
|
@ -49,7 +49,7 @@ proc verify_block_signature*(
|
||||||
true
|
true
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||||
proc verifyStateRoot(state: BeaconState, blck: BeaconBlock): bool =
|
proc verifyStateRoot(state: BeaconState, blck: UntrustedBeaconBlock): bool =
|
||||||
# This is inlined in state_transition(...) in spec.
|
# This is inlined in state_transition(...) in spec.
|
||||||
let state_root = hash_tree_root(state)
|
let state_root = hash_tree_root(state)
|
||||||
if state_root != blck.state_root:
|
if state_root != blck.state_root:
|
||||||
|
@ -125,7 +125,7 @@ proc process_slots*(state: var HashedBeaconState, slot: Slot,
|
||||||
if slotProcessed notin updateFlags or state.data.slot != slot:
|
if slotProcessed notin updateFlags or state.data.slot != slot:
|
||||||
notice(
|
notice(
|
||||||
"Unusual request for a slot in the past",
|
"Unusual request for a slot in the past",
|
||||||
state_root = shortLog(state.root),
|
state_root = state.root,
|
||||||
current_slot = state.data.slot,
|
current_slot = state.data.slot,
|
||||||
target_slot = slot
|
target_slot = slot
|
||||||
)
|
)
|
||||||
|
@ -142,7 +142,7 @@ proc noRollback*(state: var HashedBeaconState) =
|
||||||
|
|
||||||
proc state_transition*(
|
proc state_transition*(
|
||||||
preset: RuntimePreset,
|
preset: RuntimePreset,
|
||||||
state: var HashedBeaconState, signedBlock: SomeSignedBeaconBlock,
|
state: var HashedBeaconState, signedBlock: SignedBeaconBlock,
|
||||||
stateCache: var StateCache,
|
stateCache: var StateCache,
|
||||||
flags: UpdateFlags, rollback: RollbackHashedProc): bool {.nbench.} =
|
flags: UpdateFlags, rollback: RollbackHashedProc): bool {.nbench.} =
|
||||||
## Time in the beacon chain moves by slots. Every time (haha.) that happens,
|
## Time in the beacon chain moves by slots. Every time (haha.) that happens,
|
||||||
|
@ -175,8 +175,8 @@ proc state_transition*(
|
||||||
verify_block_signature(state.data, signedBlock):
|
verify_block_signature(state.data, signedBlock):
|
||||||
|
|
||||||
trace "state_transition: processing block, signature passed",
|
trace "state_transition: processing block, signature passed",
|
||||||
signature = shortLog(signedBlock.signature),
|
signature = signedBlock.signature,
|
||||||
blockRoot = shortLog(signedBlock.root)
|
blockRoot = signedBlock.root
|
||||||
let res = process_block(preset, state.data, signedBlock.message, flags, stateCache)
|
let res = process_block(preset, state.data, signedBlock.message, flags, stateCache)
|
||||||
if res.isOk:
|
if res.isOk:
|
||||||
if skipStateRootValidation in flags or verifyStateRoot(state.data, signedBlock.message):
|
if skipStateRootValidation in flags or verifyStateRoot(state.data, signedBlock.message):
|
||||||
|
@ -193,10 +193,10 @@ proc state_transition*(
|
||||||
return true
|
return true
|
||||||
else:
|
else:
|
||||||
debug "state_transition: process_block failed",
|
debug "state_transition: process_block failed",
|
||||||
blck = shortLog(signedBlock.message),
|
blck = signedBlock.message,
|
||||||
slot = state.data.slot,
|
slot = state.data.slot,
|
||||||
eth1_deposit_index = state.data.eth1_deposit_index,
|
eth1_deposit_index = state.data.eth1_deposit_index,
|
||||||
deposit_root = shortLog(state.data.eth1_data.deposit_root),
|
deposit_root = state.data.eth1_data.deposit_root,
|
||||||
error = res.error
|
error = res.error
|
||||||
|
|
||||||
# Block processing failed, roll back changes
|
# Block processing failed, roll back changes
|
||||||
|
@ -213,13 +213,13 @@ proc makeBeaconBlock*(
|
||||||
randao_reveal: ValidatorSig,
|
randao_reveal: ValidatorSig,
|
||||||
eth1_data: Eth1Data,
|
eth1_data: Eth1Data,
|
||||||
graffiti: GraffitiBytes,
|
graffiti: GraffitiBytes,
|
||||||
attestations: seq[Attestation],
|
attestations: seq[Attestation[Unchecked]],
|
||||||
deposits: seq[Deposit],
|
deposits: seq[Deposit],
|
||||||
proposerSlashings: seq[ProposerSlashing],
|
proposerSlashings: seq[ProposerSlashing],
|
||||||
attesterSlashings: seq[AttesterSlashing],
|
attesterSlashings: seq[AttesterSlashing[Unchecked]],
|
||||||
voluntaryExits: seq[SignedVoluntaryExit],
|
voluntaryExits: seq[SignedVoluntaryExit],
|
||||||
rollback: RollbackHashedProc,
|
rollback: RollbackHashedProc,
|
||||||
cache: var StateCache): Option[BeaconBlock] =
|
cache: var StateCache): Option[BeaconBlock[Unchecked]] =
|
||||||
## Create a block for the given state. The last block applied to it must be
|
## Create a block for the given state. The last block applied to it must be
|
||||||
## the one identified by parent_root and process_slots must be called up to
|
## the one identified by parent_root and process_slots must be called up to
|
||||||
## the slot for which a block is to be created.
|
## the slot for which a block is to be created.
|
||||||
|
@ -227,31 +227,35 @@ proc makeBeaconBlock*(
|
||||||
# To create a block, we'll first apply a partial block to the state, skipping
|
# To create a block, we'll first apply a partial block to the state, skipping
|
||||||
# some validations.
|
# some validations.
|
||||||
|
|
||||||
var blck = BeaconBlock(
|
# TODO: finish the code refactoring
|
||||||
|
# the result should be TransitionVerified
|
||||||
|
var blck = BeaconBlock[Unchecked](
|
||||||
slot: state.data.slot,
|
slot: state.data.slot,
|
||||||
proposer_index: proposer_index.uint64,
|
proposer_index: proposer_index.uint64,
|
||||||
parent_root: parent_root,
|
parent_root: parent_root,
|
||||||
body: BeaconBlockBody(
|
body: BeaconBlockBody[Unchecked](
|
||||||
randao_reveal: randao_reveal,
|
randao_reveal: randao_reveal,
|
||||||
eth1_data: eth1data,
|
eth1_data: eth1data,
|
||||||
graffiti: graffiti,
|
graffiti: graffiti,
|
||||||
proposer_slashings: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS](
|
proposer_slashings: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS](
|
||||||
proposerSlashings),
|
proposerSlashings),
|
||||||
attester_slashings: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS](
|
attester_slashings: List[AttesterSlashing[Unchecked], Limit MAX_ATTESTER_SLASHINGS](
|
||||||
attesterSlashings),
|
attesterSlashings),
|
||||||
attestations: List[Attestation, Limit MAX_ATTESTATIONS](attestations),
|
attestations: List[Attestation[Unchecked], Limit MAX_ATTESTATIONS](attestations),
|
||||||
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
|
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
|
||||||
voluntary_exits:
|
voluntary_exits:
|
||||||
List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS](voluntaryExits)))
|
List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS](voluntaryExits)))
|
||||||
|
|
||||||
let res = process_block(preset, state.data, blck, {skipBlsValidation}, cache)
|
let res = process_block(
|
||||||
|
preset, state.data, blck,
|
||||||
|
{skipBlsValidation}, cache)
|
||||||
|
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
warn "Unable to apply new block to state",
|
warn "Unable to apply new block to state",
|
||||||
blck = shortLog(blck),
|
blck = blck,
|
||||||
slot = state.data.slot,
|
slot = state.data.slot,
|
||||||
eth1_deposit_index = state.data.eth1_deposit_index,
|
eth1_deposit_index = state.data.eth1_deposit_index,
|
||||||
deposit_root = shortLog(state.data.eth1_data.deposit_root),
|
deposit_root = state.data.eth1_data.deposit_root,
|
||||||
error = res.error
|
error = res.error
|
||||||
rollback(state)
|
rollback(state)
|
||||||
return
|
return
|
||||||
|
|
|
@ -27,9 +27,11 @@ import
|
||||||
./signatures, ./presets,
|
./signatures, ./presets,
|
||||||
../../nbench/bench_lab
|
../../nbench/bench_lab
|
||||||
|
|
||||||
|
export sets # Generics visibility issue with toSeq(items(intersection(HashSet, HashSet)))
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#block-header
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#block-header
|
||||||
func process_block_header*(
|
func process_block_header*(
|
||||||
state: var BeaconState, blck: SomeBeaconBlock, flags: UpdateFlags,
|
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags,
|
||||||
stateCache: var StateCache): Result[void, cstring] {.nbench.} =
|
stateCache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||||
# Verify that the slots match
|
# Verify that the slots match
|
||||||
if not (blck.slot == state.slot):
|
if not (blck.slot == state.slot):
|
||||||
|
@ -72,7 +74,7 @@ func `xor`[T: array](a, b: T): T =
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#randao
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#randao
|
||||||
proc process_randao(
|
proc process_randao(
|
||||||
state: var BeaconState, body: SomeBeaconBlockBody, flags: UpdateFlags,
|
state: var BeaconState, body: BeaconBlockBody, flags: UpdateFlags,
|
||||||
stateCache: var StateCache): bool {.nbench.} =
|
stateCache: var StateCache): bool {.nbench.} =
|
||||||
let
|
let
|
||||||
proposer_index = get_beacon_proposer_index(state, stateCache)
|
proposer_index = get_beacon_proposer_index(state, stateCache)
|
||||||
|
@ -108,7 +110,7 @@ proc process_randao(
|
||||||
true
|
true
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#eth1-data
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#eth1-data
|
||||||
func process_eth1_data(state: var BeaconState, body: SomeBeaconBlockBody) {.nbench.}=
|
func process_eth1_data(state: var BeaconState, body: BeaconBlockBody) {.nbench.}=
|
||||||
state.eth1_data_votes.add body.eth1_data
|
state.eth1_data_votes.add body.eth1_data
|
||||||
|
|
||||||
if state.eth1_data_votes.asSeq.count(body.eth1_data).uint64 * 2 >
|
if state.eth1_data_votes.asSeq.count(body.eth1_data).uint64 * 2 >
|
||||||
|
@ -189,9 +191,9 @@ func is_slashable_attestation_data*(
|
||||||
data_2.target.epoch < data_1.target.epoch)
|
data_2.target.epoch < data_1.target.epoch)
|
||||||
|
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attester-slashings
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attester-slashings
|
||||||
proc check_attester_slashing*(
|
proc check_attester_slashing*[Trust](
|
||||||
state: var BeaconState,
|
state: var BeaconState,
|
||||||
attester_slashing: AttesterSlashing,
|
attester_slashing: AttesterSlashing[Trust],
|
||||||
flags: UpdateFlags
|
flags: UpdateFlags
|
||||||
): Result[seq[ValidatorIndex], cstring] {.nbench.} =
|
): Result[seq[ValidatorIndex], cstring] {.nbench.} =
|
||||||
let
|
let
|
||||||
|
@ -210,6 +212,8 @@ proc check_attester_slashing*(
|
||||||
|
|
||||||
var slashed_indices: seq[ValidatorIndex]
|
var slashed_indices: seq[ValidatorIndex]
|
||||||
|
|
||||||
|
# export sets otherwise
|
||||||
|
# generics visibility issue with toSeq(items(intersection(HashSet, HashSet)))
|
||||||
for index in sorted(toSeq(intersection(
|
for index in sorted(toSeq(intersection(
|
||||||
toHashSet(attestation_1.attesting_indices.asSeq),
|
toHashSet(attestation_1.attesting_indices.asSeq),
|
||||||
toHashSet(attestation_2.attesting_indices.asSeq)).items), system.cmp):
|
toHashSet(attestation_2.attesting_indices.asSeq)).items), system.cmp):
|
||||||
|
@ -305,7 +309,7 @@ proc process_voluntary_exit*(
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#operations
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#operations
|
||||||
proc process_operations(preset: RuntimePreset,
|
proc process_operations(preset: RuntimePreset,
|
||||||
state: var BeaconState,
|
state: var BeaconState,
|
||||||
body: SomeBeaconBlockBody,
|
body: BeaconBlockBody,
|
||||||
flags: UpdateFlags,
|
flags: UpdateFlags,
|
||||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||||
# Verify that outstanding deposits are processed up to the maximum number of
|
# Verify that outstanding deposits are processed up to the maximum number of
|
||||||
|
@ -339,7 +343,7 @@ proc process_operations(preset: RuntimePreset,
|
||||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#block-processing
|
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#block-processing
|
||||||
proc process_block*(
|
proc process_block*(
|
||||||
preset: RuntimePreset,
|
preset: RuntimePreset,
|
||||||
state: var BeaconState, blck: SomeBeaconBlock, flags: UpdateFlags,
|
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags,
|
||||||
stateCache: var StateCache): Result[void, cstring] {.nbench.}=
|
stateCache: var StateCache): Result[void, cstring] {.nbench.}=
|
||||||
## When there's a new block, we need to verify that the block is sane and
|
## When there's a new block, we need to verify that the block is sane and
|
||||||
## update the state accordingly - the state is left in an unknown state when
|
## update the state accordingly - the state is left in an unknown state when
|
||||||
|
|
Loading…
Reference in New Issue