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))),
|
||||
latest_block_header:
|
||||
BeaconBlockHeader(
|
||||
body_root: hash_tree_root(BeaconBlockBody(
|
||||
body_root: hash_tree_root(BeaconBlockBody[Unchecked](
|
||||
# This differs from the spec intentionally.
|
||||
# We must specify the default value for `ValidatorSig`
|
||||
# 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)
|
||||
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
|
||||
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
|
||||
func get_initial_beacon_block*(state: BeaconState): SignedBeaconBlock =
|
||||
let message = BeaconBlock(
|
||||
func get_initial_beacon_block*(state: BeaconState): SignedBeaconBlock[Unchecked] =
|
||||
let message = BeaconBlock[Unchecked](
|
||||
slot: state.slot,
|
||||
state_root: hash_tree_root(state),
|
||||
body: emptyBeaconBlockBody())
|
||||
# parent_root, randao_reveal, eth1_data, signature, and body automatically
|
||||
# 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
|
||||
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
|
||||
proc is_valid_indexed_attestation*(
|
||||
state: BeaconState, indexed_attestation: SomeIndexedAttestation,
|
||||
state: BeaconState,
|
||||
indexed_attestation: IndexedAttestation[Unchecked],
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
## Check if ``indexed_attestation`` is not empty, has sorted and unique
|
||||
## indices and has a valid aggregate signature.
|
||||
|
@ -516,31 +517,15 @@ func get_attesting_indices*(state: BeaconState,
|
|||
result.incl index
|
||||
|
||||
# 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,
|
||||
cache: var StateCache): IndexedAttestation =
|
||||
func get_indexed_attestation[Trust](state: BeaconState, attestation: Attestation[Trust],
|
||||
cache: var StateCache): IndexedAttestation[Trust] =
|
||||
## Return the indexed attestation corresponding to ``attestation``.
|
||||
let
|
||||
attesting_indices =
|
||||
get_attesting_indices(
|
||||
state, attestation.data, attestation.aggregation_bits, cache)
|
||||
|
||||
IndexedAttestation(
|
||||
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(
|
||||
IndexedAttestation[Trust](
|
||||
attesting_indices:
|
||||
List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init(
|
||||
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
|
||||
proc check_attestation*(
|
||||
state: BeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
state: BeaconState, attestation: Attestation, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] =
|
||||
## 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
|
||||
|
@ -621,13 +606,13 @@ proc check_attestation*(
|
|||
if not (data.source == state.previous_justified_checkpoint):
|
||||
return err("FFG data not matching previous justified epoch")
|
||||
|
||||
? is_valid_indexed_attestation(
|
||||
state, get_indexed_attestation(state, attestation, cache), flags)
|
||||
let idx_att = get_indexed_attestation(state, attestation, cache)
|
||||
? is_valid_indexed_attestation(state, idx_att, flags)
|
||||
|
||||
ok()
|
||||
|
||||
proc process_attestation*(
|
||||
state: var BeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
state: var BeaconState, attestation: Attestation, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||
# 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
|
||||
|
|
|
@ -78,6 +78,55 @@ const
|
|||
template maxSize*(n: int) {.pragma.}
|
||||
|
||||
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
|
||||
# ---------------------------------------------------------------
|
||||
# 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
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attesterslashing
|
||||
AttesterSlashing* = object
|
||||
attestation_1*: IndexedAttestation
|
||||
attestation_2*: IndexedAttestation
|
||||
AttesterSlashing*[Trust] = object
|
||||
attestation_1*: IndexedAttestation[Trust]
|
||||
attestation_2*: IndexedAttestation[Trust]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#indexedattestation
|
||||
IndexedAttestation* = object
|
||||
attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE]
|
||||
data*: AttestationData
|
||||
signature*: ValidatorSig
|
||||
|
||||
TrustedIndexedAttestation* = object
|
||||
IndexedAttestation*[Trust] = object
|
||||
attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE]
|
||||
data*: AttestationData
|
||||
when Trust is SigVerified|Trusted:
|
||||
signature*: TrustedSig
|
||||
else:
|
||||
signature*: ValidatorSig
|
||||
|
||||
CommitteeValidatorsBits* = BitList[Limit MAX_VALIDATORS_PER_COMMITTEE]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestation
|
||||
Attestation* = object
|
||||
aggregation_bits*: CommitteeValidatorsBits
|
||||
data*: AttestationData
|
||||
signature*: ValidatorSig
|
||||
|
||||
TrustedAttestation* = object
|
||||
Attestation*[Trust] = object
|
||||
aggregation_bits*: CommitteeValidatorsBits
|
||||
data*: AttestationData
|
||||
when Trust is SigVerified|Trusted:
|
||||
signature*: TrustedSig
|
||||
else:
|
||||
signature*: ValidatorSig
|
||||
|
||||
ForkDigest* = distinct array[4, byte]
|
||||
|
||||
|
@ -203,7 +248,7 @@ type
|
|||
validator_index*: uint64
|
||||
|
||||
# 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
|
||||
## 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.
|
||||
|
@ -219,30 +264,7 @@ type
|
|||
state_root*: Eth2Digest ##\
|
||||
## The state root, _after_ this block has been processed
|
||||
|
||||
body*: BeaconBlockBody
|
||||
|
||||
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
|
||||
body*: BeaconBlockBody[Trust]
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconblockheader
|
||||
BeaconBlockHeader* = object
|
||||
|
@ -260,35 +282,20 @@ type
|
|||
GraffitiBytes* = distinct array[MAX_GRAFFITI_SIZE, byte]
|
||||
|
||||
# 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
|
||||
eth1_data*: Eth1Data
|
||||
graffiti*: GraffitiBytes
|
||||
|
||||
# Operations
|
||||
proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS]
|
||||
attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS]
|
||||
attestations*: List[Attestation, Limit MAX_ATTESTATIONS]
|
||||
attester_slashings*: List[AttesterSlashing[Trust], Limit MAX_ATTESTER_SLASHINGS]
|
||||
attestations*: List[Attestation[Trust], Limit MAX_ATTESTATIONS]
|
||||
deposits*: List[Deposit, Limit MAX_DEPOSITS]
|
||||
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS]
|
||||
|
||||
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
|
||||
voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS] # TODO: trust system?
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#beaconstate
|
||||
BeaconState* = object
|
||||
|
@ -417,15 +424,12 @@ type
|
|||
signature*: ValidatorSig
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#signedbeaconblock
|
||||
SignedBeaconBlock* = object
|
||||
message*: BeaconBlock
|
||||
signature*: ValidatorSig
|
||||
|
||||
root* {.dontSerialize.}: Eth2Digest # cached root of signed beacon block
|
||||
|
||||
TrustedSignedBeaconBlock* = object
|
||||
message*: TrustedBeaconBlock
|
||||
SignedBeaconBlock*[Trust] = object
|
||||
message*: BeaconBlock[Trust]
|
||||
when Trust is SigVerified|Trusted:
|
||||
signature*: TrustedSig
|
||||
else:
|
||||
signature*: ValidatorSig
|
||||
|
||||
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
|
||||
AggregateAndProof* = object
|
||||
aggregator_index*: uint64
|
||||
aggregate*: Attestation
|
||||
aggregate*: Attestation[Trusted]
|
||||
selection_proof*: ValidatorSig
|
||||
|
||||
# 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 =
|
||||
e - GENESIS_EPOCH
|
||||
|
||||
func shortLog*(v: SomeBeaconBlock): auto =
|
||||
func shortLog*(v: BeaconBlock): auto =
|
||||
(
|
||||
slot: shortLog(v.slot),
|
||||
proposer_index: v.proposer_index,
|
||||
|
@ -682,7 +686,7 @@ func shortLog*(v: SomeBeaconBlock): auto =
|
|||
voluntary_exits_len: v.body.voluntary_exits.len(),
|
||||
)
|
||||
|
||||
func shortLog*(v: SomeSignedBeaconBlock): auto =
|
||||
func shortLog*(v: SignedBeaconBlock): auto =
|
||||
(
|
||||
blck: shortLog(v.message),
|
||||
signature: shortLog(v.signature)
|
||||
|
@ -733,14 +737,14 @@ func shortLog*(v: PendingAttestation): auto =
|
|||
proposer_index: v.proposer_index
|
||||
)
|
||||
|
||||
func shortLog*(v: SomeAttestation): auto =
|
||||
func shortLog*(v: Attestation): auto =
|
||||
(
|
||||
aggregation_bits: v.aggregation_bits,
|
||||
data: shortLog(v.data),
|
||||
signature: shortLog(v.signature)
|
||||
)
|
||||
|
||||
func shortLog*(v: SomeIndexedAttestation): auto =
|
||||
func shortLog*(v: IndexedAttestation): auto =
|
||||
(
|
||||
attestating_indices: v.attesting_indices,
|
||||
data: shortLog(v.data),
|
||||
|
@ -773,9 +777,15 @@ func shortLog*(v: SignedVoluntaryExit): auto =
|
|||
|
||||
chronicles.formatIt Slot: 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 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
|
||||
|
||||
import json_serialization
|
||||
|
|
|
@ -90,7 +90,7 @@ func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
|
|||
raiseAssert e.msg
|
||||
|
||||
func getAttestationTopic*(forkDigest: ForkDigest,
|
||||
attestation: Attestation,
|
||||
attestation: Attestation[Unchecked],
|
||||
num_active_validators: uint64): string =
|
||||
getAttestationTopic(
|
||||
forkDigest,
|
||||
|
|
|
@ -84,7 +84,7 @@ func get_block_signature*(
|
|||
|
||||
proc verify_block_signature*(
|
||||
fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot,
|
||||
blck: Eth2Digest | SomeBeaconBlock | BeaconBlockHeader,
|
||||
blck: Eth2Digest | BeaconBlock | BeaconBlockHeader,
|
||||
pubkey: ValidatorPubKey,
|
||||
signature: SomeSig): bool =
|
||||
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
|
||||
proc verify_block_signature*(
|
||||
state: BeaconState, signed_block: SomeSignedBeaconBlock): bool {.nbench.} =
|
||||
state: BeaconState, signed_block: SignedBeaconBlock): bool {.nbench.} =
|
||||
let
|
||||
proposer_index = signed_block.message.proposer_index
|
||||
if proposer_index >= state.validators.lenu64:
|
||||
|
@ -49,7 +49,7 @@ proc verify_block_signature*(
|
|||
true
|
||||
|
||||
# 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.
|
||||
let state_root = hash_tree_root(state)
|
||||
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:
|
||||
notice(
|
||||
"Unusual request for a slot in the past",
|
||||
state_root = shortLog(state.root),
|
||||
state_root = state.root,
|
||||
current_slot = state.data.slot,
|
||||
target_slot = slot
|
||||
)
|
||||
|
@ -142,7 +142,7 @@ proc noRollback*(state: var HashedBeaconState) =
|
|||
|
||||
proc state_transition*(
|
||||
preset: RuntimePreset,
|
||||
state: var HashedBeaconState, signedBlock: SomeSignedBeaconBlock,
|
||||
state: var HashedBeaconState, signedBlock: SignedBeaconBlock,
|
||||
stateCache: var StateCache,
|
||||
flags: UpdateFlags, rollback: RollbackHashedProc): bool {.nbench.} =
|
||||
## 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):
|
||||
|
||||
trace "state_transition: processing block, signature passed",
|
||||
signature = shortLog(signedBlock.signature),
|
||||
blockRoot = shortLog(signedBlock.root)
|
||||
signature = signedBlock.signature,
|
||||
blockRoot = signedBlock.root
|
||||
let res = process_block(preset, state.data, signedBlock.message, flags, stateCache)
|
||||
if res.isOk:
|
||||
if skipStateRootValidation in flags or verifyStateRoot(state.data, signedBlock.message):
|
||||
|
@ -193,10 +193,10 @@ proc state_transition*(
|
|||
return true
|
||||
else:
|
||||
debug "state_transition: process_block failed",
|
||||
blck = shortLog(signedBlock.message),
|
||||
blck = signedBlock.message,
|
||||
slot = state.data.slot,
|
||||
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
|
||||
|
||||
# Block processing failed, roll back changes
|
||||
|
@ -213,13 +213,13 @@ proc makeBeaconBlock*(
|
|||
randao_reveal: ValidatorSig,
|
||||
eth1_data: Eth1Data,
|
||||
graffiti: GraffitiBytes,
|
||||
attestations: seq[Attestation],
|
||||
attestations: seq[Attestation[Unchecked]],
|
||||
deposits: seq[Deposit],
|
||||
proposerSlashings: seq[ProposerSlashing],
|
||||
attesterSlashings: seq[AttesterSlashing],
|
||||
attesterSlashings: seq[AttesterSlashing[Unchecked]],
|
||||
voluntaryExits: seq[SignedVoluntaryExit],
|
||||
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
|
||||
## the one identified by parent_root and process_slots must be called up to
|
||||
## 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
|
||||
# some validations.
|
||||
|
||||
var blck = BeaconBlock(
|
||||
# TODO: finish the code refactoring
|
||||
# the result should be TransitionVerified
|
||||
var blck = BeaconBlock[Unchecked](
|
||||
slot: state.data.slot,
|
||||
proposer_index: proposer_index.uint64,
|
||||
parent_root: parent_root,
|
||||
body: BeaconBlockBody(
|
||||
body: BeaconBlockBody[Unchecked](
|
||||
randao_reveal: randao_reveal,
|
||||
eth1_data: eth1data,
|
||||
graffiti: graffiti,
|
||||
proposer_slashings: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS](
|
||||
proposerSlashings),
|
||||
attester_slashings: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS](
|
||||
attester_slashings: List[AttesterSlashing[Unchecked], Limit MAX_ATTESTER_SLASHINGS](
|
||||
attesterSlashings),
|
||||
attestations: List[Attestation, Limit MAX_ATTESTATIONS](attestations),
|
||||
attestations: List[Attestation[Unchecked], Limit MAX_ATTESTATIONS](attestations),
|
||||
deposits: List[Deposit, Limit MAX_DEPOSITS](deposits),
|
||||
voluntary_exits:
|
||||
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:
|
||||
warn "Unable to apply new block to state",
|
||||
blck = shortLog(blck),
|
||||
blck = blck,
|
||||
slot = state.data.slot,
|
||||
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
|
||||
rollback(state)
|
||||
return
|
||||
|
|
|
@ -27,9 +27,11 @@ import
|
|||
./signatures, ./presets,
|
||||
../../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
|
||||
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.} =
|
||||
# Verify that the slots match
|
||||
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
|
||||
proc process_randao(
|
||||
state: var BeaconState, body: SomeBeaconBlockBody, flags: UpdateFlags,
|
||||
state: var BeaconState, body: BeaconBlockBody, flags: UpdateFlags,
|
||||
stateCache: var StateCache): bool {.nbench.} =
|
||||
let
|
||||
proposer_index = get_beacon_proposer_index(state, stateCache)
|
||||
|
@ -108,7 +110,7 @@ proc process_randao(
|
|||
true
|
||||
|
||||
# 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
|
||||
|
||||
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)
|
||||
|
||||
# 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,
|
||||
attester_slashing: AttesterSlashing,
|
||||
attester_slashing: AttesterSlashing[Trust],
|
||||
flags: UpdateFlags
|
||||
): Result[seq[ValidatorIndex], cstring] {.nbench.} =
|
||||
let
|
||||
|
@ -210,6 +212,8 @@ proc check_attester_slashing*(
|
|||
|
||||
var slashed_indices: seq[ValidatorIndex]
|
||||
|
||||
# export sets otherwise
|
||||
# generics visibility issue with toSeq(items(intersection(HashSet, HashSet)))
|
||||
for index in sorted(toSeq(intersection(
|
||||
toHashSet(attestation_1.attesting_indices.asSeq),
|
||||
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
|
||||
proc process_operations(preset: RuntimePreset,
|
||||
state: var BeaconState,
|
||||
body: SomeBeaconBlockBody,
|
||||
body: BeaconBlockBody,
|
||||
flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||
# 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
|
||||
proc process_block*(
|
||||
preset: RuntimePreset,
|
||||
state: var BeaconState, blck: SomeBeaconBlock, flags: UpdateFlags,
|
||||
state: var BeaconState, blck: BeaconBlock, flags: UpdateFlags,
|
||||
stateCache: var StateCache): Result[void, cstring] {.nbench.}=
|
||||
## 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
|
||||
|
|
Loading…
Reference in New Issue