From 48d7e62335e191ff2ac74c68847c676d7f77cda1 Mon Sep 17 00:00:00 2001 From: tersec Date: Fri, 27 Oct 2023 21:54:48 +0000 Subject: [PATCH 01/45] bump nim-confutils to facilitate IpAddress usage (#5533) --- vendor/nim-confutils | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/nim-confutils b/vendor/nim-confutils index 07b598ff2..7568f1b7c 160000 --- a/vendor/nim-confutils +++ b/vendor/nim-confutils @@ -1 +1 @@ -Subproject commit 07b598ff2875f5c86da6546f075d3ed7a1a45b0f +Subproject commit 7568f1b7c3142d8e87c1f3dd42924238926affbe From 34eade3a992634d45c53a211a22274fae760794b Mon Sep 17 00:00:00 2001 From: tersec Date: Sat, 28 Oct 2023 05:10:23 +0000 Subject: [PATCH 02/45] sign blinded blob sidecars during builder API proposals (#5537) --- beacon_chain/spec/signatures.nim | 5 +++-- beacon_chain/validators/beacon_validators.nim | 11 ++++++++++- beacon_chain/validators/validator_pool.nim | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 5b756d64e..1e456db62 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -90,7 +90,7 @@ func compute_block_signing_root*( func compute_blob_signing_root( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blob: BlobSidecar): Eth2Digest = + blob: BlindedBlobSidecar | BlobSidecar): Eth2Digest = let epoch = epoch(slot) domain = get_domain(fork, DOMAIN_BLOB_SIDECAR, epoch, @@ -109,7 +109,8 @@ func get_block_signature*( # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/deneb/validator.md#constructing-the-signedblobsidecars proc get_blob_sidecar_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blob: BlobSidecar, privkey: ValidatorPrivKey): CookedSig = + blob: BlindedBlobSidecar | BlobSidecar, privkey: ValidatorPrivKey): + CookedSig = let signing_root = compute_blob_signing_root( fork, genesis_validators_root, slot, blob) diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index ee3b2da7d..3eeba31ea 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -761,9 +761,18 @@ proc blindedBlockCheckSlashingAndSign[ fork, genesis_validators_root, slot, blockRoot, blindedBlockContents.signed_blinded_block.message) if res.isErr(): - return err("Unable to sign block: " & res.error()) + return err("Unable to sign blinded block: " & res.error()) res.get() + for signedBlindedBlobSidecar in mitems( + blindedBlockContents.signed_blinded_blob_sidecars): + signedBlindedBlobSidecar.signature = validator.getBlobSignature( + fork, genesis_validators_root, slot, + signedBlindedBlobSidecar.message).valueOr: + warn "Unable to sign blinded blob", + reason = error() + return + return ok blindedBlockContents proc getUnsignedBlindedBeaconBlock[ diff --git a/beacon_chain/validators/validator_pool.nim b/beacon_chain/validators/validator_pool.nim index ec3d75060..5ed1b52d0 100644 --- a/beacon_chain/validators/validator_pool.nim +++ b/beacon_chain/validators/validator_pool.nim @@ -628,7 +628,8 @@ proc getBlockSignature*(v: AttachedValidator, fork: Fork, # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/deneb/validator.md#constructing-the-signedblobsidecars proc getBlobSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blob: BlobSidecar): SignatureResult = + blob: BlindedBlobSidecar | BlobSidecar): + SignatureResult = return case v.kind of ValidatorKind.Local: From b0d50015710e6570d765a86bb2bff6d61b0a211d Mon Sep 17 00:00:00 2001 From: tersec Date: Sun, 29 Oct 2023 00:06:13 +0000 Subject: [PATCH 03/45] implement getBlobSidecars Beacon API endpoint (#5530) --- beacon_chain/rpc/rest_beacon_api.nim | 47 ++++++++++++++++++++++++++++ beacon_chain/rpc/rest_constants.nim | 3 +- ncli/resttest-rules.json | 24 ++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/beacon_chain/rpc/rest_beacon_api.nim b/beacon_chain/rpc/rest_beacon_api.nim index 876b48d4e..352a46da6 100644 --- a/beacon_chain/rpc/rest_beacon_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -1374,3 +1374,50 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = VoluntaryExitValidationError, $res.error()) return RestApiResponse.jsonMsgResponse(VoluntaryExitValidationSuccess) + + # https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.2#/Beacon/getBlobSidecars + # https://github.com/ethereum/beacon-APIs/blob/v2.4.2/apis/beacon/blob_sidecars/blob_sidecars.yaml + router.api(MethodGet, "/eth/v1/beacon/blob_sidecars/{block_id}") do ( + block_id: BlockIdent, indices: seq[uint64]) -> RestApiResponse: + let + bid = block_id.valueOr: + return RestApiResponse.jsonError(Http400, InvalidBlockIdValueError, + $error) + + bdata = node.getForkedBlock(bid).valueOr: + return RestApiResponse.jsonError(Http404, BlockNotFoundError) + + contentType = block: + let res = preferredContentType(jsonMediaType, + sszMediaType) + if res.isErr(): + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + res.get() + + # https://github.com/ethereum/beacon-APIs/blob/v2.4.2/types/deneb/blob_sidecar.yaml#L2-L28 + let data = newClone(default(List[BlobSidecar, Limit MAX_BLOBS_PER_BLOCK])) + + if indices.isErr: + return RestApiResponse.jsonError(Http400, + InvalidSidecarIndexValueError) + + let indexFilter = indices.get.toHashSet + + for blobIndex in 0'u64 ..< MAX_BLOBS_PER_BLOCK: + if indexFilter.len > 0 and blobIndex notin indexFilter: + continue + + var blobSidecar = new BlobSidecar + + if node.dag.db.getBlobSidecar(bdata.root, blobIndex, blobSidecar[]): + discard data[].add blobSidecar[] + + return + if contentType == sszMediaType: + RestApiResponse.sszResponse( + data[], headers = [("eth-consensus-version", + node.dag.cfg.consensusForkAtEpoch(bid.slot.epoch).toString())]) + elif contentType == jsonMediaType: + RestApiResponse.jsonResponse(data) + else: + RestApiResponse.jsonError(Http500, InvalidAcceptError) diff --git a/beacon_chain/rpc/rest_constants.nim b/beacon_chain/rpc/rest_constants.nim index 09e4bdfdf..a57ddeb2a 100644 --- a/beacon_chain/rpc/rest_constants.nim +++ b/beacon_chain/rpc/rest_constants.nim @@ -241,4 +241,5 @@ const "Failed to obtain fork information" InvalidTimestampValue* = "Invalid or missing timestamp value" - + InvalidSidecarIndexValueError* = + "Invalid blob index" diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index a0e593c85..8b0999908 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -2669,6 +2669,30 @@ "body": [{"operator": "jstructcmps", "start": ["data"],"value": [{"message": {"validator_index": "", "from_bls_pubkey": "", "to_execution_address": ""}, "signature": ""}]}] } }, + { + "topics": ["beacon", "blob_sidecars_blockid"], + "request": { + "url": "/eth/v1/beacon/blob_sidecars/head", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "200"}} + }, + { + "topics": ["beacon", "blob_sidecars_blockid"], + "request": { + "url": "/eth/v1/beacon/blob_sidecars/finalized", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "200"}} + }, + { + "topics": ["beacon", "blob_sidecars_blockid"], + "request": { + "url": "/eth/v1/beacon/blob_sidecars/0x0000000000000000000000000000000000000000000000000000000000000000", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "404"}} + }, { "topics": ["builder", "states_expected_withdrawals"], "request": { From 62d59daaa7b7ad51b597fdd81000a4c9dc118e56 Mon Sep 17 00:00:00 2001 From: tersec Date: Mon, 30 Oct 2023 06:44:43 +0000 Subject: [PATCH 04/45] consensus-spec URL updates to v1.4.0-beta.3 (#5541) --- beacon_chain/beacon_chain_db_immutable.nim | 2 +- .../consensus_object_pools/attestation_pool.nim | 2 +- beacon_chain/consensus_object_pools/block_dag.nim | 2 +- .../consensus_object_pools/blockchain_dag.nim | 2 +- beacon_chain/consensus_object_pools/spec_cache.nim | 2 +- beacon_chain/el/el_manager.nim | 2 +- beacon_chain/gossip_processing/README.md | 2 +- .../gossip_processing/gossip_validation.nim | 4 ++-- beacon_chain/libnimbus_lc/libnimbus_lc.h | 14 +++++++------- beacon_chain/networking/eth2_network.nim | 4 ++-- beacon_chain/spec/beacon_time.nim | 2 +- beacon_chain/spec/beaconstate.nim | 6 +++--- beacon_chain/spec/datatypes/altair.nim | 4 ++-- beacon_chain/spec/datatypes/constants.nim | 2 +- beacon_chain/spec/datatypes/deneb.nim | 6 +++--- beacon_chain/spec/keystore.nim | 2 +- beacon_chain/spec/signatures.nim | 12 ++++++------ beacon_chain/spec/state_transition_block.nim | 2 +- beacon_chain/spec/state_transition_epoch.nim | 2 +- beacon_chain/validators/slashing_protection_v2.nim | 2 +- beacon_chain/validators/validator_pool.nim | 2 +- docs/attestation_flow.md | 2 +- tests/consensus_spec/fixtures_utils.nim | 2 +- 23 files changed, 41 insertions(+), 41 deletions(-) diff --git a/beacon_chain/beacon_chain_db_immutable.nim b/beacon_chain/beacon_chain_db_immutable.nim index cde1cd32d..5c462715b 100644 --- a/beacon_chain/beacon_chain_db_immutable.nim +++ b/beacon_chain/beacon_chain_db_immutable.nim @@ -127,7 +127,7 @@ type current_sync_committee*: SyncCommittee # [New in Altair] next_sync_committee*: SyncCommittee # [New in Altair] - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconstate # Memory-representation-equivalent to a Bellatrix BeaconState for in-place SSZ # reading and writing BellatrixBeaconStateNoImmutableValidators* = object diff --git a/beacon_chain/consensus_object_pools/attestation_pool.nim b/beacon_chain/consensus_object_pools/attestation_pool.nim index c5cb4c7cd..555382371 100644 --- a/beacon_chain/consensus_object_pools/attestation_pool.nim +++ b/beacon_chain/consensus_object_pools/attestation_pool.nim @@ -739,7 +739,7 @@ func getAggregatedAttestation*(pool: var AttestationPool, index: CommitteeIndex): Opt[Attestation] = ## Select the attestation that has the most votes going for it in the given ## slot/index - ## https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#construct-aggregate + ## https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#construct-aggregate let candidateIdx = pool.candidateIdx(slot) if candidateIdx.isNone: return Opt.none(Attestation) diff --git a/beacon_chain/consensus_object_pools/block_dag.nim b/beacon_chain/consensus_object_pools/block_dag.nim index b7e375619..b18c7daf5 100644 --- a/beacon_chain/consensus_object_pools/block_dag.nim +++ b/beacon_chain/consensus_object_pools/block_dag.nim @@ -134,7 +134,7 @@ func link*(parent, child: BlockRef) = func get_ancestor*(blck: BlockRef, slot: Slot, maxDepth = 100'i64 * 365 * 24 * 60 * 60 div SECONDS_PER_SLOT.int): BlockRef = - ## https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/fork-choice.md#get_ancestor + ## https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/fork-choice.md#get_ancestor ## Return the most recent block as of the time at `slot` that not more recent ## than `blck` itself if isNil(blck): return nil diff --git a/beacon_chain/consensus_object_pools/blockchain_dag.nim b/beacon_chain/consensus_object_pools/blockchain_dag.nim index d601aa59f..fc5cd5efd 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag.nim @@ -2613,7 +2613,7 @@ func aggregateAll*( # Aggregation spec requires non-empty collection # - https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04 # Consensus specs require at least one attesting index in attestation - # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation + # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation return err("aggregate: no attesting keys") let diff --git a/beacon_chain/consensus_object_pools/spec_cache.nim b/beacon_chain/consensus_object_pools/spec_cache.nim index dd3b01257..f803e74c6 100644 --- a/beacon_chain/consensus_object_pools/spec_cache.nim +++ b/beacon_chain/consensus_object_pools/spec_cache.nim @@ -191,7 +191,7 @@ func makeAttestationData*( epoch: current_epoch, root: epoch_boundary_block.blck.root)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#validator-assignments +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#validator-assignments iterator get_committee_assignments*( shufflingRef: ShufflingRef, validator_indices: HashSet[ValidatorIndex]): tuple[committee_index: CommitteeIndex, diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index 928056057..4c0d3517b 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -423,7 +423,7 @@ template toGaugeValue(x: Quantity): int64 = # doAssert SECONDS_PER_ETH1_BLOCK * cfg.ETH1_FOLLOW_DISTANCE < GENESIS_DELAY, # "Invalid configuration: GENESIS_DELAY is set too low" -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#get_eth1_data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#get_eth1_data func compute_time_at_slot(genesis_time: uint64, slot: Slot): uint64 = genesis_time + slot * SECONDS_PER_SLOT diff --git a/beacon_chain/gossip_processing/README.md b/beacon_chain/gossip_processing/README.md index 83f6eccba..cd1cf4613 100644 --- a/beacon_chain/gossip_processing/README.md +++ b/beacon_chain/gossip_processing/README.md @@ -9,7 +9,7 @@ This folder holds a collection of modules to: Gossip validation is different from consensus verification in particular for blocks. -- Blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_block +- Blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_block - Attestations (aggregated): https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof - Attestations (unaggregated): https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#attestation-subnets - Voluntary exits: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#voluntary_exit diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 939f4eec5..3d58cf22e 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -276,7 +276,7 @@ template validateBeaconBlockBellatrix( # # `is_merge_transition_complete(state)` tests for # `state.latest_execution_payload_header != ExecutionPayloadHeader()`, while - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/beacon-chain.md#block-processing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#block-processing # shows that `state.latest_execution_payload_header` being default or not is # exactly equivalent to whether that block's execution payload is default or # not, so test cached block information rather than reconstructing a state. @@ -1012,7 +1012,7 @@ proc validateAttesterSlashing*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#proposer_slashing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#proposer_slashing proc validateProposerSlashing*( pool: ValidatorChangePool, proposer_slashing: ProposerSlashing): Result[void, ValidationError] = diff --git a/beacon_chain/libnimbus_lc/libnimbus_lc.h b/beacon_chain/libnimbus_lc/libnimbus_lc.h index f9bb665ab..1c00d71bc 100644 --- a/beacon_chain/libnimbus_lc/libnimbus_lc.h +++ b/beacon_chain/libnimbus_lc/libnimbus_lc.h @@ -149,11 +149,11 @@ typedef struct ETHBeaconState ETHBeaconState; * representation - If successful. * @return `NULL` - If the given `sszBytes` is malformed. * - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/phase0/beacon-chain.md#beaconstate - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/altair/beacon-chain.md#beaconstate - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/bellatrix/beacon-chain.md#beaconstate - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/capella/beacon-chain.md#beaconstate - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/configs/README.md + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconstate + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#beaconstate + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconstate + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/configs/README.md */ ETH_RESULT_USE_CHECK ETHBeaconState *ETHBeaconStateCreateFromSsz( @@ -595,7 +595,7 @@ const ETHLightClientHeader *ETHLightClientStoreGetFinalizedHeader( * @return Whether or not the next sync committee is currently known. * * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/light-client/sync-protocol.md#is_next_sync_committee_known - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/light-client/light-client.md + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/light-client.md */ ETH_RESULT_USE_CHECK bool ETHLightClientStoreIsNextSyncCommitteeKnown(const ETHLightClientStore *store); @@ -669,7 +669,7 @@ void ETHLightClientHeaderDestroy(ETHLightClientHeader *header); * * @return Pointer to a copy of the given header's beacon block root. * - * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/beacon-chain.md#hash_tree_root + * @see https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#hash_tree_root */ ETH_RESULT_USE_CHECK ETHRoot *ETHLightClientHeaderCopyBeaconRoot( diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index f7e2be389..dd99abb3f 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -174,7 +174,7 @@ type MounterProc* = proc(network: Eth2Node) {.gcsafe, raises: [CatchableError].} MessageContentPrinter* = proc(msg: pointer): string {.gcsafe, raises: [].} - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#goodbye + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#goodbye DisconnectionReason* = enum # might see other values on the wire! ClientShutDown = 1 @@ -2263,7 +2263,7 @@ proc getPersistentNetKeys*( func gossipId( data: openArray[byte], phase0Prefix, topic: string): seq[byte] = # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#topics-and-messages - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/p2p-interface.md#topics-and-messages + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#topics-and-messages const MESSAGE_DOMAIN_VALID_SNAPPY = [0x01'u8, 0x00, 0x00, 0x00] let messageDigest = withEth2Hash: h.update(MESSAGE_DOMAIN_VALID_SNAPPY) diff --git a/beacon_chain/spec/beacon_time.nim b/beacon_chain/spec/beacon_time.nim index f9281c73b..46fd49110 100644 --- a/beacon_chain/spec/beacon_time.nim +++ b/beacon_chain/spec/beacon_time.nim @@ -188,7 +188,7 @@ func epoch*(slot: Slot): Epoch = # aka compute_epoch_at_slot if slot == FAR_FUTURE_SLOT: FAR_FUTURE_EPOCH else: Epoch(slot div SLOTS_PER_EPOCH) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/fork-choice.md#compute_slots_since_epoch_start +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/fork-choice.md#compute_slots_since_epoch_start func since_epoch_start*(slot: Slot): uint64 = # aka compute_slots_since_epoch_start ## How many slots since the beginning of the epoch (`[0..SLOTS_PER_EPOCH-1]`) (slot mod SLOTS_PER_EPOCH) diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 5c1499a36..19a01c58c 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -142,7 +142,7 @@ func initiate_validator_exit*( from ./datatypes/deneb import BeaconState -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#slash_validator # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-slash_validator # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#modified-slash_validator func get_slashing_penalty*(state: ForkyBeaconState, @@ -342,7 +342,7 @@ func is_eligible_for_activation_queue*(validator: Validator): bool = validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and validator.effective_balance == MAX_EFFECTIVE_BALANCE -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#is_eligible_for_activation +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_eligible_for_activation func is_eligible_for_activation*( state: ForkyBeaconState, validator: Validator): bool = ## Check if ``validator`` is eligible for activation. @@ -1342,7 +1342,7 @@ func upgrade_to_capella*(cfg: RuntimeConfig, pre: bellatrix.BeaconState): # historical_summaries initialized to correct default automatically ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/deneb/fork.md#upgrading-the-state +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/fork.md#upgrading-the-state func upgrade_to_deneb*(cfg: RuntimeConfig, pre: capella.BeaconState): ref deneb.BeaconState = let diff --git a/beacon_chain/spec/datatypes/altair.nim b/beacon_chain/spec/datatypes/altair.nim index 89e9de5a9..4dfafa3f1 100644 --- a/beacon_chain/spec/datatypes/altair.nim +++ b/beacon_chain/spec/datatypes/altair.nim @@ -102,7 +102,7 @@ type pubkeys*: HashArray[Limit SYNC_COMMITTEE_SIZE, ValidatorPubKey] aggregate_pubkey*: ValidatorPubKey - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#synccommitteemessage + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#synccommitteemessage SyncCommitteeMessage* = object slot*: Slot ## Slot to which this contribution pertains @@ -456,7 +456,7 @@ type SyncnetBits* = BitArray[SYNC_COMMITTEE_SUBNET_COUNT] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/p2p-interface.md#metadata + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#metadata MetaData* = object seq_number*: uint64 attnets*: AttnetBits diff --git a/beacon_chain/spec/datatypes/constants.nim b/beacon_chain/spec/datatypes/constants.nim index 703198c66..70c111193 100644 --- a/beacon_chain/spec/datatypes/constants.nim +++ b/beacon_chain/spec/datatypes/constants.nim @@ -16,7 +16,7 @@ type DomainType* = distinct array[4, byte] const - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#constants + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#constants NODE_ID_BITS* = 256 # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#configuration diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index d25c71f08..b6d85b636 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -47,13 +47,13 @@ type # current spec doesn't ever SSZ-serialize it or hash_tree_root it VersionedHash* = array[32, byte] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#custom-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#custom-types BlobIndex* = uint64 # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/polynomial-commitments.md#custom-types Blob* = array[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB, byte] - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/p2p-interface.md#blobsidecar + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/p2p-interface.md#blobsidecar BlobSidecar* = object block_root*: Eth2Digest index*: BlobIndex @@ -110,7 +110,7 @@ type proofs*:seq[KZGProof] blobs*: Blobs - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#executionpayloadheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object # Execution block header fields parent_hash*: Eth2Digest diff --git a/beacon_chain/spec/keystore.nim b/beacon_chain/spec/keystore.nim index dbeb55f57..68ae49ee7 100644 --- a/beacon_chain/spec/keystore.nim +++ b/beacon_chain/spec/keystore.nim @@ -1385,7 +1385,7 @@ proc createWallet*(kdfKind: KdfKind, crypto: crypto, nextAccount: nextAccount.get(0)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#bls_withdrawal_prefix +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#bls_withdrawal_prefix func makeWithdrawalCredentials*(k: ValidatorPubKey): Eth2Digest = var bytes = eth2digest(k.toRaw()) bytes.data[0] = BLS_WITHDRAWAL_PREFIX.uint8 diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 1e456db62..1aa318537 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -44,7 +44,7 @@ func compute_slot_signing_root*( fork, DOMAIN_SELECTION_PROOF, epoch, genesis_validators_root) compute_signing_root(slot, domain) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#aggregation-selection +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#aggregation-selection func get_slot_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, privkey: ValidatorPrivKey): CookedSig = @@ -97,7 +97,7 @@ func compute_blob_signing_root( genesis_validators_root) compute_signing_root(blob, domain) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#signature +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#signature func get_block_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, root: Eth2Digest, privkey: ValidatorPrivKey): CookedSig = @@ -106,7 +106,7 @@ func get_block_signature*( blsSign(privkey, signing_root.data) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/deneb/validator.md#constructing-the-signedblobsidecars +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/validator.md#constructing-the-signedblobsidecars proc get_blob_sidecar_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, blob: BlindedBlobSidecar | BlobSidecar, privkey: ValidatorPrivKey): @@ -147,7 +147,7 @@ func compute_aggregate_and_proof_signing_root*( fork, DOMAIN_AGGREGATE_AND_PROOF, epoch, genesis_validators_root) compute_signing_root(aggregate_and_proof, domain) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#broadcast-aggregate +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#broadcast-aggregate func get_aggregate_and_proof_signature*(fork: Fork, genesis_validators_root: Eth2Digest, aggregate_and_proof: AggregateAndProof, privkey: ValidatorPrivKey): CookedSig = @@ -175,7 +175,7 @@ func compute_attestation_signing_root*( fork, DOMAIN_BEACON_ATTESTER, epoch, genesis_validators_root) compute_signing_root(attestation_data, domain) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#aggregate-signature +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#aggregate-signature func get_attestation_signature*( fork: Fork, genesis_validators_root: Eth2Digest, attestation_data: AttestationData, @@ -265,7 +265,7 @@ proc verify_voluntary_exit_signature*( blsVerify(pubkey, signing_root.data, signature) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#prepare-sync-committee-message +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#prepare-sync-committee-message func compute_sync_committee_message_signing_root*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, beacon_block_root: Eth2Digest): Eth2Digest = diff --git a/beacon_chain/spec/state_transition_block.nim b/beacon_chain/spec/state_transition_block.nim index 102661665..21b027e56 100644 --- a/beacon_chain/spec/state_transition_block.nim +++ b/beacon_chain/spec/state_transition_block.nim @@ -747,7 +747,7 @@ func tx_peek_blob_versioned_hashes(opaque_tx: Transaction): # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash func kzg_commitment_to_versioned_hash*( kzg_commitment: KzgCommitment): VersionedHash = - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#blob + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#blob const VERSIONED_HASH_VERSION_KZG = 0x01'u8 var res: VersionedHash diff --git a/beacon_chain/spec/state_transition_epoch.nim b/beacon_chain/spec/state_transition_epoch.nim index 1af914092..8a1316a21 100644 --- a/beacon_chain/spec/state_transition_epoch.nim +++ b/beacon_chain/spec/state_transition_epoch.nim @@ -1152,7 +1152,7 @@ proc process_epoch*( info.init(state) - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/altair/beacon-chain.md#justification-and-finalization + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#justification-and-finalization # [Modified in Altair] process_justification_and_finalization(state, info.balances, flags) diff --git a/beacon_chain/validators/slashing_protection_v2.nim b/beacon_chain/validators/slashing_protection_v2.nim index c6202f88c..4f39d5770 100644 --- a/beacon_chain/validators/slashing_protection_v2.nim +++ b/beacon_chain/validators/slashing_protection_v2.nim @@ -33,7 +33,7 @@ import # - https://notes.ethereum.org/@djrtwo/Bkn3zpwxB#Validator-responsibilities # # Phase 0 spec - Honest Validator - how to avoid slashing -# - https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#how-to-avoid-slashing +# - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#how-to-avoid-slashing # # In-depth reading on slashing conditions # diff --git a/beacon_chain/validators/validator_pool.nim b/beacon_chain/validators/validator_pool.nim index 5ed1b52d0..345712e47 100644 --- a/beacon_chain/validators/validator_pool.nim +++ b/beacon_chain/validators/validator_pool.nim @@ -640,7 +640,7 @@ proc getBlobSignature*(v: AttachedValidator, fork: Fork, of ValidatorKind.Remote: return SignatureResult.err("web3signer not supported for blobs") -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#aggregate-signature +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#aggregate-signature proc getAttestationSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, data: AttestationData diff --git a/docs/attestation_flow.md b/docs/attestation_flow.md index f0a483ba5..14ce970ca 100644 --- a/docs/attestation_flow.md +++ b/docs/attestation_flow.md @@ -52,7 +52,7 @@ These GossipSub topics are used to listen for attestations: The attestations are then validated by `validateAttestation()` or `validateAggregate()` in either `attestationValidator()` or `aggregateValidator()` according to the P2P specs. - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof -- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#attestation-subnets +- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attestation-subnets Finally, valid attestations are added to the local `attestationPool`. Attestations are dropped in case of an error. diff --git a/tests/consensus_spec/fixtures_utils.nim b/tests/consensus_spec/fixtures_utils.nim index e62c780f3..468237872 100644 --- a/tests/consensus_spec/fixtures_utils.nim +++ b/tests/consensus_spec/fixtures_utils.nim @@ -75,7 +75,7 @@ type rewards*: List[uint64, Limit VALIDATOR_REGISTRY_LIMIT] penalties*: List[uint64, Limit VALIDATOR_REGISTRY_LIMIT] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#eth1block + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#eth1block Eth1Block* = object timestamp*: uint64 deposit_root*: Eth2Digest From d289da8cd497d717b0608fd56fd0bcf73a11a54c Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 31 Oct 2023 01:56:52 +0100 Subject: [PATCH 05/45] extract trusted node sync trigger into separate function (#5544) To prepare for calling trusted node sync from the main Nimbus startup logic, extract the trusted node sync trigger into a separate function. Further allow passing a pre-opened database, as that will be needed to check whether trusted node sync needs to be called during regular start. --- beacon_chain/nimbus_beacon_node.nim | 96 ++++++++++++++++++----------- beacon_chain/trusted_node_sync.nim | 11 ++-- 2 files changed, 64 insertions(+), 43 deletions(-) diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 8506bcb74..553da4b4c 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -114,6 +114,57 @@ declareGauge next_action_wait, logScope: topics = "beacnde" +proc doRunTrustedNodeSync( + db: BeaconChainDB, + metadata: Eth2NetworkMetadata, + databaseDir: string, + eraDir: string, + restUrl: string, + stateId: Option[string], + trustedBlockRoot: Option[Eth2Digest], + backfill: bool, + reindex: bool, + downloadDepositSnapshot: bool) {.async.} = + let + cfg = metadata.cfg + syncTarget = + if stateId.isSome: + if trustedBlockRoot.isSome: + warn "Ignoring `trustedBlockRoot`, `stateId` is set", + stateId, trustedBlockRoot + TrustedNodeSyncTarget( + kind: TrustedNodeSyncKind.StateId, + stateId: stateId.get) + elif trustedBlockRoot.isSome: + TrustedNodeSyncTarget( + kind: TrustedNodeSyncKind.TrustedBlockRoot, + trustedBlockRoot: trustedBlockRoot.get) + else: + TrustedNodeSyncTarget( + kind: TrustedNodeSyncKind.StateId, + stateId: "finalized") + genesis = + if metadata.hasGenesis: + let genesisBytes = try: await metadata.fetchGenesisBytes() + except CatchableError as err: + error "Failed to obtain genesis state", + source = metadata.genesis.sourceDesc, + err = err.msg + quit 1 + newClone(readSszForkedHashedBeaconState(cfg, genesisBytes)) + else: nil + + await db.doTrustedNodeSync( + cfg, + databaseDir, + eraDir, + restUrl, + syncTarget, + backfill, + reindex, + downloadDepositSnapshot, + genesis) + func getVanityLogs(stdoutKind: StdoutLogKind): VanityLogs = case stdoutKind of StdoutLogKind.Auto: raiseAssert "inadmissable here" @@ -2143,51 +2194,24 @@ proc handleStartUpCmd(config: var BeaconNodeConf) {.raises: [CatchableError].} = of BNStartUpCmd.web3: doWeb3Cmd(config, rng[]) of BNStartUpCmd.slashingdb: doSlashingInterchange(config) of BNStartUpCmd.trustedNodeSync: - let - network = loadEth2Network(config) - cfg = network.cfg - syncTarget = - if config.stateId.isSome: - if config.lcTrustedBlockRoot.isSome: - warn "Ignoring `trustedBlockRoot`, `stateId` is set", - stateId = config.stateId, - trustedBlockRoot = config.lcTrustedBlockRoot - TrustedNodeSyncTarget( - kind: TrustedNodeSyncKind.StateId, - stateId: config.stateId.get) - elif config.lcTrustedBlockRoot.isSome: - TrustedNodeSyncTarget( - kind: TrustedNodeSyncKind.TrustedBlockRoot, - trustedBlockRoot: config.lcTrustedBlockRoot.get) - else: - TrustedNodeSyncTarget( - kind: TrustedNodeSyncKind.StateId, - stateId: "finalized") - genesis = - if network.hasGenesis: - let genesisBytes = try: waitFor network.fetchGenesisBytes() - except CatchableError as err: - error "Failed to obtain genesis state", - source = network.genesis.sourceDesc, - err = err.msg - quit 1 - newClone(readSszForkedHashedBeaconState(cfg, genesisBytes)) - else: nil - if config.blockId.isSome(): error "--blockId option has been removed - use --state-id instead!" quit 1 - waitFor doTrustedNodeSync( - cfg, + let + metadata = loadEth2Network(config) + db = BeaconChainDB.new(config.databaseDir, metadata.cfg, inMemory = false) + waitFor db.doRunTrustedNodeSync( + metadata, config.databaseDir, config.eraDir, config.trustedNodeUrl, - syncTarget, + config.stateId, + config.lcTrustedBlockRoot, config.backfillBlocks, config.reindex, - config.downloadDepositSnapshot, - genesis) + config.downloadDepositSnapshot) + db.close() {.pop.} # TODO moduletests exceptions diff --git a/beacon_chain/trusted_node_sync.nim b/beacon_chain/trusted_node_sync.nim index cdd147761..8e4851688 100644 --- a/beacon_chain/trusted_node_sync.nim +++ b/beacon_chain/trusted_node_sync.nim @@ -68,6 +68,7 @@ func shortLog*(v: TrustedNodeSyncTarget): auto = chronicles.formatIt(TrustedNodeSyncTarget): shortLog(it) proc doTrustedNodeSync*( + db: BeaconChainDB, cfg: RuntimeConfig, databaseDir: string, eraDir: string, @@ -89,11 +90,6 @@ proc doTrustedNodeSync*( error "Cannot connect to server", error = error quit 1 - let - db = BeaconChainDB.new(databaseDir, cfg, inMemory = false) - defer: - db.close() - # If possible, we'll store the genesis state in the database - this is not # strictly necessary but renders the resulting database compatible with # versions prior to 22.11 and makes reindexing possible @@ -551,7 +547,8 @@ when isMainModule: kind: TrustedNodeSyncKind.StateId, stateId: os.paramStr(5)) backfill = os.paramCount() > 5 and os.paramStr(6) == "true" - - waitFor doTrustedNodeSync( + db = BeaconChainDB.new(databaseDir, cfg, inMemory = false) + waitFor db.doTrustedNodeSync( getRuntimeConfig(some os.paramStr(1)), os.paramStr(2), os.paramStr(3), os.paramStr(4), syncTarget, backfill, false, true) + db.close() From 8c81515bf68a02515050b2ec3118f42d2a87616e Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Tue, 31 Oct 2023 11:15:38 +0100 Subject: [PATCH 06/45] log slashing protection database error on failure to load (#5542) * log slashing protection database error on failure to load ...and fix noreturn warning * fix the copied one too * oops * oops 2 --- .../validators/message_router_mev.nim | 38 +++++++++---------- .../validators/slashing_protection_v2.nim | 12 +++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/beacon_chain/validators/message_router_mev.nim b/beacon_chain/validators/message_router_mev.nim index 8364a2d39..7f6e6a6d8 100644 --- a/beacon_chain/validators/message_router_mev.nim +++ b/beacon_chain/validators/message_router_mev.nim @@ -72,7 +72,7 @@ proc unblindAndRouteBlockMEV*( if hash_tree_root( blindedBlock.message.body.execution_payload_header) != hash_tree_root(unblindedPayload.data.data): - return err("unblinded payload doesn't match blinded payload header: " & + err("unblinded payload doesn't match blinded payload header: " & $blindedBlock.message.body.execution_payload_header) else: # Signature provided is consistent with unblinded execution payload, @@ -107,19 +107,17 @@ proc unblindAndRouteBlockMEV*( blockRoot = shortLog(signedBlock.root), blck = shortLog(signedBlock), signature = shortLog(signedBlock.signature) - return ok newBlockRef + ok newBlockRef else: - return err("submitBlindedBlock failed with HTTP error code" & + # https://github.com/ethereum/builder-specs/blob/v0.3.0/specs/bellatrix/validator.md#proposer-slashing + # This means if a validator publishes a signature for a + # `BlindedBeaconBlock` (via a dissemination of a + # `SignedBlindedBeaconBlock`) then the validator **MUST** not use the + # local build process as a fallback, even in the event of some failure + # with the external builder network. + err("submitBlindedBlock failed with HTTP error code" & $unblindedPayload.status & ": " & $shortLog(blindedBlock)) - # https://github.com/ethereum/builder-specs/blob/v0.3.0/specs/bellatrix/validator.md#proposer-slashing - # This means if a validator publishes a signature for a - # `BlindedBeaconBlock` (via a dissemination of a - # `SignedBlindedBeaconBlock`) then the validator **MUST** not use the - # local build process as a fallback, even in the event of some failure - # with the external builder network. - return err("unblindAndRouteBlockMEV error") - # TODO currently cannot be combined into one generic function proc unblindAndRouteBlockMEV*( node: BeaconNode, payloadBuilderRestClient: RestClientRef, @@ -150,7 +148,7 @@ proc unblindAndRouteBlockMEV*( if hash_tree_root( blindedBlock.message.body.execution_payload_header) != hash_tree_root(unblindedPayload.data.data.execution_payload): - return err("unblinded payload doesn't match blinded payload header: " & + err("unblinded payload doesn't match blinded payload header: " & $blindedBlock.message.body.execution_payload_header) else: # Signature provided is consistent with unblinded execution payload, @@ -189,14 +187,14 @@ proc unblindAndRouteBlockMEV*( discard $denebImplementationMissing & ": route unblinded blobs" - return ok newBlockRef + ok newBlockRef else: - return err("submitBlindedBlock failed with HTTP error code" & + # https://github.com/ethereum/builder-specs/blob/v0.3.0/specs/bellatrix/validator.md#proposer-slashing + # This means if a validator publishes a signature for a + # `BlindedBeaconBlock` (via a dissemination of a + # `SignedBlindedBeaconBlock`) then the validator **MUST** not use the + # local build process as a fallback, even in the event of some failure + # with the external builder network. + err("submitBlindedBlock failed with HTTP error code" & $unblindedPayload.status & ": " & $shortLog(blindedBlock)) - # https://github.com/ethereum/builder-specs/blob/v0.3.0/specs/bellatrix/validator.md#proposer-slashing - # This means if a validator publishes a signature for a - # `BlindedBeaconBlock` (via a dissemination of a - # `SignedBlindedBeaconBlock`) then the validator **MUST** not use the - # local build process as a fallback, even in the event of some failure - # with the external builder network. diff --git a/beacon_chain/validators/slashing_protection_v2.nim b/beacon_chain/validators/slashing_protection_v2.nim index 4f39d5770..f38928f81 100644 --- a/beacon_chain/validators/slashing_protection_v2.nim +++ b/beacon_chain/validators/slashing_protection_v2.nim @@ -674,8 +674,9 @@ proc initCompatV1*( let alreadyExists = fileExists(databasePath / databaseName & ".sqlite3") - backend = SqStoreRef.init(databasePath, databaseName).valueOr: - fatal "Failed to open slashing protection database" + backendRes = SqStoreRef.init(databasePath, databaseName) + backend = backendRes.valueOr: # TODO https://github.com/nim-lang/Nim/issues/22605 + fatal "Failed to open slashing protection database", err = backendRes.error quit 1 result.db = T(backend: backend) @@ -716,9 +717,10 @@ proc init*(T: type SlashingProtectionDB_v2, let alreadyExists = fileExists(databasePath / databaseName & ".sqlite3") - backend = SqStoreRef.init(databasePath, databaseName, - keyspaces = []).valueOr: - fatal "Failed to open slashing protection database" + backendRes = SqStoreRef.init(databasePath, databaseName, + keyspaces = []) + backend = backendRes.valueOr: # TODO https://github.com/nim-lang/Nim/issues/22605 + fatal "Failed to open slashing protection database", err = backendRes.error quit 1 result = T(backend: backend) From 173582ad70ddb6c0371f9c791b0d86d4680c096f Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 31 Oct 2023 13:43:46 +0100 Subject: [PATCH 07/45] initialize KZG crypto before starting network (#5543) Move KZG trusted setup initialization before `BeaconNode.init` to avoid edge case where network message is received and processed before crypto library has been properly initialized. Followup from #4870. --- beacon_chain/nimbus_beacon_node.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 553da4b4c..7a45fd7b2 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -2066,9 +2066,7 @@ proc doRunBeaconNode(config: var BeaconNodeConf, rng: ref HmacDrbgContext) {.rai bnStatus = BeaconNodeStatus.Stopping c_signal(ansi_c.SIGTERM, SIGTERMHandler) - let node = waitFor BeaconNode.init(rng, config, metadata) - - if node.dag.cfg.DENEB_FORK_EPOCH != FAR_FUTURE_EPOCH: + if metadata.cfg.DENEB_FORK_EPOCH != FAR_FUTURE_EPOCH: let res = if config.trustedSetupFile.isNone: conf.loadKzgTrustedSetup() @@ -2077,6 +2075,8 @@ proc doRunBeaconNode(config: var BeaconNodeConf, rng: ref HmacDrbgContext) {.rai if res.isErr(): raiseAssert res.error() + let node = waitFor BeaconNode.init(rng, config, metadata) + if bnStatus == BeaconNodeStatus.Stopping: return From 556d5e71142080d57a3cb2a3a0fed311043f73fd Mon Sep 17 00:00:00 2001 From: tersec Date: Wed, 1 Nov 2023 05:53:09 +0100 Subject: [PATCH 08/45] rm unused code (#5538) --- .../consensus_object_pools/blockchain_dag.nim | 4 - .../blockchain_dag_light_client.nim | 6 +- beacon_chain/el/el_conf.nim | 3 - beacon_chain/el/el_manager.nim | 48 +++-------- beacon_chain/era_db.nim | 2 +- beacon_chain/networking/eth2_network.nim | 11 --- beacon_chain/networking/network_metadata.nim | 2 +- beacon_chain/spec/beaconstate.nim | 14 ---- beacon_chain/spec/forks.nim | 16 ++-- .../validators/keystore_management.nim | 10 +-- ncli/logtrace.nim | 79 +++---------------- 11 files changed, 35 insertions(+), 160 deletions(-) diff --git a/beacon_chain/consensus_object_pools/blockchain_dag.nim b/beacon_chain/consensus_object_pools/blockchain_dag.nim index fc5cd5efd..4d5c8c6bf 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag.nim @@ -553,8 +553,6 @@ func init*( dag.putShufflingRef(tmp) tmp - attester_dependent_root = withState(state): - forkyState.attester_dependent_root total_active_balance = withState(state): get_total_active_balance(forkyState.data, cache) epochRef = EpochRef( @@ -2421,7 +2419,6 @@ proc updateHead*( if not(isNil(dag.onHeadChanged)): let - currentEpoch = epoch(newHead.slot) depRoot = withState(dag.headState): forkyState.proposer_dependent_root prevDepRoot = withState(dag.headState): forkyState.attester_dependent_root @@ -2733,7 +2730,6 @@ proc rebuildIndex*(dag: ChainDAGRef) = if state_root.isZero: # If we can find an era file with this state, use it as an alternative # starting point - ignore failures for now - var bytes: seq[byte] if dag.era.getState( historicalRoots, historicalSummaries, slot, state[]).isOk(): state_root = getStateRoot(state[]) diff --git a/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim b/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim index 6e32dd264..b605f3e4e 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim @@ -723,11 +723,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) = blocks.add bid # Process blocks (reuses `dag.headState`, but restores it to the current head) - var - tmpState = assignClone(dag.headState) - tmpCache, cache: StateCache - oldCheckpoint: Checkpoint - cpIndex = 0 + var cache: StateCache for i in countdown(blocks.high, blocks.low): bid = blocks[i] if not dag.updateExistingState( diff --git a/beacon_chain/el/el_conf.nim b/beacon_chain/el/el_conf.nim index 5f96105ca..1458d4613 100644 --- a/beacon_chain/el/el_conf.nim +++ b/beacon_chain/el/el_conf.nim @@ -71,9 +71,6 @@ func unknownRoleMsg(role: string): string = template raiseError(reader: var TomlReader, msg: string) = raiseTomlErr(reader.lex, msg) -template raiseError(reader: var JsonReader, msg: string) = - raiseTomlErr(reader.lex, msg) - proc readValue*(reader: var TomlReader, value: var EngineApiRoles) {.raises: [SerializationError, IOError].} = let roles = reader.readValue seq[string] diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index 4c0d3517b..e9334594f 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -96,7 +96,6 @@ const type Eth1BlockNumber* = uint64 Eth1BlockTimestamp* = uint64 - Eth1BlockHeader = engine_api.BlockHeader Eth1Block* = ref object hash*: Eth2Digest @@ -393,9 +392,6 @@ template trackedRequestWithTimeout[T](connection: ELConnection, template cfg(m: ELManager): auto = m.eth1Chain.cfg -template db(m: ELManager): BeaconChainDB = - m.eth1Chain.db - func hasJwtSecret*(m: ELManager): bool = for c in m.elConnections: if c.engineUrl.jwtSecret.isSome: @@ -409,12 +405,6 @@ func isSynced*(m: ELManager): bool = template eth1ChainBlocks*(m: ELManager): Deque[Eth1Block] = m.eth1Chain.blocks -template finalizedDepositsMerkleizer(m: ELManager): auto = - m.eth1Chain.finalizedDepositsMerkleizer - -template headMerkleizer(m: ELManager): auto = - m.eth1Chain.headMerkleizer - template toGaugeValue(x: Quantity): int64 = toGaugeValue(distinctBase x) @@ -885,15 +875,6 @@ template EngineApiResponseType*(T: type capella.ExecutionPayloadForSigning): typ template EngineApiResponseType*(T: type deneb.ExecutionPayloadForSigning): type = engine_api.GetPayloadV3Response -template payload(response: engine_api.ExecutionPayloadV1): engine_api.ExecutionPayloadV1 = - response - -template payload(response: engine_api.GetPayloadV2Response): engine_api.ExecutionPayloadV1OrV2 = - response.executionPayload - -template payload(response: engine_api.GetPayloadV3Response): engine_api.ExecutionPayloadV3 = - response.executionPayload - template toEngineWithdrawals*(withdrawals: seq[capella.Withdrawal]): seq[WithdrawalV1] = mapIt(withdrawals, toEngineWithdrawal(it)) @@ -1810,10 +1791,6 @@ func new*(T: type ELConnection, engineUrl: engineUrl, depositContractSyncStatus: DepositContractSyncStatus.unknown) -template getOrDefault[T, E](r: Result[T, E]): T = - type TT = T - get(r, default(TT)) - proc init*(T: type Eth1Chain, cfg: RuntimeConfig, db: BeaconChainDB, @@ -2017,12 +1994,6 @@ proc syncBlockRange(m: ELManager, blockNumber = lastBlock.number, depositsProcessed = lastBlock.depositCount -func init(T: type FullBlockId, blk: Eth1BlockHeader|BlockObject): T = - FullBlockId(number: Eth1BlockNumber blk.number, hash: blk.hash) - -func isNewLastBlock(m: ELManager, blk: Eth1BlockHeader|BlockObject): bool = - m.latestEth1Block.isNone or blk.number.uint64 > m.latestEth1BlockNumber - func hasConnection*(m: ELManager): bool = m.elConnections.len > 0 @@ -2121,7 +2092,6 @@ proc syncEth1Chain(m: ELManager, connection: ELConnection) {.async.} = debug "Starting Eth1 syncing", `from` = shortLog(m.eth1Chain.blocks[^1]) - var didPollOnce = false while true: debug "syncEth1Chain tick" @@ -2182,7 +2152,7 @@ proc startChainSyncingLoop(m: ELManager) {.async.} = continue await syncEth1Chain(m, syncedConnectionFut.read) - except CatchableError as err: + except CatchableError: await sleepAsync(10.seconds) # A more detailed error is already logged by trackEngineApiRequest @@ -2238,17 +2208,17 @@ proc testWeb3Provider*(web3Url: Uri, stdout.write "\n" res - let - chainId = request "Chain ID": - web3.provider.eth_chainId() + discard request "Chain ID": + web3.provider.eth_chainId() + discard request "Sync status": + web3.provider.eth_syncing() + + let latestBlock = request "Latest block": web3.provider.eth_getBlockByNumber(blockId("latest"), false) - syncStatus = request "Sync status": - web3.provider.eth_syncing() - ns = web3.contractSender(DepositContract, depositContractAddress) - depositRoot = request "Deposit root": - ns.get_deposit_root.call(blockNumber = latestBlock.number.uint64) + discard request "Deposit root": + ns.get_deposit_root.call(blockNumber = latestBlock.number.uint64) diff --git a/beacon_chain/era_db.nim b/beacon_chain/era_db.nim index bd7c88a89..d5ab39b03 100644 --- a/beacon_chain/era_db.nim +++ b/beacon_chain/era_db.nim @@ -316,7 +316,7 @@ proc getBlock*( readSszBytes(tmp, result.get(), updateRoot = root.isNone) if root.isSome(): result.get().root = root.get() - except CatchableError as exc: + except CatchableError: result.err() proc getStateSZ*( diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index dd99abb3f..1fa57e3ff 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -1887,9 +1887,6 @@ proc new(T: type Eth2Node, node -template publicKey(node: Eth2Node): keys.PublicKey = - node.discovery.privKey.toPublicKey - proc startListening*(node: Eth2Node) {.async.} = if node.discoveryEnabled: try: @@ -2173,14 +2170,6 @@ proc peerTrimmerHeartbeat(node: Eth2Node) {.async.} = func asEthKey*(key: PrivateKey): keys.PrivateKey = keys.PrivateKey(key.skkey) -proc initAddress(T: type MultiAddress, str: string): T = - let address = MultiAddress.init(str) - if IPFS.match(address) and matchPartial(multiaddress.TCP, address): - result = address - else: - raise newException(MultiAddressError, - "Invalid bootstrap node multi-address") - template tcpEndPoint(address, port): auto = MultiAddress.init(address, tcpProtocol, port) diff --git a/beacon_chain/networking/network_metadata.nim b/beacon_chain/networking/network_metadata.nim index a7eea86e3..c56a13d30 100644 --- a/beacon_chain/networking/network_metadata.nim +++ b/beacon_chain/networking/network_metadata.nim @@ -474,7 +474,7 @@ when const_preset in ["mainnet", "gnosis"]: toOpenArray(metadata.genesis.bakedBytes, 0, sizeof(BeaconStateHeader) - 1), BeaconStateHeader) Opt.some header.genesis_validators_root - except SerializationError as err: + except SerializationError: raiseAssert "Invalid baken-in genesis state" else: Opt.none Eth2Digest diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 19a01c58c..088bdeda5 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -1102,20 +1102,6 @@ proc initialize_beacon_state_from_eth1*( # TODO https://github.com/nim-lang/Nim/issues/19094 # state -proc initialize_hashed_beacon_state_from_eth1( - cfg: RuntimeConfig, - eth1_block_hash: Eth2Digest, - eth1_timestamp: uint64, - deposits: openArray[DepositData], - execution_payload_header: ForkyExecutionPayloadHeader, - flags: UpdateFlags = {}): auto = - # TODO https://github.com/nim-lang/Nim/issues/19094 - result = initHashedBeaconState( - initialize_beacon_state_from_eth1( - cfg, eth1_block_hash, eth1_timestamp, deposits, - execution_payload_header, flags)) - result.root = hash_tree_root(result.data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/fork.md#upgrading-the-state func translate_participation( state: var altair.BeaconState, diff --git a/beacon_chain/spec/forks.nim b/beacon_chain/spec/forks.nim index 5cd8f8c42..1360cd2f0 100644 --- a/beacon_chain/spec/forks.nim +++ b/beacon_chain/spec/forks.nim @@ -646,11 +646,11 @@ template forky( template withEpochInfo*(x: ForkedEpochInfo, body: untyped): untyped = case x.kind of EpochInfoFork.Phase0: - const infoFork {.inject.} = EpochInfoFork.Phase0 + const infoFork {.inject, used.} = EpochInfoFork.Phase0 template info: untyped {.inject.} = x.phase0Data body of EpochInfoFork.Altair: - const infoFork {.inject.} = EpochInfoFork.Altair + const infoFork {.inject, used.} = EpochInfoFork.Altair template info: untyped {.inject.} = x.altairData body @@ -797,11 +797,11 @@ template withBlck*( case x.kind of ConsensusFork.Phase0: const consensusFork {.inject, used.} = ConsensusFork.Phase0 - template forkyBlck: untyped {.inject.} = x.phase0Data + template forkyBlck: untyped {.inject, used.} = x.phase0Data body of ConsensusFork.Altair: const consensusFork {.inject, used.} = ConsensusFork.Altair - template forkyBlck: untyped {.inject.} = x.altairData + template forkyBlck: untyped {.inject, used.} = x.altairData body of ConsensusFork.Bellatrix: const consensusFork {.inject, used.} = ConsensusFork.Bellatrix @@ -809,11 +809,11 @@ template withBlck*( body of ConsensusFork.Capella: const consensusFork {.inject, used.} = ConsensusFork.Capella - template forkyBlck: untyped {.inject.} = x.capellaData + template forkyBlck: untyped {.inject, used.} = x.capellaData body of ConsensusFork.Deneb: const consensusFork {.inject, used.} = ConsensusFork.Deneb - template forkyBlck: untyped {.inject.} = x.denebData + template forkyBlck: untyped {.inject, used.} = x.denebData body func proposer_index*(x: ForkedBeaconBlock): uint64 = @@ -899,8 +899,8 @@ template withStateAndBlck*( body of ConsensusFork.Phase0: const consensusFork {.inject.} = ConsensusFork.Phase0 - template forkyState: untyped {.inject.} = s.phase0Data - template forkyBlck: untyped {.inject.} = b.phase0Data + template forkyState: untyped {.inject, used.} = s.phase0Data + template forkyBlck: untyped {.inject, used.} = b.phase0Data body func toBeaconBlockHeader*( diff --git a/beacon_chain/validators/keystore_management.nim b/beacon_chain/validators/keystore_management.nim index 241bba84a..ced5f2367 100644 --- a/beacon_chain/validators/keystore_management.nim +++ b/beacon_chain/validators/keystore_management.nim @@ -1021,10 +1021,7 @@ proc createLocalValidatorFiles*( encodedStorage: string ): Result[void, KeystoreGenerationError] {.raises: [].} = - var - success = false # becomes true when everything is created successfully - cleanupSecretsDir = true # becomes false if secretsDir already existed - cleanupValidatorsDir = true # becomes false if validatorsDir already existed + var success = false # becomes true when everything is created successfully # secretsDir: let secretsDirExisted: bool = dirExists(secretsDir) @@ -1068,10 +1065,7 @@ proc createLockedLocalValidatorFiles( encodedStorage: string ): Result[FileLockHandle, KeystoreGenerationError] {.raises: [].} = - var - success = false # becomes true when everything is created successfully - cleanupSecretsDir = true # becomes false if secretsDir already existed - cleanupValidatorsDir = true # becomes false if validatorsDir already existed + var success = false # becomes true when everything is created successfully # secretsDir: let secretsDirExisted: bool = dirExists(secretsDir) diff --git a/ncli/logtrace.nim b/ncli/logtrace.nim index fdcdcb574..0650a7c43 100644 --- a/ncli/logtrace.nim +++ b/ncli/logtrace.nim @@ -10,19 +10,6 @@ import from stew/io2 import IoErrorCode -const - LogTraceName = "Beacon-Chain LogTrace Tool" - LogTraceMajor: int = 0 - LogTraceMinor: int = 0 - LogTracePatch: int = 4 - LogTraceVersion = $LogTraceMajor & "." & $LogTraceMinor & "." & - $LogTracePatch - LogTraceCopyright = "Copyright(C) 2021-2023" & - " Status Research & Development GmbH" - LogTraceHeader = LogTraceName & ", Version " & LogTraceVersion & - " [" & hostOS & ": " & hostCPU & "]\r\n" & - LogTraceCopyright & "\r\n" - type StartUpCommand* {.pure.} = enum pubsub, asl, asr, aggasr, scmsr, csr, lat, traceAll, localSimChecks @@ -314,9 +301,6 @@ proc print(r: FileReport) = template fatal(issuesGroup: IssuesGroup, msg: string) = issuesGroup.fatalIssues.add msg -template warning(issuesGroup: IssuesGroup, msg: string) = - issuesGroup.warnings.add msg - proc new(T: type IssuesGroup, name: string): T = T(name: name) @@ -466,56 +450,6 @@ proc readLogFileForASRMessages(file: string, srnode: var SRANode, finally: stream.close() -proc readLogFileForSCMSendMessages(file: string, - ignoreErrors = true, - dumpErrors = false): seq[SlotMessage] = - var res = newSeq[SlotMessage]() - var stream = newFileStream(file) - var line: string - var counter = 0 - try: - while not(stream.atEnd()): - line = stream.readLine() - inc(counter) - var m: LogMessage - try: - m = Json.decode(line, LogMessage, allowUnknownFields = true) - except SerializationError as exc: - if dumpErrors: - error "Serialization error while reading file, ignoring", file = file, - line_number = counter, errorMsg = exc.formatMsg(line) - else: - error "Serialization error while reading file, ignoring", file = file, - line_number = counter - if not(ignoreErrors): - raise exc - else: - continue - - if m.msg == "Sync committee message sent": - let scmm = Json.decode(line, SCMSentMessage, - allowUnknownFields = true) - let m = SlotMessage(kind: SMessageType.SCMSent, - scmsmsg: scmm) - res.add(m) - elif m.msg == "Slot start": - let sm = Json.decode(line, SlotStartMessage, - allowUnknownFields = true) - let m = SlotMessage(kind: SMessageType.SlotStart, - ssmsg: sm) - res.add(m) - - if counter mod 10_000 == 0: - info "Processing file", file = extractFilename(file), - lines_processed = counter, - lines_filtered = len(res) - result = res - - except CatchableError as exc: - warn "Error reading data from file", file = file, errorMsg = exc.msg - finally: - stream.close() - proc readLogFileForSCMSRMessages(file: string, srnode: var SRSCNode, ignoreErrors = true, dumpErrors = false) = var stream = newFileStream(file) @@ -1191,6 +1125,19 @@ proc run*(conf: LogTraceConf) = quit ord(issuesDetected) when isMainModule: + const + LogTraceName = "Beacon-Chain LogTrace Tool" + LogTraceMajor: int = 0 + LogTraceMinor: int = 0 + LogTracePatch: int = 4 + LogTraceVersion = $LogTraceMajor & "." & $LogTraceMinor & "." & + $LogTracePatch + LogTraceCopyright = "Copyright(C) 2021-2023" & + " Status Research & Development GmbH" + LogTraceHeader = LogTraceName & ", Version " & LogTraceVersion & + " [" & hostOS & ": " & hostCPU & "]\r\n" & + LogTraceCopyright & "\r\n" + echo LogTraceHeader var conf = LogTraceConf.load(version = LogTraceVersion) run(conf) From 70aaeee7040edd3298e32f4528d4c392ebbfdc77 Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 1 Nov 2023 09:27:43 +0200 Subject: [PATCH 09/45] Enable comprehensive reasons when REST server faults to create server. (#5546) Bump chronos & presto. --- beacon_chain/nimbus_binary_common.nim | 33 ++++++++++++--------------- vendor/nim-chronos | 2 +- vendor/nim-presto | 2 +- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/beacon_chain/nimbus_binary_common.nim b/beacon_chain/nimbus_binary_common.nim index 73ada81de..7defa0d5b 100644 --- a/beacon_chain/nimbus_binary_common.nim +++ b/beacon_chain/nimbus_binary_common.nim @@ -356,9 +356,10 @@ proc init*(T: type RestServerRef, allowedOrigin: Option[string], validateFn: PatternCallback, config: AnyConf): T = - let address = initTAddress(ip, port) - let serverFlags = {HttpServerFlags.QueryCommaSeparatedArray, - HttpServerFlags.NotifyDisconnect} + let + address = initTAddress(ip, port) + serverFlags = {HttpServerFlags.QueryCommaSeparatedArray, + HttpServerFlags.NotifyDisconnect} # We increase default timeout to help validator clients who poll our server # at least once per slot (12.seconds). let @@ -370,26 +371,20 @@ proc init*(T: type RestServerRef, maxHeadersSize = config.restMaxRequestHeadersSize * 1024 maxRequestBodySize = config.restMaxRequestBodySize * 1024 - let res = try: - RestServerRef.new(RestRouter.init(validateFn, allowedOrigin), - address, serverFlags = serverFlags, - httpHeadersTimeout = headersTimeout, - maxHeadersSize = maxHeadersSize, - maxRequestBodySize = maxRequestBodySize) - except CatchableError as err: - notice "Rest server could not be started", address = $address, - reason = err.msg - return nil - + let res = RestServerRef.new(RestRouter.init(validateFn, allowedOrigin), + address, serverFlags = serverFlags, + httpHeadersTimeout = headersTimeout, + maxHeadersSize = maxHeadersSize, + maxRequestBodySize = maxRequestBodySize, + errorType = string) if res.isErr(): - notice "Rest server could not be started", address = $address, + notice "REST HTTP server could not be started", address = $address, reason = res.error() nil else: - notice "Starting REST HTTP server", - url = "http://" & $ip & ":" & $port & "/" - - res.get() + let server = res.get() + notice "Starting REST HTTP server", url = "http://" & $server.localAddress() + server type KeymanagerInitResult* = object diff --git a/vendor/nim-chronos b/vendor/nim-chronos index 253bc3cfc..be2edab3a 160000 --- a/vendor/nim-chronos +++ b/vendor/nim-chronos @@ -1 +1 @@ -Subproject commit 253bc3cfc079de35f9b96b9934ce702605400a51 +Subproject commit be2edab3ac101da03a70cbf52bc3f3d972b35d91 diff --git a/vendor/nim-presto b/vendor/nim-presto index 2ae448ff5..5ca16485e 160000 --- a/vendor/nim-presto +++ b/vendor/nim-presto @@ -1 +1 @@ -Subproject commit 2ae448ff5b0808c8f562c6f0a70bbd7a05407a37 +Subproject commit 5ca16485e4d74e531d50d289ebc0f869d9e6352b From 1a5bcb479eae2be19e58bf119202b6bc7dd0bb6c Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 1 Nov 2023 09:31:18 +0200 Subject: [PATCH 10/45] Fix `broadcast_validation` handling in `publishBlockV2` (fixes #5531) (#5547) * Address issue #5531. * Add more tests. * Add to resttest ability to check values. Fix tests. --- beacon_chain/rpc/rest_beacon_api.nim | 29 +++-- beacon_chain/rpc/rest_constants.nim | 2 + .../eth2_apis/eth2_rest_serialization.nim | 21 ++++ beacon_chain/spec/eth2_apis/rest_types.nim | 3 + ncli/resttest-rules.json | 104 ++++++++++++++++++ ncli/resttest.nim | 42 +++++-- 6 files changed, 183 insertions(+), 18 deletions(-) diff --git a/beacon_chain/rpc/rest_beacon_api.nim b/beacon_chain/rpc/rest_beacon_api.nim index 352a46da6..56b741999 100644 --- a/beacon_chain/rpc/rest_beacon_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -906,19 +906,32 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = # https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlockV2 router.api(MethodPost, "/eth/v2/beacon/blocks") do ( + broadcast_validation: Option[BroadcastValidationType], contentBody: Option[ContentBody]) -> RestApiResponse: let res = block: - if contentBody.isNone(): - return RestApiResponse.jsonError(Http400, EmptyRequestBodyError) - if request.headers.getString("broadcast_validation") != "gossip": - # TODO (henridf): support 'consensus' and 'consensus_and_equivocation' - # broadcast_validation - return RestApiResponse.jsonError( - Http500, "gossip broadcast_validation only supported") let - body = contentBody.get() version = request.headers.getString("eth-consensus-version") + validation = + block: + let res = + if broadcast_validation.isNone(): + BroadcastValidationType.Gossip + else: + broadcast_validation.get().valueOr: + return RestApiResponse.jsonError(Http400, + InvalidBroadcastValidationType) + # TODO (henridf): support 'consensus' and + # 'consensus_and_equivocation' broadcast_validation types. + if res != BroadcastValidationType.Gossip: + return RestApiResponse.jsonError(Http500, + "Only `gossip` broadcast_validation option supported") + res + body = + block: + if contentBody.isNone(): + return RestApiResponse.jsonError(Http400, EmptyRequestBodyError) + contentBody.get() var restBlock = decodeBodyJsonOrSsz(RestPublishedSignedBlockContents, body, version).valueOr: diff --git a/beacon_chain/rpc/rest_constants.nim b/beacon_chain/rpc/rest_constants.nim index a57ddeb2a..49819d723 100644 --- a/beacon_chain/rpc/rest_constants.nim +++ b/beacon_chain/rpc/rest_constants.nim @@ -243,3 +243,5 @@ const "Invalid or missing timestamp value" InvalidSidecarIndexValueError* = "Invalid blob index" + InvalidBroadcastValidationType* = + "Invalid broadcast_validation type value" diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 5498610c4..b7d5789a3 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -3606,6 +3606,15 @@ proc encodeString*(value: StateIdent): RestResult[string] = of StateIdentType.Justified: ok("justified") +proc encodeString*(value: BroadcastValidationType): RestResult[string] = + case value + of BroadcastValidationType.Gossip: + ok("gossip") + of BroadcastValidationType.Consensus: + ok("consensus") + of BroadcastValidationType.ConsensusAndEquivocation: + ok("consensus_and_equivocation") + proc encodeString*(value: BlockIdent): RestResult[string] = case value.kind of BlockQueryKind.Slot: @@ -3821,6 +3830,18 @@ proc decodeString*(t: typedesc[BlockIdent], let res = ? Base10.decode(uint64, value) ok(BlockIdent(kind: BlockQueryKind.Slot, slot: Slot(res))) +proc decodeString*(t: typedesc[BroadcastValidationType], + value: string): Result[BroadcastValidationType, cstring] = + case value + of "gossip": + ok(BroadcastValidationType.Gossip) + of "consensus": + ok(BroadcastValidationType.Consensus) + of "consensus_and_equivocation": + ok(BroadcastValidationType.ConsensusAndEquivocation) + else: + err("Incorrect broadcast validation type value") + proc decodeString*(t: typedesc[ValidatorIdent], value: string): Result[ValidatorIdent, cstring] = if len(value) > 2: diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index 41459ceaf..1015cf55a 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -84,6 +84,9 @@ type StateIdentType* {.pure.} = enum Head, Genesis, Finalized, Justified + BroadcastValidationType* {.pure.} = enum + Gossip, Consensus, ConsensusAndEquivocation + StateIdent* = object case kind*: StateQueryKind of StateQueryKind.Slot: diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 8b0999908..18bcfdcd1 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -3611,5 +3611,109 @@ }} ] } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks", + }, + "response": { + "status": {"operator": "equals", "value": "400"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpns", "value": {"code": 400, "message": "Empty request's body"}}] + } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks?broadcast_validation=gossip", + }, + "response": { + "status": {"operator": "equals", "value": "400"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpnsav", "value": {"code": 400, "message": "Empty request's body"}}] + } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks?broadcast_validation=test", + }, + "response": { + "status": {"operator": "equals", "value": "400"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpnsav", "value": {"code": 400, "message": "Invalid broadcast_validation type value"}}] + } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks?broadcast_validation=", + }, + "response": { + "status": {"operator": "equals", "value": "400"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpnsav", "value": {"code": 400, "message": "Invalid broadcast_validation type value"}}] + } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks?broadcast_validation=consensus", + }, + "comment": "TODO: This should be replaced when `consensus` become supported", + "response": { + "status": {"operator": "equals", "value": "500"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpnsav", "value": {"code": 500, "message": "Only `gossip` broadcast_validation option supported"}}] + } + }, + { + "topics": ["beacon", "beacon_blocks_publish_v2"], + "request": { + "method": "POST", + "headers": { + "Accept": "application/json", + "Content-Type": "application/json", + "Eth-Consensus-Version": "capella" + }, + "url": "/eth/v2/beacon/blocks?broadcast_validation=consensus_and_equivocation", + }, + "comment": "TODO: This should be replaced when `consensus_and_equivocation` become supported", + "response": { + "status": {"operator": "equals", "value": "500"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmpnsav", "value": {"code": 500, "message": "Only `gossip` broadcast_validation option supported"}}] + } } ] diff --git a/ncli/resttest.nim b/ncli/resttest.nim index c8a9c47af..c1150d91a 100644 --- a/ncli/resttest.nim +++ b/ncli/resttest.nim @@ -34,7 +34,8 @@ type Exists, NotExists, Equals, OneOf, Substr BodyOperatorKind {.pure.} = enum - Exists, JsonStructCmpS, JsonStructCmpNS + Exists, JsonStructCmpS, JsonStructCmpNS, + JsonStructCmpSAV, JsonStructCmpNSAV StatusExpect = object kind: StatusOperatorKind @@ -649,13 +650,18 @@ proc getResponseBodyExpect(rule: JsonNode): Result[BodyExpect, cstring] = BodyOperatorKind.JsonStructCmpS of "jstructcmpns": BodyOperatorKind.JsonStructCmpNS + of "jstructcmpsav": + BodyOperatorKind.JsonStructCmpSAV + of "jstructcmpnsav": + BodyOperatorKind.JsonStructCmpNSAV else: return err("`response.body` element has incorrect operator") case operator of BodyOperatorKind.Exists: res.add(BodyItemExpect(kind: operator)) - of BodyOperatorKind.JsonStructCmpS, BodyOperatorKind.JsonStructCmpNS: + of BodyOperatorKind.JsonStructCmpS, BodyOperatorKind.JsonStructCmpNS, + BodyOperatorKind.JsonStructCmpSAV, BodyOperatorKind.JsonStructCmpNSAV: let start = block: var default: seq[string] @@ -762,7 +768,7 @@ proc getPath(jobj: JsonNode, path: seq[string]): Result[JsonNode, cstring] = jnode = jitem ok(jnode) -proc structCmp(j1, j2: JsonNode, strict: bool): bool = +proc structCmp(j1, j2: JsonNode, strict: bool, checkvalue: bool): bool = if j1.kind != j2.kind: return false case j1.kind @@ -776,7 +782,7 @@ proc structCmp(j1, j2: JsonNode, strict: bool): bool = false else: for item in j1.elems: - if not(structCmp(item, j2.elems[0], strict)): + if not(structCmp(item, j2.elems[0], strict, checkvalue)): return false true of JObject: @@ -787,7 +793,7 @@ proc structCmp(j1, j2: JsonNode, strict: bool): bool = let j2node = j2.getOrDefault(key) if isNil(j2node): return false - if not(structCmp(value, j2node, strict)): + if not(structCmp(value, j2node, strict, checkvalue)): return false true else: @@ -795,10 +801,18 @@ proc structCmp(j1, j2: JsonNode, strict: bool): bool = let j1node = j1.getOrDefault(key) if isNil(j1node): return false - if not(structCmp(j1node, value, strict)): + if not(structCmp(j1node, value, strict, checkvalue)): return false true - else: + of JString: + if checkvalue: j1.str == j2.str else: true + of JInt: + if checkvalue: j1.num == j2.num else: true + of JFloat: + if checkvalue: j1.fnum == j2.fnum else: true + of JBool: + if checkvalue: j1.bval == j2.bval else: true + of JNull: true proc validateBody(body: openArray[byte], expect: BodyExpect): bool = @@ -810,7 +824,8 @@ proc validateBody(body: openArray[byte], expect: BodyExpect): bool = of BodyOperatorKind.Exists: if len(body) == 0: return false - of BodyOperatorKind.JsonStructCmpS, BodyOperatorKind.JsonStructCmpNS: + of BodyOperatorKind.JsonStructCmpS, BodyOperatorKind.JsonStructCmpNS, + BodyOperatorKind.JsonStructCmpSAV, BodyOperatorKind.JsonStructCmpNSAV: let jbody = block: let jres = jsonBody(body) @@ -822,11 +837,18 @@ proc validateBody(body: openArray[byte], expect: BodyExpect): bool = return false jpathres.get() let strict = - if item.kind == BodyOperatorKind.JsonStructCmpS: + if item.kind in {BodyOperatorKind.JsonStructCmpS, + BodyOperatorKind.JsonStructCmpSAV}: true else: false - if not(structCmp(jbody, item.value, strict)): + let checkvalue = + if item.kind in {BodyOperatorKind.JsonStructCmpSAV, + BodyOperatorKind.JsonStructCmpNSAV}: + true + else: + false + if not(structCmp(jbody, item.value, strict, checkvalue)): return false true From e1f47bb27a5b529886de31b8c1bddbfcec02f1ed Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 1 Nov 2023 09:32:41 +0200 Subject: [PATCH 11/45] Address #5539. (#5548) --- beacon_chain/rpc/rest_node_api.nim | 16 ++++++---------- .../spec/eth2_apis/eth2_rest_serialization.nim | 10 ++++++++++ beacon_chain/spec/eth2_apis/rest_types.nim | 2 ++ ncli/resttest-rules.json | 18 +++++++++--------- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/beacon_chain/rpc/rest_node_api.nim b/beacon_chain/rpc/rest_node_api.nim index f547db90f..a747d04e7 100644 --- a/beacon_chain/rpc/rest_node_api.nim +++ b/beacon_chain/rpc/rest_node_api.nim @@ -176,24 +176,19 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) = if state.isErr(): return RestApiResponse.jsonError(Http400, InvalidPeerStateValueError, $state.error()) - let sres = validateState(state.get()) - if sres.isErr(): + validateState(state.get()).valueOr: return RestApiResponse.jsonError(Http400, InvalidPeerStateValueError, - $sres.error()) - sres.get() + $error) let directionMask = block: if direction.isErr(): return RestApiResponse.jsonError(Http400, InvalidPeerDirectionValueError, $direction.error()) - let dres = validateDirection(direction.get()) - if dres.isErr(): + validateDirection(direction.get()).valueOr: return RestApiResponse.jsonError(Http400, InvalidPeerDirectionValueError, - $dres.error()) - dres.get() - + $error) var res: seq[RestNodePeer] for peer in node.network.peers.values(): if (peer.connectionState in connectionMask) and @@ -209,7 +204,8 @@ proc installNodeApiHandlers*(router: var RestRouter, node: BeaconNode) = proto: node.network.switch.peerStore[ProtoVersionBook][peer.peerId] ) res.add(peer) - return RestApiResponse.jsonResponseWMeta(res, (count: uint64(len(res)))) + return RestApiResponse.jsonResponseWMeta(res, + (count: RestNumeric(len(res)))) # https://ethereum.github.io/beacon-APIs/#/Node/getPeerCount router.api(MethodGet, "/eth/v1/node/peer_count") do () -> RestApiResponse: diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index b7d5789a3..e3e3d64f1 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -642,6 +642,16 @@ proc readValue*(reader: var JsonReader[RestJson], value: var uint8) {. else: reader.raiseUnexpectedValue($res.error() & ": " & svalue) +## RestNumeric +proc writeValue*(w: var JsonWriter[RestJson], + value: RestNumeric) {.raises: [IOError].} = + writeValue(w, int(value)) + +proc readValue*(reader: var JsonReader[RestJson], + value: var RestNumeric) {. + raises: [IOError, SerializationError].} = + value = RestNumeric(reader.readValue(int)) + ## JustificationBits proc writeValue*( w: var JsonWriter[RestJson], value: JustificationBits diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index 1015cf55a..c36d25a61 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -116,6 +116,8 @@ type PeerDirectKind* {.pure.} = enum Inbound, Outbound + RestNumeric* = distinct int + RestAttesterDuty* = object pubkey*: ValidatorPubKey validator_index*: ValidatorIndex diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 18bcfdcd1..59c249fee 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -2899,7 +2899,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2911,7 +2911,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2923,7 +2923,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2935,7 +2935,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2947,7 +2947,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2959,7 +2959,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2971,7 +2971,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2983,7 +2983,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { @@ -2995,7 +2995,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": ""}}}] + "body": [{"operator": "jstructcmpns", "value": {"data": [{"peer_id": "", "enr": "", "last_seen_p2p_address": "", "state": "", "direction": ""}], "meta": {"count": 0}}}] } }, { From ed446b1d5a81a191f20b39cab70cba4e63a1119f Mon Sep 17 00:00:00 2001 From: tersec Date: Wed, 1 Nov 2023 08:33:00 +0100 Subject: [PATCH 12/45] replace ValidIpAddress with IpAddress in configurations (#5536) --- beacon_chain/conf.nim | 24 ++++++++++++------------ beacon_chain/conf_light_client.nim | 2 +- beacon_chain/networking/eth2_network.nim | 6 ++++-- beacon_chain/nimbus_beacon_node.nim | 2 +- ncli/ncli_testnet.nim | 8 ++++---- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 10ba6d1cc..0692c2e09 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -36,7 +36,7 @@ from consensus_object_pools/block_pools_types_light_client export uri, nat, enr, - defaultEth2TcpPort, enabledLogLevel, ValidIpAddress, + defaultEth2TcpPort, enabledLogLevel, defs, parseCmdArg, completeCmdArg, network_metadata, el_conf, network, BlockHashOrNumber, confTomlDefs, confTomlNet, confTomlUri, @@ -47,8 +47,8 @@ declareGauge network_name, "network name", ["name"] const # TODO: How should we select between IPv4 and IPv6 # Maybe there should be a config option for this. - defaultListenAddress* = (static ValidIpAddress.init("0.0.0.0")) - defaultAdminListenAddress* = (static ValidIpAddress.init("127.0.0.1")) + defaultListenAddress* = (static parseIpAddress("0.0.0.0")) + defaultAdminListenAddress* = (static parseIpAddress("127.0.0.1")) defaultSigningNodeRequestTimeout* = 60 defaultBeaconNode* = "http://127.0.0.1:" & $defaultEth2RestPort defaultBeaconNodeUri* = parseUri(defaultBeaconNode) @@ -292,7 +292,7 @@ type desc: "Listening address for the Ethereum LibP2P and Discovery v5 traffic" defaultValue: defaultListenAddress defaultValueDesc: $defaultListenAddressDesc - name: "listen-address" .}: ValidIpAddress + name: "listen-address" .}: IpAddress tcpPort* {. desc: "Listening TCP port for Ethereum LibP2P traffic" @@ -408,7 +408,7 @@ type desc: "Listening address of the metrics server" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "metrics-address" .}: ValidIpAddress + name: "metrics-address" .}: IpAddress metricsPort* {. desc: "Listening HTTP port of the metrics server" @@ -449,7 +449,7 @@ type # Deprecated > 1.7.0 hidden desc: "Deprecated for removal" - name: "rpc-address" .}: Option[ValidIpAddress] + name: "rpc-address" .}: Option[IpAddress] restEnabled* {. desc: "Enable the REST server" @@ -466,7 +466,7 @@ type desc: "Listening address of the REST server" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "rest-address" .}: ValidIpAddress + name: "rest-address" .}: IpAddress restAllowedOrigin* {. desc: "Limit the access to the REST API to a particular hostname " & @@ -520,7 +520,7 @@ type desc: "Listening port for the REST keymanager API" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "keymanager-address" .}: ValidIpAddress + name: "keymanager-address" .}: IpAddress keymanagerAllowedOrigin* {. desc: "Limit the access to the Keymanager API to a particular hostname " & @@ -776,7 +776,7 @@ type of RecordCmd.create: ipExt* {. desc: "External IP address" - name: "ip" .}: ValidIpAddress + name: "ip" .}: IpAddress tcpPortExt* {. desc: "External TCP port" @@ -973,7 +973,7 @@ type desc: "Listening port for the REST keymanager API" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "keymanager-address" .}: ValidIpAddress + name: "keymanager-address" .}: IpAddress keymanagerAllowedOrigin* {. desc: "Limit the access to the Keymanager API to a particular hostname " & @@ -993,7 +993,7 @@ type desc: "Listening address of the metrics server (BETA)" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "metrics-address" .}: ValidIpAddress + name: "metrics-address" .}: IpAddress metricsPort* {. desc: "Listening HTTP port of the metrics server (BETA)" @@ -1091,7 +1091,7 @@ type desc: "Listening address of the REST HTTP server" defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "bind-address" .}: ValidIpAddress + name: "bind-address" .}: IpAddress tlsEnabled* {. desc: "Use secure TLS communication for REST server" diff --git a/beacon_chain/conf_light_client.nim b/beacon_chain/conf_light_client.nim index 0b64b520d..627961750 100644 --- a/beacon_chain/conf_light_client.nim +++ b/beacon_chain/conf_light_client.nim @@ -65,7 +65,7 @@ type LightClientConf* = object desc: "Listening address for the Ethereum LibP2P and Discovery v5 traffic" defaultValue: defaultListenAddress defaultValueDesc: $defaultListenAddressDesc - name: "listen-address" .}: ValidIpAddress + name: "listen-address" .}: IpAddress tcpPort* {. desc: "Listening TCP port for Ethereum LibP2P traffic" diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index 1fa57e3ff..d572ba005 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -2304,7 +2304,8 @@ proc createEth2Node*(rng: ref HmacDrbgContext, cfg, getBeaconTime().slotOrZero.epoch, genesis_validators_root) (extIp, extTcpPort, extUdpPort) = try: setupAddress( - config.nat, config.listenAddress, config.tcpPort, config.udpPort, clientId) + config.nat, ValidIpAddress.init config.listenAddress, config.tcpPort, + config.udpPort, clientId) except CatchableError as exc: raise exc except Exception as exc: raiseAssert exc.msg @@ -2326,7 +2327,8 @@ proc createEth2Node*(rng: ref HmacDrbgContext, info "Adding privileged direct peer", peerId, address res - hostAddress = tcpEndPoint(config.listenAddress, config.tcpPort) + hostAddress = tcpEndPoint( + ValidIpAddress.init config.listenAddress, config.tcpPort) announcedAddresses = if extIp.isNone() or extTcpPort.isNone(): @[] else: @[tcpEndPoint(extIp.get(), extTcpPort.get())] diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 7a45fd7b2..cb49eb300 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -2108,7 +2108,7 @@ proc doRecord(config: BeaconNodeConf, rng: var HmacDrbgContext) {. let record = enr.Record.init( config.seqNumber, netKeys.seckey.asEthKey, - some(config.ipExt), + some(ValidIpAddress.init config.ipExt), some(config.tcpPortExt), some(config.udpPortExt), fieldPairs).expect("Record within size limits") diff --git a/ncli/ncli_testnet.nim b/ncli/ncli_testnet.nim index 0f0c6f8be..c247aefb1 100644 --- a/ncli/ncli_testnet.nim +++ b/ncli/ncli_testnet.nim @@ -117,9 +117,9 @@ type bootstrapAddress* {. desc: "The public IP address that will be advertised as a bootstrap node for the testnet" - defaultValue: init(ValidIpAddress, defaultAdminListenAddress) + defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "bootstrap-address" .}: ValidIpAddress + name: "bootstrap-address" .}: IpAddress bootstrapPort* {. desc: "The TCP/UDP port that will be used by the bootstrap node" @@ -194,9 +194,9 @@ type enrAddress* {. desc: "The public IP address of that ENR" - defaultValue: init(ValidIpAddress, defaultAdminListenAddress) + defaultValue: defaultAdminListenAddress defaultValueDesc: $defaultAdminListenAddressDesc - name: "enr-address" .}: ValidIpAddress + name: "enr-address" .}: IpAddress enrPort* {. desc: "The TCP/UDP port of that ENR" From 657de2721ab5203bef7cfdc69bcf56808f08fef4 Mon Sep 17 00:00:00 2001 From: tersec Date: Wed, 1 Nov 2023 14:00:21 +0100 Subject: [PATCH 13/45] fill blindedblockbody KZG commitments from deneb blinded header (#5550) --- beacon_chain/spec/datatypes/deneb.nim | 2 +- beacon_chain/validators/beacon_validators.nim | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index b6d85b636..5b0c73542 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -107,7 +107,7 @@ type executionPayload*: ExecutionPayload blockValue*: Wei kzgs*: KzgCommitments - proofs*:seq[KZGProof] + proofs*: seq[KZGProof] blobs*: Blobs # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#executionpayloadheader diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 3eeba31ea..30afdaa92 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -619,6 +619,7 @@ from ./message_router_mev import func constructSignableBlindedBlock[T: capella_mev.SignedBlindedBeaconBlock]( blck: capella.BeaconBlock, executionPayloadHeader: capella.ExecutionPayloadHeader): T = + # Leaves signature field default, to be filled in by caller const blckFields = getFieldNames(typeof(blck)) blckBodyFields = getFieldNames(typeof(blck.body)) @@ -659,12 +660,16 @@ proc constructSignableBlindedBlock[T: deneb_mev.SignedBlindedBeaconBlockContents doAssert bbb.proofs.len == bbb.blob_roots.len doAssert bbb.proofs.len == bbb.commitments.len + assign(blindedBlock.message.body.blob_kzg_commitments, bbb.commitments) + + let blockRoot = hash_tree_root(blindedBlock.message) + if blindedBlockContents.signed_blinded_blob_sidecars.setLen(bbb.proofs.len): for i in 0 ..< blindedBlockContents.signed_blinded_blob_sidecars.lenu64: assign( blindedBlockContents.signed_blinded_blob_sidecars[i], deneb_mev.SignedBlindedBlobSidecar(message: deneb_mev.BlindedBlobSidecar( - block_root: hash_tree_root(blck), + block_root: blockRoot, index: i, slot: distinctBase(blck.slot), block_parent_root: blck.parent_root, From ab89e962655e9fb1aac5cc6d6ac41e032f40db9b Mon Sep 17 00:00:00 2001 From: tersec Date: Thu, 2 Nov 2023 04:56:04 +0100 Subject: [PATCH 14/45] fill in transactions root and KZG commitments from deneb.BlindedBeaconBlock in state transition (#5553) --- beacon_chain/spec/state_transition.nim | 16 +++++++++++----- beacon_chain/validators/beacon_validators.nim | 18 +++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/beacon_chain/spec/state_transition.nim b/beacon_chain/spec/state_transition.nim index d74400115..6b8cb9ded 100644 --- a/beacon_chain/spec/state_transition.nim +++ b/beacon_chain/spec/state_transition.nim @@ -403,7 +403,8 @@ proc makeBeaconBlock*( # removed if we don't use invalid signatures there verificationFlags: UpdateFlags, transactions_root: Opt[Eth2Digest], - execution_payload_root: Opt[Eth2Digest]): + execution_payload_root: Opt[Eth2Digest], + kzg_commitments: Opt[KzgCommitments]): Result[ForkedBeaconBlock, cstring] = ## Create a block for the given state. The latest block applied to it will ## be used for the parent_root value, and the slot will be take from @@ -428,7 +429,7 @@ proc makeBeaconBlock*( rollback(state) return err(res.error()) - # Override for MEV + # Override for Builder API if transactions_root.isSome and execution_payload_root.isSome: withState(state): when consensusFork < ConsensusFork.Capella: @@ -455,6 +456,9 @@ proc makeBeaconBlock*( execution_payload_root.get, hash_tree_root(validator_changes.bls_to_execution_changes)]) elif consensusFork == ConsensusFork.Deneb: + forkyState.data.latest_execution_payload_header.transactions_root = + transactions_root.get + when executionPayload is deneb.ExecutionPayloadForSigning: # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#beaconblockbody forkyState.data.latest_block_header.body_root = hash_tree_root( @@ -469,7 +473,7 @@ proc makeBeaconBlock*( hash_tree_root(sync_aggregate), execution_payload_root.get, hash_tree_root(validator_changes.bls_to_execution_changes), - hash_tree_root(executionPayload.kzgs) + hash_tree_root(kzg_commitments.get) ]) else: raiseAssert "Attempt to use non-Deneb payload with post-Deneb state" @@ -517,7 +521,8 @@ proc makeBeaconBlock*( attestations, deposits, validator_changes, sync_aggregate, executionPayload, rollback, cache, verificationFlags = {}, transactions_root = Opt.none Eth2Digest, - execution_payload_root = Opt.none Eth2Digest) + execution_payload_root = Opt.none Eth2Digest, + kzg_commitments = Opt.none KzgCommitments) proc makeBeaconBlock*( cfg: RuntimeConfig, state: var ForkedHashedBeaconState, @@ -536,4 +541,5 @@ proc makeBeaconBlock*( executionPayload, rollback, cache, verificationFlags = verificationFlags, transactions_root = Opt.none Eth2Digest, - execution_payload_root = Opt.none Eth2Digest) + execution_payload_root = Opt.none Eth2Digest, + kzg_commitments = Opt.none KzgCommitments) diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 30afdaa92..7face4f0d 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -440,7 +440,8 @@ proc makeBeaconBlockForHeadAndSlot*( execution_payload: Opt[PayloadType], transactions_root: Opt[Eth2Digest], execution_payload_root: Opt[Eth2Digest], - withdrawals_root: Opt[Eth2Digest]): + withdrawals_root: Opt[Eth2Digest], + kzg_commitments: Opt[KzgCommitments]): Future[ForkedBlockResult] {.async.} = # Advance state to the slot that we're proposing for var cache = StateCache() @@ -528,7 +529,8 @@ proc makeBeaconBlockForHeadAndSlot*( cache, verificationFlags = {}, transactions_root = transactions_root, - execution_payload_root = execution_payload_root).mapErr do (error: cstring) -> string: + execution_payload_root = execution_payload_root, + kzg_commitments = kzg_commitments).mapErr do (error: cstring) -> string: # This is almost certainly a bug, but it's complex enough that there's a # small risk it might happen even when most proposals succeed - thus we # log instead of asserting @@ -560,7 +562,8 @@ proc makeBeaconBlockForHeadAndSlot*( execution_payload = Opt.none(PayloadType), transactions_root = Opt.none(Eth2Digest), execution_payload_root = Opt.none(Eth2Digest), - withdrawals_root = Opt.none(Eth2Digest)) + withdrawals_root = Opt.none(Eth2Digest), + kzg_commitments = Opt.none(KzgCommitments)) proc getBlindedExecutionPayload[ EPH: capella.ExecutionPayloadHeader | @@ -846,6 +849,7 @@ proc getBlindedBlockParts[ template actualEPH: untyped = executionPayloadHeader.get.blindedBlckPart let withdrawals_root = Opt.some executionPayloadHeader.get.blindedBlckPart.withdrawals_root + const kzg_commitments = Opt.none KzgCommitments var shimExecutionPayload: PayloadType copyFields( @@ -855,7 +859,10 @@ proc getBlindedBlockParts[ type PayloadType = deneb.ExecutionPayloadForSigning template actualEPH: untyped = executionPayloadHeader.get.blindedBlckPart.execution_payload_header - let withdrawals_root = Opt.some actualEPH.withdrawals_root + let + withdrawals_root = Opt.some actualEPH.withdrawals_root + kzg_commitments = Opt.some( + executionPayloadHeader.get.blindedBlckPart.blinded_blobs_bundle.commitments) var shimExecutionPayload: PayloadType type DenebEPH = @@ -870,7 +877,8 @@ proc getBlindedBlockParts[ execution_payload = Opt.some shimExecutionPayload, transactions_root = Opt.some actualEPH.transactions_root, execution_payload_root = Opt.some hash_tree_root(actualEPH), - withdrawals_root = withdrawals_root) + withdrawals_root = withdrawals_root, + kzg_commitments = kzg_commitments) if newBlock.isErr(): # Haven't committed to the MEV block, so allow EL fallback. From baf81595a7fac13621923bd5bbe94c0704ee9421 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 3 Nov 2023 14:54:21 +0100 Subject: [PATCH 15/45] add `KZG_COMMITMENT_INCLUSION_PROOF_DEPTH` preset constant (#5555) `v1.4.0-beta.4` added `KZG_COMMITMENT_INCLUSION_PROOF_DEPTH` to preset: - Spec PR: https://github.com/ethereum/consensus-specs/pull/3531 - Gnosis PR: https://github.com/gnosischain/configs/pull/17 --- beacon_chain/rpc/rest_config_api.nim | 10 ++++++++++ beacon_chain/spec/presets/gnosis/altair_preset.nim | 2 +- beacon_chain/spec/presets/gnosis/bellatrix_preset.nim | 2 +- beacon_chain/spec/presets/gnosis/capella_preset.nim | 2 +- beacon_chain/spec/presets/gnosis/deneb_preset.nim | 6 ++++-- beacon_chain/spec/presets/gnosis/phase0_preset.nim | 2 +- beacon_chain/spec/presets/mainnet/deneb_preset.nim | 6 ++++-- beacon_chain/spec/presets/minimal/deneb_preset.nim | 6 ++++-- ncli/resttest-rules.json | 2 +- 9 files changed, 27 insertions(+), 11 deletions(-) diff --git a/beacon_chain/rpc/rest_config_api.nim b/beacon_chain/rpc/rest_config_api.nim index e01ec57b1..2b354909c 100644 --- a/beacon_chain/rpc/rest_config_api.nim +++ b/beacon_chain/rpc/rest_config_api.nim @@ -128,6 +128,16 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: Base10.toString(uint64(MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP)), + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/deneb.yaml + FIELD_ELEMENTS_PER_BLOB: + Base10.toString(deneb_preset.FIELD_ELEMENTS_PER_BLOB), + MAX_BLOB_COMMITMENTS_PER_BLOCK: + Base10.toString(MAX_BLOB_COMMITMENTS_PER_BLOCK), + MAX_BLOBS_PER_BLOCK: + Base10.toString(MAX_BLOBS_PER_BLOCK), + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: + Base10.toString(uint64(KZG_COMMITMENT_INCLUSION_PROOF_DEPTH)), + # https://github.com/ethereum/consensus-specs/blob/v1.3.0/configs/mainnet.yaml PRESET_BASE: cfg.PRESET_BASE, diff --git a/beacon_chain/spec/presets/gnosis/altair_preset.nim b/beacon_chain/spec/presets/gnosis/altair_preset.nim index 2db32470a..8841c8f41 100644 --- a/beacon_chain/spec/presets/gnosis/altair_preset.nim +++ b/beacon_chain/spec/presets/gnosis/altair_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Mainnet preset - Altair -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/altair.yaml +# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/altair.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim b/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim index 5375df014..6b6fe445c 100644 --- a/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim +++ b/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Bellatrix -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/bellatrix.yaml +# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/bellatrix.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/capella_preset.nim b/beacon_chain/spec/presets/gnosis/capella_preset.nim index a61736e0e..6807c16b6 100644 --- a/beacon_chain/spec/presets/gnosis/capella_preset.nim +++ b/beacon_chain/spec/presets/gnosis/capella_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Capella -# https://github.com/gnosischain/configs/blob/main/presets/gnosis/capella.yaml +# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/capella.yaml const # Max operations per block # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/deneb_preset.nim b/beacon_chain/spec/presets/gnosis/deneb_preset.nim index 80aaffa2a..3e34a87f5 100644 --- a/beacon_chain/spec/presets/gnosis/deneb_preset.nim +++ b/beacon_chain/spec/presets/gnosis/deneb_preset.nim @@ -5,8 +5,8 @@ # * 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. -# Mainnet preset - Deneb -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/presets/mainnet/deneb.yaml +# Gnosis preset - Deneb +# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/deneb.yaml const # `uint64(4096)` FIELD_ELEMENTS_PER_BLOB*: uint64 = 4096 @@ -14,3 +14,5 @@ const MAX_BLOB_COMMITMENTS_PER_BLOCK*: uint64 = 4096 # `uint64(2**2)` (= 4) MAX_BLOBS_PER_BLOCK*: uint64 = 4 + # `floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments')) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 12 = 17 + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH* = 17 diff --git a/beacon_chain/spec/presets/gnosis/phase0_preset.nim b/beacon_chain/spec/presets/gnosis/phase0_preset.nim index 97d5f4cf2..cd6f9f784 100644 --- a/beacon_chain/spec/presets/gnosis/phase0_preset.nim +++ b/beacon_chain/spec/presets/gnosis/phase0_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Phase0 -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/presets/mainnet/phase0.yaml +# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/phase0.yaml const # diff --git a/beacon_chain/spec/presets/mainnet/deneb_preset.nim b/beacon_chain/spec/presets/mainnet/deneb_preset.nim index 809b4623d..3caccbe8d 100644 --- a/beacon_chain/spec/presets/mainnet/deneb_preset.nim +++ b/beacon_chain/spec/presets/mainnet/deneb_preset.nim @@ -6,11 +6,13 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Mainnet preset - Deneb -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/deneb.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/deneb.yaml const # `uint64(4096)` FIELD_ELEMENTS_PER_BLOB*: uint64 = 4096 # `uint64(2**12)` (= 4096) MAX_BLOB_COMMITMENTS_PER_BLOCK*: uint64 = 4096 - # `uint64(2**2)` (= 4) + # `uint64(6)` MAX_BLOBS_PER_BLOCK*: uint64 = 6 + # `floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments')) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 12 = 17 + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH* = 17 diff --git a/beacon_chain/spec/presets/minimal/deneb_preset.nim b/beacon_chain/spec/presets/minimal/deneb_preset.nim index d98d0a318..6197ffac0 100644 --- a/beacon_chain/spec/presets/minimal/deneb_preset.nim +++ b/beacon_chain/spec/presets/minimal/deneb_preset.nim @@ -6,11 +6,13 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Minimal preset - Deneb -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/minimal/deneb.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/minimal/deneb.yaml const - # [customized] + # `uint64(4096)` FIELD_ELEMENTS_PER_BLOB*: uint64 = 4096 # [customized] MAX_BLOB_COMMITMENTS_PER_BLOCK*: uint64 = 16 # `uint64(6)` MAX_BLOBS_PER_BLOCK*: uint64 = 6 + # [customized] `floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments')) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 4 = 9 + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH* = 9 diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 59c249fee..032bd9841 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -2826,7 +2826,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","ATTESTATION_SUBNET_COUNT":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":""}}] + "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","FIELD_ELEMENTS_PER_BLOB":"","MAX_BLOB_COMMITMENTS_PER_BLOCK":"","MAX_BLOBS_PER_BLOCK":"","KZG_COMMITMENT_INCLUSION_PROOF_DEPTH":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","ATTESTATION_SUBNET_COUNT":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":""}}] } }, { From c95f9feec435313f866a942543bd2b1fcddf5666 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 3 Nov 2023 15:37:44 +0100 Subject: [PATCH 16/45] remove unused Deneb code (#5556) The `process_blob_kzg_commitments` step was removed in `v1.4.0-alpha.1`, but we haven't deleted the now unused functions. Do that now. --- beacon_chain/spec/datatypes/deneb.nim | 3 -- beacon_chain/spec/state_transition_block.nim | 54 -------------------- 2 files changed, 57 deletions(-) diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index 5b0c73542..250314df4 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -33,9 +33,6 @@ const # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/polynomial-commitments.md#constants BYTES_PER_FIELD_ELEMENT = 32 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#blob - BLOB_TX_TYPE* = 0x03'u8 - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/polynomial-commitments.md#constants BLS_MODULUS* = "52435875175126190479447740508185965837690552500527637822603658699938581184513".u256 diff --git a/beacon_chain/spec/state_transition_block.nim b/beacon_chain/spec/state_transition_block.nim index 21b027e56..1d0270ee5 100644 --- a/beacon_chain/spec/state_transition_block.nim +++ b/beacon_chain/spec/state_transition_block.nim @@ -715,35 +715,6 @@ func process_withdrawals*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#tx_peek_blob_versioned_hashes -func tx_peek_blob_versioned_hashes(opaque_tx: Transaction): - Result[seq[VersionedHash], cstring] = - ## This function retrieves the hashes from the `SignedBlobTransaction` as - ## defined in Deneb, using SSZ offsets. Offsets are little-endian `uint32` - ## values, as defined in the SSZ specification. See the full details of - ## `blob_versioned_hashes` offset calculation. - if not (opaque_tx[0] == BLOB_TX_TYPE): - return err("tx_peek_blob_versioned_hashes: invalid opaque transaction type") - let message_offset = 1 + bytes_to_uint32(opaque_tx.asSeq.toOpenArray(1, 4)) - - if opaque_tx.lenu64 < (message_offset + 192).uint64: - return err("tx_peek_blob_versioned_hashes: opaque transaction too short") - - # field offset: 32 + 8 + 32 + 32 + 8 + 4 + 32 + 4 + 4 + 32 = 188 - let blob_versioned_hashes_offset = ( - message_offset + bytes_to_uint32( - opaque_tx[(message_offset + 188) ..< (message_offset + 192)])) - - if blob_versioned_hashes_offset.uint64 > high(int).uint64: - return err("tx_peek_blob_versioned_hashes: blob_versioned_hashes_offset too high") - - var res: seq[VersionedHash] - for x in countup(blob_versioned_hashes_offset.int, len(opaque_tx) - 1, 32): - var versionedHash: VersionedHash - versionedHash[0 .. 31] = opaque_tx.asSeq.toOpenArray(x, x + 31) - res.add versionedHash - ok res - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash func kzg_commitment_to_versioned_hash*( kzg_commitment: KzgCommitment): VersionedHash = @@ -755,31 +726,6 @@ func kzg_commitment_to_versioned_hash*( res[1 .. 31] = eth2digest(kzg_commitment).data.toOpenArray(1, 31) res -# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#verify_kzg_commitments_against_transactions -func verify_kzg_commitments_against_transactions*( - transactions: seq[Transaction], - kzg_commitments: seq[KzgCommitment]): bool = - var all_versioned_hashes: seq[VersionedHash] - for tx in transactions: - if tx[0] == BLOB_TX_TYPE: - let maybe_versioned_hashed = tx_peek_blob_versioned_hashes(tx) - if maybe_versioned_hashed.isErr: - return false - all_versioned_hashes.add maybe_versioned_hashed.get - # TODO valueOr version fails to compile - #all_versioned_hashes.add tx_peek_blob_versioned_hashes(tx).valueOr: - # return false - - all_versioned_hashes == mapIt( - kzg_commitments, it.kzg_commitment_to_versioned_hash) - -func process_blob_kzg_commitments( - body: deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody | - deneb.SigVerifiedBeaconBlockBody): bool = - verify_kzg_commitments_against_transactions( - body.execution_payload.transactions.asSeq, - body.blob_kzg_commitments.asSeq) - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/fork-choice.md#validate_blobs proc validate_blobs*(expected_kzg_commitments: seq[KzgCommitment], blobs: seq[KzgBlob], From 29fe9589089e2ee833b7023c323626f7a5116597 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 3 Nov 2023 16:07:49 +0100 Subject: [PATCH 17/45] allow to pass trusted node sync options during BN startup (#5545) Using trusted node sync currently requires to run two commands - first the `trustedNodeSync` command to initialize the database, followed by the regular startup command to continue syncing. The `trustedNodeSync` options are now also available during regular startup, and are used when the database is empty to simplify setting up a new Nimbus beacon node. This also aligns behaviour closer with other Ethereum consensus implementations. The new logic only applies if the database has not yet been initialized; same as before. Also, the database needs to be removed under the same conditions as before when a fresh sync is desired. --- beacon_chain/conf.nim | 17 +++++++-- beacon_chain/nimbus_beacon_node.nim | 20 ++++++++++ docs/the_nimbus_book/src/options.md | 8 +++- docs/the_nimbus_book/src/start-syncing.md | 46 +++++++++++++++++++++++ 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 0692c2e09..274c443d1 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -339,16 +339,27 @@ type desc: "Weak subjectivity checkpoint in the format block_root:epoch_number" name: "weak-subjectivity-checkpoint" .}: Option[Checkpoint] + externalBeaconApiUrl* {. + desc: "External beacon API to use for syncing (on empty database)" + name: "external-beacon-api-url" .}: Option[string] + syncLightClient* {. - desc: "Accelerate execution layer sync using light client" + desc: "Accelerate sync using light client" defaultValue: true name: "sync-light-client" .}: bool trustedBlockRoot* {. - hidden - desc: "Recent trusted finalized block root to initialize light client from" + desc: "Recent trusted finalized block root to sync from external " & + "beacon API (with `--external-beacon-api-url`). " & + "Uses the light client sync protocol to obtain the latest " & + "finalized checkpoint (LC is initialized from trusted block root)" name: "trusted-block-root" .}: Option[Eth2Digest] + trustedStateRoot* {. + desc: "Recent trusted finalized state root to sync from external " & + "beacon API (with `--external-beacon-api-url`)" + name: "trusted-state-root" .}: Option[Eth2Digest] + finalizedCheckpointState* {. desc: "SSZ file specifying a recent finalized state" name: "finalized-checkpoint-state" .}: Option[InputFile] diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index cb49eb300..1721505ec 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -555,6 +555,26 @@ proc init*(T: type BeaconNode, ) db = BeaconChainDB.new(config.databaseDir, cfg, inMemory = false) + if config.externalBeaconApiUrl.isSome and ChainDAGRef.isInitialized(db).isErr: + if config.trustedStateRoot.isNone and config.trustedBlockRoot.isNone: + warn "Ignoring `--external-beacon-api-url`, neither " & + "`--trusted-block-root` nor `--trusted-state-root` are provided", + externalBeaconApiUrl = config.externalBeaconApiUrl.get, + trustedBlockRoot = config.trustedBlockRoot, + trustedStateRoot = config.trustedStateRoot + else: + await db.doRunTrustedNodeSync( + metadata, + config.databaseDir, + config.eraDir, + config.externalBeaconApiUrl.get, + config.trustedStateRoot.map do (x: Eth2Digest) -> string: + "0x" & x.data.toHex, + config.trustedBlockRoot, + backfill = false, + reindex = false, + downloadDepositSnapshot = false) + if config.finalizedCheckpointBlock.isSome: warn "--finalized-checkpoint-block has been deprecated, ignoring" diff --git a/docs/the_nimbus_book/src/options.md b/docs/the_nimbus_book/src/options.md index 03c070926..914ea86bb 100644 --- a/docs/the_nimbus_book/src/options.md +++ b/docs/the_nimbus_book/src/options.md @@ -66,7 +66,13 @@ The following options are available: seen by other nodes it communicates with. This option allows to enable/disable this functionality [=false]. --weak-subjectivity-checkpoint Weak subjectivity checkpoint in the format block_root:epoch_number. - --sync-light-client Accelerate execution layer sync using light client [=true]. + --external-beacon-api-url External beacon API to use for syncing (on empty database). + --sync-light-client Accelerate sync using light client [=true]. + --trusted-block-root Recent trusted finalized block root to sync from external beacon API (with + `--external-beacon-api-url`). Uses the light client sync protocol to obtain the + latest finalized checkpoint (LC is initialized from trusted block root). + --trusted-state-root Recent trusted finalized state root to sync from external beacon API (with + `--external-beacon-api-url`). --finalized-checkpoint-state SSZ file specifying a recent finalized state. --genesis-state SSZ file specifying the genesis state of the network (for networks without a built-in genesis state). diff --git a/docs/the_nimbus_book/src/start-syncing.md b/docs/the_nimbus_book/src/start-syncing.md index e3be4916a..8ae1f5cc8 100644 --- a/docs/the_nimbus_book/src/start-syncing.md +++ b/docs/the_nimbus_book/src/start-syncing.md @@ -82,3 +82,49 @@ More information is available from the [options](./options.md) page. ## Keep track of your sync progress See [here](./keep-an-eye.md#keep-track-of-your-syncing-progress) for how to keep track of your sync progress. + +## Checkpoint sync + +!!! note "" + This feature is available from `v23.11.0` onwards. + +You can use an existing synced node or a third-party service to accelerate sync significantly. Instead of downloading and verifying the entire blockchain, you can point Nimbus to a trusted block. + +!!! warning + Selecting a block from an untrusted source or using an outdated block or state may lead to Nimbus syncing to an unexpected state. Especially when [running a validator](./run-a-validator.md), it is vital to pick a recent trusted block for checkpoint sync, and to verify that Nimbus is synced to the correct state before starting validator duties. + +!!! note + The Nimbus database must be empty to use checkpoint sync. When using a pre-existing database, checkpoint sync options are ignored. + +!!! tip + A list of community-operated checkpoint sync nodes can be found [here](https://eth-clients.github.io/checkpoint-sync-endpoints/). + +To use checkpoint sync, run the following commands (inserting the checkpoint sync endpoint and your own trusted block root): + +=== "Holesky" + ```sh + CHECKPOINT_SYNC_ENDPOINT=http://127.0.0.1:8551 + TRUSTED_BLOCK_ROOT=0x1234567890123456789012345678901234567890123456789012345678901234 + ./run-holesky-beacon-node.sh \ + --external-beacon-api-url=$CHECKPOINT_SYNC_ENDPOINT \ + --trusted-block-root=$TRUSTED_BLOCK_ROOT + ``` + +=== "Mainnet" + ```sh + TRUSTED_BLOCK_ROOT=0x1234567890123456789012345678901234567890123456789012345678901234 + ./run-mainnet-beacon-node.sh \ + --external-beacon-api-url=$CHECKPOINT_SYNC_ENDPOINT \ + --trusted-block-root=$TRUSTED_BLOCK_ROOT + ``` + +The following [configuration options](./options.md) control checkpoint sync behaviour: + +| Option | Description | +|------------------------------------------|-------------| +| `--external-beacon-api-url` |
  • External beacon API to use for checkpoint sync
| +| `--trusted-block-root` |
  • Recent trusted finalized block root to sync from external beacon API
  • Uses the [light client sync protocol](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md) to obtain the latest finalized checkpoint
| +| `--trusted-state-root` |
  • Recent trusted finalized state root to sync from external beacon API
  • Takes precedence over `--trusted-block-root` if both are specified
| + +!!! info + If the external beacon API does not support serving [light client data](./light-client-data.md), use the `--trusted-state-root` option instead of `--trusted-block-root`. From 8cec3af61c8847675235c69c3e716567bc3951e3 Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Sat, 4 Nov 2023 09:14:14 +0200 Subject: [PATCH 18/45] VC: Obtain randao signature before slot proposal. (#5490) * Randao calculation caching for VC implementation. * Add time monitoring for randao signatures process. * Add delay calculation. * Address review comments. * Address review comments. --- .../validator_client/block_service.nim | 103 +++++++++++++----- beacon_chain/validator_client/common.nim | 3 +- beacon_chain/validators/validator_pool.nim | 15 ++- 3 files changed, 94 insertions(+), 27 deletions(-) diff --git a/beacon_chain/validator_client/block_service.nim b/beacon_chain/validator_client/block_service.nim index ad4cad057..995d3c377 100644 --- a/beacon_chain/validator_client/block_service.nim +++ b/beacon_chain/validator_client/block_service.nim @@ -32,6 +32,9 @@ type blockRoot*: Eth2Digest data*: ForkedBlindedBeaconBlock +proc proposeBlock(vc: ValidatorClientRef, slot: Slot, + proposerKey: ValidatorPubKey) {.async.} + proc produceBlock( vc: ValidatorClientRef, currentSlot, slot: Slot, @@ -86,7 +89,6 @@ proc produceBlock( data: ForkedBeaconBlock.init(blck), blobsOpt: Opt.some(blobs))) - proc produceBlindedBlock( vc: ValidatorClientRef, currentSlot, slot: Slot, @@ -125,6 +127,58 @@ proc lazyWait[T](fut: Future[T]) {.async.} = except CatchableError: discard +proc prepareRandao(vc: ValidatorClientRef, slot: Slot, + proposerKey: ValidatorPubKey) {.async.} = + if slot == GENESIS_SLOT: + return + + let + destSlot = slot - 1'u64 + destOffset = TimeDiff(nanoseconds: NANOSECONDS_PER_SLOT.int64 div 2) + deadline = destSlot.start_beacon_time() + destOffset + epoch = slot.epoch() + # We going to wait to T - (T / 4 * 2), where T is proposer's + # duty slot. + currentSlot = (await vc.checkedWaitForSlot(destSlot, destOffset, + false)).valueOr: + debug "Unable to perform RANDAO signature preparation because of " & + "system time failure" + return + validator = + vc.getValidatorForDuties(proposerKey, slot, true).valueOr: return + + if currentSlot <= destSlot: + # We do not need result, because we want it to be cached. + let + start = Moment.now() + genesisRoot = vc.beaconGenesis.genesis_validators_root + fork = vc.forkAtEpoch(epoch) + rsig = await validator.getEpochSignature(fork, genesisRoot, epoch) + timeElapsed = Moment.now() - start + if rsig.isErr(): + debug "Unable to prepare RANDAO signature", epoch = epoch, + validator = shortLog(validator), elapsed_time = timeElapsed, + current_slot = currentSlot, destination_slot = destSlot, + delay = vc.getDelay(deadline) + else: + debug "RANDAO signature has been prepared", epoch = epoch, + validator = shortLog(validator), elapsed_time = timeElapsed, + current_slot = currentSlot, destination_slot = destSlot, + delay = vc.getDelay(deadline) + else: + debug "RANDAO signature preparation timed out", epoch = epoch, + validator = shortLog(validator), + current_slot = currentSlot, destination_slot = destSlot, + delay = vc.getDelay(deadline) + +proc spawnProposalTask(vc: ValidatorClientRef, + duty: RestProposerDuty): ProposerTask = + ProposerTask( + randaoFut: prepareRandao(vc, duty.slot, duty.pubkey), + proposeFut: proposeBlock(vc, duty.slot, duty.pubkey), + duty: duty + ) + proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, validator: AttachedValidator) {.async.} = let @@ -146,21 +200,22 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, debug "Publishing block", delay = vc.getDelay(slot.block_deadline()), genesis_root = genesisRoot, graffiti = graffiti, fork = fork - let randaoReveal = - try: - let res = await validator.getEpochSignature(fork, genesisRoot, slot.epoch) - if res.isErr(): - warn "Unable to generate randao reveal using remote signer", - reason = res.error() + + let + randaoReveal = + try: + (await validator.getEpochSignature(fork, genesisRoot, + slot.epoch())).valueOr: + warn "Unable to generate RANDAO reveal using remote signer", + reason = error + return + except CancelledError as exc: + debug "RANDAO reveal production has been interrupted" + raise exc + except CatchableError as exc: + error "An unexpected error occurred while receiving RANDAO data", + error_name = exc.name, error_msg = exc.msg return - res.get() - except CancelledError as exc: - debug "Randao reveal production has been interrupted" - raise exc - except CatchableError as exc: - error "An unexpected error occurred while receiving randao data", - error_name = exc.name, error_msg = exc.msg - return var beaconBlocks = block: @@ -408,11 +463,6 @@ proc proposeBlock(vc: ValidatorClientRef, slot: Slot, error "Unexpected error encountered while proposing block", slot = slot, validator = shortLog(validator) -proc spawnProposalTask(vc: ValidatorClientRef, - duty: RestProposerDuty): ProposerTask = - let future = proposeBlock(vc, duty.slot, duty.pubkey) - ProposerTask(future: future, duty: duty) - proc contains(data: openArray[RestProposerDuty], task: ProposerTask): bool = for item in data: if (item.pubkey == task.duty.pubkey) and (item.slot == task.duty.slot): @@ -462,13 +512,14 @@ proc addOrReplaceProposers*(vc: ValidatorClientRef, epoch: Epoch, for task in epochDuties.duties: if task notin duties: # Task is no more relevant, so cancel it. - debug "Cancelling running proposal duty task", + debug "Cancelling running proposal duty tasks", slot = task.duty.slot, validator = shortLog(task.duty.pubkey) - task.future.cancelSoon() + task.proposeFut.cancelSoon() + task.randaoFut.cancelSoon() else: # If task is already running for proper slot, we keep it alive. - debug "Keep running previous proposal duty task", + debug "Keep running previous proposal duty tasks", slot = task.duty.slot, validator = shortLog(task.duty.pubkey) res.add(task) @@ -783,8 +834,10 @@ proc mainLoop(service: BlockServiceRef) {.async.} = var res: seq[FutureBase] for epoch, data in vc.proposers.pairs(): for duty in data.duties.items(): - if not(duty.future.finished()): - res.add(duty.future.cancelAndWait()) + if not(duty.proposeFut.finished()): + res.add(duty.proposeFut.cancelAndWait()) + if not(duty.randaoFut.finished()): + res.add(duty.randaoFut.cancelAndWait()) await noCancel allFutures(res) proc init*(t: typedesc[BlockServiceRef], diff --git a/beacon_chain/validator_client/common.nim b/beacon_chain/validator_client/common.nim index 7202bc9aa..eb4a50557 100644 --- a/beacon_chain/validator_client/common.nim +++ b/beacon_chain/validator_client/common.nim @@ -95,7 +95,8 @@ type ProposerTask* = object duty*: RestProposerDuty - future*: Future[void] + proposeFut*: Future[void] + randaoFut*: Future[void] ProposedData* = object epoch*: Epoch diff --git a/beacon_chain/validators/validator_pool.nim b/beacon_chain/validators/validator_pool.nim index 345712e47..6ad6e4416 100644 --- a/beacon_chain/validators/validator_pool.nim +++ b/beacon_chain/validators/validator_pool.nim @@ -66,6 +66,10 @@ type # if the validator will be aggregating (in the near future) slotSignature*: Opt[tuple[slot: Slot, signature: ValidatorSig]] + # Cache the latest epoch signature - the epoch signature is used for block + # proposing. + epochSignature*: Opt[tuple[epoch: Epoch, signature: ValidatorSig]] + # For the external payload builder; each epoch, the external payload # builder should be informed of current validators externalBuilderRegistration*: Opt[SignedValidatorRegistrationV1] @@ -746,7 +750,10 @@ proc getContributionAndProofSignature*(v: AttachedValidator, fork: Fork, proc getEpochSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, epoch: Epoch ): Future[SignatureResult] {.async.} = - return + if v.epochSignature.isSome and v.epochSignature.get.epoch == epoch: + return SignatureResult.ok(v.epochSignature.get.signature) + + let signature = case v.kind of ValidatorKind.Local: SignatureResult.ok(get_epoch_signature( @@ -757,6 +764,12 @@ proc getEpochSignature*(v: AttachedValidator, fork: Fork, fork, genesis_validators_root, epoch) await v.signData(request) + if signature.isErr: + return signature + + v.epochSignature = Opt.some((epoch, signature.get)) + signature + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/validator.md#aggregation-selection proc getSlotSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot From 3e9b3a50d0c6e53f7419803b3dc4d9db5a39bcc8 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Sat, 4 Nov 2023 09:01:31 +0100 Subject: [PATCH 19/45] libp2p: revert scoring (#5549) * Use libp2p b2eac7e-and-revert-c6aa085 * Fix libp2p branch reference --------- Co-authored-by: Diego Co-authored-by: Zahary Karadjov --- .gitmodules | 2 +- vendor/nim-libp2p | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 71d512a1c..c0e39c3a2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -24,7 +24,7 @@ path = vendor/nim-libp2p url = https://github.com/status-im/nim-libp2p.git ignore = untracked - branch = unstable + branch = b2eac7e-and-revert-c6aa085 [submodule "vendor/nimbus-build-system"] path = vendor/nimbus-build-system url = https://github.com/status-im/nimbus-build-system.git diff --git a/vendor/nim-libp2p b/vendor/nim-libp2p index b2eac7ecb..0011a5e72 160000 --- a/vendor/nim-libp2p +++ b/vendor/nim-libp2p @@ -1 +1 @@ -Subproject commit b2eac7ecbdb695b0b7033f2069b03a63d28aee2b +Subproject commit 0011a5e720e2e61beb75b3384cd788c72548284a From fb18f09e5527d912b222461d1c15b639ae249ca7 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sat, 4 Nov 2023 10:25:06 +0100 Subject: [PATCH 20/45] align `Blobs` limit for SSZ transport (#5558) Capacity should be set to theoretical limit to ensure correct hash root. Actual length may be shorter. Only use is `ExecutionPayloadForSigning` so it doesn't matter yet in practice, but still worth fixing. --- beacon_chain/spec/datatypes/deneb.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index 250314df4..f58a8acce 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -38,7 +38,7 @@ const type KzgCommitments* = List[KzgCommitment, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK] - Blobs* = List[Blob, Limit MAX_BLOBS_PER_BLOCK] + Blobs* = List[Blob, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK] # TODO this apparently is suppposed to be SSZ-equivalent to Bytes32, but # current spec doesn't ever SSZ-serialize it or hash_tree_root it From a05278e26374fa640dfb907281489442b9c6b373 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sat, 4 Nov 2023 14:49:58 +0100 Subject: [PATCH 21/45] wrap `kzgs`/`proofs`/`blobs` fields as `BlobsBundle` (#5562) Less type conversion / copying by keeping the `BlobsBundle` together. --- beacon_chain/el/el_manager.nim | 11 ++++--- beacon_chain/rpc/rest_validator_api.nim | 33 ++++++------------- beacon_chain/spec/datatypes/deneb.nim | 17 +++++----- beacon_chain/spec/state_transition.nim | 2 +- beacon_chain/sync/request_manager.nim | 5 ++- beacon_chain/validators/beacon_validators.nim | 22 ++++--------- 6 files changed, 34 insertions(+), 56 deletions(-) diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index e9334594f..271afc47b 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -551,10 +551,13 @@ func asConsensusType*(payload: engine_api.GetPayloadV3Response): # The `mapIt` calls below are necessary only because we use different distinct # types for KZG commitments and Blobs in the `web3` and the `deneb` spec types. # Both are defined as `array[N, byte]` under the hood. - kzgs: KzgCommitments payload.blobsBundle.commitments.mapIt(it.bytes), - proofs: payload.blobsBundle.proofs.mapIt(it.bytes), - blobs: Blobs payload.blobsBundle.blobs.mapIt(it.bytes) - ) + blobsBundle: BlobsBundle( + commitments: KzgCommitments.init( + payload.blobsBundle.commitments.mapIt(it.bytes)), + proofs: KzgProofs.init( + payload.blobsBundle.proofs.mapIt(it.bytes)), + blobs: Blobs.init( + payload.blobsBundle.blobs.mapIt(it.bytes)))) func asEngineExecutionPayload*(executionPayload: bellatrix.ExecutionPayload): ExecutionPayloadV1 = diff --git a/beacon_chain/rpc/rest_validator_api.nim b/beacon_chain/rpc/rest_validator_api.nim index 4312ff041..c016f899f 100644 --- a/beacon_chain/rpc/rest_validator_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -392,21 +392,13 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = qslot, proposer, qrandao, qskip_randao_verification): return RestApiResponse.jsonError(Http400, InvalidRandaoRevealValue) - let res = - case node.dag.cfg.consensusForkAtEpoch(qslot.epoch) - of ConsensusFork.Deneb: + let res = withConsensusFork( + node.dag.cfg.consensusForkAtEpoch(qslot.epoch)): + when consensusFork >= ConsensusFork.Bellatrix: await makeBeaconBlockForHeadAndSlot( - deneb.ExecutionPayloadForSigning, + consensusFork.ExecutionPayloadForSigning, node, qrandao, proposer, qgraffiti, qhead, qslot) - of ConsensusFork.Capella: - await makeBeaconBlockForHeadAndSlot( - capella.ExecutionPayloadForSigning, - node, qrandao, proposer, qgraffiti, qhead, qslot) - of ConsensusFork.Bellatrix: - await makeBeaconBlockForHeadAndSlot( - bellatrix.ExecutionPayloadForSigning, - node, qrandao, proposer, qgraffiti, qhead, qslot) - of ConsensusFork.Altair, ConsensusFork.Phase0: + else: return RestApiResponse.jsonError(Http400, InvalidSlotValueError) if res.isErr(): return RestApiResponse.jsonError(Http400, res.error()) @@ -414,7 +406,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = return withBlck(message.blck): let data = - when forkyBlck is deneb.BeaconBlock: + when consensusFork >= ConsensusFork.Deneb: let bundle = message.blobsBundleOpt.get() let blockRoot = hash_tree_root(forkyBlck) var sidecars = newSeqOfCap[BlobSidecar](bundle.blobs.len) @@ -426,7 +418,7 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = block_parent_root: forkyBlck.parent_root, proposer_index: forkyBlck.proposer_index, blob: bundle.blobs[i], - kzg_commitment: bundle.kzgs[i], + kzg_commitment: bundle.commitments[i], kzg_proof: bundle.proofs[i] ) sidecars.add(sidecar) @@ -435,18 +427,13 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = `block`: forkyBlck, blob_sidecars: List[BlobSidecar, Limit MAX_BLOBS_PER_BLOCK].init(sidecars)) - elif forkyBlck is phase0.BeaconBlock or - forkyBlck is altair.BeaconBlock or - forkyBlck is bellatrix.BeaconBlock or - forkyBlck is capella.BeaconBlock: - forkyBlck else: - static: raiseAssert "produceBlockV2 received unexpected version" + forkyBlck if contentType == sszMediaType: - let headers = [("eth-consensus-version", message.blck.kind.toString())] + let headers = [("eth-consensus-version", consensusFork.toString())] RestApiResponse.sszResponse(data, headers) elif contentType == jsonMediaType: - RestApiResponse.jsonResponseWVersion(data, message.blck.kind) + RestApiResponse.jsonResponseWVersion(data, consensusFork) else: raiseAssert "preferredContentType() returns invalid content type" diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index f58a8acce..e5e2cafc3 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -38,6 +38,7 @@ const type KzgCommitments* = List[KzgCommitment, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK] + KzgProofs* = List[KzgProof, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK] Blobs* = List[Blob, Limit MAX_BLOB_COMMITMENTS_PER_BLOCK] # TODO this apparently is suppposed to be SSZ-equivalent to Bytes32, but @@ -50,6 +51,12 @@ type # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/polynomial-commitments.md#custom-types Blob* = array[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB, byte] + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/validator.md#blobsbundle + BlobsBundle* = object + commitments*: KzgCommitments + proofs*: KzgProofs + blobs*: Blobs + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/p2p-interface.md#blobsidecar BlobSidecar* = object block_root*: Eth2Digest @@ -103,9 +110,7 @@ type ExecutionPayloadForSigning* = object executionPayload*: ExecutionPayload blockValue*: Wei - kzgs*: KzgCommitments - proofs*: seq[KZGProof] - blobs*: Blobs + blobsBundle*: BlobsBundle # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object @@ -131,12 +136,6 @@ type blob_gas_used*: uint64 # [New in Deneb:EIP4844] excess_blob_gas*: uint64 # [New in Deneb:EIP4844] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/validator.md#blobsbundle - BlobsBundle* = object - commitments*: seq[KZGCommitment] - proofs*: seq[KZGProof] - blobs*: seq[Blob] - ExecutePayload* = proc( execution_payload: ExecutionPayload): bool {.gcsafe, raises: [].} diff --git a/beacon_chain/spec/state_transition.nim b/beacon_chain/spec/state_transition.nim index 6b8cb9ded..3e7716363 100644 --- a/beacon_chain/spec/state_transition.nim +++ b/beacon_chain/spec/state_transition.nim @@ -380,7 +380,7 @@ func partialBeaconBlock*( # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/validator.md#constructing-the-beaconblockbody when consensusFork >= ConsensusFork.Deneb: - res.body.blob_kzg_commitments = execution_payload.kzgs + res.body.blob_kzg_commitments = execution_payload.blobsBundle.commitments res diff --git a/beacon_chain/sync/request_manager.nim b/beacon_chain/sync/request_manager.nim index 8fe3b3ff5..d37a13d50 100644 --- a/beacon_chain/sync/request_manager.nim +++ b/beacon_chain/sync/request_manager.nim @@ -292,7 +292,7 @@ proc getMissingBlobs(rman: RequestManager): seq[BlobIdentifier] = warn "quarantine missing blobs, but missing indices is empty", blk=blobless.root, indices=rman.blobQuarantine[].blobIndices(blobless.root), - kzgs=len(blobless.message.body.blob_kzg_commitments) + commitments=len(blobless.message.body.blob_kzg_commitments) for idx in missing.indices: let id = BlobIdentifier(block_root: blobless.root, index: idx) if id notin fetches: @@ -302,7 +302,7 @@ proc getMissingBlobs(rman: RequestManager): seq[BlobIdentifier] = warn "missing blob handler found blobless block with all blobs", blk=blobless.root, indices=rman.blobQuarantine[].blobIndices(blobless.root), - kzgs=len(blobless.message.body.blob_kzg_commitments) + commitments=len(blobless.message.body.blob_kzg_commitments) discard rman.blockVerifier(ForkedSignedBeaconBlock.init(blobless), false) rman.quarantine[].removeBlobless(blobless) @@ -356,4 +356,3 @@ proc stop*(rman: RequestManager) = rman.blockLoopFuture.cancelSoon() if not(isNil(rman.blobLoopFuture)): rman.blobLoopFuture.cancelSoon() - diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 7face4f0d..ee27a0027 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -88,9 +88,6 @@ declarePublicGauge(attached_validator_balance_total, logScope: topics = "beacval" type - BlobsBundle = tuple[blobs: deneb.Blobs, - kzgs: KzgCommitments, - proofs: seq[kzg_abi.KZGProof]] ForkedBlockResult = Result[tuple[blck: ForkedBeaconBlock, blockValue: Wei, @@ -541,10 +538,7 @@ proc makeBeaconBlockForHeadAndSlot*( var blobsBundleOpt = Opt.none(BlobsBundle) when payload is deneb.ExecutionPayloadForSigning: - let bb: BlobsBundle = (blobs: payload.blobs, - kzgs: payload.kzgs, - proofs: payload.proofs) - blobsBundleOpt = Opt.some(bb) + blobsBundleOpt = Opt.some(payload.blobsBundle) return if blck.isOk: ok((blck.get, payload.blockValue, blobsBundleOpt)) else: @@ -1176,10 +1170,11 @@ proc proposeBlockAux( .registerBlock(validator_index, validator.pubkey, slot, signingRoot) let blobSidecarsOpt = - when forkyBlck is deneb.BeaconBlock: + when consensusFork >= ConsensusFork.Deneb: var sidecars: seq[BlobSidecar] let bundle = collectedBids.engineBlockFut.read.get().blobsBundleOpt.get - let (blobs, kzgs, proofs) = (bundle.blobs, bundle.kzgs, bundle.proofs) + let (blobs, commitments, proofs) = ( + bundle.blobs, bundle.commitments, bundle.proofs) for i in 0.. Date: Sat, 4 Nov 2023 15:20:34 +0100 Subject: [PATCH 22/45] introduce `BlobId` type for tracking blob subnets (#5560) Instead of mixing up `SubnetId` (attestation subnet type) for blobs, introduce dedicated `BlobId` type. --- beacon_chain/gossip_processing/eth2_processor.nim | 4 ++-- beacon_chain/gossip_processing/gossip_validation.nim | 6 +++--- beacon_chain/networking/eth2_network.nim | 2 +- beacon_chain/nimbus_beacon_node.nim | 10 +++++----- beacon_chain/spec/datatypes/base.nim | 8 ++++++++ beacon_chain/spec/network.nim | 12 ++++++------ tests/test_honest_validator.nim | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/beacon_chain/gossip_processing/eth2_processor.nim b/beacon_chain/gossip_processing/eth2_processor.nim index f26f099d5..71f22f66d 100644 --- a/beacon_chain/gossip_processing/eth2_processor.nim +++ b/beacon_chain/gossip_processing/eth2_processor.nim @@ -275,7 +275,7 @@ proc processSignedBeaconBlock*( proc processSignedBlobSidecar*( self: var Eth2Processor, src: MsgSource, - signedBlobSidecar: deneb.SignedBlobSidecar, idx: BlobIndex): ValidationRes = + signedBlobSidecar: deneb.SignedBlobSidecar, subnet_id: BlobId): ValidationRes = let wallTime = self.getCurrentBeaconTime() (afterGenesis, wallSlot) = wallTime.toSlot() @@ -296,7 +296,7 @@ proc processSignedBlobSidecar*( let v = self.dag.validateBlobSidecar(self.quarantine, self.blobQuarantine, - signedBlobSidecar, wallTime, idx) + signedBlobSidecar, wallTime, subnet_id) if v.isErr(): debug "Dropping blob", error = v.error() diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 3d58cf22e..8ec4538f0 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -305,12 +305,12 @@ template validateBeaconBlockBellatrix( # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id proc validateBlobSidecar*( dag: ChainDAGRef, quarantine: ref Quarantine, - blobQuarantine: ref BlobQuarantine,sbs: SignedBlobSidecar, - wallTime: BeaconTime, idx: BlobIndex): Result[void, ValidationError] = + blobQuarantine: ref BlobQuarantine, sbs: SignedBlobSidecar, + wallTime: BeaconTime, subnet_id: BlobId): Result[void, ValidationError] = # [REJECT] The sidecar is for the correct topic -- # i.e. sidecar.index matches the topic {index}. - if sbs.message.index != idx: + if sbs.message.index != subnet_id: return dag.checkedReject("SignedBlobSidecar: mismatched gossip topic index") if dag.getBlockRef(sbs.message.block_root).isSome(): diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index d572ba005..23f6c5ad8 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -2678,7 +2678,7 @@ proc broadcastBeaconBlock*( node.broadcast(topic, blck) proc broadcastBlobSidecar*( - node: Eth2Node, subnet_id: SubnetId, blob: deneb.SignedBlobSidecar): + node: Eth2Node, subnet_id: BlobId, blob: deneb.SignedBlobSidecar): Future[SendResult] = let forkPrefix = node.forkDigestAtEpoch(node.getWallEpoch) diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 1721505ec..39c91cd11 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -1733,18 +1733,18 @@ proc installMessageValidators(node: BeaconNode) = MsgSource.gossip, msg))) when consensusFork >= ConsensusFork.Deneb: - # blob_sidecar_{index} + # blob_sidecar_{subnet_id} # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id - for i in 0 ..< BLOB_SIDECAR_SUBNET_COUNT: + for it in BlobId: closureScope: # Needed for inner `proc`; don't lift it out of loop. - let idx = i + let subnet_id = it node.network.addValidator( - getBlobSidecarTopic(digest, SubnetId(idx)), proc ( + getBlobSidecarTopic(digest, subnet_id), proc ( signedBlobSidecar: SignedBlobSidecar ): ValidationResult = toValidationResult( node.processor[].processSignedBlobSidecar( - MsgSource.gossip, signedBlobSidecar, idx))) + MsgSource.gossip, signedBlobSidecar, subnet_id))) node.installLightClientMessageValidators() diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index 0d2997441..6b311a9b5 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -187,6 +187,13 @@ type ## The `SubnetId` type is constrained to values in the range ## `[0, ATTESTATION_SUBNET_COUNT)` during initialization. + BlobId* = distinct uint8 + ## The blob id maps which gossip subscription to use to publish a + ## blob sidecar - it is distinct from the CommitteeIndex in particular + ## + ## The `BlobId` type is constrained to values in the range + ## `[0, BLOB_SIDECAR_SUBNET_COUNT)` during initialization. + # BitVector[4] in the spec, ie 4 bits which end up encoded as a byte for # SSZ / hashing purposes JustificationBits* = distinct uint8 @@ -603,6 +610,7 @@ template makeLimitedU64*(T: untyped, limit: uint64) = makeLimitedU64(CommitteeIndex, MAX_COMMITTEES_PER_SLOT) makeLimitedU64(SubnetId, ATTESTATION_SUBNET_COUNT) +makeLimitedU64(BlobId, BLOB_SIDECAR_SUBNET_COUNT) const validatorIndexLimit = min(uint64(int32.high), VALIDATOR_REGISTRY_LIMIT) diff --git a/beacon_chain/spec/network.nim b/beacon_chain/spec/network.nim index 7f86eea41..c03b8d0e4 100644 --- a/beacon_chain/spec/network.nim +++ b/beacon_chain/spec/network.nim @@ -100,14 +100,14 @@ func getSyncCommitteeContributionAndProofTopic*(forkDigest: ForkDigest): string ## For subscribing and unsubscribing to/from a subnet. eth2Prefix(forkDigest) & "sync_committee_contribution_and_proof/ssz_snappy" -# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/p2p-interface.md#blob_sidecar_index +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id func getBlobSidecarTopic*(forkDigest: ForkDigest, - subnet_id: SubnetId): string = + subnet_id: BlobId): string = eth2Prefix(forkDigest) & "blob_sidecar_" & $subnet_id & "/ssz_snappy" # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/validator.md#sidecar -func compute_subnet_for_blob_sidecar*(blob_index: BlobIndex): SubnetId = - SubnetId(blob_index mod BLOB_SIDECAR_SUBNET_COUNT) +func compute_subnet_for_blob_sidecar*(blob_index: BlobIndex): BlobId = + BlobId(blob_index mod BLOB_SIDECAR_SUBNET_COUNT) # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_finality_update func getLightClientFinalityUpdateTopic*(forkDigest: ForkDigest): string = @@ -220,5 +220,5 @@ func getSyncSubnets*( res iterator blobSidecarTopics*(forkDigest: ForkDigest): string = - for i in 0.SubnetId ..< static(BLOB_SIDECAR_SUBNET_COUNT.SubnetId): - yield getBlobSidecarTopic(forkDigest, i) + for subnet_id in BlobId: + yield getBlobSidecarTopic(forkDigest, subnet_id) diff --git a/tests/test_honest_validator.nim b/tests/test_honest_validator.nim index 509ffe776..969a67d80 100644 --- a/tests/test_honest_validator.nim +++ b/tests/test_honest_validator.nim @@ -77,7 +77,7 @@ suite "Honest validator": "/eth2/00000000/sync_committee_1/ssz_snappy" getSyncCommitteeTopic(forkDigest, SyncSubcommitteeIndex(3)) == "/eth2/00000000/sync_committee_3/ssz_snappy" - getBlobSidecarTopic(forkDigest, SubnetId(1)) == + getBlobSidecarTopic(forkDigest, BlobId(1)) == "/eth2/00000000/blob_sidecar_1/ssz_snappy" toSeq(blobSidecarTopics(forkDigest)) == ["/eth2/00000000/blob_sidecar_0/ssz_snappy", From 6958f67af3f477b5dc106aa2f267afb047c26205 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sat, 4 Nov 2023 20:35:41 +0100 Subject: [PATCH 23/45] add test runner for v1.4.0-beta.4 Merkle proof tests (#5567) Create a test runner for validating the new `Merkle proof` Deneb tests that are added with `v1.4.0-beta.4` specs. --- .../consensus_spec_tests_preset.nim | 1 + .../test_fixture_merkle_proof.nim | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/consensus_spec/test_fixture_merkle_proof.nim diff --git a/tests/consensus_spec/consensus_spec_tests_preset.nim b/tests/consensus_spec/consensus_spec_tests_preset.nim index 24bd8bf01..cc3e3785d 100644 --- a/tests/consensus_spec/consensus_spec_tests_preset.nim +++ b/tests/consensus_spec/consensus_spec_tests_preset.nim @@ -20,6 +20,7 @@ import ./test_fixture_light_client_single_merkle_proof, ./test_fixture_light_client_sync, ./test_fixture_light_client_update_ranking, + ./test_fixture_merkle_proof, ./test_fixture_sanity_blocks, ./test_fixture_sanity_slots, ./test_fixture_transition diff --git a/tests/consensus_spec/test_fixture_merkle_proof.nim b/tests/consensus_spec/test_fixture_merkle_proof.nim new file mode 100644 index 000000000..828a4e048 --- /dev/null +++ b/tests/consensus_spec/test_fixture_merkle_proof.nim @@ -0,0 +1,74 @@ +# beacon_chain +# Copyright (c) 2023 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/[sequtils, streams], + # Status libraries + stew/bitops2, + # Third-party + yaml, + # Beacon chain internals + ../../beacon_chain/spec/helpers, + # Test utilities + ../testutil, + ./fixtures_utils, ./os_ops + +proc runTest[T](suiteName, path: string, objType: typedesc[T]) = + test "Merkle proof - Single merkle proof - " & path.relativePath(SszTestsDir): + type + TestProof = object + leaf: string + leaf_index: GeneralizedIndex + branch: seq[string] + + let + proof = block: + let s = openFileStream(path/"proof.yaml") + defer: close(s) + var res: TestProof + yaml.load(s, res) + res + + obj = newClone(parseTest(path/"object.ssz_snappy", SSZ, T)) + + var computedProof = newSeq[Eth2Digest](log2trunc(proof.leaf_index)) + build_proof(obj[], proof.leaf_index, computedProof).get + + check: + computedProof == proof.branch.mapIt(Eth2Digest.fromHex(it)) + is_valid_merkle_branch( + Eth2Digest.fromHex(proof.leaf), + computedProof, + log2trunc(proof.leaf_index), + get_subtree_index(proof.leaf_index), + hash_tree_root(obj[])) + +suite "EF - Merkle proof" & preset(): + const presetPath = SszTestsDir/const_preset + for kind, path in walkDir(presetPath, relative = true, checkDir = true): + let testsPath = presetPath/path/"merkle_proof"/"single_merkle_proof" + if kind != pcDir or not dirExists(testsPath): + continue + let fork = forkForPathComponent(path).valueOr: + test "Merkle proof - Single merkle proof - " & path: + skip() + continue + for kind, path in walkDir(testsPath, relative = true, checkDir = true): + let suitePath = testsPath/path + if kind != pcDir or not dirExists(suitePath): + continue + let objName = path + withConsensusFork(fork): + for kind, path in walkDir(suitePath, relative = true, checkDir = true): + case objName + of "BeaconBlockBody": + runTest(suiteName, suitePath/path, consensusFork.BeaconBlockBody) + else: + raiseAssert "Unknown test object: " & suitePath/path From 8d46809a5c8488ef13728beb5853d9d780d00c77 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sat, 4 Nov 2023 20:36:01 +0100 Subject: [PATCH 24/45] skip upcoming FC tests for intentional block reorgs until implemented (#5566) v1.4.0-beta.4 adds tests for intentional block reorgs. To reflect the implementation status, skip those tests for now and mark them as such. --- tests/consensus_spec/test_fixture_fork_choice.nim | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/consensus_spec/test_fixture_fork_choice.nim b/tests/consensus_spec/test_fixture_fork_choice.nim index c83165279..f4edfc4c4 100644 --- a/tests/consensus_spec/test_fixture_fork_choice.nim +++ b/tests/consensus_spec/test_fixture_fork_choice.nim @@ -354,6 +354,12 @@ proc runTest(suiteName: static[string], path: string, fork: ConsensusFork) = "too_late_for_merge", "block_lookup_failed", "all_valid", + + # TODO intentional reorgs + "should_override_forkchoice_update__false", + "should_override_forkchoice_update__true", + "basic_is_parent_root", + "basic_is_head_root", ] test suiteName & " - " & path.relativePath(SszTestsDir): From f14389bb8440f437e9cea6f2ba6d6386fbdd2219 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sat, 4 Nov 2023 20:36:12 +0100 Subject: [PATCH 25/45] avoid perpetually sending blobs to peers (#5563) Fix regression from #4808 where blobs that are already known are issued ACCEPT verdict, propagating them to peers over and over again. `validateBlobSidecar` contains the correct IGNORE logic. Moved it above the expensive checks to retain the performance of the check. --- beacon_chain/gossip_processing/eth2_processor.nim | 7 +------ beacon_chain/gossip_processing/gossip_validation.nim | 12 ++++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/beacon_chain/gossip_processing/eth2_processor.nim b/beacon_chain/gossip_processing/eth2_processor.nim index 71f22f66d..87406275b 100644 --- a/beacon_chain/gossip_processing/eth2_processor.nim +++ b/beacon_chain/gossip_processing/eth2_processor.nim @@ -287,12 +287,7 @@ proc processSignedBlobSidecar*( # Potential under/overflows are fine; would just create odd metrics and logs let delay = wallTime - signedBlobSidecar.message.slot.start_beacon_time - - if self.blobQuarantine[].hasBlob(signedBlobSidecar.message): - debug "Blob received, already in quarantine", delay - return ValidationRes.ok - else: - debug "Blob received", delay + debug "Blob received", delay let v = self.dag.validateBlobSidecar(self.quarantine, self.blobQuarantine, diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 8ec4538f0..5874a8349 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -331,6 +331,12 @@ proc validateBlobSidecar*( if not (sbs.message.slot > dag.finalizedHead.slot): return errIgnore("SignedBlobSidecar: slot already finalized") + # [IGNORE] The sidecar is the only sidecar with valid signature + # received for the tuple (sidecar.block_root, sidecar.index). + if blobQuarantine[].hasBlob(sbs.message): + return errIgnore( + "SignedBlobSidecar: already have blob with valid signature") + # [IGNORE] The block's parent (defined by block.parent_root) has # been seen (via both gossip and non-gossip sources) (a client MAY # queue blocks for processing once the parent block is retrieved). @@ -376,12 +382,6 @@ proc validateBlobSidecar*( sbs.signature): return dag.checkedReject("SignedBlobSidecar: invalid blob signature") - # [IGNORE] The sidecar is the only sidecar with valid signature - # received for the tuple (sidecar.block_root, sidecar.index). - if blobQuarantine[].hasBlob(sbs.message): - return errIgnore( - "SignedBlobSidecar: already have blob with valid signature") - ok() From 28b84ff93b412cdec40d9edb7d79e818e0491b0a Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sun, 5 Nov 2023 09:13:57 +0100 Subject: [PATCH 26/45] extend `hasBlob` to all blocks from same proposer and slot (#5568) `v1.4.0-beta.4` made the Gossip rules more strict and now requires to ignore blobs from other branches if there are equivocating blocks. Those blobs are only requestable via Req/Resp. --- .../blob_quarantine.nim | 17 +++++++++--- .../gossip_processing/gossip_validation.nim | 26 +++++++++++-------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/beacon_chain/consensus_object_pools/blob_quarantine.nim b/beacon_chain/consensus_object_pools/blob_quarantine.nim index c7a78b404..cd62e1535 100644 --- a/beacon_chain/consensus_object_pools/blob_quarantine.nim +++ b/beacon_chain/consensus_object_pools/blob_quarantine.nim @@ -37,8 +37,8 @@ func put*(quarantine: var BlobQuarantine, blobSidecar: ref BlobSidecar) = oldest_blob_key = k break quarantine.blobs.del oldest_blob_key - discard quarantine.blobs.hasKeyOrPut((blobSidecar.block_root, - blobSidecar.index), blobSidecar) + discard quarantine.blobs.hasKeyOrPut( + (blobSidecar.block_root, blobSidecar.index), blobSidecar) func blobIndices*(quarantine: BlobQuarantine, digest: Eth2Digest): seq[BlobIndex] = @@ -48,8 +48,17 @@ func blobIndices*(quarantine: BlobQuarantine, digest: Eth2Digest): r.add(i) r -func hasBlob*(quarantine: BlobQuarantine, blobSidecar: BlobSidecar): bool = - quarantine.blobs.hasKey((blobSidecar.block_root, blobSidecar.index)) +func hasBlob*( + quarantine: BlobQuarantine, + slot: Slot, + proposer_index: uint64, + index: BlobIndex): bool = + for blob_sidecar in quarantine.blobs.values: + if blob_sidecar.slot == slot and + blob_sidecar.proposer_index == proposer_index and + blob_sidecar.index == index: + return true + false func popBlobs*(quarantine: var BlobQuarantine, digest: Eth2Digest): seq[ref BlobSidecar] = diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 5874a8349..dbac3b26d 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -307,15 +307,16 @@ proc validateBlobSidecar*( dag: ChainDAGRef, quarantine: ref Quarantine, blobQuarantine: ref BlobQuarantine, sbs: SignedBlobSidecar, wallTime: BeaconTime, subnet_id: BlobId): Result[void, ValidationError] = + # Some of the checks below have been reordered compared to the spec, to + # perform the cheap checks first - in particular, we want to avoid loading + # an `EpochRef` and checking signatures. This reordering might lead to + # different IGNORE/REJECT results in turn affecting gossip scores. # [REJECT] The sidecar is for the correct topic -- # i.e. sidecar.index matches the topic {index}. if sbs.message.index != subnet_id: return dag.checkedReject("SignedBlobSidecar: mismatched gossip topic index") - if dag.getBlockRef(sbs.message.block_root).isSome(): - return errIgnore("SignedBlobSidecar: already have block") - # [IGNORE] The sidecar is not from a future slot (with a # MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance) -- i.e. validate that # sidecar.slot <= current_slot (a client MAY queue future sidecars @@ -331,11 +332,14 @@ proc validateBlobSidecar*( if not (sbs.message.slot > dag.finalizedHead.slot): return errIgnore("SignedBlobSidecar: slot already finalized") - # [IGNORE] The sidecar is the only sidecar with valid signature - # received for the tuple (sidecar.block_root, sidecar.index). - if blobQuarantine[].hasBlob(sbs.message): - return errIgnore( - "SignedBlobSidecar: already have blob with valid signature") + # [IGNORE] The sidecar is the first sidecar for the tuple + # (block_header.slot, block_header.proposer_index, blob_sidecar.index) + # with valid header signature, sidecar inclusion proof, and kzg proof. + if dag.getBlockRef(sbs.message.block_root).isSome(): + return errIgnore("SignedBlobSidecar: already have block") + if blobQuarantine[].hasBlob( + sbs.message.slot, sbs.message.proposer_index, sbs.message.index): + return errIgnore("SignedBlobSidecar: already have valid blob from same proposer") # [IGNORE] The block's parent (defined by block.parent_root) has # been seen (via both gossip and non-gossip sources) (a client MAY @@ -498,7 +502,7 @@ proc validateBeaconBlock*( blockRoot = shortLog(signed_beacon_block.root), blck = shortLog(signed_beacon_block.message), signature = shortLog(signed_beacon_block.signature) - return errIgnore("BeaconBlock: Parent not found") + return errIgnore("BeaconBlock: parent not found") # Continues block parent validity checking in optimistic case, where it does # appear as a `BlockRef` (and not handled above) but isn't usable for gossip @@ -539,12 +543,12 @@ proc validateBeaconBlock*( let proposer = getProposer( dag, parent, signed_beacon_block.message.slot).valueOr: - warn "cannot compute proposer for message" + warn "cannot compute proposer for block" return errIgnore("BeaconBlock: Cannot compute proposer") # internal issue if uint64(proposer) != signed_beacon_block.message.proposer_index: quarantine[].addUnviable(signed_beacon_block.root) - return dag.checkedReject("BeaconBlock: Unexpected proposer proposer") + return dag.checkedReject("BeaconBlock: Unexpected proposer") # [REJECT] The proposer signature, signed_beacon_block.signature, is valid # with respect to the proposer_index pubkey. From e4dacc30c4c347399e7951c602807caa9a916e05 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Sun, 5 Nov 2023 09:14:47 +0100 Subject: [PATCH 27/45] fix validation of blob index against gossip topic (#5569) In `v1.4.0-alpha.0`, the blob index validation on gossip was changed to use `compute_subnet_for_blob_sidecar` instead of having a separate topic for each individual blob. We updated the spec reference in #5363 without updating the code accordingly. Fixing this now, and also adding the new `MAX_BLOBS_PER_BLOCK` check from `v1.4.0-beta.3` as it shares the theme. --- .../gossip_processing/gossip_validation.nim | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index dbac3b26d..49248b832 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -312,15 +312,19 @@ proc validateBlobSidecar*( # an `EpochRef` and checking signatures. This reordering might lead to # different IGNORE/REJECT results in turn affecting gossip scores. - # [REJECT] The sidecar is for the correct topic -- - # i.e. sidecar.index matches the topic {index}. - if sbs.message.index != subnet_id: - return dag.checkedReject("SignedBlobSidecar: mismatched gossip topic index") + # [REJECT] The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` + # -- i.e. `blob_sidecar.index < MAX_BLOBS_PER_BLOCK` + if not (sbs.message.index < MAX_BLOBS_PER_BLOCK): + return dag.checkedReject("SignedBlobSidecar: index inconsistent") + + # [REJECT] The sidecar is for the correct subnet -- i.e. + # `compute_subnet_for_blob_sidecar(blob_sidecar.index) == subnet_id`. + if not (compute_subnet_for_blob_sidecar(sbs.message.index) == subnet_id): + return dag.checkedReject("SignedBlobSidecar: subnet incorrect") # [IGNORE] The sidecar is not from a future slot (with a - # MAXIMUM_GOSSIP_CLOCK_DISPARITY allowance) -- i.e. validate that - # sidecar.slot <= current_slot (a client MAY queue future sidecars - # for processing at the appropriate slot). + # `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that + # `block_header.slot <= current_slot` (a client MAY queue future sidecars if not (sbs.message.slot <= (wallTime + MAXIMUM_GOSSIP_CLOCK_DISPARITY).slotOrZero): return errIgnore("SignedBlobSidecar: slot too high") From 40196b75d0c6bcba665b75bf4509e8edec6ecd4e Mon Sep 17 00:00:00 2001 From: xiaolou86 <20718693+xiaolou86@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:56:07 +0800 Subject: [PATCH 28/45] docs: fix typos (#5571) --- beacon_chain/sync/README.md | 2 +- docs/e2store.md | 2 +- docs/the_nimbus_book/src/web3signer.md | 2 +- ncli/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/beacon_chain/sync/README.md b/beacon_chain/sync/README.md index 162aa4eb1..282615f1c 100644 --- a/beacon_chain/sync/README.md +++ b/beacon_chain/sync/README.md @@ -21,7 +21,7 @@ Blocks are received by batch: - in case of failure: - `push(SyncQueue, SyncRequest)` is called to reschedule the sync request. -Every second when sync is not in progress, the beacon node will ask the RequestManager to download all missing blocks currently in quarantaine. +Every second when sync is not in progress, the beacon node will ask the RequestManager to download all missing blocks currently in quarantine. - via `handleMissingBlocks` - which calls `fetchAncestorBlocks` - which asynchronously enqueue the request in the SharedBlockQueue `AsyncQueue[BlockEntry]`. diff --git a/docs/e2store.md b/docs/e2store.md index 725fda503..16712b5a1 100644 --- a/docs/e2store.md +++ b/docs/e2store.md @@ -327,7 +327,7 @@ An era is typically `8192` slots (in the mainnet configuration), or roughly 27.3 ## What happens after the merge? -Era files will store execution block contents, but not execution states (these are too large) - a full era history thus gives the full ethereum history from the merge onwards for convenient cold storage. Work is underway to similarily cover the rest of history. +Era files will store execution block contents, but not execution states (these are too large) - a full era history thus gives the full ethereum history from the merge onwards for convenient cold storage. Work is underway to similarly cover the rest of history. ## Which state should be stored in the era file? diff --git a/docs/the_nimbus_book/src/web3signer.md b/docs/the_nimbus_book/src/web3signer.md index e5f773461..c8a7f0b12 100644 --- a/docs/the_nimbus_book/src/web3signer.md +++ b/docs/the_nimbus_book/src/web3signer.md @@ -40,7 +40,7 @@ The fields have the following semantics: 5. `remote` - An URL of a remote signing server. 6. `remotes` - A [distributed keystore](#distributed-keystores) configuration including two or more remote signing servers. 7. `ignore_ssl_verification` - An optional boolean flag allowing the use of self-signed certificates by the signing server. -8. `proven_block_properties` - When the `verifying-web3signer` type is used, this is a list of locations withing the SSZ block body for which the block signing requests will contain additional Merkle proofs, allowing the signer to verify certain details about the signed blocks (e.g. the `fee_recipient` value). +8. `proven_block_properties` - When the `verifying-web3signer` type is used, this is a list of locations within the SSZ block body for which the block signing requests will contain additional Merkle proofs, allowing the signer to verify certain details about the signed blocks (e.g. the `fee_recipient` value). !!! info The current version of the remote keystore format is `3` which adds support for the experimental [verifying web3signer setups](#verifying-web3signer). diff --git a/ncli/README.md b/ncli/README.md index 72aae6559..f645007ed 100644 --- a/ncli/README.md +++ b/ncli/README.md @@ -1,6 +1,6 @@ # Introduction -`ncli` is a set of low level / debugging tools to interact with the nimbus [beacon chain specification](https://github.com/ethereum/consensus-specs/tree/dev/specs) implementation, simliar to [zcli](https://github.com/protolambda/zcli). With it, you explore SSZ, make state transitions and compute hash tree roots. +`ncli` is a set of low level / debugging tools to interact with the nimbus [beacon chain specification](https://github.com/ethereum/consensus-specs/tree/dev/specs) implementation, similar to [zcli](https://github.com/protolambda/zcli). With it, you explore SSZ, make state transitions and compute hash tree roots. # Tools From d8a7f0df81761b0861ed11f6b1a5d0aa58d17ae9 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 6 Nov 2023 07:48:43 +0100 Subject: [PATCH 29/45] update Deneb for blob sidecar inclusion proofs (#5565) `BlobSidecar` is no longer signed, instead use Merkle proof to link blobs with block. - https://github.com/ethereum/consensus-specs/pull/3531 Associated beacon-API / builder-specs still TBD; minimal changes done to compile in similar style to previous spec, but not standardized yet. - https://github.com/ethereum/beacon-APIs/pull/369 - https://github.com/ethereum/builder-specs/pull/90 --- AllTests-mainnet.md | 5 +- ConsensusSpecPreset-mainnet.md | 23 ++- ConsensusSpecPreset-minimal.md | 26 ++- beacon_chain/beacon_chain_db.nim | 3 +- .../blob_quarantine.nim | 10 +- .../gossip_processing/eth2_processor.nim | 25 ++- .../gossip_processing/gossip_validation.nim | 159 ++++++++++++------ beacon_chain/networking/eth2_network.nim | 2 +- beacon_chain/nimbus_beacon_node.nim | 8 +- beacon_chain/rpc/rest_beacon_api.nim | 42 ++--- beacon_chain/rpc/rest_validator_api.nim | 21 +-- beacon_chain/spec/datatypes/base.nim | 2 +- beacon_chain/spec/datatypes/constants.nim | 3 - beacon_chain/spec/datatypes/deneb.nim | 73 ++++---- .../eth2_apis/eth2_rest_serialization.nim | 43 +++-- beacon_chain/spec/eth2_apis/rest_types.nim | 6 +- beacon_chain/spec/forks.nim | 17 +- beacon_chain/spec/helpers.nim | 48 ++++++ beacon_chain/spec/mev/deneb_mev.nim | 15 +- beacon_chain/spec/signatures.nim | 30 ---- beacon_chain/sync/request_manager.nim | 8 +- beacon_chain/sync/sync_manager.nim | 9 +- beacon_chain/sync/sync_queue.nim | 4 +- .../validator_client/block_service.nim | 44 ++--- beacon_chain/validators/beacon_validators.nim | 107 ++---------- beacon_chain/validators/message_router.nim | 30 ++-- .../validators/message_router_mev.nim | 5 +- beacon_chain/validators/validator_pool.nim | 15 -- .../test_fixture_ssz_consensus_objects.nim | 1 - tests/test_beacon_chain_db.nim | 20 ++- tests/test_message_signatures.nim | 30 ---- tests/test_rest_json_serialization.nim | 7 +- tests/test_signing_node.nim | 2 +- tests/test_sync_manager.nim | 12 +- vendor/nim-eth2-scenarios | 2 +- 35 files changed, 431 insertions(+), 426 deletions(-) diff --git a/AllTests-mainnet.md b/AllTests-mainnet.md index 007d50978..a67913aeb 100644 --- a/AllTests-mainnet.md +++ b/AllTests-mainnet.md @@ -358,7 +358,6 @@ OK: 4/4 Fail: 0/4 Skip: 0/4 ```diff + Aggregate and proof signatures OK + Attestation signatures OK -+ Blob sidecar signatures OK + Deposit signatures OK + Slot signatures OK + Sync committee message signatures OK @@ -366,7 +365,7 @@ OK: 4/4 Fail: 0/4 Skip: 0/4 + Sync committee signed contribution and proof signatures OK + Voluntary exit signatures OK ``` -OK: 9/9 Fail: 0/9 Skip: 0/9 +OK: 8/8 Fail: 0/8 Skip: 0/8 ## Network metadata ```diff + goerli OK @@ -715,4 +714,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2 OK: 9/9 Fail: 0/9 Skip: 0/9 ---TOTAL--- -OK: 404/409 Fail: 0/409 Skip: 5/409 +OK: 403/408 Fail: 0/408 Skip: 5/408 diff --git a/ConsensusSpecPreset-mainnet.md b/ConsensusSpecPreset-mainnet.md index a24609145..d88b377a8 100644 --- a/ConsensusSpecPreset-mainnet.md +++ b/ConsensusSpecPreset-mainnet.md @@ -2258,7 +2258,6 @@ OK: 34/34 Fail: 0/34 Skip: 0/34 + Testing SignedBLSToExecutionChange OK + Testing SignedBeaconBlock OK + Testing SignedBeaconBlockHeader OK -+ Testing SignedBlobSidecar OK + Testing SignedContributionAndProof OK + Testing SignedVoluntaryExit OK + Testing SigningData OK @@ -2271,7 +2270,7 @@ OK: 34/34 Fail: 0/34 Skip: 0/34 + Testing VoluntaryExit OK + Testing Withdrawal OK ``` -OK: 49/49 Fail: 0/49 Skip: 0/49 +OK: 48/48 Fail: 0/48 Skip: 0/48 ## EF - Deneb - Sanity - Blocks [Preset: mainnet] ```diff + [Invalid] EF - Deneb - Sanity - Blocks - invalid_all_zeroed_sig [Preset: mainnet] OK @@ -2411,6 +2410,11 @@ OK: 4/4 Fail: 0/4 Skip: 0/4 + Light client - Single merkle proof - mainnet/deneb/light_client/single_merkle_proof/Beacon OK ``` OK: 14/14 Fail: 0/14 Skip: 0/14 +## EF - Merkle proof [Preset: mainnet] +```diff ++ Merkle proof - Single merkle proof - mainnet/deneb/merkle_proof/single_merkle_proof/Beacon OK +``` +OK: 1/1 Fail: 0/1 Skip: 0/1 ## EF - Phase 0 - Epoch Processing - Effective balance updates [Preset: mainnet] ```diff + Effective balance updates - effective_balance_hysteresis [Preset: mainnet] OK @@ -2825,6 +2829,8 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 + ForkChoice - mainnet/altair/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head OK + ForkChoice - mainnet/altair/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_we OK + ForkChoice - mainnet/altair/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attesta OK + ForkChoice - mainnet/altair/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - mainnet/altair/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_roo Skip + ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK ForkChoice - mainnet/altair/fork_choice/on_block/pyspec_tests/on_block_future_block Skip @@ -2842,6 +2848,8 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 + ForkChoice - mainnet/bellatrix/fork_choice/get_head/pyspec_tests/proposer_boost_correct_he OK + ForkChoice - mainnet/bellatrix/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier OK + ForkChoice - mainnet/bellatrix/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_atte OK + ForkChoice - mainnet/bellatrix/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_ro Skip + ForkChoice - mainnet/bellatrix/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_ Skip + ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK ForkChoice - mainnet/bellatrix/fork_choice/on_block/pyspec_tests/on_block_future_block Skip @@ -2852,6 +2860,7 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/block_lookup_failed Skip ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_early_for_merge Skip ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_late_for_merge Skip + ForkChoice - mainnet/bellatrix/fork_choice/should_override_forkchoice_update/pyspec_tests/ Skip + ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_grea OK + ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_ OK + ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest OK @@ -2863,12 +2872,15 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 + ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head OK + ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_w OK + ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest OK + ForkChoice - mainnet/capella/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - mainnet/capella/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_ro Skip + ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_future_block Skip + ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost OK + ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_blo OK + ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl OK + ForkChoice - mainnet/capella/fork_choice/should_override_forkchoice_update/pyspec_tests/sh Skip + ForkChoice - mainnet/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_greate OK + ForkChoice - mainnet/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_no OK + ForkChoice - mainnet/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest_a OK @@ -2880,6 +2892,8 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 + ForkChoice - mainnet/deneb/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head OK + ForkChoice - mainnet/deneb/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_wei OK + ForkChoice - mainnet/deneb/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attestat OK + ForkChoice - mainnet/deneb/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - mainnet/deneb/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_root Skip + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_data_unavailable OK + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/invalid_incorrect_proof OK @@ -2891,8 +2905,9 @@ OK: 40/40 Fail: 0/40 Skip: 0/40 + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_is_first_block OK + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_slot OK + ForkChoice - mainnet/deneb/fork_choice/on_block/pyspec_tests/simple_blob_data OK + ForkChoice - mainnet/deneb/fork_choice/should_override_forkchoice_update/pyspec_tests/shou Skip ``` -OK: 69/77 Fail: 0/77 Skip: 8/77 +OK: 69/88 Fail: 0/88 Skip: 19/88 ## Sync ```diff + Sync - mainnet/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK @@ -2902,4 +2917,4 @@ OK: 69/77 Fail: 0/77 Skip: 8/77 OK: 3/3 Fail: 0/3 Skip: 0/3 ---TOTAL--- -OK: 2336/2344 Fail: 0/2344 Skip: 8/2344 +OK: 2336/2355 Fail: 0/2355 Skip: 19/2355 diff --git a/ConsensusSpecPreset-minimal.md b/ConsensusSpecPreset-minimal.md index decf1beca..b60273090 100644 --- a/ConsensusSpecPreset-minimal.md +++ b/ConsensusSpecPreset-minimal.md @@ -2355,7 +2355,6 @@ OK: 34/34 Fail: 0/34 Skip: 0/34 + Testing SignedBLSToExecutionChange OK + Testing SignedBeaconBlock OK + Testing SignedBeaconBlockHeader OK -+ Testing SignedBlobSidecar OK + Testing SignedContributionAndProof OK + Testing SignedVoluntaryExit OK + Testing SigningData OK @@ -2368,7 +2367,7 @@ OK: 34/34 Fail: 0/34 Skip: 0/34 + Testing VoluntaryExit OK + Testing Withdrawal OK ``` -OK: 49/49 Fail: 0/49 Skip: 0/49 +OK: 48/48 Fail: 0/48 Skip: 0/48 ## EF - Deneb - Sanity - Blocks [Preset: minimal] ```diff + [Invalid] EF - Deneb - Sanity - Blocks - invalid_all_zeroed_sig [Preset: minimal] OK @@ -2551,6 +2550,11 @@ OK: 20/20 Fail: 0/20 Skip: 0/20 + Light client - Update ranking - minimal/deneb/light_client/update_ranking/pyspec_tests/upd OK ``` OK: 4/4 Fail: 0/4 Skip: 0/4 +## EF - Merkle proof [Preset: minimal] +```diff ++ Merkle proof - Single merkle proof - minimal/deneb/merkle_proof/single_merkle_proof/Beacon OK +``` +OK: 1/1 Fail: 0/1 Skip: 0/1 ## EF - Phase 0 - Epoch Processing - Effective balance updates [Preset: minimal] ```diff + Effective balance updates - effective_balance_hysteresis [Preset: minimal] OK @@ -2977,6 +2981,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/altair/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attesta OK + ForkChoice - minimal/altair/fork_choice/get_head/pyspec_tests/voting_source_beyond_two_epo OK + ForkChoice - minimal/altair/fork_choice/get_head/pyspec_tests/voting_source_within_two_epo OK + ForkChoice - minimal/altair/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - minimal/altair/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_roo Skip + ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/incompatible_justification_u OK + ForkChoice - minimal/altair/fork_choice/on_block/pyspec_tests/incompatible_justification_u OK @@ -3023,6 +3029,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/bellatrix/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_atte OK + ForkChoice - minimal/bellatrix/fork_choice/get_head/pyspec_tests/voting_source_beyond_two_ OK + ForkChoice - minimal/bellatrix/fork_choice/get_head/pyspec_tests/voting_source_within_two_ OK + ForkChoice - minimal/bellatrix/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_ro Skip + ForkChoice - minimal/bellatrix/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_ Skip + ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/incompatible_justificatio OK + ForkChoice - minimal/bellatrix/fork_choice/on_block/pyspec_tests/incompatible_justificatio OK @@ -3058,6 +3066,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/bellatrix/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delay OK + ForkChoice - minimal/bellatrix/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delay OK + ForkChoice - minimal/bellatrix/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_witho OK + ForkChoice - minimal/bellatrix/fork_choice/should_override_forkchoice_update/pyspec_tests/ Skip + ForkChoice - minimal/bellatrix/fork_choice/should_override_forkchoice_update/pyspec_tests/ Skip + ForkChoice - minimal/bellatrix/fork_choice/withholding/pyspec_tests/withholding_attack OK + ForkChoice - minimal/bellatrix/fork_choice/withholding/pyspec_tests/withholding_attack_unv OK + ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest OK @@ -3073,6 +3083,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest OK + ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/voting_source_beyond_two_ep OK + ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/voting_source_within_two_ep OK + ForkChoice - minimal/capella/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - minimal/capella/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_ro Skip + ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/incompatible_justification_ OK + ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/incompatible_justification_ OK @@ -3104,6 +3116,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/capella/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delayed OK + ForkChoice - minimal/capella/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delayed OK + ForkChoice - minimal/capella/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_without OK + ForkChoice - minimal/capella/fork_choice/should_override_forkchoice_update/pyspec_tests/sh Skip + ForkChoice - minimal/capella/fork_choice/should_override_forkchoice_update/pyspec_tests/sh Skip + ForkChoice - minimal/capella/fork_choice/withholding/pyspec_tests/withholding_attack OK + ForkChoice - minimal/capella/fork_choice/withholding/pyspec_tests/withholding_attack_unvia OK + ForkChoice - minimal/deneb/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest_a OK @@ -3119,6 +3133,8 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/deneb/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attestat OK + ForkChoice - minimal/deneb/fork_choice/get_head/pyspec_tests/voting_source_beyond_two_epoc OK + ForkChoice - minimal/deneb/fork_choice/get_head/pyspec_tests/voting_source_within_two_epoc OK + ForkChoice - minimal/deneb/fork_choice/get_proposer_head/pyspec_tests/basic_is_head_root Skip + ForkChoice - minimal/deneb/fork_choice/get_proposer_head/pyspec_tests/basic_is_parent_root Skip + ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/basic OK + ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/incompatible_justification_up OK + ForkChoice - minimal/deneb/fork_choice/on_block/pyspec_tests/incompatible_justification_up OK @@ -3155,10 +3171,12 @@ OK: 45/45 Fail: 0/45 Skip: 0/45 + ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delayed_j OK + ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_delayed_j OK + ForkChoice - minimal/deneb/fork_choice/reorg/pyspec_tests/simple_attempted_reorg_without_e OK + ForkChoice - minimal/deneb/fork_choice/should_override_forkchoice_update/pyspec_tests/shou Skip + ForkChoice - minimal/deneb/fork_choice/should_override_forkchoice_update/pyspec_tests/shou Skip + ForkChoice - minimal/deneb/fork_choice/withholding/pyspec_tests/withholding_attack OK + ForkChoice - minimal/deneb/fork_choice/withholding/pyspec_tests/withholding_attack_unviabl OK ``` -OK: 185/193 Fail: 0/193 Skip: 8/193 +OK: 185/207 Fail: 0/207 Skip: 22/207 ## Sync ```diff + Sync - minimal/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK @@ -3168,4 +3186,4 @@ OK: 185/193 Fail: 0/193 Skip: 8/193 OK: 3/3 Fail: 0/3 Skip: 0/3 ---TOTAL--- -OK: 2578/2586 Fail: 0/2586 Skip: 8/2586 +OK: 2578/2600 Fail: 0/2600 Skip: 22/2600 diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 2290505f5..88d96789d 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -793,7 +793,8 @@ proc putBlock*( proc putBlobSidecar*( db: BeaconChainDB, value: BlobSidecar) = - db.blobs.putSZSSZ(blobkey(value.block_root, value.index), value) + let block_root = hash_tree_root(value.signed_block_header.message) + db.blobs.putSZSSZ(blobkey(block_root, value.index), value) proc delBlobSidecar*( db: BeaconChainDB, diff --git a/beacon_chain/consensus_object_pools/blob_quarantine.nim b/beacon_chain/consensus_object_pools/blob_quarantine.nim index cd62e1535..0bf137129 100644 --- a/beacon_chain/consensus_object_pools/blob_quarantine.nim +++ b/beacon_chain/consensus_object_pools/blob_quarantine.nim @@ -7,7 +7,7 @@ {.push raises: [].} -import ../spec/datatypes/deneb +import ../spec/helpers from std/sequtils import mapIt from std/strutils import join @@ -37,8 +37,9 @@ func put*(quarantine: var BlobQuarantine, blobSidecar: ref BlobSidecar) = oldest_blob_key = k break quarantine.blobs.del oldest_blob_key + let block_root = hash_tree_root(blobSidecar.signed_block_header.message) discard quarantine.blobs.hasKeyOrPut( - (blobSidecar.block_root, blobSidecar.index), blobSidecar) + (block_root, blobSidecar.index), blobSidecar) func blobIndices*(quarantine: BlobQuarantine, digest: Eth2Digest): seq[BlobIndex] = @@ -54,8 +55,9 @@ func hasBlob*( proposer_index: uint64, index: BlobIndex): bool = for blob_sidecar in quarantine.blobs.values: - if blob_sidecar.slot == slot and - blob_sidecar.proposer_index == proposer_index and + template block_header: untyped = blob_sidecar.signed_block_header.message + if block_header.slot == slot and + block_header.proposer_index == proposer_index and blob_sidecar.index == index: return true false diff --git a/beacon_chain/gossip_processing/eth2_processor.nim b/beacon_chain/gossip_processing/eth2_processor.nim index 87406275b..f9a0acf40 100644 --- a/beacon_chain/gossip_processing/eth2_processor.nim +++ b/beacon_chain/gossip_processing/eth2_processor.nim @@ -245,7 +245,7 @@ proc processSignedBeaconBlock*( Opt.some(self.blobQuarantine[].popBlobs(signedBlock.root)) else: if not self.quarantine[].addBlobless(self.dag.finalizedHead.slot, - signedBlock): + signedBlock): notice "Block quarantine full (blobless)", blockRoot = shortLog(signedBlock.root), blck = shortLog(signedBlock.message), @@ -273,25 +273,26 @@ proc processSignedBeaconBlock*( v -proc processSignedBlobSidecar*( +proc processBlobSidecar*( self: var Eth2Processor, src: MsgSource, - signedBlobSidecar: deneb.SignedBlobSidecar, subnet_id: BlobId): ValidationRes = + blobSidecar: deneb.BlobSidecar, subnet_id: BlobId): ValidationRes = + template block_header: untyped = blobSidecar.signed_block_header.message + let wallTime = self.getCurrentBeaconTime() (afterGenesis, wallSlot) = wallTime.toSlot() logScope: - blob = shortLog(signedBlobSidecar.message) - signature = shortLog(signedBlobSidecar.signature) + blob = shortLog(blobSidecar) wallSlot # Potential under/overflows are fine; would just create odd metrics and logs - let delay = wallTime - signedBlobSidecar.message.slot.start_beacon_time + let delay = wallTime - block_header.slot.start_beacon_time debug "Blob received", delay let v = self.dag.validateBlobSidecar(self.quarantine, self.blobQuarantine, - signedBlobSidecar, wallTime, subnet_id) + blobSidecar, wallTime, subnet_id) if v.isErr(): debug "Dropping blob", error = v.error() @@ -299,21 +300,19 @@ proc processSignedBlobSidecar*( return v debug "Blob validated, putting in blob quarantine" - self.blobQuarantine[].put(newClone(signedBlobSidecar.message)) + self.blobQuarantine[].put(newClone(blobSidecar)) var skippedBlocks = false - if (let o = self.quarantine[].popBlobless( - signedBlobSidecar.message.block_root); o.isSome): + let block_root = hash_tree_root(block_header) + if (let o = self.quarantine[].popBlobless(block_root); o.isSome): let blobless = o.unsafeGet() if self.blobQuarantine[].hasBlobs(blobless): self.blockProcessor[].enqueueBlock( MsgSource.gossip, ForkedSignedBeaconBlock.init(blobless), - Opt.some(self.blobQuarantine[].popBlobs( - signedBlobSidecar.message.block_root)) - ) + Opt.some(self.blobQuarantine[].popBlobs(block_root))) else: discard self.quarantine[].addBlobless(self.dag.finalizedHead.slot, blobless) diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 49248b832..2f0770c6c 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -182,6 +182,20 @@ func check_attestation_subnet( ok() +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/p2p-interface.md#verify_blob_sidecar_inclusion_proof +func verify_blob_sidecar_inclusion_proof( + blob_sidecar: deneb.BlobSidecar): Result[void, ValidationError] = + let gindex = kzg_commitment_inclusion_proof_gindex(blob_sidecar.index) + if not is_valid_merkle_branch( + hash_tree_root(blob_sidecar.kzg_commitment), + blob_sidecar.kzg_commitment_inclusion_proof, + KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, + get_subtree_index(gindex), + blob_sidecar.signed_block_header.message.body_root): + return errReject("BlobSidecar: inclusion proof not valid") + + ok() + # Gossip Validation # ---------------------------------------------------------------- @@ -302,93 +316,132 @@ template validateBeaconBlockBellatrix( # cannot occur here, because Nimbus's optimistic sync waits for either # `ACCEPTED` or `SYNCING` from the EL to get this far. -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id proc validateBlobSidecar*( dag: ChainDAGRef, quarantine: ref Quarantine, - blobQuarantine: ref BlobQuarantine, sbs: SignedBlobSidecar, + blobQuarantine: ref BlobQuarantine, blob_sidecar: BlobSidecar, wallTime: BeaconTime, subnet_id: BlobId): Result[void, ValidationError] = # Some of the checks below have been reordered compared to the spec, to # perform the cheap checks first - in particular, we want to avoid loading # an `EpochRef` and checking signatures. This reordering might lead to # different IGNORE/REJECT results in turn affecting gossip scores. + template block_header: untyped = blob_sidecar.signed_block_header.message # [REJECT] The sidecar's index is consistent with `MAX_BLOBS_PER_BLOCK` # -- i.e. `blob_sidecar.index < MAX_BLOBS_PER_BLOCK` - if not (sbs.message.index < MAX_BLOBS_PER_BLOCK): - return dag.checkedReject("SignedBlobSidecar: index inconsistent") + if not (blob_sidecar.index < MAX_BLOBS_PER_BLOCK): + return dag.checkedReject("BlobSidecar: index inconsistent") # [REJECT] The sidecar is for the correct subnet -- i.e. # `compute_subnet_for_blob_sidecar(blob_sidecar.index) == subnet_id`. - if not (compute_subnet_for_blob_sidecar(sbs.message.index) == subnet_id): - return dag.checkedReject("SignedBlobSidecar: subnet incorrect") + if not (compute_subnet_for_blob_sidecar(blob_sidecar.index) == subnet_id): + return dag.checkedReject("BlobSidecar: subnet incorrect") # [IGNORE] The sidecar is not from a future slot (with a # `MAXIMUM_GOSSIP_CLOCK_DISPARITY` allowance) -- i.e. validate that # `block_header.slot <= current_slot` (a client MAY queue future sidecars - if not (sbs.message.slot <= + # for processing at the appropriate slot). + if not (block_header.slot <= (wallTime + MAXIMUM_GOSSIP_CLOCK_DISPARITY).slotOrZero): - return errIgnore("SignedBlobSidecar: slot too high") + return errIgnore("BlobSidecar: slot too high") - # [IGNORE] The block is from a slot greater than the latest - # finalized slot -- i.e. validate that - # signed_beacon_block.message.slot > - # compute_start_slot_at_epoch(state.finalized_checkpoint.epoch) - if not (sbs.message.slot > dag.finalizedHead.slot): - return errIgnore("SignedBlobSidecar: slot already finalized") + # [IGNORE] The sidecar is from a slot greater than the latest + # finalized slot -- i.e. validate that `block_header.slot > + # compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)` + if not (block_header.slot > dag.finalizedHead.slot): + return errIgnore("BlobSidecar: slot already finalized") # [IGNORE] The sidecar is the first sidecar for the tuple # (block_header.slot, block_header.proposer_index, blob_sidecar.index) # with valid header signature, sidecar inclusion proof, and kzg proof. - if dag.getBlockRef(sbs.message.block_root).isSome(): - return errIgnore("SignedBlobSidecar: already have block") + let block_root = hash_tree_root(block_header) + if dag.getBlockRef(block_root).isSome(): + return errIgnore("BlobSidecar: already have block") if blobQuarantine[].hasBlob( - sbs.message.slot, sbs.message.proposer_index, sbs.message.index): - return errIgnore("SignedBlobSidecar: already have valid blob from same proposer") + block_header.slot, block_header.proposer_index, blob_sidecar.index): + return errIgnore("BlobSidecar: already have valid blob from same proposer") - # [IGNORE] The block's parent (defined by block.parent_root) has - # been seen (via both gossip and non-gossip sources) (a client MAY - # queue blocks for processing once the parent block is retrieved). - # [REJECT] The sidecar's block's parent (defined by sidecar.block_parent_root) - # passes validation. - let parentRes = dag.getBlockRef(sbs.message.block_parent_root) - if parentRes.isErr: - if sbs.message.block_parent_root in quarantine[].unviable: - return dag.checkedReject("SignedBlobSidecar: parent not validated") + # [REJECT] The sidecar's inclusion proof is valid as verified by + # `verify_blob_sidecar_inclusion_proof(blob_sidecar)`. + block: + let v = verify_blob_sidecar_inclusion_proof(blob_sidecar) + if v.isErr: + return dag.checkedReject(v.error) + + # [IGNORE] The sidecar's block's parent (defined by + # `block_header.parent_root`) has been seen (via both gossip and + # non-gossip sources) (a client MAY queue sidecars for processing + # once the parent block is retrieved). + # + # [REJECT] The sidecar's block's parent (defined by + # `block_header.parent_root`) passes validation. + let parent = dag.getBlockRef(block_header.parent_root).valueOr: + if block_header.parent_root in quarantine[].unviable: + quarantine[].addUnviable(block_root) + return dag.checkedReject("BlobSidecar: parent not validated") else: - return errIgnore("SignedBlobSidecar: parent not found") - template parent: untyped = parentRes.get + quarantine[].addMissing(block_header.parent_root) + return errIgnore("BlobSidecar: parent not found") # [REJECT] The sidecar is from a higher slot than the sidecar's - # block's parent (defined by sidecar.block_parent_root). - if sbs.message.slot <= parent.bid.slot: - return dag.checkedReject("SignedBlobSidecar: slot lower than parents'") + # block's parent (defined by `block_header.parent_root`). + if not (block_header.slot > parent.bid.slot): + return dag.checkedReject("BlobSidecar: slot lower than parents'") - # [REJECT] The sidecar is proposed by the expected proposer_index + # [REJECT] The current finalized_checkpoint is an ancestor of the sidecar's + # block -- i.e. `get_checkpoint_block(store, block_header.parent_root, + # store.finalized_checkpoint.epoch) == store.finalized_checkpoint.root`. + let + finalized_checkpoint = getStateField(dag.headState, finalized_checkpoint) + ancestor = get_ancestor(parent, finalized_checkpoint.epoch.start_slot) + + if ancestor.isNil: + # This shouldn't happen: we should always be able to trace the parent back + # to the finalized checkpoint (else it wouldn't be in the DAG) + return errIgnore("BlobSidecar: Can't find ancestor") + + if not ( + finalized_checkpoint.root == ancestor.root or + finalized_checkpoint.root.isZero): + quarantine[].addUnviable(block_root) + return dag.checkedReject( + "BlobSidecar: Finalized checkpoint not an ancestor") + + # [REJECT] The sidecar is proposed by the expected `proposer_index` # for the block's slot in the context of the current shuffling - # (defined by block_parent_root/slot). If the proposer_index - # cannot immediately be verified against the expected shuffling, - # the sidecar MAY be queued for later processing while proposers + # (defined by `block_header.parent_root`/`block_header.slot`). + # If the proposer_index cannot immediately be verified against the expected + # shuffling, the sidecar MAY be queued for later processing while proposers # for the block's branch are calculated -- in such a case do not # REJECT, instead IGNORE this message. - let - proposer = getProposer( - dag, parent, sbs.message.slot).valueOr: - warn "cannot compute proposer for blob" - return errIgnore("SignedBlobSidecar: Cannot compute proposer") + let proposer = getProposer(dag, parent, block_header.slot).valueOr: + warn "cannot compute proposer for blob" + return errIgnore("BlobSidecar: Cannot compute proposer") # internal issue - if uint64(proposer) != sbs.message.proposer_index: - return dag.checkedReject("SignedBlobSidecar: Unexpected proposer") + if uint64(proposer) != block_header.proposer_index: + return dag.checkedReject("BlobSidecar: Unexpected proposer") - # [REJECT] The proposer signature, signed_blob_sidecar.signature, - # is valid as verified by verify_sidecar_signature. - if not verify_blob_signature( - dag.forkAtEpoch(sbs.message.slot.epoch), - getStateField(dag.headState, genesis_validators_root), - sbs.message.slot, - sbs.message, - dag.validatorKey(proposer).get(), - sbs.signature): - return dag.checkedReject("SignedBlobSidecar: invalid blob signature") + # [REJECT] The proposer signature of `blob_sidecar.signed_block_header`, + # is valid with respect to the `block_header.proposer_index` pubkey. + if not verify_block_signature( + dag.forkAtEpoch(block_header.slot.epoch), + getStateField(dag.headState, genesis_validators_root), + block_header.slot, + block_root, + dag.validatorKey(proposer).get(), + blob_sidecar.signed_block_header.signature): + return dag.checkedReject("BlobSidecar: Invalid proposer signature") + + # [REJECT] The sidecar's blob is valid as verified by `verify_blob_kzg_proof( + # blob_sidecar.blob, blob_sidecar.kzg_commitment, blob_sidecar.kzg_proof)`. + block: + let ok = verifyProof( + blob_sidecar.blob, + blob_sidecar.kzg_commitment, + blob_sidecar.kzg_proof).valueOr: + return dag.checkedReject("BlobSidecar: blob verify failed") + if not ok: + return dag.checkedReject("BlobSidecar: blob invalid") ok() diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index 23f6c5ad8..25049c8a3 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -2678,7 +2678,7 @@ proc broadcastBeaconBlock*( node.broadcast(topic, blck) proc broadcastBlobSidecar*( - node: Eth2Node, subnet_id: BlobId, blob: deneb.SignedBlobSidecar): + node: Eth2Node, subnet_id: BlobId, blob: deneb.BlobSidecar): Future[SendResult] = let forkPrefix = node.forkDigestAtEpoch(node.getWallEpoch) diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 39c91cd11..ac90b41f6 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -1734,17 +1734,17 @@ proc installMessageValidators(node: BeaconNode) = when consensusFork >= ConsensusFork.Deneb: # blob_sidecar_{subnet_id} - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/p2p-interface.md#blob_sidecar_subnet_id for it in BlobId: closureScope: # Needed for inner `proc`; don't lift it out of loop. let subnet_id = it node.network.addValidator( getBlobSidecarTopic(digest, subnet_id), proc ( - signedBlobSidecar: SignedBlobSidecar + blobSidecar: deneb.BlobSidecar ): ValidationResult = toValidationResult( - node.processor[].processSignedBlobSidecar( - MsgSource.gossip, signedBlobSidecar, subnet_id))) + node.processor[].processBlobSidecar( + MsgSource.gossip, blobSidecar, subnet_id))) node.installLightClientMessageValidators() diff --git a/beacon_chain/rpc/rest_beacon_api.nim b/beacon_chain/rpc/rest_beacon_api.nim index 56b741999..944002f51 100644 --- a/beacon_chain/rpc/rest_beacon_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -873,28 +873,29 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = of ConsensusFork.Phase0: var blck = restBlock.phase0Data blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Altair: var blck = restBlock.altairData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Bellatrix: var blck = restBlock.bellatrixData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Capella: var blck = restBlock.capellaData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Deneb: var blck = restBlock.denebData.signed_block blck.root = hash_tree_root(blck.message) await node.router.routeSignedBeaconBlock( - blck, Opt.some(asSeq restBlock.denebData.signed_blob_sidecars)) + blck, Opt.some(blck.create_blob_sidecars( + restBlock.denebData.kzg_proofs, restBlock.denebData.blobs))) if res.isErr(): return RestApiResponse.jsonError( @@ -948,28 +949,29 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = of ConsensusFork.Phase0: var blck = restBlock.phase0Data blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Altair: var blck = restBlock.altairData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Bellatrix: var blck = restBlock.bellatrixData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Capella: var blck = restBlock.capellaData blck.root = hash_tree_root(blck.message) - await node.router.routeSignedBeaconBlock(blck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + blck, Opt.none(seq[BlobSidecar])) of ConsensusFork.Deneb: var blck = restBlock.denebData.signed_block blck.root = hash_tree_root(blck.message) await node.router.routeSignedBeaconBlock( - blck, Opt.some(asSeq restBlock.denebData.signed_blob_sidecars)) + blck, Opt.some(blck.create_blob_sidecars( + restBlock.denebData.kzg_proofs, restBlock.denebData.blobs))) if res.isErr(): return RestApiResponse.jsonError( @@ -1066,8 +1068,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = let res = withBlck(forked): forkyBlck.root = hash_tree_root(forkyBlck.message) - await node.router.routeSignedBeaconBlock(forkyBlck, - Opt.none(SignedBlobSidecars)) + await node.router.routeSignedBeaconBlock( + forkyBlck, Opt.none(seq[BlobSidecar])) if res.isErr(): return RestApiResponse.jsonError( diff --git a/beacon_chain/rpc/rest_validator_api.nim b/beacon_chain/rpc/rest_validator_api.nim index c016f899f..734d974d5 100644 --- a/beacon_chain/rpc/rest_validator_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -407,26 +407,11 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = withBlck(message.blck): let data = when consensusFork >= ConsensusFork.Deneb: - let bundle = message.blobsBundleOpt.get() - let blockRoot = hash_tree_root(forkyBlck) - var sidecars = newSeqOfCap[BlobSidecar](bundle.blobs.len) - for i in 0..= ConsensusFork.Deneb: + if kzg_proofs.isNone(): + reader.raiseUnexpectedValue("Field `kzg_proofs` is missing") + if blobs.isNone(): + reader.raiseUnexpectedValue("Field `blobs` is missing") + else: + if kzg_proofs.isSome(): + reader.raiseUnexpectedValue("Field `kzg_proofs` found but unsupported") + if blobs.isSome(): + reader.raiseUnexpectedValue("Field `blobs` found but unsupported") + case blck.kind of ConsensusFork.Phase0: value = RestPublishedSignedBlockContents( @@ -1865,7 +1885,8 @@ proc readValue*(reader: var JsonReader[RestJson], denebData: DenebSignedBlockContents( # Constructed to be internally consistent signed_block: signed_message.get().distinctBase.denebData, - signed_blob_sidecars: signed_blob_sidecars.get() + kzg_proofs: kzg_proofs.get(), + blobs: blobs.get() ) ) diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index c36d25a61..9280cb666 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -317,7 +317,8 @@ type DenebSignedBlockContents* = object signed_block*: deneb.SignedBeaconBlock - signed_blob_sidecars*: List[SignedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK] + kzg_proofs*: deneb.KzgProofs + blobs*: deneb.Blobs RestPublishedSignedBlockContents* = object case kind*: ConsensusFork @@ -339,7 +340,8 @@ type DenebBlockContents* = object `block`*: deneb.BeaconBlock - blob_sidecars*: List[BlobSidecar, Limit MAX_BLOBS_PER_BLOCK] + kzg_proofs*: deneb.KzgProofs + blobs*: deneb.Blobs ProduceBlockResponseV2* = object case kind*: ConsensusFork diff --git a/beacon_chain/spec/forks.nim b/beacon_chain/spec/forks.nim index 1360cd2f0..8dc3d39ad 100644 --- a/beacon_chain/spec/forks.nim +++ b/beacon_chain/spec/forks.nim @@ -905,8 +905,9 @@ template withStateAndBlck*( func toBeaconBlockHeader*( blck: SomeForkyBeaconBlock | - capella_mev.BlindedBeaconBlock | deneb_mev.BlindedBeaconBlock): - BeaconBlockHeader = + capella_mev.BlindedBeaconBlock | + deneb_mev.BlindedBeaconBlock +): BeaconBlockHeader = ## Reduce a given `BeaconBlock` to its `BeaconBlockHeader`. BeaconBlockHeader( slot: blck.slot, @@ -918,7 +919,7 @@ func toBeaconBlockHeader*( template toBeaconBlockHeader*( blck: SomeForkySignedBeaconBlock): BeaconBlockHeader = ## Reduce a given `SignedBeaconBlock` to its `BeaconBlockHeader`. - blck.message.toBeaconBlockHeader + blck.message.toBeaconBlockHeader() template toBeaconBlockHeader*( blckParam: ForkedMsgTrustedSignedBeaconBlock | @@ -926,6 +927,16 @@ template toBeaconBlockHeader*( ## Reduce a given signed beacon block to its `BeaconBlockHeader`. withBlck(blckParam): forkyBlck.toBeaconBlockHeader() +func toSignedBeaconBlockHeader*( + signedBlock: SomeForkySignedBeaconBlock | + capella_mev.SignedBlindedBeaconBlock | + deneb_mev.SignedBlindedBeaconBlock +): SignedBeaconBlockHeader = + ## Reduce a given `SignedBeaconBlock` to its `SignedBeaconBlockHeader`. + SignedBeaconBlockHeader( + message: signedBlock.message.toBeaconBlockHeader(), + signature: signedBlock.signature) + func genesisFork*(cfg: RuntimeConfig): Fork = Fork( previous_version: cfg.GENESIS_FORK_VERSION, diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index b392d612e..dc6c44846 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -211,6 +211,54 @@ func has_flag*(flags: ParticipationFlags, flag_index: TimelyFlag): bool = let flag = ParticipationFlags(1'u8 shl ord(flag_index)) (flags and flag) == flag +func create_blob_sidecars*( + forkyBlck: deneb.SignedBeaconBlock, + kzg_proofs: KzgProofs, + blobs: Blobs): seq[BlobSidecar] = + template kzg_commitments: untyped = + forkyBlck.message.body.blob_kzg_commitments + doAssert kzg_proofs.len == blobs.len + doAssert kzg_proofs.len == kzg_commitments.len + + var res = newSeqOfCap[BlobSidecar](blobs.len) + let signedBlockHeader = forkyBlck.toSignedBeaconBlockHeader() + for i in 0 ..< blobs.lenu64: + var sidecar = BlobSidecar( + index: i, + blob: blobs[i], + kzg_commitment: kzg_commitments[i], + kzg_proof: kzg_proofs[i], + signed_block_header: signedBlockHeader) + forkyBlck.message.body.build_proof( + kzg_commitment_inclusion_proof_gindex(i), + sidecar.kzg_commitment_inclusion_proof).expect("Valid gindex") + res.add(sidecar) + res + +func create_blob_sidecars*( + forkyBlck: deneb_mev.SignedBlindedBeaconBlock, + kzg_proofs: KzgProofs, + blob_roots: BlobRoots): seq[BlindedBlobSidecar] = + template kzg_commitments: untyped = + forkyBlck.message.body.blob_kzg_commitments + doAssert kzg_proofs.len == blob_roots.len + doAssert kzg_proofs.len == kzg_commitments.len + + var res = newSeqOfCap[BlindedBlobSidecar](blob_roots.len) + let signedBlockHeader = forkyBlck.toSignedBeaconBlockHeader() + for i in 0 ..< blob_roots.lenu64: + var sidecar = BlindedBlobSidecar( + index: i, + blob_root: blob_roots[i], + kzg_commitment: kzg_commitments[i], + kzg_proof: kzg_proofs[i], + signed_block_header: signedBlockHeader) + forkyBlck.message.body.build_proof( + kzg_commitment_inclusion_proof_gindex(i), + sidecar.kzg_commitment_inclusion_proof).expect("Valid gindex") + res.add(sidecar) + res + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_sync_committee_update template is_sync_committee_update*(update: SomeForkyLightClientUpdate): bool = when update is SomeForkyLightClientUpdateWithSyncCommittee: diff --git a/beacon_chain/spec/mev/deneb_mev.nim b/beacon_chain/spec/mev/deneb_mev.nim index 736ed0bf7..f64f87860 100644 --- a/beacon_chain/spec/mev/deneb_mev.nim +++ b/beacon_chain/spec/mev/deneb_mev.nim @@ -69,25 +69,18 @@ type # https://github.com/ethereum/builder-specs/blob/534e4f81276b8346d785ed9aba12c4c74b927ec6/specs/deneb/builder.md#blindedblobsidecar BlindedBlobSidecar* = object - block_root*: Eth2Digest index*: uint64 - slot*: uint64 - block_parent_root*: Eth2Digest - proposer_index*: uint64 blob_root*: Eth2Digest kzg_commitment*: KZGCommitment kzg_proof*: KZGProof - - # https://github.com/ethereum/builder-specs/blob/534e4f81276b8346d785ed9aba12c4c74b927ec6/specs/deneb/builder.md#signedblindedblobsidecar - SignedBlindedBlobSidecar* = object - message*: BlindedBlobSidecar - signature*: ValidatorSig + signed_block_header*: SignedBeaconBlockHeader + kzg_commitment_inclusion_proof*: + array[KZG_COMMITMENT_INCLUSION_PROOF_DEPTH, Eth2Digest] # https://github.com/ethereum/builder-specs/blob/534e4f81276b8346d785ed9aba12c4c74b927ec6/specs/deneb/builder.md#signedblindedblockcontents SignedBlindedBeaconBlockContents* = object signed_blinded_block*: deneb_mev.SignedBlindedBeaconBlock - signed_blinded_blob_sidecars*: - List[SignedBlindedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK] + blinded_blob_sidecars*: List[BlindedBlobSidecar, Limit MAX_BLOBS_PER_BLOCK] # https://github.com/ethereum/builder-specs/blob/534e4f81276b8346d785ed9aba12c4c74b927ec6/specs/deneb/builder.md#executionpayloadandblobsbundle ExecutionPayloadAndBlobsBundle* = object diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 1aa318537..417c75122 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -88,15 +88,6 @@ func compute_block_signing_root*( fork, DOMAIN_BEACON_PROPOSER, epoch, genesis_validators_root) compute_signing_root(blck, domain) -func compute_blob_signing_root( - fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blob: BlindedBlobSidecar | BlobSidecar): Eth2Digest = - let - epoch = epoch(slot) - domain = get_domain(fork, DOMAIN_BLOB_SIDECAR, epoch, - genesis_validators_root) - compute_signing_root(blob, domain) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/validator.md#signature func get_block_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, @@ -106,16 +97,6 @@ func get_block_signature*( blsSign(privkey, signing_root.data) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/validator.md#constructing-the-signedblobsidecars -proc get_blob_sidecar_signature*( - fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blob: BlindedBlobSidecar | BlobSidecar, privkey: ValidatorPrivKey): - CookedSig = - let signing_root = compute_blob_signing_root( - fork, genesis_validators_root, slot, blob) - - blsSign(privkey, signing_root.data) - proc verify_block_signature*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, blck: Eth2Digest | SomeForkyBeaconBlock | BeaconBlockHeader, @@ -127,17 +108,6 @@ proc verify_block_signature*( blsVerify(pubkey, signing_root.data, signature) -proc verify_blob_signature*( - fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, - blobSidecar: BlobSidecar, - pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool = - withTrust(signature): - let - signing_root = compute_blob_signing_root( - fork, genesis_validators_root, slot, blobSidecar) - - blsVerify(pubkey, signing_root.data, signature) - func compute_aggregate_and_proof_signing_root*( fork: Fork, genesis_validators_root: Eth2Digest, aggregate_and_proof: AggregateAndProof): Eth2Digest = diff --git a/beacon_chain/sync/request_manager.nim b/beacon_chain/sync/request_manager.nim index d37a13d50..045943e44 100644 --- a/beacon_chain/sync/request_manager.nim +++ b/beacon_chain/sync/request_manager.nim @@ -93,9 +93,10 @@ proc checkResponse(idList: seq[BlobIdentifier], if len(blobs) > len(idList): return false for blob in blobs: + let block_root = hash_tree_root(blob.signed_block_header.message) var found = false for id in idList: - if id.block_root == blob.block_root and + if id.block_root == block_root and id.index == blob.index: found = true break @@ -204,8 +205,9 @@ proc fetchBlobsFromNetwork(self: RequestManager, self.blobQuarantine[].put(b) var curRoot: Eth2Digest for b in ublobs: - if b.block_root != curRoot: - curRoot = b.block_root + let block_root = hash_tree_root(b.signed_block_header.message) + if block_root != curRoot: + curRoot = block_root if (let o = self.quarantine[].popBlobless(curRoot); o.isSome): let b = o.unsafeGet() discard await self.blockVerifier(ForkedSignedBeaconBlock.init(b), false) diff --git a/beacon_chain/sync/sync_manager.nim b/beacon_chain/sync/sync_manager.nim index 2bd07a20a..c0c35567e 100644 --- a/beacon_chain/sync/sync_manager.nim +++ b/beacon_chain/sync/sync_manager.nim @@ -247,9 +247,9 @@ func groupBlobs*[T](req: SyncRequest[T], # reached end of blobs, have more blobless blocks break for blob in blobs[blobCursor..len(blobs)-1]: - if blob.slot < slot: + if blob.signed_block_header.message.slot < slot: return Result[seq[BlobSidecars], string].err "invalid blob sequence" - if blob.slot==slot: + if blob.signed_block_header.message.slot == slot: grouped[i].add(blob) blobCursor = blobCursor + 1 i = i + 1 @@ -439,7 +439,7 @@ proc syncStep[A, B](man: SyncManager[A, B], index: int, peer: A) {.async.} = blobs_map = blobSmap, request = req if len(blobData) > 0: - let slots = mapIt(blobData, it[].slot) + let slots = mapIt(blobData, it[].signed_block_header.message.slot) let uniqueSlots = foldl(slots, combine(a, b), @[slots[0]]) if not(checkResponse(req, uniqueSlots)): peer.updateScore(PeerScoreBadResponse) @@ -464,7 +464,8 @@ proc syncStep[A, B](man: SyncManager[A, B], index: int, peer: A) {.async.} = man.queue.push(req) return for i, blk in blockData: - if len(blobs[i]) > 0 and blk[].slot != blobs[i][0].slot: + if len(blobs[i]) > 0 and blk[].slot != + blobs[i][0].signed_block_header.message.slot: peer.updateScore(PeerScoreNoValues) man.queue.push(req) debug "block and blobs data have inconsistent slots" diff --git a/beacon_chain/sync/sync_queue.nim b/beacon_chain/sync/sync_queue.nim index 9e1f306cb..fb2fbb762 100644 --- a/beacon_chain/sync/sync_queue.nim +++ b/beacon_chain/sync/sync_queue.nim @@ -119,9 +119,9 @@ proc getShortMap*[T](req: SyncRequest[T], if cur >= lenu64(data): res.add('|') continue - if slot == data[cur].slot: + if slot == data[cur].signed_block_header.message.slot: for k in cur..= lenu64(data) or slot != data[k].slot: + if k >= lenu64(data) or slot != data[k].signed_block_header.message.slot: res.add('|') break else: diff --git a/beacon_chain/validator_client/block_service.nim b/beacon_chain/validator_client/block_service.nim index 995d3c377..a05464777 100644 --- a/beacon_chain/validator_client/block_service.nim +++ b/beacon_chain/validator_client/block_service.nim @@ -21,12 +21,11 @@ const logScope: service = ServiceName type - BlobList = List[BlobSidecar, Limit MAX_BLOBS_PER_BLOCK] - PreparedBeaconBlock = object blockRoot*: Eth2Digest data*: ForkedBeaconBlock - blobsOpt*: Opt[BlobList] + kzgProofsOpt*: Opt[deneb.KzgProofs] + blobsOpt*: Opt[deneb.Blobs] PreparedBlindedBeaconBlock = object blockRoot*: Eth2Digest @@ -66,27 +65,34 @@ proc produceBlock( let blck = produceBlockResponse.phase0Data return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck), data: ForkedBeaconBlock.init(blck), - blobsOpt: Opt.none(BlobList))) + kzgProofsOpt: Opt.none(deneb.KzgProofs), + blobsOpt: Opt.none(deneb.Blobs))) of ConsensusFork.Altair: let blck = produceBlockResponse.altairData return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck), data: ForkedBeaconBlock.init(blck), - blobsOpt: Opt.none(BlobList))) + kzgProofsOpt: Opt.none(deneb.KzgProofs), + blobsOpt: Opt.none(deneb.Blobs))) of ConsensusFork.Bellatrix: let blck = produceBlockResponse.bellatrixData return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck), data: ForkedBeaconBlock.init(blck), - blobsOpt: Opt.none(BlobList))) + kzgProofsOpt: Opt.none(deneb.KzgProofs), + blobsOpt: Opt.none(deneb.Blobs))) of ConsensusFork.Capella: let blck = produceBlockResponse.capellaData return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck), data: ForkedBeaconBlock.init(blck), - blobsOpt: Opt.none(BlobList))) + kzgProofsOpt: Opt.none(deneb.KzgProofs), + blobsOpt: Opt.none(deneb.Blobs))) of ConsensusFork.Deneb: - let blck = produceBlockResponse.denebData.`block` - let blobs = produceBlockResponse.denebData.blob_sidecars + let + blck = produceBlockResponse.denebData.`block` + kzgProofs = produceBlockResponse.denebData.kzg_proofs + blobs = produceBlockResponse.denebData.blobs return Opt.some(PreparedBeaconBlock(blockRoot: hash_tree_root(blck), data: ForkedBeaconBlock.init(blck), + kzgProofsOpt: Opt.some(kzgProofs), blobsOpt: Opt.some(blobs))) proc produceBlindedBlock( @@ -388,30 +394,14 @@ proc publishBlock(vc: ValidatorClientRef, currentSlot, slot: Slot, root: preparedBlock.blockRoot, signature: signature)) of ConsensusFork.Deneb: - let blobs = preparedBlock.blobsOpt.get() - var signed: seq[SignedBlobSidecar] = @[] - for i in 0..= ConsensusFork.Deneb: - var sidecars: seq[BlobSidecar] - let bundle = collectedBids.engineBlockFut.read.get().blobsBundleOpt.get - let (blobs, commitments, proofs) = ( - bundle.blobs, bundle.commitments, bundle.proofs) - for i in 0..= ConsensusFork.Deneb: + template blobsBundle: untyped = + collectedBids.engineBlockFut.read.get.blobsBundleOpt.get + Opt.some(signedBlock.create_blob_sidecars( + blobsBundle.proofs, blobsBundle.blobs)) else: - static: doAssert "Unknown SignedBeaconBlock type" - signedBlobs = - when forkyBlck is phase0.BeaconBlock or - forkyBlck is altair.BeaconBlock or - forkyBlck is bellatrix.BeaconBlock or - forkyBlck is capella.BeaconBlock: - Opt.none(SignedBlobSidecars) - elif forkyBlck is deneb.BeaconBlock: - var signed: seq[SignedBlobSidecar] - let blobSidecars = blobSidecarsOpt.get() - for i in 0.. 0 or kzgCommits.len > 0: - let res = validate_blobs(kzgCommits, blobs.mapIt(it.message.blob), - blobs.mapIt(it.message.kzg_proof)) + let res = validate_blobs(kzgCommits, blobs.mapIt(it.blob), + blobs.mapIt(it.kzg_proof)) if res.isErr(): warn "blobs failed validation", blockRoot = shortLog(blck.root), @@ -145,26 +141,26 @@ proc routeSignedBeaconBlock*( blockRoot = shortLog(blck.root), blck = shortLog(blck.message), signature = shortLog(blck.signature), error = res.error() - var blobs = Opt.none(seq[ref BlobSidecar]) + var blobRefs = Opt.none(BlobSidecars) if blobsOpt.isSome(): - let signedBlobs = blobsOpt.get() - var workers = newSeq[Future[SendResult]](signedBlobs.len) - for i in 0.. Date: Mon, 6 Nov 2023 12:10:36 +0100 Subject: [PATCH 30/45] do not download Holesky genesis on `git clone` (#5573) Holesky genesis.ssz file may be unavailable due to quota limits on `eth-clients/holesky`; do not download it by default during checkout. Nimbus will download it on first startup from a mirror instead. --- Makefile | 4 ++-- ci/Jenkinsfile.benchmarks | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a11259c6b..26c29d38a 100644 --- a/Makefile +++ b/Makefile @@ -118,9 +118,9 @@ ifneq ($(OS), Windows_NT) PLATFORM_SPECIFIC_TARGETS += gnosis-build endif -# We don't need the `vendor/holesky/public-keys/all.txt` file but fetching it +# We don't need these `vendor/holesky` files but fetching them # may trigger 'This repository is over its data quota' from GitHub -GIT_SUBMODULE_CONFIG := -c lfs.fetchexclude=/public-keys/all.txt +GIT_SUBMODULE_CONFIG := -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz,/custom_config_data/parsedBeaconState.json ifeq ($(NIM_PARAMS),) # "variables.mk" was not included, so we update the submodules. diff --git a/ci/Jenkinsfile.benchmarks b/ci/Jenkinsfile.benchmarks index e58492590..481b84b42 100644 --- a/ci/Jenkinsfile.benchmarks +++ b/ci/Jenkinsfile.benchmarks @@ -23,7 +23,7 @@ node("metal") { /* source code checkout */ checkout scm /* we need to update the submodules before caching kicks in */ - sh "git -c lfs.fetchexclude=/public-keys/all.txt submodule update --init --recursive" + sh "git -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz,/custom_config_data/parsedBeaconState.json submodule update --init --recursive" } stage("Build") { From 49c851109ea41e9fcb59d4adeb7187ee4eaf6cb5 Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Mon, 6 Nov 2023 16:40:44 +0200 Subject: [PATCH 31/45] VC: Add pruning slashing database. (#5551) * Add slashing database pruning to VC. Fix GetBlockHeaderResponse object declaration (spec has been changed). * Switch to getFinalizedBlockHeader instead. * Fix proper sign. Add statements. Show pruning log statement only when pruning happens. * Optimize and remove debugging helpers. --- .../eth2_apis/eth2_rest_serialization.nim | 1 + beacon_chain/spec/eth2_apis/rest_types.nim | 7 +- beacon_chain/validator_client/api.nim | 89 +++++++++++++++++++ beacon_chain/validator_client/common.nim | 3 + .../validator_client/duties_service.nim | 75 +++++++++++++++- 5 files changed, 173 insertions(+), 2 deletions(-) diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 1fd672f1a..546bb2d38 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -130,6 +130,7 @@ type DataRootEnclosedObject | DataOptimisticObject | DataVersionEnclosedObject | + DataOptimisticAndFinalizedObject | GetBlockV2Response | GetDistributedKeystoresResponse | GetKeystoresResponse | diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index 9280cb666..b442a495c 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -395,6 +395,11 @@ type data*: T execution_optimistic*: Option[bool] + DataOptimisticAndFinalizedObject*[T] = object + data*: T + execution_optimistic*: Option[bool] + finalized*: Option[bool] + ForkedSignedBlockHeader* = object message*: uint32 # message offset signature*: ValidatorSig @@ -515,7 +520,7 @@ type GetAggregatedAttestationResponse* = DataEnclosedObject[Attestation] GetAttesterDutiesResponse* = DataRootEnclosedObject[seq[RestAttesterDuty]] GetBlockAttestationsResponse* = DataEnclosedObject[seq[Attestation]] - GetBlockHeaderResponse* = DataOptimisticObject[RestBlockHeaderInfo] + GetBlockHeaderResponse* = DataOptimisticAndFinalizedObject[RestBlockHeaderInfo] GetBlockHeadersResponse* = DataEnclosedObject[seq[RestBlockHeaderInfo]] GetBlockRootResponse* = DataOptimisticObject[RestRoot] GetDebugChainHeadsResponse* = DataEnclosedObject[seq[RestChainHead]] diff --git a/beacon_chain/validator_client/api.nim b/beacon_chain/validator_client/api.nim index 89855588b..9304a73aa 100644 --- a/beacon_chain/validator_client/api.nim +++ b/beacon_chain/validator_client/api.nim @@ -2570,3 +2570,92 @@ proc getValidatorsLiveness*( res return GetValidatorsLivenessResponse(data: response) + +proc getFinalizedBlockHeader*( + vc: ValidatorClientRef, + ): Future[Opt[GetBlockHeaderResponse]] {.async.} = + const RequestName = "getFinalizedBlockHeader" + + let + blockIdent = BlockIdent.init(BlockIdentType.Finalized) + resp = vc.onceToAll(RestPlainResponse, + SlotDuration, + ViableNodeStatus, + {BeaconNodeRole.Duties}, + getBlockHeaderPlain(it, blockIdent)) + case resp.status + of ApiOperation.Timeout: + debug "Unable to obtain finalized block header in time", + timeout = SlotDuration + return Opt.none(GetBlockHeaderResponse) + of ApiOperation.Interrupt: + debug "Finalized block header request was interrupted" + return Opt.none(GetBlockHeaderResponse) + of ApiOperation.Failure: + debug "Unexpected error happened while trying to get finalized block header" + return Opt.none(GetBlockHeaderResponse) + of ApiOperation.Success: + var oldestBlockHeader: GetBlockHeaderResponse + var oldestEpoch: Opt[Epoch] + for apiResponse in resp.data: + if apiResponse.data.isErr(): + debug "Unable to get finalized block header", + endpoint = apiResponse.node, error = apiResponse.data.error + else: + let response = apiResponse.data.get() + case response.status + of 200: + let res = decodeBytes(GetBlockHeaderResponse, + response.data, response.contentType) + if res.isOk(): + let + rdata = res.get() + epoch = rdata.data.header.message.slot.epoch() + if oldestEpoch.get(FAR_FUTURE_EPOCH) > epoch: + oldestEpoch = Opt.some(epoch) + oldestBlockHeader = rdata + else: + let failure = ApiNodeFailure.init( + ApiFailure.UnexpectedResponse, RequestName, + apiResponse.node, response.status, $res.error) + # We do not update beacon node's status anymore because of + # issue #5377. + debug ResponseDecodeError, reason = getFailureReason(failure) + continue + of 400: + let failure = ApiNodeFailure.init( + ApiFailure.Invalid, RequestName, + apiResponse.node, response.status, response.getErrorMessage()) + # We do not update beacon node's status anymore because of + # issue #5377. + debug ResponseInvalidError, reason = getFailureReason(failure) + continue + of 404: + let failure = ApiNodeFailure.init( + ApiFailure.NotFound, RequestName, + apiResponse.node, response.status, response.getErrorMessage()) + # We do not update beacon node's status anymore because of + # issue #5377. + debug ResponseNotFoundError, reason = getFailureReason(failure) + continue + of 500: + let failure = ApiNodeFailure.init( + ApiFailure.Internal, RequestName, + apiResponse.node, response.status, response.getErrorMessage()) + # We do not update beacon node's status anymore because of + # issue #5377. + debug ResponseInternalError, reason = getFailureReason(failure) + continue + else: + let failure = ApiNodeFailure.init( + ApiFailure.UnexpectedCode, RequestName, + apiResponse.node, response.status, response.getErrorMessage()) + # We do not update beacon node's status anymore because of + # issue #5377. + debug ResponseUnexpectedError, reason = getFailureReason(failure) + continue + + if oldestEpoch.isSome(): + return Opt.some(oldestBlockHeader) + else: + return Opt.none(GetBlockHeaderResponse) diff --git a/beacon_chain/validator_client/common.nim b/beacon_chain/validator_client/common.nim index eb4a50557..2d6dd0767 100644 --- a/beacon_chain/validator_client/common.nim +++ b/beacon_chain/validator_client/common.nim @@ -65,7 +65,9 @@ type DutiesServiceRef* = ref object of ClientServiceRef pollingAttesterDutiesTask*: Future[void] pollingSyncDutiesTask*: Future[void] + pruneSlashingDatabaseTask*: Future[void] syncSubscriptionEpoch*: Opt[Epoch] + lastSlashingEpoch*: Opt[Epoch] FallbackServiceRef* = ref object of ClientServiceRef changesEvent*: AsyncEvent @@ -229,6 +231,7 @@ type blocksSeen*: Table[Slot, BlockDataItem] rootsSeen*: Table[Eth2Digest, Slot] processingDelay*: Opt[Duration] + finalizedEpoch*: Opt[Epoch] rng*: ref HmacDrbgContext ApiStrategyKind* {.pure.} = enum diff --git a/beacon_chain/validator_client/duties_service.nim b/beacon_chain/validator_client/duties_service.nim index fe5a6a431..561f1bb8a 100644 --- a/beacon_chain/validator_client/duties_service.nim +++ b/beacon_chain/validator_client/duties_service.nim @@ -19,7 +19,8 @@ logScope: service = ServiceName type DutiesServiceLoop* = enum AttesterLoop, ProposerLoop, IndicesLoop, SyncCommitteeLoop, - ProposerPreparationLoop, ValidatorRegisterLoop, DynamicValidatorsLoop + ProposerPreparationLoop, ValidatorRegisterLoop, DynamicValidatorsLoop, + SlashPruningLoop chronicles.formatIt(DutiesServiceLoop): case it @@ -30,6 +31,7 @@ chronicles.formatIt(DutiesServiceLoop): of ProposerPreparationLoop: "proposer_prepare_loop" of ValidatorRegisterLoop: "validator_register_loop" of DynamicValidatorsLoop: "dynamic_validators_loop" + of SlashPruningLoop: "slashing_pruning_loop" proc checkDuty(duty: RestAttesterDuty): bool = (duty.committee_length <= MAX_VALIDATORS_PER_COMMITTEE) and @@ -677,6 +679,70 @@ proc syncCommitteeDutiesLoop(service: DutiesServiceRef) {.async.} = # Spawning new attestation duties task. service.pollingSyncDutiesTask = service.pollForSyncCommitteeDuties() +proc getNextEpochMiddleSlot(vc: ValidatorClientRef): Slot = + let + middleSlot = Slot(SLOTS_PER_EPOCH div 2) + currentSlot = vc.beaconClock.now().slotOrZero() + slotInEpoch = currentSlot.since_epoch_start() + + if slotInEpoch >= middleSlot: + (currentSlot.epoch + 1'u64).start_slot() + uint64(middleSlot) + else: + currentSlot + (uint64(middleSlot) - uint64(slotInEpoch)) + +proc pruneSlashingDatabase(service: DutiesServiceRef) {.async.} = + let + vc = service.client + currentSlot = vc.beaconClock.now().slotOrZero() + startTime = Moment.now() + blockHeader = + try: + await vc.getFinalizedBlockHeader() + except CancelledError as exc: + debug "Finalized block header request was interrupted", + slot = currentSlot + raise exc + except CatchableError as exc: + error "Unexpected error occured while requesting " & + "finalized block header", slot = currentSlot, + err_name = exc.name, err_msg = exc.msg + Opt.none(GetBlockHeaderResponse) + checkpointTime = Moment.now() + if blockHeader.isSome(): + let epoch = blockHeader.get().data.header.message.slot.epoch + vc.finalizedEpoch = Opt.some(epoch) + if service.lastSlashingEpoch.get(FAR_FUTURE_EPOCH) != epoch: + vc.attachedValidators[] + .slashingProtection + .pruneAfterFinalization(epoch) + service.lastSlashingEpoch = Opt.some(epoch) + let finishTime = Moment.now() + debug "Slashing database has been pruned", slot = currentSlot, + epoch = currentSlot.epoch(), + finalized_epoch = epoch, + elapsed_time = (finishTime - startTime), + pruning_time = (finishTime - checkpointTime) + +proc slashingDatabasePruningLoop(service: DutiesServiceRef) {.async.} = + let vc = service.client + debug "Slashing database pruning loop is waiting for initialization" + await allFutures( + vc.preGenesisEvent.wait(), + vc.indicesAvailable.wait(), + vc.forksAvailable.wait() + ) + doAssert(len(vc.forks) > 0, "Fork schedule must not be empty at this point") + while true: + let slot = await vc.checkedWaitForSlot(vc.getNextEpochMiddleSlot(), + aggregateSlotOffset, false) + if slot.isNone(): + continue + + if not(isNil(service.pruneSlashingDatabaseTask)) and + not(service.pruneSlashingDatabaseTask.finished()): + await cancelAndWait(service.pruneSlashingDatabaseTask) + service.pruneSlashingDatabaseTask = service.pruneSlashingDatabase() + template checkAndRestart(serviceLoop: DutiesServiceLoop, future: Future[void], body: untyped): untyped = if future.finished(): @@ -715,6 +781,7 @@ proc mainLoop(service: DutiesServiceRef) {.async.} = else: debug "Dynamic validators update loop disabled" @[] + slashPruningFut = service.slashingDatabasePruningLoop() web3SignerUrls = vc.config.web3SignerUrls while true: @@ -729,6 +796,7 @@ proc mainLoop(service: DutiesServiceRef) {.async.} = FutureBase(indicesFut), FutureBase(syncFut), FutureBase(prepareFut), + FutureBase(slashPruningFut) ] for fut in dynamicFuts: futures.add fut @@ -749,6 +817,8 @@ proc mainLoop(service: DutiesServiceRef) {.async.} = service.dynamicValidatorsLoop( web3SignerUrls[i], vc.config.web3signerUpdateInterval)) + checkAndRestart(SlashPruningLoop, slashPruningFut, + service.slashingDatabasePruningLoop()) false except CancelledError: debug "Service interrupted" @@ -774,6 +844,9 @@ proc mainLoop(service: DutiesServiceRef) {.async.} = if not(isNil(service.pollingSyncDutiesTask)) and not(service.pollingSyncDutiesTask.finished()): pending.add(service.pollingSyncDutiesTask.cancelAndWait()) + if not(isNil(service.pruneSlashingDatabaseTask)) and + not(service.pruneSlashingDatabaseTask.finished()): + pending.add(service.pruneSlashingDatabaseTask.cancelAndWait()) await allFutures(pending) true except CatchableError as exc: From 8a98de6bd098d30c1e2218172221cfb185cd44db Mon Sep 17 00:00:00 2001 From: tersec Date: Tue, 7 Nov 2023 05:12:16 +0100 Subject: [PATCH 32/45] bump holesky to remove large, extraneous JSON file (#5574) --- vendor/holesky | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/holesky b/vendor/holesky index ea39b9006..bd43fac06 160000 --- a/vendor/holesky +++ b/vendor/holesky @@ -1 +1 @@ -Subproject commit ea39b9006210848e13f28d92e12a30548cecd41d +Subproject commit bd43fac06847124d4dadcc994401a4993b5fe9d1 From aa6c13cd67a788c26c8b02597d7d5a9718978e2a Mon Sep 17 00:00:00 2001 From: tersec Date: Tue, 7 Nov 2023 16:52:30 +0100 Subject: [PATCH 33/45] use newer geth testnet binary directory names (#5575) * use newer geth testnet binary directory names * linting; Geth requires merged genesis --- .github/workflows/ci.yml | 2 +- scripts/execution_genesis.json.template | 11 +++++++---- scripts/geth_binaries.sh | 19 ++++++++++++------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1031e2047..f8906befb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -215,7 +215,7 @@ jobs: if: ${{ !cancelled() }} && github.event_name == 'pull_request' run: | excluded_files="config.yaml" - excluded_extensions="ans|json|md|png|service|ssz|txt" + excluded_extensions="ans|json|json\\.template|md|png|service|ssz|txt" current_year=$(date +"%Y") outdated_files=() diff --git a/scripts/execution_genesis.json.template b/scripts/execution_genesis.json.template index 3c4e585d6..574c36392 100644 --- a/scripts/execution_genesis.json.template +++ b/scripts/execution_genesis.json.template @@ -12,15 +12,18 @@ "muirGlacierBlock":0, "berlinBlock":0, "londonBlock":0, - "shanghaiTime": SHANGHAI_FORK_TIME, - "shardingForkTime": SHARDING_FORK_TIME, - "terminalTotalDifficulty":0 + "shanghaiTime": 0, + "shardingForkTime": 0, + "mergeForkBlock":0, + "mergeNetsplitBlock":0, + "terminalTotalDifficulty":0, + "terminalTotalDifficultyPassed":true }, "nonce":"0x42", "timestamp":"0x00", "extraData":"", "gasLimit":"0x1C9C380", - "difficulty":"0x400000000", + "difficulty":"0x000000000", "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase":"0x0000000000000000000000000000000000000000", "alloc":{ diff --git a/scripts/geth_binaries.sh b/scripts/geth_binaries.sh index cc536fa4f..2d53d2956 100644 --- a/scripts/geth_binaries.sh +++ b/scripts/geth_binaries.sh @@ -1,3 +1,10 @@ +# beacon_chain +# Copyright (c) 2023 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. + if [ -z "${GETH_BINARIES_SOURCED:-}" ]; then GETH_BINARIES_SOURCED=1 @@ -9,12 +16,12 @@ source "${SCRIPTS_DIR}/bash_utils.sh" : ${CURL_BINARY:="curl"} : ${STABLE_GETH_BINARY:="${BUILD_DIR}/downloads/geth$EXE_EXTENSION"} -: ${GETH_CAPELLA_BINARY:="${BUILD_DIR}/downloads/geth_capella$EXE_EXTENSION"} +: ${GETH_CAPELLA_BINARY:="$STABLE_GETH_BINARY"} : ${GETH_DENEB_BINARY:="${BUILD_DIR}/downloads/geth_deneb$EXE_EXTENSION"} download_geth_stable() { if [[ ! -e "${STABLE_GETH_BINARY}" ]]; then - GETH_VERSION="1.10.26-e5eb32ac" + GETH_VERSION="1.13.5-unstable-f20b334f" # not actually a stable version but first with macOS ARM64 GETH_URL="https://gethstore.blob.core.windows.net/builds/" case "${OS}-${ARCH}" in @@ -28,9 +35,7 @@ download_geth_stable() { GETH_TARBALL="geth-darwin-amd64-${GETH_VERSION}.tar.gz" ;; macos-arm64|macos-aarch64) - # There is no official binary for macOS/ARM at the moment - # The AMD64 binary should work under Rosetta - GETH_TARBALL="geth-darwin-amd64-${GETH_VERSION}.tar.gz" + GETH_TARBALL="geth-darwin-arm64-${GETH_VERSION}.tar.gz" ;; windows-amd64|windows-x86_64) GETH_TARBALL="geth-windows-amd64-${GETH_VERSION}.zip" @@ -102,11 +107,11 @@ download_status_geth_binary() { } download_geth_capella() { - download_status_geth_binary withdrawals-timestamp "$GETH_CAPELLA_BINARY" + download_geth_stable } download_geth_deneb() { - download_status_geth_binary eip-4844 "$GETH_DENEB_BINARY" + download_status_geth_binary deneb "$GETH_DENEB_BINARY" } fi From 7e3aeaea0942a0e7e78dd3e9dacd823252bdd250 Mon Sep 17 00:00:00 2001 From: tersec Date: Wed, 8 Nov 2023 05:28:03 +0000 Subject: [PATCH 34/45] automated consensus spec URL updating to v1.4.0-beta.4 (#5577) --- beacon_chain/beacon_chain_db_immutable.nim | 10 +- beacon_chain/consensus_object_pools/README.md | 10 +- .../attestation_pool.nim | 2 +- .../consensus_object_pools/blockchain_dag.nim | 6 +- .../consensus_object_pools/spec_cache.nim | 12 +-- beacon_chain/deposits.nim | 2 +- beacon_chain/el/merkle_minimal.nim | 2 +- beacon_chain/fork_choice/fork_choice.nim | 2 +- beacon_chain/gossip_processing/README.md | 2 +- .../gossip_processing/block_processor.nim | 2 +- .../gossip_processing/eth2_processor.nim | 4 +- .../gossip_processing/gossip_validation.nim | 8 +- .../light_client_processor.nim | 4 +- beacon_chain/libnimbus_lc/libnimbus_lc.nim | 36 +++---- beacon_chain/light_client.nim | 4 +- beacon_chain/networking/eth2_network.nim | 8 +- beacon_chain/nimbus_beacon_node.nim | 8 +- beacon_chain/rpc/rest_config_api.nim | 6 +- beacon_chain/spec/beacon_time.nim | 10 +- beacon_chain/spec/beaconstate.nim | 86 ++++++++-------- beacon_chain/spec/crypto.nim | 6 +- beacon_chain/spec/datatypes/altair.nim | 40 ++++---- beacon_chain/spec/datatypes/base.nim | 48 ++++----- beacon_chain/spec/datatypes/bellatrix.nim | 14 +-- beacon_chain/spec/datatypes/capella.nim | 48 ++++----- beacon_chain/spec/datatypes/constants.nim | 10 +- beacon_chain/spec/datatypes/deneb.nim | 34 +++---- beacon_chain/spec/datatypes/phase0.nim | 8 +- beacon_chain/spec/digest.nim | 2 +- beacon_chain/spec/forks.nim | 4 +- beacon_chain/spec/helpers.nim | 54 +++++----- beacon_chain/spec/keystore.nim | 2 +- beacon_chain/spec/light_client_sync.nim | 10 +- beacon_chain/spec/network.nim | 14 +-- beacon_chain/spec/presets.nim | 2 +- .../spec/presets/mainnet/altair_preset.nim | 2 +- .../spec/presets/mainnet/bellatrix_preset.nim | 2 +- .../spec/presets/mainnet/capella_preset.nim | 2 +- .../spec/presets/minimal/altair_preset.nim | 2 +- .../spec/presets/minimal/bellatrix_preset.nim | 2 +- .../spec/presets/minimal/capella_preset.nim | 2 +- beacon_chain/spec/signatures.nim | 8 +- beacon_chain/spec/signatures_batch.nim | 4 +- beacon_chain/spec/state_transition.nim | 10 +- beacon_chain/spec/state_transition_block.nim | 42 ++++---- beacon_chain/spec/state_transition_epoch.nim | 98 +++++++++---------- beacon_chain/spec/validator.nim | 28 +++--- beacon_chain/spec/weak_subjectivity.nim | 6 +- beacon_chain/statediff.nim | 2 +- beacon_chain/sync/light_client_manager.nim | 10 +- beacon_chain/sync/sync_protocol.nim | 8 +- beacon_chain/trusted_node_sync.nim | 2 +- docs/attestation_flow.md | 6 +- docs/block_flow.md | 2 +- docs/the_nimbus_book/src/el-light-client.md | 4 +- docs/the_nimbus_book/src/light-client-data.md | 2 +- docs/the_nimbus_book/src/start-syncing.md | 2 +- docs/the_nimbus_book/src/web3signer.md | 2 +- ...est_fixture_light_client_sync_protocol.nim | 4 +- tests/testblockutil.nim | 2 +- 60 files changed, 387 insertions(+), 387 deletions(-) diff --git a/beacon_chain/beacon_chain_db_immutable.nim b/beacon_chain/beacon_chain_db_immutable.nim index 5c462715b..2172b83c3 100644 --- a/beacon_chain/beacon_chain_db_immutable.nim +++ b/beacon_chain/beacon_chain_db_immutable.nim @@ -16,7 +16,7 @@ from ./spec/datatypes/capella import from ./spec/datatypes/deneb import ExecutionPayloadHeader type - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconstate # Memory-representation-equivalent to a phase0 BeaconState for in-place SSZ # reading and writing Phase0BeaconStateNoImmutableValidators* = object @@ -69,7 +69,7 @@ type current_justified_checkpoint*: Checkpoint finalized_checkpoint*: Checkpoint - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#beaconstate # Memory-representation-equivalent to an Altair BeaconState for in-place SSZ # reading and writing AltairBeaconStateNoImmutableValidators* = object @@ -127,7 +127,7 @@ type current_sync_committee*: SyncCommittee # [New in Altair] next_sync_committee*: SyncCommittee # [New in Altair] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#beaconstate # Memory-representation-equivalent to a Bellatrix BeaconState for in-place SSZ # reading and writing BellatrixBeaconStateNoImmutableValidators* = object @@ -186,7 +186,7 @@ type # Execution latest_execution_payload_header*: bellatrix.ExecutionPayloadHeader # [New in Bellatrix] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconstate # with indirect changes via ExecutionPayload # Memory-representation-equivalent to a Capella BeaconState for in-place SSZ # reading and writing @@ -258,7 +258,7 @@ type HashList[HistoricalSummary, Limit HISTORICAL_ROOTS_LIMIT] # [New in Capella] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconstate # with indirect changes via ExecutionPayloadHeader # Memory-representation-equivalent to a Deneb BeaconState for in-place SSZ # reading and writing diff --git a/beacon_chain/consensus_object_pools/README.md b/beacon_chain/consensus_object_pools/README.md index fac7c9a04..51dfd33ba 100644 --- a/beacon_chain/consensus_object_pools/README.md +++ b/beacon_chain/consensus_object_pools/README.md @@ -4,12 +4,12 @@ This folder holds the various consensus object pools needed for a blockchain cli Object in those pools have passed the "gossip validation" filter according to specs: -- blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_block -- aggregate attestations: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof +- blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_block +- aggregate attestations: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof - unaggregated attestation: https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id -- voluntary exits: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#voluntary_exit -- Attester slashings: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attester_slashing -- Proposer slashings: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#proposer_slashing +- voluntary exits: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#voluntary_exit +- Attester slashings: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#attester_slashing +- Proposer slashings: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#proposer_slashing After "gossip validation" the consensus objects can be rebroadcasted as they are optimistically good, however for internal processing further verification is needed. For blocks, this means verifying state transition and all contained cryptographic signatures (instead of just the proposer signature). diff --git a/beacon_chain/consensus_object_pools/attestation_pool.nim b/beacon_chain/consensus_object_pools/attestation_pool.nim index 555382371..bdc599ee4 100644 --- a/beacon_chain/consensus_object_pools/attestation_pool.nim +++ b/beacon_chain/consensus_object_pools/attestation_pool.nim @@ -769,7 +769,7 @@ proc getBeaconHead*( finalizedExecutionPayloadHash = pool.dag.loadExecutionBlockHash(pool.dag.finalizedHead.blck) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/fork_choice/safe-block.md#get_safe_execution_payload_hash + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/fork_choice/safe-block.md#get_safe_execution_payload_hash safeBlockRoot = pool.forkChoice.get_safe_beacon_block_root() safeBlock = pool.dag.getBlockRef(safeBlockRoot) safeExecutionPayloadHash = diff --git a/beacon_chain/consensus_object_pools/blockchain_dag.nim b/beacon_chain/consensus_object_pools/blockchain_dag.nim index 4d5c8c6bf..0f37da776 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag.nim @@ -1117,7 +1117,7 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB, # should have `previous_version` set to `current_version` while # this doesn't happen to be the case in network that go through # regular hard-fork upgrades. See for example: - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#testing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#testing if stateFork.current_version != configFork.current_version: error "State from database does not match network, check --network parameter", tail = dag.tail, headRef, stateFork, configFork @@ -1920,7 +1920,7 @@ proc pruneBlocksDAG(dag: ChainDAGRef) = prunedHeads = hlen - dag.heads.len, dagPruneDur = Moment.now() - startTick -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/sync/optimistic.md#helpers +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/sync/optimistic.md#helpers template is_optimistic*(dag: ChainDAGRef, bid: BlockId): bool = let blck = if bid.slot <= dag.finalizedHead.slot: @@ -2610,7 +2610,7 @@ func aggregateAll*( # Aggregation spec requires non-empty collection # - https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04 # Consensus specs require at least one attesting index in attestation - # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation + # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_valid_indexed_attestation return err("aggregate: no attesting keys") let diff --git a/beacon_chain/consensus_object_pools/spec_cache.nim b/beacon_chain/consensus_object_pools/spec_cache.nim index f803e74c6..eb991f025 100644 --- a/beacon_chain/consensus_object_pools/spec_cache.nim +++ b/beacon_chain/consensus_object_pools/spec_cache.nim @@ -25,7 +25,7 @@ logScope: topics = "spec_cache" func count_active_validators*(shufflingRef: ShufflingRef): uint64 = shufflingRef.shuffled_active_validator_indices.lenu64 -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_committee_count_per_slot +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_committee_count_per_slot func get_committee_count_per_slot*(shufflingRef: ShufflingRef): uint64 = get_committee_count_per_slot(count_active_validators(shufflingRef)) @@ -38,7 +38,7 @@ func get_committee_index*(shufflingRef: ShufflingRef, index: uint64): Result[CommitteeIndex, cstring] = check_attestation_index(index, get_committee_count_per_slot(shufflingRef)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_beacon_committee +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_beacon_committee iterator get_beacon_committee*( shufflingRef: ShufflingRef, slot: Slot, committee_index: CommitteeIndex): (int, ValidatorIndex) = @@ -51,7 +51,7 @@ iterator get_beacon_committee*( committees_per_slot * SLOTS_PER_EPOCH ): yield (index_in_committee, idx) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_beacon_committee +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_beacon_committee func get_beacon_committee*( shufflingRef: ShufflingRef, slot: Slot, committee_index: CommitteeIndex): seq[ValidatorIndex] = @@ -64,7 +64,7 @@ func get_beacon_committee*( committees_per_slot * SLOTS_PER_EPOCH ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_beacon_committee +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_beacon_committee func get_beacon_committee_len*( shufflingRef: ShufflingRef, slot: Slot, committee_index: CommitteeIndex): uint64 = ## Return the number of members in the beacon committee at ``slot`` for ``index``. @@ -76,7 +76,7 @@ func get_beacon_committee_len*( committees_per_slot * SLOTS_PER_EPOCH ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_attesting_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_attesting_indices iterator get_attesting_indices*(shufflingRef: ShufflingRef, slot: Slot, committee_index: CommitteeIndex, @@ -155,7 +155,7 @@ func get_attesting_indices_one*(shufflingRef: ShufflingRef, res = some(validator_index) res -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_attesting_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_attesting_indices func get_attesting_indices*(shufflingRef: ShufflingRef, slot: Slot, committee_index: CommitteeIndex, diff --git a/beacon_chain/deposits.nim b/beacon_chain/deposits.nim index ebbc0b2b3..08a22841c 100644 --- a/beacon_chain/deposits.nim +++ b/beacon_chain/deposits.nim @@ -228,7 +228,7 @@ proc restValidatorExit(config: BeaconNodeConf) {.async.} = block: let s = spec.getOrDefault("DENEB_FORK_EPOCH", $FAR_FUTURE_EPOCH) Epoch(Base10.decode(uint64, s).get(uint64(FAR_FUTURE_EPOCH))) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#voluntary-exits + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#voluntary-exits # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.0/specs/deneb/beacon-chain.md#modified-process_voluntary_exit if currentEpoch >= denebForkEpoch: let capellaForkVersion = diff --git a/beacon_chain/el/merkle_minimal.nim b/beacon_chain/el/merkle_minimal.nim index 0d736e30c..0dedab527 100644 --- a/beacon_chain/el/merkle_minimal.nim +++ b/beacon_chain/el/merkle_minimal.nim @@ -7,7 +7,7 @@ {.push raises: [].} -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/tests/core/pyspec/eth2spec/utils/merkle_minimal.py +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/tests/core/pyspec/eth2spec/utils/merkle_minimal.py # Merkle tree helpers # --------------------------------------------------------------- diff --git a/beacon_chain/fork_choice/fork_choice.nim b/beacon_chain/fork_choice/fork_choice.nim index f899991ba..51fa7e5db 100644 --- a/beacon_chain/fork_choice/fork_choice.nim +++ b/beacon_chain/fork_choice/fork_choice.nim @@ -377,7 +377,7 @@ proc get_head*(self: var ForkChoice, self.checkpoints.justified.balances, self.checkpoints.proposer_boost_root) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/fork_choice/safe-block.md#get_safe_beacon_block_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/fork_choice/safe-block.md#get_safe_beacon_block_root func get_safe_beacon_block_root*(self: ForkChoice): Eth2Digest = # Use most recent justified block as a stopgap self.checkpoints.justified.checkpoint.root diff --git a/beacon_chain/gossip_processing/README.md b/beacon_chain/gossip_processing/README.md index cd1cf4613..a201fd98f 100644 --- a/beacon_chain/gossip_processing/README.md +++ b/beacon_chain/gossip_processing/README.md @@ -9,7 +9,7 @@ This folder holds a collection of modules to: Gossip validation is different from consensus verification in particular for blocks. -- Blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_block +- Blocks: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_block - Attestations (aggregated): https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof - Attestations (unaggregated): https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#attestation-subnets - Voluntary exits: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#voluntary_exit diff --git a/beacon_chain/gossip_processing/block_processor.nim b/beacon_chain/gossip_processing/block_processor.nim index b973c1dd9..2b827986b 100644 --- a/beacon_chain/gossip_processing/block_processor.nim +++ b/beacon_chain/gossip_processing/block_processor.nim @@ -804,7 +804,7 @@ proc processBlock( # - MUST NOT optimistically import the block. # - MUST NOT apply the block to the fork choice store. # - MAY queue the block for later processing. - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/sync/optimistic.md#execution-engine-errors + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/sync/optimistic.md#execution-engine-errors await sleepAsync(chronos.seconds(1)) self[].enqueueBlock( entry.src, entry.blck, entry.blobs, entry.resfut, entry.maybeFinalized, diff --git a/beacon_chain/gossip_processing/eth2_processor.nim b/beacon_chain/gossip_processing/eth2_processor.nim index f9a0acf40..a90ed5735 100644 --- a/beacon_chain/gossip_processing/eth2_processor.nim +++ b/beacon_chain/gossip_processing/eth2_processor.nim @@ -652,7 +652,7 @@ proc processSignedContributionAndProof*( err(v.error()) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update proc processLightClientFinalityUpdate*( self: var Eth2Processor, src: MsgSource, finality_update: ForkedLightClientFinalityUpdate @@ -668,7 +668,7 @@ proc processLightClientFinalityUpdate*( beacon_light_client_finality_update_dropped.inc(1, [$v.error[0]]) v -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_optimistic_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_optimistic_update proc processLightClientOptimisticUpdate*( self: var Eth2Processor, src: MsgSource, optimistic_update: ForkedLightClientOptimisticUpdate diff --git a/beacon_chain/gossip_processing/gossip_validation.nim b/beacon_chain/gossip_processing/gossip_validation.nim index 2f0770c6c..8aedab031 100644 --- a/beacon_chain/gossip_processing/gossip_validation.nim +++ b/beacon_chain/gossip_processing/gossip_validation.nim @@ -290,7 +290,7 @@ template validateBeaconBlockBellatrix( # # `is_merge_transition_complete(state)` tests for # `state.latest_execution_payload_header != ExecutionPayloadHeader()`, while - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#block-processing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#block-processing # shows that `state.latest_execution_payload_header` being default or not is # exactly equivalent to whether that block's execution payload is default or # not, so test cached block information rather than reconstructing a state. @@ -1073,7 +1073,7 @@ proc validateAttesterSlashing*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#proposer_slashing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#proposer_slashing proc validateProposerSlashing*( pool: ValidatorChangePool, proposer_slashing: ProposerSlashing): Result[void, ValidationError] = @@ -1366,7 +1366,7 @@ proc validateContribution*( return ok((blck.bid, sig, participants)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_finality_update proc validateLightClientFinalityUpdate*( pool: var LightClientPool, dag: ChainDAGRef, finality_update: ForkedLightClientFinalityUpdate, @@ -1402,7 +1402,7 @@ proc validateLightClientFinalityUpdate*( pool.latestForwardedFinalitySlot = finalized_slot ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update proc validateLightClientOptimisticUpdate*( pool: var LightClientPool, dag: ChainDAGRef, optimistic_update: ForkedLightClientOptimisticUpdate, diff --git a/beacon_chain/gossip_processing/light_client_processor.nim b/beacon_chain/gossip_processing/light_client_processor.nim index 515caa269..feb42519e 100644 --- a/beacon_chain/gossip_processing/light_client_processor.nim +++ b/beacon_chain/gossip_processing/light_client_processor.nim @@ -522,7 +522,7 @@ func toValidationError( # previously forwarded `optimistic_update`s errIgnore($r.error) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update proc processLightClientFinalityUpdate*( self: var LightClientProcessor, src: MsgSource, finality_update: ForkedLightClientFinalityUpdate @@ -537,7 +537,7 @@ proc processLightClientFinalityUpdate*( self.latestFinalityUpdate = finality_update.toOptimistic v -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_finality_update proc processLightClientOptimisticUpdate*( self: var LightClientProcessor, src: MsgSource, optimistic_update: ForkedLightClientOptimisticUpdate diff --git a/beacon_chain/libnimbus_lc/libnimbus_lc.nim b/beacon_chain/libnimbus_lc/libnimbus_lc.nim index 844a2b8e3..05a2dc966 100644 --- a/beacon_chain/libnimbus_lc/libnimbus_lc.nim +++ b/beacon_chain/libnimbus_lc/libnimbus_lc.nim @@ -78,7 +78,7 @@ proc ETHConsensusConfigCreateFromYaml( ## * `NULL` - If the given `config.yaml` is malformed or incompatible. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/configs/README.md + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/configs/README.md let cfg = RuntimeConfig.new() try: cfg[] = readRuntimeConfig($configFileContent, "config.yaml")[0] @@ -142,11 +142,11 @@ proc ETHBeaconStateCreateFromSsz( ## * `NULL` - If the given `sszBytes` is malformed. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconstate - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#beaconstate - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconstate - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/configs/README.md + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconstate + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#beaconstate + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#beaconstate + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconstate + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/configs/README.md let consensusFork = ConsensusFork.decodeString($consensusVersion).valueOr: return nil @@ -195,7 +195,7 @@ proc ETHRootDestroy(root: ptr Eth2Digest) {.exported.} = ## * `root` - Merkle root. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#custom-types + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#custom-types root.destroy() proc ETHForkDigestsCreateFromState( @@ -214,7 +214,7 @@ proc ETHForkDigestsCreateFromState( ## * Pointer to an initialized fork digests cache based on the beacon state. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_fork_digest + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_fork_digest let forkDigests = ForkDigests.new() forkDigests[] = ForkDigests.init( cfg[], getStateField(state[], genesis_validators_root)) @@ -265,7 +265,7 @@ proc ETHBeaconClockGetSlot(beaconClock: ptr BeaconClock): cint {.exported.} = ## * `0` - If genesis is still pending. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#custom-types + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#custom-types beaconClock[].now().slotOrZero().cint const lcDataFork = LightClientDataFork.high @@ -324,8 +324,8 @@ proc ETHLightClientStoreCreateFromBootstrap( ## See: ## * https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.1#/Beacon/getLightClientBootstrap ## * https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.4.1#/Events/eventstream - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/light-client.md - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/weak-subjectivity.md#weak-subjectivity-period + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/light-client.md + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/weak-subjectivity.md#weak-subjectivity-period let mediaType = MediaType.init($mediaType) consensusFork = ConsensusFork.decodeString($consensusVersion).valueOr: @@ -731,7 +731,7 @@ func ETHLightClientStoreGetFinalizedHeader( ## * Latest finalized header. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#modified-lightclientheader + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-lightclientheader addr store[].finalized_header func ETHLightClientStoreIsNextSyncCommitteeKnown( @@ -750,8 +750,8 @@ func ETHLightClientStoreIsNextSyncCommitteeKnown( ## * Whether or not the next sync committee is currently known. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_next_sync_committee_known - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/light-client.md + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_next_sync_committee_known + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/light-client.md store[].is_next_sync_committee_known func ETHLightClientStoreGetOptimisticHeader( @@ -770,7 +770,7 @@ func ETHLightClientStoreGetOptimisticHeader( ## * Latest optimistic header. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#modified-lightclientheader + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-lightclientheader addr store[].optimistic_header func ETHLightClientStoreGetSafetyThreshold( @@ -791,7 +791,7 @@ func ETHLightClientStoreGetSafetyThreshold( ## * Light client store safety threshold. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#get_safety_threshold + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#get_safety_threshold store[].get_safety_threshold.cint proc ETHLightClientHeaderCreateCopy( @@ -837,7 +837,7 @@ proc ETHLightClientHeaderCopyBeaconRoot( ## * Pointer to a copy of the given header's beacon block root. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#hash_tree_root + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#hash_tree_root discard cfg # Future-proof against new fields, see `get_lc_execution_root`. let root = Eth2Digest.new() root[] = header[].beacon.hash_tree_root() @@ -859,7 +859,7 @@ func ETHLightClientHeaderGetBeacon( ## * Beacon block header. ## ## See: - ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblockheader + ## * https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconblockheader addr header[].beacon func ETHBeaconBlockHeaderGetSlot( diff --git a/beacon_chain/light_client.nim b/beacon_chain/light_client.nim index 0fefa2446..30b71b49a 100644 --- a/beacon_chain/light_client.nim +++ b/beacon_chain/light_client.nim @@ -347,7 +347,7 @@ proc installMessageValidators*( digest = forkDigests[].atConsensusFork(contextFork) # light_client_optimistic_update - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_finality_update + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_finality_update lightClient.network.addValidator( getLightClientFinalityUpdateTopic(digest), proc ( msg: lcDataFork.LightClientFinalityUpdate @@ -355,7 +355,7 @@ proc installMessageValidators*( validate(msg, contextFork, processLightClientFinalityUpdate)) # light_client_optimistic_update - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update lightClient.network.addValidator( getLightClientOptimisticUpdateTopic(digest), proc ( msg: lcDataFork.LightClientOptimisticUpdate diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index 25049c8a3..14b99488f 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -174,7 +174,7 @@ type MounterProc* = proc(network: Eth2Node) {.gcsafe, raises: [CatchableError].} MessageContentPrinter* = proc(msg: pointer): string {.gcsafe, raises: [].} - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#goodbye + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#goodbye DisconnectionReason* = enum # might see other values on the wire! ClientShutDown = 1 @@ -2252,7 +2252,7 @@ proc getPersistentNetKeys*( func gossipId( data: openArray[byte], phase0Prefix, topic: string): seq[byte] = # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#topics-and-messages - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#topics-and-messages + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/p2p-interface.md#topics-and-messages const MESSAGE_DOMAIN_VALID_SNAPPY = [0x01'u8, 0x00, 0x00, 0x00] let messageDigest = withEth2Hash: h.update(MESSAGE_DOMAIN_VALID_SNAPPY) @@ -2559,7 +2559,7 @@ proc updateStabilitySubnetMetadata*(node: Eth2Node, attnets: AttnetBits) = node.metadata.attnets = attnets # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#attestation-subnet-subscription - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attestation-subnet-bitfield + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#attestation-subnet-bitfield let res = node.discovery.updateRecord({ enrAttestationSubnetsField: SSZ.encode(node.metadata.attnets) }) @@ -2571,7 +2571,7 @@ proc updateStabilitySubnetMetadata*(node: Eth2Node, attnets: AttnetBits) = debug "Stability subnets changed; updated ENR attnets", attnets proc updateSyncnetsMetadata*(node: Eth2Node, syncnets: SyncnetBits) = - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#sync-committee-subnet-stability + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#sync-committee-subnet-stability if node.metadata.syncnets == syncnets: return diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index ac90b41f6..cdb709527 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -871,7 +871,7 @@ func forkDigests(node: BeaconNode): auto = node.dag.forkDigests.deneb] forkDigestsArray -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attestation-subnet-subscription +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#attestation-subnet-subscription proc updateAttestationSubnetHandlers(node: BeaconNode, slot: Slot) = if node.gossipState.card == 0: # When disconnected, updateGossipState is responsible for all things @@ -1669,7 +1669,7 @@ proc installMessageValidators(node: BeaconNode) = MsgSource.gossip, signedAggregateAndProof))) # attester_slashing - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attester_slashing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#attester_slashing node.network.addValidator( getAttesterSlashingsTopic(digest), proc ( attesterSlashing: AttesterSlashing @@ -1713,7 +1713,7 @@ proc installMessageValidators(node: BeaconNode) = MsgSource.gossip, msg, idx))) # sync_committee_contribution_and_proof - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#sync_committee_contribution_and_proof + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/p2p-interface.md#sync_committee_contribution_and_proof node.network.addAsyncValidator( getSyncCommitteeContributionAndProofTopic(digest), proc ( msg: SignedContributionAndProof @@ -1723,7 +1723,7 @@ proc installMessageValidators(node: BeaconNode) = MsgSource.gossip, msg))) when consensusFork >= ConsensusFork.Capella: - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/p2p-interface.md#bls_to_execution_change + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/p2p-interface.md#bls_to_execution_change node.network.addAsyncValidator( getBlsToExecutionChangeTopic(digest), proc ( msg: SignedBLSToExecutionChange diff --git a/beacon_chain/rpc/rest_config_api.nim b/beacon_chain/rpc/rest_config_api.nim index 2b354909c..17937a306 100644 --- a/beacon_chain/rpc/rest_config_api.nim +++ b/beacon_chain/rpc/rest_config_api.nim @@ -88,7 +88,7 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = MAX_VOLUNTARY_EXITS: Base10.toString(MAX_VOLUNTARY_EXITS), - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/altair.yaml + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/altair.yaml INACTIVITY_PENALTY_QUOTIENT_ALTAIR: Base10.toString(INACTIVITY_PENALTY_QUOTIENT_ALTAIR), MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: @@ -104,7 +104,7 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = UPDATE_TIMEOUT: Base10.toString(UPDATE_TIMEOUT), - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/bellatrix.yaml + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/bellatrix.yaml INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: Base10.toString(INACTIVITY_PENALTY_QUOTIENT_BELLATRIX), MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: @@ -120,7 +120,7 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = MAX_EXTRA_DATA_BYTES: Base10.toString(uint64(MAX_EXTRA_DATA_BYTES)), - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/capella.yaml + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/capella.yaml MAX_BLS_TO_EXECUTION_CHANGES: Base10.toString(uint64(MAX_BLS_TO_EXECUTION_CHANGES)), MAX_WITHDRAWALS_PER_PAYLOAD: diff --git a/beacon_chain/spec/beacon_time.nim b/beacon_chain/spec/beacon_time.nim index 46fd49110..487b7cd72 100644 --- a/beacon_chain/spec/beacon_time.nim +++ b/beacon_chain/spec/beacon_time.nim @@ -142,13 +142,13 @@ const # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#prepare-sync-committee-message syncCommitteeMessageSlotOffset* = TimeDiff(nanoseconds: NANOSECONDS_PER_SLOT.int64 div INTERVALS_PER_SLOT) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#broadcast-sync-committee-contribution + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#broadcast-sync-committee-contribution syncContributionSlotOffset* = TimeDiff(nanoseconds: NANOSECONDS_PER_SLOT.int64 * 2 div INTERVALS_PER_SLOT) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#sync-committee + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#sync-committee lightClientFinalityUpdateSlotOffset* = TimeDiff(nanoseconds: NANOSECONDS_PER_SLOT.int64 div INTERVALS_PER_SLOT) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#sync-committee + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#sync-committee lightClientOptimisticUpdateSlotOffset* = TimeDiff(nanoseconds: NANOSECONDS_PER_SLOT.int64 div INTERVALS_PER_SLOT) @@ -196,14 +196,14 @@ func since_epoch_start*(slot: Slot): uint64 = # aka compute_slots_since_epoch_st template is_epoch*(slot: Slot): bool = slot.since_epoch_start == 0 -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_start_slot_at_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_start_slot_at_epoch func start_slot*(epoch: Epoch): Slot = # aka compute_start_slot_at_epoch ## Return the start slot of ``epoch``. const maxEpoch = Epoch(FAR_FUTURE_SLOT div SLOTS_PER_EPOCH) if epoch >= maxEpoch: FAR_FUTURE_SLOT else: Slot(epoch * SLOTS_PER_EPOCH) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_previous_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_previous_epoch func get_previous_epoch*(current_epoch: Epoch): Epoch = ## Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``). if current_epoch == GENESIS_EPOCH: diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 088bdeda5..6f0974d07 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -22,7 +22,7 @@ from ./datatypes/capella import BeaconState, ExecutionPayloadHeader, Withdrawal export extras, forks, validator, chronicles -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#increase_balance +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#increase_balance func increase_balance*(balance: var Gwei, delta: Gwei) = balance += delta @@ -32,7 +32,7 @@ func increase_balance*( if delta != 0: # avoid dirtying the balance cache if not needed increase_balance(state.balances.mitem(index), delta) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#decrease_balance +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#decrease_balance func decrease_balance*(balance: var Gwei, delta: Gwei) = balance = if delta > balance: @@ -66,13 +66,13 @@ func get_validator_from_deposit*(deposit: DepositData): effective_balance: effective_balance ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_activation_exit_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_activation_exit_epoch func compute_activation_exit_epoch*(epoch: Epoch): Epoch = ## Return the epoch during which validator activations and exits initiated in ## ``epoch`` take effect. epoch + 1 + MAX_SEED_LOOKAHEAD -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_validator_churn_limit +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_validator_churn_limit func get_validator_churn_limit*( cfg: RuntimeConfig, state: ForkyBeaconState, cache: var StateCache): uint64 = @@ -91,7 +91,7 @@ func get_validator_activation_churn_limit*( cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, get_validator_churn_limit(cfg, state, cache)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#initiate_validator_exit +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#initiate_validator_exit func initiate_validator_exit*( cfg: RuntimeConfig, state: var ForkyBeaconState, index: ValidatorIndex, cache: var StateCache): Result[void, cstring] = @@ -142,9 +142,9 @@ func initiate_validator_exit*( from ./datatypes/deneb import BeaconState -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#modified-slash_validator func get_slashing_penalty*(state: ForkyBeaconState, validator_effective_balance: Gwei): Gwei = # TODO Consider whether this is better than splitting the functions apart; in @@ -159,15 +159,15 @@ func get_slashing_penalty*(state: ForkyBeaconState, else: {.fatal: "invalid BeaconState type".} -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#modified-slash_validator func get_whistleblower_reward*(validator_effective_balance: Gwei): Gwei = validator_effective_balance div WHISTLEBLOWER_REWARD_QUOTIENT -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#modified-slash_validator func get_proposer_reward(state: ForkyBeaconState, whistleblower_reward: Gwei): Gwei = when state is phase0.BeaconState: whistleblower_reward div PROPOSER_REWARD_QUOTIENT @@ -177,9 +177,9 @@ func get_proposer_reward(state: ForkyBeaconState, whistleblower_reward: Gwei): G else: {.fatal: "invalid BeaconState type".} -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-slash_validator -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#modified-slash_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#modified-slash_validator proc slash_validator*( cfg: RuntimeConfig, state: var ForkyBeaconState, slashed_index: ValidatorIndex, cache: var StateCache): @@ -232,7 +232,7 @@ func genesis_time_from_eth1_timestamp( cfg: RuntimeConfig, eth1_timestamp: uint64): uint64 = eth1_timestamp + cfg.GENESIS_DELAY -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#genesis-block +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#genesis-block func get_initial_beacon_block*(state: phase0.HashedBeaconState): phase0.TrustedSignedBeaconBlock = # The genesis block is implicitly trusted @@ -256,7 +256,7 @@ func get_initial_beacon_block*(state: altair.HashedBeaconState): altair.TrustedSignedBeaconBlock( message: message, root: hash_tree_root(message)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#testing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#testing func get_initial_beacon_block*(state: bellatrix.HashedBeaconState): bellatrix.TrustedSignedBeaconBlock = # The genesis block is implicitly trusted @@ -268,7 +268,7 @@ func get_initial_beacon_block*(state: bellatrix.HashedBeaconState): bellatrix.TrustedSignedBeaconBlock( message: message, root: hash_tree_root(message)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#testing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#testing func get_initial_beacon_block*(state: capella.HashedBeaconState): capella.TrustedSignedBeaconBlock = # The genesis block is implicitly trusted @@ -297,7 +297,7 @@ func get_initial_beacon_block*(state: ForkedHashedBeaconState): withState(state): ForkedTrustedSignedBeaconBlock.init(get_initial_beacon_block(forkyState)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_block_root_at_slot +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_block_root_at_slot func get_block_root_at_slot*(state: ForkyBeaconState, slot: Slot): Eth2Digest = ## Return the block root at a recent ``slot``. @@ -315,7 +315,7 @@ func get_block_root_at_slot*( withState(state): get_block_root_at_slot(forkyState.data, slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_block_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_block_root func get_block_root*(state: ForkyBeaconState, epoch: Epoch): Eth2Digest = ## Return the block root at the start of a recent ``epoch``. get_block_root_at_slot(state, epoch.start_slot()) @@ -325,7 +325,7 @@ func get_block_root(state: ForkedHashedBeaconState, epoch: Epoch): Eth2Digest = withState(state): get_block_root(forkyState.data, epoch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_total_balance +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_total_balance template get_total_balance( state: ForkyBeaconState, validator_indices: untyped): Gwei = ## Return the combined effective balance of the ``indices``. @@ -342,7 +342,7 @@ func is_eligible_for_activation_queue*(validator: Validator): bool = validator.activation_eligibility_epoch == FAR_FUTURE_EPOCH and validator.effective_balance == MAX_EFFECTIVE_BALANCE -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_eligible_for_activation +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_eligible_for_activation func is_eligible_for_activation*( state: ForkyBeaconState, validator: Validator): bool = ## Check if ``validator`` is eligible for activation. @@ -390,7 +390,7 @@ proc is_valid_indexed_attestation*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_attesting_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_attesting_indices iterator get_attesting_indices_iter*(state: ForkyBeaconState, data: AttestationData, bits: CommitteeValidatorsBits, @@ -411,7 +411,7 @@ iterator get_attesting_indices_iter*(state: ForkyBeaconState, if bits[index_in_committee]: yield validator_index -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_attesting_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_attesting_indices func get_attesting_indices*(state: ForkyBeaconState, data: AttestationData, bits: CommitteeValidatorsBits, @@ -464,7 +464,7 @@ proc is_valid_indexed_attestation( # Attestation validation # ------------------------------------------------------------------------------------------ -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attestations +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attestations # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id func check_attestation_slot_target*(data: AttestationData): Result[Slot, cstring] = @@ -481,8 +481,8 @@ func check_attestation_target_epoch( ok(data.target.epoch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attestations -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#modified-process_attestation +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attestations +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#modified-process_attestation # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.0/specs/deneb/beacon-chain.md#modified-process_attestation func check_attestation_inclusion( consensusFork: static ConsensusFork, attestation_slot: Slot, @@ -512,7 +512,7 @@ func check_attestation_index( Result[CommitteeIndex, cstring] = check_attestation_index(data.index, committees_per_slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#get_attestation_participation_flag_indices func get_attestation_participation_flag_indices( state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState, data: AttestationData, inclusion_delay: uint64): set[TimelyFlag] = @@ -585,7 +585,7 @@ func get_attestation_participation_flag_indices( # TODO these duplicate some stuff in state_transition_epoch which uses TotalBalances # better to centralize around that if feasible -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_total_active_balance +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_total_active_balance func get_total_active_balance*(state: ForkyBeaconState, cache: var StateCache): Gwei = ## Return the combined effective balance of the active validators. ## Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei @@ -601,7 +601,7 @@ func get_total_active_balance*(state: ForkyBeaconState, cache: var StateCache): cache.total_active_balance[epoch] = tab return tab -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#get_base_reward_per_increment +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#get_base_reward_per_increment func get_base_reward_per_increment_sqrt( total_active_balance_sqrt: uint64): Gwei = EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR div total_active_balance_sqrt @@ -610,7 +610,7 @@ func get_base_reward_per_increment*( total_active_balance: Gwei): Gwei = get_base_reward_per_increment_sqrt(integer_squareroot(total_active_balance)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#get_base_reward +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#get_base_reward func get_base_reward( state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState, @@ -621,7 +621,7 @@ func get_base_reward( state.validators[index].effective_balance div EFFECTIVE_BALANCE_INCREMENT increments * base_reward_per_increment -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attestations +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attestations proc check_attestation*( state: ForkyBeaconState, attestation: SomeAttestation, flags: UpdateFlags, cache: var StateCache): Result[void, cstring] = @@ -656,7 +656,7 @@ proc check_attestation*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#new-process_bls_to_execution_change +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#new-process_bls_to_execution_change proc check_bls_to_execution_change*( genesisFork: Fork, state: capella.BeaconState | deneb.BeaconState, signed_address_change: SignedBLSToExecutionChange, flags: UpdateFlags): @@ -762,7 +762,7 @@ proc process_attestation*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#get_next_sync_committee_indices +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#get_next_sync_committee_indices func get_next_sync_committee_keys( state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState): @@ -800,19 +800,19 @@ func get_next_sync_committee_keys( i += 1'u64 res -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#has_eth1_withdrawal_credential func has_eth1_withdrawal_credential*(validator: Validator): bool = ## Check if ``validator`` has an 0x01 prefixed "eth1" withdrawal credential. validator.withdrawal_credentials.data[0] == ETH1_ADDRESS_WITHDRAWAL_PREFIX -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#is_fully_withdrawable_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#is_fully_withdrawable_validator func is_fully_withdrawable_validator( validator: Validator, balance: Gwei, epoch: Epoch): bool = ## Check if ``validator`` is fully withdrawable. has_eth1_withdrawal_credential(validator) and validator.withdrawable_epoch <= epoch and balance > 0 -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#is_partially_withdrawable_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#is_partially_withdrawable_validator func is_partially_withdrawable_validator( validator: Validator, balance: Gwei): bool = ## Check if ``validator`` is partially withdrawable. @@ -823,7 +823,7 @@ func is_partially_withdrawable_validator( has_eth1_withdrawal_credential(validator) and has_max_effective_balance and has_excess_balance -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#new-get_expected_withdrawals +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#new-get_expected_withdrawals func get_expected_withdrawals*( state: capella.BeaconState | deneb.BeaconState): seq[Withdrawal] = let @@ -859,7 +859,7 @@ func get_expected_withdrawals*( validator_index = (validator_index + 1) mod num_validators withdrawals -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#get_next_sync_committee +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#get_next_sync_committee func get_next_sync_committee*( state: altair.BeaconState | bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState): @@ -980,7 +980,7 @@ proc initialize_hashed_beacon_state_from_eth1*( cfg, eth1_block_hash, eth1_timestamp, deposits, flags)) result.root = hash_tree_root(result.data) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#testing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#testing # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/capella/beacon-chain.md#testing # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#testing proc initialize_beacon_state_from_eth1*( @@ -1328,7 +1328,7 @@ func upgrade_to_capella*(cfg: RuntimeConfig, pre: bellatrix.BeaconState): # historical_summaries initialized to correct default automatically ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/fork.md#upgrading-the-state +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/fork.md#upgrading-the-state func upgrade_to_deneb*(cfg: RuntimeConfig, pre: capella.BeaconState): ref deneb.BeaconState = let diff --git a/beacon_chain/spec/crypto.nim b/beacon_chain/spec/crypto.nim index 6ae4f630e..13e0faf82 100644 --- a/beacon_chain/spec/crypto.nim +++ b/beacon_chain/spec/crypto.nim @@ -98,7 +98,7 @@ export # API # ---------------------------------------------------------------------- -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#bls-signatures +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#bls-signatures func toPubKey*(privkey: ValidatorPrivKey): CookedPubKey = ## Derive a public key from a private key @@ -206,7 +206,7 @@ func finish*(agg: AggregateSignature): CookedSig {.inline.} = sig.finish(agg) CookedSig(sig) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#bls-signatures +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#bls-signatures func blsVerify*( pubkey: CookedPubKey, message: openArray[byte], signature: CookedSig): bool = @@ -219,7 +219,7 @@ func blsVerify*( ## to enforce correct usage. PublicKey(pubkey).verify(message, blscurve.Signature(signature)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#bls-signatures +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#bls-signatures proc blsVerify*( pubkey: ValidatorPubKey, message: openArray[byte], signature: CookedSig): bool = diff --git a/beacon_chain/spec/datatypes/altair.nim b/beacon_chain/spec/datatypes/altair.nim index 4dfafa3f1..a32c9ae39 100644 --- a/beacon_chain/spec/datatypes/altair.nim +++ b/beacon_chain/spec/datatypes/altair.nim @@ -40,7 +40,7 @@ static: doAssert ord(TIMELY_HEAD_FLAG_INDEX) == 2 const - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#incentivization-weights + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#incentivization-weights TIMELY_SOURCE_WEIGHT* = 14 TIMELY_TARGET_WEIGHT* = 26 TIMELY_HEAD_WEIGHT* = 14 @@ -55,7 +55,7 @@ const TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE* = 16 SYNC_COMMITTEE_SUBNET_COUNT* = 4 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#constants + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#constants # All of these indices are rooted in `BeaconState`. # The first member (`genesis_time`) is 32, subsequent members +1 each. # If there are ever more than 32 members in `BeaconState`, indices change! @@ -65,7 +65,7 @@ const CURRENT_SYNC_COMMITTEE_INDEX* = 54.GeneralizedIndex # `current_sync_committee` NEXT_SYNC_COMMITTEE_INDEX* = 55.GeneralizedIndex # `next_sync_committee` - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#inactivity-penalties + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#inactivity-penalties INACTIVITY_SCORE_BIAS* = 4 INACTIVITY_SCORE_RECOVERY_RATE* = 16 @@ -79,7 +79,7 @@ static: doAssert TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT + type ### New types - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#custom-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#custom-types ParticipationFlags* = uint8 EpochParticipationFlags* = @@ -88,7 +88,7 @@ type ## effectively making the cost of clearing the cache higher than the typical ## gains - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#syncaggregate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#syncaggregate SyncAggregate* = object sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE] sync_committee_signature*: ValidatorSig @@ -97,12 +97,12 @@ type sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE] sync_committee_signature*: TrustedSig - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#synccommittee + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#synccommittee SyncCommittee* = object pubkeys*: HashArray[Limit SYNC_COMMITTEE_SIZE, ValidatorPubKey] aggregate_pubkey*: ValidatorPubKey - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#synccommitteemessage + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#synccommitteemessage SyncCommitteeMessage* = object slot*: Slot ## Slot to which this contribution pertains @@ -116,7 +116,7 @@ type signature*: ValidatorSig ## Signature by the validator over the block root of `slot` - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#synccommitteecontribution + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#synccommitteecontribution SyncCommitteeAggregationBits* = BitArray[SYNC_SUBCOMMITTEE_SIZE] @@ -165,12 +165,12 @@ type NextSyncCommitteeBranch* = array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientheader LightClientHeader* = object beacon*: BeaconBlockHeader ## Beacon block header - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientbootstrap + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientbootstrap LightClientBootstrap* = object header*: LightClientHeader ## Header matching the requested beacon block root @@ -179,7 +179,7 @@ type ## Current sync committee corresponding to `header.beacon.state_root` current_sync_committee_branch*: CurrentSyncCommitteeBranch - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientupdate LightClientUpdate* = object attested_header*: LightClientHeader ## Header attested to by the sync committee @@ -198,7 +198,7 @@ type signature_slot*: Slot ## Slot at which the aggregate signature was created (untrusted) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate LightClientFinalityUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -212,7 +212,7 @@ type # Slot at which the aggregate signature was created (untrusted) signature_slot*: Slot - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate LightClientOptimisticUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -238,7 +238,7 @@ type LightClientBootstrap | SomeLightClientUpdate - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientstore + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientstore LightClientStore* = object finalized_header*: LightClientHeader ## Header that is finalized @@ -261,7 +261,7 @@ type InactivityScores* = HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#beaconstate BeaconState* = object # Versioning genesis_time*: uint64 @@ -347,7 +347,7 @@ type data*: BeaconState root*: Eth2Digest # hash_tree_root(data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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 @@ -404,7 +404,7 @@ type state_root*: Eth2Digest body*: TrustedBeaconBlockBody - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#beaconblockbody + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#beaconblockbody BeaconBlockBody* = object randao_reveal*: ValidatorSig eth1_data*: Eth1Data @@ -456,7 +456,7 @@ type SyncnetBits* = BitArray[SYNC_COMMITTEE_SUBNET_COUNT] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#metadata + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/p2p-interface.md#metadata MetaData* = object seq_number*: uint64 attnets*: AttnetBits @@ -481,7 +481,7 @@ type # [New in Altair] sync_aggregate*: TrustedSyncAggregate - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedbeaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedbeaconblock SignedBeaconBlock* = object message*: BeaconBlock signature*: ValidatorSig @@ -659,7 +659,7 @@ chronicles.formatIt SyncCommitteeContribution: shortLog(it) chronicles.formatIt ContributionAndProof: shortLog(it) chronicles.formatIt SignedContributionAndProof: shortLog(it) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_valid_light_client_header +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_valid_light_client_header func is_valid_light_client_header*( header: LightClientHeader, cfg: RuntimeConfig): bool = true diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index b0dc75d8e..7b9bec795 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -146,7 +146,7 @@ template ethAmountUnit*(typ: type) {.dirty.} = ethAmountUnit Ether type - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#custom-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#custom-types Eth2Domain* = array[32, byte] ValidatorIndex* = distinct uint32 @@ -198,7 +198,7 @@ type # SSZ / hashing purposes JustificationBits* = distinct uint8 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#proposerslashing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#proposerslashing ProposerSlashing* = object signed_header_1*: SignedBeaconBlockHeader signed_header_2*: SignedBeaconBlockHeader @@ -210,7 +210,7 @@ type signed_header_1*: TrustedSignedBeaconBlockHeader signed_header_2*: TrustedSignedBeaconBlockHeader - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attesterslashing + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attesterslashing AttesterSlashing* = object attestation_1*: IndexedAttestation attestation_2*: IndexedAttestation @@ -222,7 +222,7 @@ type attestation_1*: TrustedIndexedAttestation attestation_2*: TrustedIndexedAttestation - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#indexedattestation + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#indexedattestation IndexedAttestation* = object attesting_indices*: List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE] data*: AttestationData @@ -238,7 +238,7 @@ type CommitteeValidatorsBits* = BitList[Limit MAX_VALIDATORS_PER_COMMITTEE] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attestation + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attestation Attestation* = object aggregation_bits*: CommitteeValidatorsBits data*: AttestationData @@ -254,17 +254,17 @@ type ForkDigest* = distinct array[4, byte] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#forkdata + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#forkdata ForkData* = object current_version*: Version genesis_validators_root*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#checkpoint + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#checkpoint Checkpoint* = object epoch*: Epoch root*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#AttestationData + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#AttestationData AttestationData* = object slot*: Slot @@ -277,20 +277,20 @@ type source*: Checkpoint target*: Checkpoint - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#deposit + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#deposit Deposit* = object proof*: array[DEPOSIT_CONTRACT_TREE_DEPTH + 1, Eth2Digest] ## Merkle path to deposit root data*: DepositData - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#depositmessage + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#depositmessage DepositMessage* = object pubkey*: ValidatorPubKey withdrawal_credentials*: Eth2Digest amount*: Gwei - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#depositdata + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#depositdata DepositData* = object pubkey*: ValidatorPubKey withdrawal_credentials*: Eth2Digest @@ -300,7 +300,7 @@ type signature*: ValidatorSig ## Signing over DepositMessage - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#voluntaryexit + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#voluntaryexit VoluntaryExit* = object epoch*: Epoch ## Earliest epoch when voluntary exit can be processed @@ -328,7 +328,7 @@ type pubkey*: CookedPubKey withdrawal_credentials*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#validator + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#validator Validator* = object pubkey*: ValidatorPubKey @@ -350,7 +350,7 @@ type withdrawable_epoch*: Epoch ## When validator can withdraw funds - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#pendingattestation + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#pendingattestation PendingAttestation* = object aggregation_bits*: CommitteeValidatorsBits data*: AttestationData @@ -359,12 +359,12 @@ type proposer_index*: uint64 # `ValidatorIndex` after validation - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#historicalbatch + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#historicalbatch HistoricalBatch* = object block_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] state_roots* : array[SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#fork + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#fork Fork* = object previous_version*: Version current_version*: Version @@ -372,13 +372,13 @@ type epoch*: Epoch ## Epoch of latest fork - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#eth1data + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#eth1data Eth1Data* = object deposit_root*: Eth2Digest deposit_count*: uint64 block_hash*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedvoluntaryexit + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedvoluntaryexit SignedVoluntaryExit* = object message*: VoluntaryExit signature*: ValidatorSig @@ -387,7 +387,7 @@ type message*: VoluntaryExit signature*: TrustedSig - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblockheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconblockheader BeaconBlockHeader* = object slot*: Slot proposer_index*: uint64 # `ValidatorIndex` after validation @@ -395,14 +395,14 @@ type state_root*: Eth2Digest body_root*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signingdata + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signingdata SigningData* = object object_root*: Eth2Digest domain*: Eth2Domain GraffitiBytes* = distinct array[MAX_GRAFFITI_SIZE, byte] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedbeaconblockheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedbeaconblockheader SignedBeaconBlockHeader* = object message*: BeaconBlockHeader signature*: ValidatorSig @@ -435,12 +435,12 @@ type sync_committees*: Table[SyncCommitteePeriod, SyncCommitteeCache] # This matches the mutable state of the Solidity deposit contract - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/solidity_deposit_contract/deposit_contract.sol + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/solidity_deposit_contract/deposit_contract.sol DepositContractState* = object branch*: array[DEPOSIT_CONTRACT_TREE_DEPTH, Eth2Digest] deposit_count*: array[32, byte] # Uint256 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#validator + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#validator ValidatorStatus* = object # This is a validator without the expensive, immutable, append-only parts # serialized. They're represented in memory to allow in-place SSZ reading @@ -466,7 +466,7 @@ type withdrawable_epoch*: Epoch ## When validator can withdraw funds - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#validator + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#validator ValidatorStatusCapella* = object # This is a validator without the expensive, immutable, append-only parts # serialized. They're represented in memory to allow in-place SSZ reading diff --git a/beacon_chain/spec/datatypes/bellatrix.nim b/beacon_chain/spec/datatypes/bellatrix.nim index 79ee1901f..9d6b06df5 100644 --- a/beacon_chain/spec/datatypes/bellatrix.nim +++ b/beacon_chain/spec/datatypes/bellatrix.nim @@ -34,7 +34,7 @@ const NEWPAYLOAD_TIMEOUT* = 8.seconds type - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#custom-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#custom-types Transaction* = List[byte, Limit MAX_BYTES_PER_TRANSACTION] ExecutionAddress* = object @@ -45,7 +45,7 @@ type PayloadID* = array[8, byte] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#executionpayload + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#executionpayload ExecutionPayload* = object # Execution block header fields parent_hash*: Eth2Digest @@ -73,7 +73,7 @@ type executionPayload*: ExecutionPayload blockValue*: Wei - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#executionpayloadheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object # Execution block header fields parent_hash*: Eth2Digest @@ -103,7 +103,7 @@ type parent_hash*: Eth2Digest total_difficulty*: Eth2Digest # uint256 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#beaconstate BeaconState* = object # Versioning genesis_time*: uint64 @@ -171,7 +171,7 @@ type data*: BeaconState root*: Eth2Digest # hash_tree_root(data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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 @@ -228,7 +228,7 @@ type state_root*: Eth2Digest body*: TrustedBeaconBlockBody - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#beaconblockbody + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#beaconblockbody BeaconBlockBody* = object randao_reveal*: ValidatorSig eth1_data*: Eth1Data @@ -306,7 +306,7 @@ type # Execution execution_payload*: ExecutionPayload # [New in Bellatrix] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedbeaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedbeaconblock SignedBeaconBlock* = object message*: BeaconBlock signature*: ValidatorSig diff --git a/beacon_chain/spec/datatypes/capella.nim b/beacon_chain/spec/datatypes/capella.nim index d588c63b0..cbfd1461d 100644 --- a/beacon_chain/spec/datatypes/capella.nim +++ b/beacon_chain/spec/datatypes/capella.nim @@ -27,7 +27,7 @@ import export json_serialization, base const - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#constants + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#constants # This index is rooted in `BeaconBlockBody`. # The first member (`randao_reveal`) is 16, subsequent members +1 each. # If there are ever more than 16 members in `BeaconBlockBody`, indices change! @@ -38,32 +38,32 @@ type SignedBLSToExecutionChangeList* = List[SignedBLSToExecutionChange, Limit MAX_BLS_TO_EXECUTION_CHANGES] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#withdrawal + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#withdrawal Withdrawal* = object index*: WithdrawalIndex validator_index*: uint64 address*: ExecutionAddress amount*: Gwei - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#blstoexecutionchange + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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/v1.4.0-beta.3/specs/capella/beacon-chain.md#signedblstoexecutionchange + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#signedblstoexecutionchange SignedBLSToExecutionChange* = object message*: BLSToExecutionChange signature*: ValidatorSig - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#historicalsummary + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#historicalsummary HistoricalSummary* = object # `HistoricalSummary` matches the components of the phase0 # `HistoricalBatch` making the two hash_tree_root-compatible. block_summary_root*: Eth2Digest state_summary_root*: Eth2Digest - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#executionpayload + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#executionpayload ExecutionPayload* = object # Execution block header fields parent_hash*: Eth2Digest @@ -93,7 +93,7 @@ type executionPayload*: ExecutionPayload blockValue*: Wei - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#executionpayloadheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object # Execution block header fields parent_hash*: Eth2Digest @@ -122,7 +122,7 @@ type ExecutionBranch* = array[log2trunc(EXECUTION_PAYLOAD_INDEX), Eth2Digest] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#modified-lightclientheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-lightclientheader LightClientHeader* = object beacon*: BeaconBlockHeader ## Beacon block header @@ -131,7 +131,7 @@ type ## Execution payload header corresponding to `beacon.body_root` (from Capella onward) execution_branch*: ExecutionBranch - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientbootstrap + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientbootstrap LightClientBootstrap* = object header*: LightClientHeader ## Header matching the requested beacon block root @@ -140,7 +140,7 @@ type ## Current sync committee corresponding to `header.beacon.state_root` current_sync_committee_branch*: altair.CurrentSyncCommitteeBranch - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientupdate LightClientUpdate* = object attested_header*: LightClientHeader ## Header attested to by the sync committee @@ -159,7 +159,7 @@ type signature_slot*: Slot ## Slot at which the aggregate signature was created (untrusted) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate LightClientFinalityUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -173,7 +173,7 @@ type # Slot at which the aggregate signature was created (untrusted) signature_slot*: Slot - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate LightClientOptimisticUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -199,7 +199,7 @@ type LightClientBootstrap | SomeLightClientUpdate - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientstore + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientstore LightClientStore* = object finalized_header*: LightClientHeader ## Header that is finalized @@ -220,7 +220,7 @@ type ## (used to compute safety threshold) current_max_active_participants*: uint64 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconstate BeaconState* = object # Versioning genesis_time*: uint64 @@ -299,7 +299,7 @@ type data*: BeaconState root*: Eth2Digest # hash_tree_root(data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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 @@ -356,7 +356,7 @@ type state_root*: Eth2Digest body*: TrustedBeaconBlockBody - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconblockbody + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconblockbody BeaconBlockBody* = object randao_reveal*: ValidatorSig eth1_data*: Eth1Data @@ -650,7 +650,7 @@ func shortLog*(v: SignedBLSToExecutionChange): auto = signature: shortLog(v.signature) ) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#get_lc_execution_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#get_lc_execution_root func get_lc_execution_root*( header: LightClientHeader, cfg: RuntimeConfig): Eth2Digest = let epoch = header.beacon.slot.epoch @@ -660,7 +660,7 @@ func get_lc_execution_root*( ZERO_HASH -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#modified-is_valid_light_client_header +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-is_valid_light_client_header func is_valid_light_client_header*( header: LightClientHeader, cfg: RuntimeConfig): bool = let epoch = header.beacon.slot.epoch @@ -677,13 +677,13 @@ func is_valid_light_client_header*( get_subtree_index(EXECUTION_PAYLOAD_INDEX), header.beacon.body_root) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data func upgrade_lc_header_to_capella*( pre: altair.LightClientHeader): LightClientHeader = LightClientHeader( beacon: pre.beacon) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data func upgrade_lc_bootstrap_to_capella*( pre: altair.LightClientBootstrap): LightClientBootstrap = LightClientBootstrap( @@ -691,7 +691,7 @@ func upgrade_lc_bootstrap_to_capella*( current_sync_committee: pre.current_sync_committee, current_sync_committee_branch: pre.current_sync_committee_branch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data func upgrade_lc_update_to_capella*( pre: altair.LightClientUpdate): LightClientUpdate = LightClientUpdate( @@ -703,7 +703,7 @@ func upgrade_lc_update_to_capella*( sync_aggregate: pre.sync_aggregate, signature_slot: pre.signature_slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data func upgrade_lc_finality_update_to_capella*( pre: altair.LightClientFinalityUpdate): LightClientFinalityUpdate = LightClientFinalityUpdate( @@ -713,7 +713,7 @@ func upgrade_lc_finality_update_to_capella*( sync_aggregate: pre.sync_aggregate, signature_slot: pre.signature_slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data func upgrade_lc_optimistic_update_to_capella*( pre: altair.LightClientOptimisticUpdate): LightClientOptimisticUpdate = LightClientOptimisticUpdate( @@ -764,7 +764,7 @@ chronicles.formatIt LightClientUpdate: shortLog(it) chronicles.formatIt LightClientFinalityUpdate: shortLog(it) chronicles.formatIt LightClientOptimisticUpdate: shortLog(it) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/fork.md#upgrading-the-store +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-the-store func upgrade_lc_store_to_capella*( pre: altair.LightClientStore): LightClientStore = let best_valid_update = diff --git a/beacon_chain/spec/datatypes/constants.nim b/beacon_chain/spec/datatypes/constants.nim index c46dd714c..44306d2c7 100644 --- a/beacon_chain/spec/datatypes/constants.nim +++ b/beacon_chain/spec/datatypes/constants.nim @@ -10,13 +10,13 @@ type Epoch* = distinct uint64 SyncCommitteePeriod* = distinct uint64 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#custom-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#custom-types WithdrawalIndex* = uint64 DomainType* = distinct array[4, byte] const - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#constants + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#constants NODE_ID_BITS* = 256 # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#configuration @@ -36,7 +36,7 @@ const FAR_FUTURE_EPOCH* = Epoch(not 0'u64) FAR_FUTURE_PERIOD* = SyncCommitteePeriod(not 0'u64) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#domain-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#domain-types DOMAIN_BEACON_PROPOSER* = DomainType([byte 0x00, 0x00, 0x00, 0x00]) DOMAIN_BEACON_ATTESTER* = DomainType([byte 0x01, 0x00, 0x00, 0x00]) DOMAIN_RANDAO* = DomainType([byte 0x02, 0x00, 0x00, 0x00]) @@ -46,12 +46,12 @@ const DOMAIN_AGGREGATE_AND_PROOF* = DomainType([byte 0x06, 0x00, 0x00, 0x00]) DOMAIN_APPLICATION_MASK* = DomainType([byte 0x00, 0x00, 0x00, 0x01]) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#domain-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#domain-types DOMAIN_SYNC_COMMITTEE* = DomainType([byte 0x07, 0x00, 0x00, 0x00]) 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/v1.4.0-beta.3/specs/capella/beacon-chain.md#domain-types + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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.4.0-beta.1/specs/phase0/fork-choice.md#configuration diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index e4622495a..1fc0b946a 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -135,7 +135,7 @@ type ExecutePayload* = proc( execution_payload: ExecutionPayload): bool {.gcsafe, raises: [].} - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/light-client/sync-protocol.md#modified-lightclientheader + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-lightclientheader LightClientHeader* = object beacon*: BeaconBlockHeader ## Beacon block header @@ -144,7 +144,7 @@ type ## Execution payload header corresponding to `beacon.body_root` (from Capella onward) execution_branch*: capella.ExecutionBranch - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientbootstrap + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientbootstrap LightClientBootstrap* = object header*: LightClientHeader ## Header matching the requested beacon block root @@ -153,7 +153,7 @@ type ## Current sync committee corresponding to `header.beacon.state_root` current_sync_committee_branch*: altair.CurrentSyncCommitteeBranch - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientupdate LightClientUpdate* = object attested_header*: LightClientHeader ## Header attested to by the sync committee @@ -172,7 +172,7 @@ type signature_slot*: Slot ## Slot at which the aggregate signature was created (untrusted) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientfinalityupdate LightClientFinalityUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -186,7 +186,7 @@ type # Slot at which the aggregate signature was created (untrusted) signature_slot*: Slot - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate LightClientOptimisticUpdate* = object # Header attested to by the sync committee attested_header*: LightClientHeader @@ -212,7 +212,7 @@ type LightClientBootstrap | SomeLightClientUpdate - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#lightclientstore + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientstore LightClientStore* = object finalized_header*: LightClientHeader ## Header that is finalized @@ -233,7 +233,7 @@ type ## (used to compute safety threshold) current_max_active_participants*: uint64 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconstate # changes indirectly via ExecutionPayloadHeader BeaconState* = object # Versioning @@ -311,7 +311,7 @@ type data*: BeaconState root*: Eth2Digest # hash_tree_root(data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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 @@ -449,7 +449,7 @@ type bls_to_execution_changes*: SignedBLSToExecutionChangeList blob_kzg_commitments*: KzgCommitments # [New in Deneb] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedbeaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedbeaconblock SignedBeaconBlock* = object message*: BeaconBlock signature*: ValidatorSig @@ -592,7 +592,7 @@ func kzg_commitment_inclusion_proof_gindex*( BLOB_KZG_COMMITMENTS_FIRST_GINDEX + index -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/sync-protocol.md#modified-get_lc_execution_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/sync-protocol.md#modified-get_lc_execution_root func get_lc_execution_root*( header: LightClientHeader, cfg: RuntimeConfig): Eth2Digest = let epoch = header.beacon.slot.epoch @@ -621,7 +621,7 @@ func get_lc_execution_root*( ZERO_HASH -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/sync-protocol.md#modified-is_valid_light_client_header +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/sync-protocol.md#modified-is_valid_light_client_header func is_valid_light_client_header*( header: LightClientHeader, cfg: RuntimeConfig): bool = let epoch = header.beacon.slot.epoch @@ -643,7 +643,7 @@ func is_valid_light_client_header*( get_subtree_index(EXECUTION_PAYLOAD_INDEX), header.beacon.body_root) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data func upgrade_lc_header_to_deneb*( pre: capella.LightClientHeader): LightClientHeader = LightClientHeader( @@ -668,7 +668,7 @@ func upgrade_lc_header_to_deneb*( excess_blob_gas: 0), # [New in Deneb:EIP4844] execution_branch: pre.execution_branch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data func upgrade_lc_bootstrap_to_deneb*( pre: capella.LightClientBootstrap): LightClientBootstrap = LightClientBootstrap( @@ -676,7 +676,7 @@ func upgrade_lc_bootstrap_to_deneb*( current_sync_committee: pre.current_sync_committee, current_sync_committee_branch: pre.current_sync_committee_branch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data func upgrade_lc_update_to_deneb*( pre: capella.LightClientUpdate): LightClientUpdate = LightClientUpdate( @@ -688,7 +688,7 @@ func upgrade_lc_update_to_deneb*( sync_aggregate: pre.sync_aggregate, signature_slot: pre.signature_slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data func upgrade_lc_finality_update_to_deneb*( pre: capella.LightClientFinalityUpdate): LightClientFinalityUpdate = LightClientFinalityUpdate( @@ -698,7 +698,7 @@ func upgrade_lc_finality_update_to_deneb*( sync_aggregate: pre.sync_aggregate, signature_slot: pre.signature_slot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-light-client-data +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data func upgrade_lc_optimistic_update_to_deneb*( pre: capella.LightClientOptimisticUpdate): LightClientOptimisticUpdate = LightClientOptimisticUpdate( @@ -749,7 +749,7 @@ chronicles.formatIt LightClientUpdate: shortLog(it) chronicles.formatIt LightClientFinalityUpdate: shortLog(it) chronicles.formatIt LightClientOptimisticUpdate: shortLog(it) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/deneb/light-client/fork.md#upgrading-the-store +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-the-store func upgrade_lc_store_to_deneb*( pre: capella.LightClientStore): LightClientStore = let best_valid_update = diff --git a/beacon_chain/spec/datatypes/phase0.nim b/beacon_chain/spec/datatypes/phase0.nim index 641cb2bc0..2bbd446b7 100644 --- a/beacon_chain/spec/datatypes/phase0.nim +++ b/beacon_chain/spec/datatypes/phase0.nim @@ -22,7 +22,7 @@ import export base type - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconstate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconstate BeaconState* = object # Versioning genesis_time*: uint64 @@ -111,7 +111,7 @@ type data*: BeaconState root*: Eth2Digest # hash_tree_root(data) - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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 @@ -167,7 +167,7 @@ type state_root*: Eth2Digest body*: TrustedBeaconBlockBody - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beaconblockbody + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beaconblockbody BeaconBlockBody* = object randao_reveal*: ValidatorSig eth1_data*: Eth1Data @@ -219,7 +219,7 @@ type deposits*: List[Deposit, Limit MAX_DEPOSITS] voluntary_exits*: List[TrustedSignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS] - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#signedbeaconblock + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#signedbeaconblock SignedBeaconBlock* = object message*: BeaconBlock signature*: ValidatorSig diff --git a/beacon_chain/spec/digest.nim b/beacon_chain/spec/digest.nim index 1a32054a8..9eed43508 100644 --- a/beacon_chain/spec/digest.nim +++ b/beacon_chain/spec/digest.nim @@ -7,7 +7,7 @@ # Consensus hash function / digest # -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#hash +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#hash # # In Phase 0 the beacon chain is deployed with SHA256 (SHA2-256). # Note that is is different from Keccak256 (often mistakenly called SHA3-256) diff --git a/beacon_chain/spec/forks.nim b/beacon_chain/spec/forks.nim index 8dc3d39ad..038a2d939 100644 --- a/beacon_chain/spec/forks.nim +++ b/beacon_chain/spec/forks.nim @@ -1080,7 +1080,7 @@ func readSszForkedSignedBeaconBlock*( withBlck(result): readSszBytes(data, forkyBlck) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_fork_data_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_fork_data_root func compute_fork_data_root*(current_version: Version, genesis_validators_root: Eth2Digest): Eth2Digest = ## Return the 32-byte fork data root for the ``current_version`` and @@ -1092,7 +1092,7 @@ func compute_fork_data_root*(current_version: Version, genesis_validators_root: genesis_validators_root )) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_fork_digest +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_fork_digest func compute_fork_digest*(current_version: Version, genesis_validators_root: Eth2Digest): ForkDigest = ## Return the 4-byte fork digest for the ``current_version`` and diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index dc6c44846..2c50976ec 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -26,7 +26,7 @@ export eth2_merkleization, forks, rlp, ssz_codec func toEther*(gwei: Gwei): Ether = - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/weak-subjectivity.md#constants + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/weak-subjectivity.md#constants const ETH_TO_GWEI = 1_000_000_000 (gwei div ETH_TO_GWEI).Ether @@ -49,7 +49,7 @@ func shortLog*(v: FinalityCheckpoints): auto = chronicles.formatIt FinalityCheckpoints: it.shortLog -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#integer_squareroot +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#integer_squareroot func integer_squareroot*(n: SomeInteger): SomeInteger = ## Return the largest integer ``x`` such that ``x**2 <= n``. doAssert n >= 0'u64 @@ -62,7 +62,7 @@ func integer_squareroot*(n: SomeInteger): SomeInteger = y = (x + n div x) div 2 x -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_active_validator +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_active_validator func is_active_validator*(validator: Validator, epoch: Epoch): bool = ## Check if ``validator`` is active. validator.activation_epoch <= epoch and epoch < validator.exit_epoch @@ -100,23 +100,23 @@ func get_active_validator_indices_len*( withState(state): get_active_validator_indices_len(forkyState.data, epoch) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_current_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_current_epoch func get_current_epoch*(state: ForkyBeaconState): Epoch = ## Return the current epoch. state.slot.epoch -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_current_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_current_epoch func get_current_epoch*(state: ForkedHashedBeaconState): Epoch = ## Return the current epoch. withState(state): get_current_epoch(forkyState.data) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_previous_epoch +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_previous_epoch func get_previous_epoch*( state: ForkyBeaconState | ForkedHashedBeaconState): Epoch = ## Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``). get_previous_epoch(get_current_epoch(state)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_randao_mix +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_randao_mix func get_randao_mix*(state: ForkyBeaconState, epoch: Epoch): Eth2Digest = ## Return the randao mix at a recent ``epoch``. state.randao_mixes[epoch mod EPOCHS_PER_HISTORICAL_VECTOR] @@ -138,7 +138,7 @@ func uint_to_bytes*(x: uint32): array[4, byte] = toBytesLE(x) func uint_to_bytes*(x: uint16): array[2, byte] = toBytesLE(x) func uint_to_bytes*(x: uint8): array[1, byte] = toBytesLE(x) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_domain +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_domain func compute_domain*( domain_type: DomainType, fork_version: Version, @@ -152,7 +152,7 @@ func compute_domain*( result[0..3] = domain_type.data result[4..31] = fork_data_root.data.toOpenArray(0, 27) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_domain +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_domain func get_domain*( fork: Fork, domain_type: DomainType, @@ -173,7 +173,7 @@ func get_domain*( ## of a message. get_domain(state.fork, domain_type, epoch, state.genesis_validators_root) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#compute_signing_root +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#compute_signing_root func compute_signing_root*(ssz_object: auto, domain: Eth2Domain): Eth2Digest = ## Return the signing root for the corresponding signing data. let domain_wrapped_object = SigningData( @@ -182,7 +182,7 @@ func compute_signing_root*(ssz_object: auto, domain: Eth2Domain): Eth2Digest = ) hash_tree_root(domain_wrapped_object) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#get_seed +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#get_seed func get_seed*( state: ForkyBeaconState, epoch: Epoch, domain_type: DomainType, mix: Eth2Digest): Eth2Digest = @@ -201,12 +201,12 @@ func get_seed*(state: ForkyBeaconState, epoch: Epoch, domain_type: DomainType): epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD - 1) state.get_seed(epoch, domain_type, mix) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#add_flag +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#add_flag func add_flag*(flags: ParticipationFlags, flag_index: TimelyFlag): ParticipationFlags = let flag = ParticipationFlags(1'u8 shl ord(flag_index)) flags or flag -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/beacon-chain.md#has_flag +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#has_flag func has_flag*(flags: ParticipationFlags, flag_index: TimelyFlag): bool = let flag = ParticipationFlags(1'u8 shl ord(flag_index)) (flags and flag) == flag @@ -259,7 +259,7 @@ func create_blob_sidecars*( res.add(sidecar) res -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_sync_committee_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_sync_committee_update template is_sync_committee_update*(update: SomeForkyLightClientUpdate): bool = when update is SomeForkyLightClientUpdateWithSyncCommittee: update.next_sync_committee_branch != @@ -267,7 +267,7 @@ template is_sync_committee_update*(update: SomeForkyLightClientUpdate): bool = else: false -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_finality_update template is_finality_update*(update: SomeForkyLightClientUpdate): bool = when update is SomeForkyLightClientUpdateWithFinality: update.finality_branch != @@ -275,19 +275,19 @@ template is_finality_update*(update: SomeForkyLightClientUpdate): bool = else: false -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_next_sync_committee_known +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_next_sync_committee_known template is_next_sync_committee_known*(store: ForkyLightClientStore): bool = store.next_sync_committee != static(default(typeof(store.next_sync_committee))) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#get_safety_threshold +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#get_safety_threshold func get_safety_threshold*(store: ForkyLightClientStore): uint64 = max( store.previous_max_active_participants, store.current_max_active_participants ) div 2 -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#is_better_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#is_better_update type LightClientUpdateMetadata* = object attested_slot*, finalized_slot*, signature_slot*: Slot has_sync_committee*, has_finality*: bool @@ -378,24 +378,24 @@ template is_better_update*[ new_update: A, old_update: B): bool = is_better_data(toMeta(new_update), toMeta(old_update)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap func contextEpoch*(bootstrap: ForkyLightClientBootstrap): Epoch = bootstrap.header.beacon.slot.epoch -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate func contextEpoch*(update: SomeForkyLightClientUpdate): Epoch = update.attested_header.beacon.slot.epoch -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#is_merge_transition_complete +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#is_merge_transition_complete func is_merge_transition_complete*( state: bellatrix.BeaconState | capella.BeaconState | deneb.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.4.0-beta.3/sync/optimistic.md#helpers +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/sync/optimistic.md#helpers func is_execution_block*(blck: SomeForkyBeaconBlock): bool = when typeof(blck).kind >= ConsensusFork.Bellatrix: const defaultExecutionPayload = @@ -404,7 +404,7 @@ func is_execution_block*(blck: SomeForkyBeaconBlock): bool = else: false -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#is_merge_transition_block +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#is_merge_transition_block func is_merge_transition_block( state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState, body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody | @@ -417,7 +417,7 @@ func is_merge_transition_block( not is_merge_transition_complete(state) and body.execution_payload != defaultExecutionPayload -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#is_execution_enabled +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#is_execution_enabled func is_execution_enabled*( state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState, body: bellatrix.BeaconBlockBody | bellatrix.TrustedBeaconBlockBody | @@ -428,7 +428,7 @@ func is_execution_enabled*( deneb.SigVerifiedBeaconBlockBody): bool = is_merge_transition_block(state, body) or is_merge_transition_complete(state) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/bellatrix/beacon-chain.md#compute_timestamp_at_slot +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/bellatrix/beacon-chain.md#compute_timestamp_at_slot func compute_timestamp_at_slot*(state: ForkyBeaconState, slot: Slot): uint64 = # Note: This function is unsafe with respect to overflows and underflows. let slots_since_genesis = slot - GENESIS_SLOT diff --git a/beacon_chain/spec/keystore.nim b/beacon_chain/spec/keystore.nim index 68ae49ee7..3fa9077ea 100644 --- a/beacon_chain/spec/keystore.nim +++ b/beacon_chain/spec/keystore.nim @@ -1391,7 +1391,7 @@ func makeWithdrawalCredentials*(k: ValidatorPubKey): Eth2Digest = bytes.data[0] = BLS_WITHDRAWAL_PREFIX.uint8 bytes -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/deposit-contract.md#withdrawal-credentials +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/deposit-contract.md#withdrawal-credentials proc makeWithdrawalCredentials*(k: CookedPubKey): Eth2Digest = makeWithdrawalCredentials(k.toPubKey()) diff --git a/beacon_chain/spec/light_client_sync.nim b/beacon_chain/spec/light_client_sync.nim index 803b8edbf..a7282cea9 100644 --- a/beacon_chain/spec/light_client_sync.nim +++ b/beacon_chain/spec/light_client_sync.nim @@ -15,7 +15,7 @@ import from ../consensus_object_pools/block_pools_types import VerifierError export block_pools_types.VerifierError -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#initialize_light_client_store +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#initialize_light_client_store func initialize_light_client_store*( trusted_block_root: Eth2Digest, bootstrap: ForkyLightClientBootstrap, @@ -42,7 +42,7 @@ func initialize_light_client_store*( current_sync_committee: bootstrap.current_sync_committee, optimistic_header: bootstrap.header)) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#validate_light_client_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#validate_light_client_update proc validate_light_client_update*( store: ForkyLightClientStore, update: SomeForkyLightClientUpdate, @@ -158,7 +158,7 @@ proc validate_light_client_update*( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#apply_light_client_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#apply_light_client_update func apply_light_client_update( store: var ForkyLightClientStore, update: SomeForkyLightClientUpdate): bool = @@ -189,7 +189,7 @@ func apply_light_client_update( didProgress = true didProgress -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_store_force_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_store_force_update type ForceUpdateResult* = enum NoUpdate, @@ -222,7 +222,7 @@ func process_light_client_store_force_update*( store.best_valid_update.reset() res -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#process_light_client_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#process_light_client_update proc process_light_client_update*( store: var ForkyLightClientStore, update: SomeForkyLightClientUpdate, diff --git a/beacon_chain/spec/network.nim b/beacon_chain/spec/network.nim index c03b8d0e4..99c24f707 100644 --- a/beacon_chain/spec/network.nim +++ b/beacon_chain/spec/network.nim @@ -15,7 +15,7 @@ export base const # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#topics-and-messages - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/p2p-interface.md#topics-and-messages + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/p2p-interface.md#topics-and-messages topicBeaconBlocksSuffix* = "beacon_block/ssz_snappy" topicVoluntaryExitsSuffix* = "voluntary_exit/ssz_snappy" topicProposerSlashingsSuffix* = "proposer_slashing/ssz_snappy" @@ -27,7 +27,7 @@ const # The spec now includes this as a bare uint64 as `RESP_TIMEOUT` RESP_TIMEOUT_DUR* = RESP_TIMEOUT.int64.seconds - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#configuration + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#configuration MAX_REQUEST_LIGHT_CLIENT_UPDATES* = 128 # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#configuration @@ -63,7 +63,7 @@ func getAttesterSlashingsTopic*(forkDigest: ForkDigest): string = func getAggregateAndProofsTopic*(forkDigest: ForkDigest): string = eth2Prefix(forkDigest) & topicAggregateAndProofsSuffix -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/p2p-interface.md#topics-and-messages +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/p2p-interface.md#topics-and-messages func getBlsToExecutionChangeTopic*(forkDigest: ForkDigest): string = eth2Prefix(forkDigest) & topicBlsToExecutionChangeSuffix @@ -89,13 +89,13 @@ func getAttestationTopic*(forkDigest: ForkDigest, ## For subscribing and unsubscribing to/from a subnet. eth2Prefix(forkDigest) & "beacon_attestation_" & $(subnetId) & "/ssz_snappy" -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#topics-and-messages +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/p2p-interface.md#topics-and-messages func getSyncCommitteeTopic*(forkDigest: ForkDigest, subcommitteeIdx: SyncSubcommitteeIndex): string = ## For subscribing and unsubscribing to/from a subnet. eth2Prefix(forkDigest) & "sync_committee_" & $subcommitteeIdx & "/ssz_snappy" -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/p2p-interface.md#topics-and-messages +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/p2p-interface.md#topics-and-messages func getSyncCommitteeContributionAndProofTopic*(forkDigest: ForkDigest): string = ## For subscribing and unsubscribing to/from a subnet. eth2Prefix(forkDigest) & "sync_committee_contribution_and_proof/ssz_snappy" @@ -109,12 +109,12 @@ func getBlobSidecarTopic*(forkDigest: ForkDigest, func compute_subnet_for_blob_sidecar*(blob_index: BlobIndex): BlobId = BlobId(blob_index mod BLOB_SIDECAR_SUBNET_COUNT) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_finality_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_finality_update func getLightClientFinalityUpdateTopic*(forkDigest: ForkDigest): string = ## For broadcasting or obtaining the latest `LightClientFinalityUpdate`. eth2Prefix(forkDigest) & "light_client_finality_update/ssz_snappy" -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#light_client_optimistic_update func getLightClientOptimisticUpdateTopic*(forkDigest: ForkDigest): string = ## For broadcasting or obtaining the latest `LightClientOptimisticUpdate`. eth2Prefix(forkDigest) & "light_client_optimistic_update/ssz_snappy" diff --git a/beacon_chain/spec/presets.nim b/beacon_chain/spec/presets.nim index 86ee2eb4b..a2b42b19c 100644 --- a/beacon_chain/spec/presets.nim +++ b/beacon_chain/spec/presets.nim @@ -17,7 +17,7 @@ export constants export stint, ethtypes.toHex, ethtypes.`==` const - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#withdrawal-prefixes + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#withdrawal-prefixes BLS_WITHDRAWAL_PREFIX*: byte = 0 ETH1_ADDRESS_WITHDRAWAL_PREFIX*: byte = 1 diff --git a/beacon_chain/spec/presets/mainnet/altair_preset.nim b/beacon_chain/spec/presets/mainnet/altair_preset.nim index fbaa66265..89c48078f 100644 --- a/beacon_chain/spec/presets/mainnet/altair_preset.nim +++ b/beacon_chain/spec/presets/mainnet/altair_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Mainnet preset - Altair -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/altair.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/altair.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/mainnet/bellatrix_preset.nim b/beacon_chain/spec/presets/mainnet/bellatrix_preset.nim index 0bf67aa53..7c7f591ea 100644 --- a/beacon_chain/spec/presets/mainnet/bellatrix_preset.nim +++ b/beacon_chain/spec/presets/mainnet/bellatrix_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Mainnet preset - Bellatrix -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/bellatrix.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/bellatrix.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/mainnet/capella_preset.nim b/beacon_chain/spec/presets/mainnet/capella_preset.nim index d6a512037..cebd4a680 100644 --- a/beacon_chain/spec/presets/mainnet/capella_preset.nim +++ b/beacon_chain/spec/presets/mainnet/capella_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Mainnet preset - Capella -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/mainnet/capella.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/mainnet/capella.yaml const # Max operations per block # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/minimal/altair_preset.nim b/beacon_chain/spec/presets/minimal/altair_preset.nim index 33ab5b34d..5080cb147 100644 --- a/beacon_chain/spec/presets/minimal/altair_preset.nim +++ b/beacon_chain/spec/presets/minimal/altair_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Minimal preset - Altair -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/minimal/altair.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/minimal/altair.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/minimal/bellatrix_preset.nim b/beacon_chain/spec/presets/minimal/bellatrix_preset.nim index 54b4e8431..6ebae9e79 100644 --- a/beacon_chain/spec/presets/minimal/bellatrix_preset.nim +++ b/beacon_chain/spec/presets/minimal/bellatrix_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Minimal preset - Bellatrix -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/minimal/bellatrix.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/minimal/bellatrix.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/minimal/capella_preset.nim b/beacon_chain/spec/presets/minimal/capella_preset.nim index 449f709a9..109638ef3 100644 --- a/beacon_chain/spec/presets/minimal/capella_preset.nim +++ b/beacon_chain/spec/presets/minimal/capella_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Minimal preset - Capella -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/presets/minimal/capella.yaml +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/presets/minimal/capella.yaml const # Max operations per block # --------------------------------------------------------------- diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 417c75122..fef88e1fd 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -235,7 +235,7 @@ proc verify_voluntary_exit_signature*( blsVerify(pubkey, signing_root.data, signature) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#prepare-sync-committee-message +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#prepare-sync-committee-message func compute_sync_committee_message_signing_root*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, beacon_block_root: Eth2Digest): Eth2Digest = @@ -270,7 +270,7 @@ proc verify_sync_committee_signature*( blsFastAggregateVerify(pubkeys, signing_root.data, signature) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#aggregation-selection +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#aggregation-selection func compute_sync_committee_selection_proof_signing_root*( fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, subcommittee_index: SyncSubcommitteeIndex): Eth2Digest = @@ -319,7 +319,7 @@ proc get_contribution_and_proof_signature*( blsSign(privkey, signing_root.data) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/validator.md#aggregation-selection +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/validator.md#aggregation-selection func is_sync_committee_aggregator*(signature: ValidatorSig): bool = let signatureDigest = eth2digest(signature.blob) @@ -359,7 +359,7 @@ proc verify_builder_signature*( let signing_root = compute_builder_signing_root(fork, msg) blsVerify(pubkey, signing_root.data, signature) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#new-process_bls_to_execution_change +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#new-process_bls_to_execution_change func compute_bls_to_execution_change_signing_root*( genesisFork: Fork, genesis_validators_root: Eth2Digest, msg: BLSToExecutionChange): Eth2Digest = diff --git a/beacon_chain/spec/signatures_batch.nim b/beacon_chain/spec/signatures_batch.nim index cf6e00b94..4c154d0fa 100644 --- a/beacon_chain/spec/signatures_batch.nim +++ b/beacon_chain/spec/signatures_batch.nim @@ -82,7 +82,7 @@ func aggregateAttesters( # Aggregation spec requires non-empty collection # - https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04 # Consensus specs require at least one attesting index in attestation - # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation + # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_valid_indexed_attestation return err("aggregateAttesters: no attesting indices") let @@ -108,7 +108,7 @@ func aggregateAttesters( # Aggregation spec requires non-empty collection # - https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04 # Consensus specs require at least one attesting index in attestation - # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation + # - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_valid_indexed_attestation return err("aggregateAttesters: no attesting indices") var attestersAgg{.noinit.}: AggregatePublicKey diff --git a/beacon_chain/spec/state_transition.nim b/beacon_chain/spec/state_transition.nim index 3e7716363..22909d152 100644 --- a/beacon_chain/spec/state_transition.nim +++ b/beacon_chain/spec/state_transition.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # State transition, as described in -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function # # The entry point is `state_transition` which is at the bottom of the file! # @@ -70,7 +70,7 @@ proc verify_block_signature( ok() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function func verifyStateRoot( state: ForkyBeaconState, blck: ForkyBeaconBlock | ForkySigVerifiedBeaconBlock): @@ -126,7 +126,7 @@ func clear_epoch_from_cache(cache: var StateCache, epoch: Epoch) = for slot in epoch.slots(): cache.beacon_proposer_indices.del slot -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function proc advance_slot( cfg: RuntimeConfig, state: var ForkyBeaconState, previous_slot_state_root: Eth2Digest, @@ -373,7 +373,7 @@ func partialBeaconBlock*( when consensusFork >= ConsensusFork.Bellatrix: res.body.execution_payload = execution_payload.executionPayload - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/validator.md#block-proposal + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/validator.md#block-proposal when consensusFork >= ConsensusFork.Capella: res.body.bls_to_execution_changes = validator_changes.bls_to_execution_changes @@ -439,7 +439,7 @@ proc makeBeaconBlock*( forkyState.data.latest_execution_payload_header.transactions_root = transactions_root.get - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#beaconblockbody + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#beaconblockbody # Effectively hash_tree_root(ExecutionPayload) with the beacon block # body, with the execution payload replaced by the execution payload # header. htr(payload) == htr(payload header), so substitute. diff --git a/beacon_chain/spec/state_transition_block.nim b/beacon_chain/spec/state_transition_block.nim index 1d0270ee5..bda4684d4 100644 --- a/beacon_chain/spec/state_transition_block.nim +++ b/beacon_chain/spec/state_transition_block.nim @@ -6,10 +6,10 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # State transition - block processing, as described in -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#block-processing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#block-processing # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/altair/beacon-chain.md#block-processing # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/beacon-chain.md#block-processing -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/capella/beacon-chain.md#block-processing +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/beacon-chain.md#block-processing # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/deneb/beacon-chain.md#block-processing # # The entry point is `process_block` which is at the bottom of this file. @@ -38,7 +38,7 @@ from ./datatypes/capella import export extras, phase0, altair -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#block-header +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#block-header func process_block_header*( state: var ForkyBeaconState, blck: SomeForkyBeaconBlock, flags: UpdateFlags, cache: var StateCache): Result[void, cstring] = @@ -80,7 +80,7 @@ func `xor`[T: array](a, b: T): T = for i in 0.. 0: # replaceOrAddEncodeEth1Votes will check whether it needs to replace or add # the votes. Which happens is a function of effectively external data, i.e. - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#eth1-data + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#eth1-data # notes it depends on things not deterministic, from a pure consensus-layer # perspective. It thus must distinguish between adding and replacing votes, # which it accomplishes by checking lengths and the most recent votes. This diff --git a/beacon_chain/sync/light_client_manager.nim b/beacon_chain/sync/light_client_manager.nim index c9cfab1cd..0084ed257 100644 --- a/beacon_chain/sync/light_client_manager.nim +++ b/beacon_chain/sync/light_client_manager.nim @@ -110,7 +110,7 @@ proc isGossipSupported*( finalizedPeriod = self.getFinalizedPeriod(), isNextSyncCommitteeKnown = self.isNextSyncCommitteeKnown()) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap proc doRequest( e: typedesc[Bootstrap], peer: Peer, @@ -119,7 +119,7 @@ proc doRequest( raises: [IOError].} = peer.lightClientBootstrap(blockRoot) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange type LightClientUpdatesByRangeResponse = NetRes[List[ForkedLightClientUpdate, MAX_REQUEST_LIGHT_CLIENT_UPDATES]] proc doRequest( @@ -138,7 +138,7 @@ proc doRequest( raise newException(ResponseError, e.error) return response -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate proc doRequest( e: typedesc[FinalityUpdate], peer: Peer @@ -146,7 +146,7 @@ proc doRequest( raises: [IOError].} = peer.lightClientFinalityUpdate() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate proc doRequest( e: typedesc[OptimisticUpdate], peer: Peer @@ -335,7 +335,7 @@ template query[E]( ): Future[bool] = self.query(e, Nothing()) -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/light-client.md#light-client-sync-process +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/light-client.md#light-client-sync-process proc loop(self: LightClientManager) {.async.} = var nextSyncTaskTime = self.getBeaconTime() while true: diff --git a/beacon_chain/sync/sync_protocol.nim b/beacon_chain/sync/sync_protocol.nim index 544475304..150cea622 100644 --- a/beacon_chain/sync/sync_protocol.nim +++ b/beacon_chain/sync/sync_protocol.nim @@ -546,7 +546,7 @@ p2pProtocol BeaconSync(version = 1, debug "BlobSidecar range request done", peer, startSlot, count = reqCount, found - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap proc lightClientBootstrap( peer: Peer, blockRoot: Eth2Digest, @@ -574,7 +574,7 @@ p2pProtocol BeaconSync(version = 1, debug "LC bootstrap request done", peer, blockRoot - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange proc lightClientUpdatesByRange( peer: Peer, startPeriod: SyncCommitteePeriod, @@ -619,7 +619,7 @@ p2pProtocol BeaconSync(version = 1, debug "LC updates by range request done", peer, startPeriod, count, found - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate proc lightClientFinalityUpdate( peer: Peer, response: SingleChunkResponse[ForkedLightClientFinalityUpdate]) @@ -646,7 +646,7 @@ p2pProtocol BeaconSync(version = 1, debug "LC finality update request done", peer - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate proc lightClientOptimisticUpdate( peer: Peer, response: SingleChunkResponse[ForkedLightClientOptimisticUpdate]) diff --git a/beacon_chain/trusted_node_sync.nim b/beacon_chain/trusted_node_sync.nim index 8e4851688..c6b4455be 100644 --- a/beacon_chain/trusted_node_sync.nim +++ b/beacon_chain/trusted_node_sync.nim @@ -177,7 +177,7 @@ proc doTrustedNodeSync*( let stateId = case syncTarget.kind of TrustedNodeSyncKind.TrustedBlockRoot: - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/light-client.md#light-client-sync-process + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/light-client.md#light-client-sync-process const lcDataFork = LightClientDataFork.high var bestViableCheckpoint: Opt[tuple[slot: Slot, state_root: Eth2Digest]] func trackBestViableCheckpoint(store: lcDataFork.LightClientStore) = diff --git a/docs/attestation_flow.md b/docs/attestation_flow.md index 14ce970ca..1329d75ba 100644 --- a/docs/attestation_flow.md +++ b/docs/attestation_flow.md @@ -9,7 +9,7 @@ It is important to distinguish attestation `validation` from attestation `verifi - Aggregated: https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof - Unaggregated: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_attestation_subnet_id - Attestation `verification` is defined in the consensus specs. Verified attestations can affect fork choice and may be included in a block. - - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#attestations + - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#attestations From the specs it seems like gossip attestation `validation` is a superset of consensus attestation `verification`. @@ -51,8 +51,8 @@ These GossipSub topics are used to listen for attestations: - Unaggregated: `/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz_snappy` The attestations are then validated by `validateAttestation()` or `validateAggregate()` in either `attestationValidator()` or `aggregateValidator()` according to the P2P specs. -- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof -- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/p2p-interface.md#attestation-subnets +- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#beacon_aggregate_and_proof +- https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/p2p-interface.md#attestation-subnets Finally, valid attestations are added to the local `attestationPool`. Attestations are dropped in case of an error. diff --git a/docs/block_flow.md b/docs/block_flow.md index ba01915e4..29c07f326 100644 --- a/docs/block_flow.md +++ b/docs/block_flow.md @@ -9,7 +9,7 @@ Important distinction: https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#beacon_block. A validated block can be forwarded on gossipsub. - and we distinguish `verification` which is defined in consensus specs: - https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#block-processing + https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#block-processing A block needs to be verified to enter fork choice, the DAG and the BeaconChainDB In particular in terms of costly checks validating a block only requires checking: diff --git a/docs/the_nimbus_book/src/el-light-client.md b/docs/the_nimbus_book/src/el-light-client.md index b8305507b..212d83cff 100644 --- a/docs/the_nimbus_book/src/el-light-client.md +++ b/docs/the_nimbus_book/src/el-light-client.md @@ -104,7 +104,7 @@ The following sections explain how to do this for certain EL clients. ## Running the light client The light client starts syncing from a trusted block. -This trusted block should be somewhat recent ([~1-2 weeks](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/weak-subjectivity.md)) and needs to be configured each time when starting the light client. +This trusted block should be somewhat recent ([~1-2 weeks](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/weak-subjectivity.md)) and needs to be configured each time when starting the light client. ### 1. Obtaining a trusted block root @@ -188,7 +188,7 @@ NOT 2022-11-21 18:04:03.982+01:00 New LC optimistic block opt ``` !!! note - The [light client protocol](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md) depends on consensus layer (CL) full nodes to serve additional data. + The [light client protocol](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md) depends on consensus layer (CL) full nodes to serve additional data. As this is a new protocol, not all implementations are supporting it yet. Therefore, it may take several minutes to discover supporting peers, during which no log messages may be produced. diff --git a/docs/the_nimbus_book/src/light-client-data.md b/docs/the_nimbus_book/src/light-client-data.md index d1c7f4f55..56a39f63b 100644 --- a/docs/the_nimbus_book/src/light-client-data.md +++ b/docs/the_nimbus_book/src/light-client-data.md @@ -2,7 +2,7 @@ Nimbus is configured by default to serve data that allows light clients to stay in sync with the Ethereum network. Light client data is imported incrementally and does not affect validator performance. -Information about the light client sync protocol can be found in the [Ethereum consensus specs](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md). +Information about the light client sync protocol can be found in the [Ethereum consensus specs](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md). !!! note Nimbus also implements a [standalone light client](./el-light-client.md) that may be used to sync an execution layer (EL) client. diff --git a/docs/the_nimbus_book/src/start-syncing.md b/docs/the_nimbus_book/src/start-syncing.md index 8ae1f5cc8..11ad2f21c 100644 --- a/docs/the_nimbus_book/src/start-syncing.md +++ b/docs/the_nimbus_book/src/start-syncing.md @@ -123,7 +123,7 @@ The following [configuration options](./options.md) control checkpoint sync beha | Option | Description | |------------------------------------------|-------------| | `--external-beacon-api-url` |
  • External beacon API to use for checkpoint sync
| -| `--trusted-block-root` |
  • Recent trusted finalized block root to sync from external beacon API
  • Uses the [light client sync protocol](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md) to obtain the latest finalized checkpoint
| +| `--trusted-block-root` |
  • Recent trusted finalized block root to sync from external beacon API
  • Uses the [light client sync protocol](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md) to obtain the latest finalized checkpoint
| | `--trusted-state-root` |
  • Recent trusted finalized state root to sync from external beacon API
  • Takes precedence over `--trusted-block-root` if both are specified
| !!! info diff --git a/docs/the_nimbus_book/src/web3signer.md b/docs/the_nimbus_book/src/web3signer.md index c8a7f0b12..f0f46e437 100644 --- a/docs/the_nimbus_book/src/web3signer.md +++ b/docs/the_nimbus_book/src/web3signer.md @@ -155,6 +155,6 @@ Since the generalized index of a particular field may change in a hard-fork, in ``` Nimbus automatically computes the generalized index depending on the currently active fork. -The remote signer is expected to verify the incoming Merkle proof through the standardized [is_valid_merkle_branch](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/phase0/beacon-chain.md#is_valid_merkle_branch) function by utilizing a similar automatic mapping mechanism for the generalized index. +The remote signer is expected to verify the incoming Merkle proof through the standardized [is_valid_merkle_branch](https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/beacon-chain.md#is_valid_merkle_branch) function by utilizing a similar automatic mapping mechanism for the generalized index. You can instruct Nimbus to use the verifying Web3Signer protocol by either supplying the `--verifying-web3-signer` command-line option or by creating a remote keystore file in the format described above. You can use the command-line option `--proven-block-property` once or multiple times to enumerate the properties of the block for which Merkle proofs will be supplied. diff --git a/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim b/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim index 14de78893..9be052087 100644 --- a/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim +++ b/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim @@ -22,7 +22,7 @@ import # Test utilities ../../testutil, ../../testblockutil -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/tests/core/pyspec/eth2spec/test/helpers/sync_committee.py#L27-L44 +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/tests/core/pyspec/eth2spec/test/helpers/sync_committee.py#L27-L44 proc compute_aggregate_sync_committee_signature( cfg: RuntimeConfig, forked: ForkedHashedBeaconState, @@ -137,7 +137,7 @@ let full_sync_committee_bits = block: res.bytes.fill(byte.high) res -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/specs/altair/light-client/sync-protocol.md#initialize_light_client_store +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#initialize_light_client_store func initialize_light_client_store( state: auto, storeDataFork: static LightClientDataFork): auto = storeDataFork.LightClientStore( diff --git a/tests/testblockutil.nim b/tests/testblockutil.nim index 00625824c..f9a281a83 100644 --- a/tests/testblockutil.nim +++ b/tests/testblockutil.nim @@ -25,7 +25,7 @@ const MockPrivKeys* = MockPrivKeysT() MockPubKeys* = MockPubKeysT() -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/tests/core/pyspec/eth2spec/test/helpers/keys.py +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/tests/core/pyspec/eth2spec/test/helpers/keys.py func `[]`*(sk: MockPrivKeysT, index: ValidatorIndex|uint64): ValidatorPrivKey = var bytes = (index.uint64 + 1'u64).toBytesLE() # Consistent with EF tests static: doAssert sizeof(bytes) <= sizeof(result) From 1c03ea80f883ac469d041e5f460df8763176632f Mon Sep 17 00:00:00 2001 From: tersec Date: Wed, 8 Nov 2023 06:13:02 +0000 Subject: [PATCH 35/45] bump nim-stew (#5578) --- vendor/nim-stew | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/nim-stew b/vendor/nim-stew index 02f0929fc..49ab3c1d5 160000 --- a/vendor/nim-stew +++ b/vendor/nim-stew @@ -1 +1 @@ -Subproject commit 02f0929fc462361c9bf38aea094be7d27ccdbabd +Subproject commit 49ab3c1d59fadd7f20042e6c1bc88bb1f806234d From 6bc038e8d5ce3537bf4b6ee9cb3ef86a36297616 Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 8 Nov 2023 14:03:51 +0200 Subject: [PATCH 36/45] VC: Obol middleware support (#5375) --- AllTests-mainnet.md | 6 +- beacon_chain/conf.nim | 5 + beacon_chain/rpc/rest_utils.nim | 24 - .../eth2_apis/eth2_rest_serialization.nim | 4 +- beacon_chain/spec/eth2_apis/rest_types.nim | 36 ++ .../spec/eth2_apis/rest_validator_calls.nim | 16 +- beacon_chain/validator_client/api.nim | 200 +++++++ beacon_chain/validator_client/common.nim | 253 +-------- .../validator_client/duties_service.nim | 50 +- .../validator_client/selection_proofs.nim | 514 ++++++++++++++++++ .../sync_committee_service.nim | 2 +- tests/test_validator_client.nim | 371 +++++++++++++ 12 files changed, 1187 insertions(+), 294 deletions(-) create mode 100644 beacon_chain/validator_client/selection_proofs.nim diff --git a/AllTests-mainnet.md b/AllTests-mainnet.md index a67913aeb..32516bfb9 100644 --- a/AllTests-mainnet.md +++ b/AllTests-mainnet.md @@ -595,13 +595,15 @@ OK: 24/24 Fail: 0/24 Skip: 0/24 OK: 1/1 Fail: 0/1 Skip: 0/1 ## Validator Client test suite ```diff ++ /eth/v1/validator/beacon_committee_selections serialization/deserialization test OK ++ /eth/v1/validator/sync_committee_selections serialization/deserialization test OK + bestSuccess() API timeout test OK + firstSuccessParallel() API timeout test OK + getAttestationDataScore() test vectors OK + getLiveness() response deserialization test OK + normalizeUri() test vectors OK ``` -OK: 5/5 Fail: 0/5 Skip: 0/5 +OK: 7/7 Fail: 0/7 Skip: 0/7 ## Validator change pool testing suite ```diff + addValidatorChangeMessage/getAttesterSlashingMessage OK @@ -714,4 +716,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2 OK: 9/9 Fail: 0/9 Skip: 0/9 ---TOTAL--- -OK: 403/408 Fail: 0/408 Skip: 5/408 +OK: 405/410 Fail: 0/410 Skip: 5/410 diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 274c443d1..450666d31 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -1027,6 +1027,11 @@ type defaultValue: false name: "payload-builder" .}: bool + distributedEnabled* {. + desc: "Enable usage of Obol middleware (BETA)" + defaultValue: false + name: "distributed".}: bool + beaconNodes* {. desc: "URL addresses to one or more beacon node HTTP REST APIs", defaultValue: @[defaultBeaconNodeUri] diff --git a/beacon_chain/rpc/rest_utils.nim b/beacon_chain/rpc/rest_utils.nim index b95625a7a..11e5070fc 100644 --- a/beacon_chain/rpc/rest_utils.nim +++ b/beacon_chain/rpc/rest_utils.nim @@ -20,10 +20,6 @@ export results, eth2_rest_serialization, blockchain_dag, presto, rest_types, rest_constants, rest_common -type - ValidatorIndexError* {.pure.} = enum - UnsupportedValue, TooHighValue - func match(data: openArray[char], charset: set[char]): int = for ch in data: if ch notin charset: @@ -216,26 +212,6 @@ template strData*(body: ContentBody): string = bind fromBytes string.fromBytes(body.data) -func toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex, - ValidatorIndexError] = - when sizeof(ValidatorIndex) == 4: - if uint64(value) < VALIDATOR_REGISTRY_LIMIT: - # On x86 platform Nim allows only `int32` indexes, so all the indexes in - # range `2^31 <= x < 2^32` are not supported. - if uint64(value) <= uint64(high(int32)): - ok(ValidatorIndex(value)) - else: - err(ValidatorIndexError.UnsupportedValue) - else: - err(ValidatorIndexError.TooHighValue) - elif sizeof(ValidatorIndex) == 8: - if uint64(value) < VALIDATOR_REGISTRY_LIMIT: - ok(ValidatorIndex(value)) - else: - err(ValidatorIndexError.TooHighValue) - else: - doAssert(false, "ValidatorIndex type size is incorrect") - func syncCommitteeParticipants*(forkedState: ForkedHashedBeaconState, epoch: Epoch ): Result[seq[ValidatorPubKey], cstring] = diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 546bb2d38..42b030d80 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -122,7 +122,9 @@ type seq[RestSyncCommitteeSubscription] | seq[SignedAggregateAndProof] | seq[SignedValidatorRegistrationV1] | - seq[ValidatorIndex] + seq[ValidatorIndex] | + seq[RestBeaconCommitteeSelection] | + seq[RestSyncCommitteeSelection] DecodeTypes* = DataEnclosedObject | diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index b442a495c..46acb0b3e 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -63,6 +63,9 @@ type ValidatorQueryKind* {.pure.} = enum Index, Key + ValidatorIndexError* {.pure.} = enum + UnsupportedValue, TooHighValue + ValidatorIdent* = object case kind*: ValidatorQueryKind of ValidatorQueryKind.Index: @@ -515,6 +518,17 @@ type timestamp3*: uint64 delay*: uint64 + RestBeaconCommitteeSelection* = object + validator_index*: RestValidatorIndex + slot*: Slot + selection_proof*: ValidatorSig + + RestSyncCommitteeSelection* = object + validator_index*: RestValidatorIndex + slot*: Slot + subcommittee_index*: uint64 + selection_proof*: ValidatorSig + # Types based on the OAPI yaml file - used in responses to requests GetBeaconHeadResponse* = DataEnclosedObject[Slot] GetAggregatedAttestationResponse* = DataEnclosedObject[Attestation] @@ -560,6 +574,8 @@ type SubmitBlindedBlockResponseDeneb* = DataEnclosedObject[deneb_mev.ExecutionPayloadAndBlobsBundle] GetValidatorsActivityResponse* = DataEnclosedObject[seq[RestActivityItem]] GetValidatorsLivenessResponse* = DataEnclosedObject[seq[RestLivenessItem]] + SubmitBeaconCommitteeSelectionsResponse* = DataEnclosedObject[seq[RestBeaconCommitteeSelection]] + SubmitSyncCommitteeSelectionsResponse* = DataEnclosedObject[seq[RestSyncCommitteeSelection]] RestNodeValidity* {.pure.} = enum valid = "VALID", @@ -904,3 +920,23 @@ func init*(t: typedesc[RestErrorMessage], code: HttpCode, message: string, stacktrace: openArray[string]): RestErrorMessage = RestErrorMessage(code: code.toInt(), message: message, stacktraces: Opt.some(@stacktrace)) + +func toValidatorIndex*(value: RestValidatorIndex): Result[ValidatorIndex, + ValidatorIndexError] = + when sizeof(ValidatorIndex) == 4: + if uint64(value) < VALIDATOR_REGISTRY_LIMIT: + # On x86 platform Nim allows only `int32` indexes, so all the indexes in + # range `2^31 <= x < 2^32` are not supported. + if uint64(value) <= uint64(high(int32)): + ok(ValidatorIndex(value)) + else: + err(ValidatorIndexError.UnsupportedValue) + else: + err(ValidatorIndexError.TooHighValue) + elif sizeof(ValidatorIndex) == 8: + if uint64(value) < VALIDATOR_REGISTRY_LIMIT: + ok(ValidatorIndex(value)) + else: + err(ValidatorIndexError.TooHighValue) + else: + doAssert(false, "ValidatorIndex type size is incorrect") diff --git a/beacon_chain/spec/eth2_apis/rest_validator_calls.nim b/beacon_chain/spec/eth2_apis/rest_validator_calls.nim index 3fc7a0ea8..38f914d3a 100644 --- a/beacon_chain/spec/eth2_apis/rest_validator_calls.nim +++ b/beacon_chain/spec/eth2_apis/rest_validator_calls.nim @@ -167,4 +167,18 @@ proc getValidatorsLiveness*(epoch: Epoch, ): RestPlainResponse {. rest, endpoint: "/eth/v1/validator/liveness/{epoch}", meth: MethodPost.} - ## https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness + +proc submitBeaconCommitteeSelectionsPlain*( + body: seq[RestBeaconCommitteeSelection] + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/beacon_committee_selections", + meth: MethodPost.} + ## https://ethereum.github.io/beacon-APIs/#/Validator/submitBeaconCommitteeSelections + +proc submitSyncCommitteeSelectionsPlain*( + body: seq[RestSyncCommitteeSelection] + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/sync_committee_selections", + meth: MethodPost.} + ## https://ethereum.github.io/beacon-APIs/#/Validator/submitSyncCommitteeSelections + diff --git a/beacon_chain/validator_client/api.nim b/beacon_chain/validator_client/api.nim index 9304a73aa..359f5de01 100644 --- a/beacon_chain/validator_client/api.nim +++ b/beacon_chain/validator_client/api.nim @@ -22,6 +22,8 @@ const ResponseNoSyncError = "Received nosync error response" ResponseDecodeError = "Received response could not be decoded" ResponseECNotInSyncError* = "Execution client not in sync" + ResponseNotImplementedError = + "Received endpoint not implemented error response" type ApiResponse*[T] = Result[T, string] @@ -772,6 +774,12 @@ template handle500(): untyped {.dirty.} = node.updateStatus(RestBeaconNodeStatus.InternalError, failure) failures.add(failure) +template handle501(): untyped {.dirty.} = + let failure = ApiNodeFailure.init(ApiFailure.NotImplemented, RequestName, + strategy, node, response.status, response.getErrorMessage()) + node.updateStatus(RestBeaconNodeStatus.Incompatible, failure) + failures.add(failure) + template handle503(): untyped {.dirty.} = let failure = ApiNodeFailure.init(ApiFailure.NotSynced, RequestName, strategy, node, response.status, response.getErrorMessage()) @@ -2659,3 +2667,195 @@ proc getFinalizedBlockHeader*( return Opt.some(oldestBlockHeader) else: return Opt.none(GetBlockHeaderResponse) + +proc submitBeaconCommitteeSelections*( + vc: ValidatorClientRef, + data: seq[RestBeaconCommitteeSelection], + strategy: ApiStrategyKind + ): Future[SubmitBeaconCommitteeSelectionsResponse] {.async.} = + const + RequestName = "submitBeaconCommitteeSelections" + + var failures: seq[ApiNodeFailure] + + case strategy + of ApiStrategyKind.First, ApiStrategyKind.Best: + let res = vc.firstSuccessParallel( + RestPlainResponse, + SubmitBeaconCommitteeSelectionsResponse, + SlotDuration, + ViableNodeStatus, + {BeaconNodeRole.Duties}, + submitBeaconCommitteeSelectionsPlain(it, data)): + if apiResponse.isErr(): + handleCommunicationError() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + apiResponse.error) + else: + let response = apiResponse.get() + case response.status + of 200: + let res = decodeBytes(SubmitBeaconCommitteeSelectionsResponse, + response.data, response.contentType) + if res.isErr(): + handleUnexpectedData() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err($res.error) + else: + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].ok(res.get()) + of 400: + handle400() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + ResponseInvalidError) + of 500: + handle500() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + ResponseInternalError) + of 501: + handle501() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + ResponseNotImplementedError) + of 503: + handle503() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + ResponseNoSyncError) + else: + handleUnexpectedCode() + ApiResponse[SubmitBeaconCommitteeSelectionsResponse].err( + ResponseUnexpectedError) + + if res.isErr(): + raise (ref ValidatorApiError)(msg: res.error, data: failures) + return res.get() + + of ApiStrategyKind.Priority: + vc.firstSuccessSequential(RestPlainResponse, + SlotDuration, + ViableNodeStatus, + {BeaconNodeRole.Duties}, + submitBeaconCommitteeSelectionsPlain(it, data)): + if apiResponse.isErr(): + handleCommunicationError() + false + else: + let response = apiResponse.get() + case response.status + of 200: + let res = decodeBytes(SubmitBeaconCommitteeSelectionsResponse, + response.data, response.contentType) + if res.isOk(): return res.get() + handleUnexpectedData() + false + of 400: + handle400() + false + of 500: + handle500() + false + of 501: + handle501() + false + of 503: + handle503() + false + else: + handleUnexpectedCode() + false + + raise (ref ValidatorApiError)( + msg: "Failed to submit beacon committee selections", data: failures) + +proc submitSyncCommitteeSelections*( + vc: ValidatorClientRef, + data: seq[RestSyncCommitteeSelection], + strategy: ApiStrategyKind + ): Future[SubmitSyncCommitteeSelectionsResponse] {.async.} = + const + RequestName = "submitBeaconCommitteeSelections" + + var failures: seq[ApiNodeFailure] + + case strategy + of ApiStrategyKind.First, ApiStrategyKind.Best: + let res = vc.firstSuccessParallel( + RestPlainResponse, + SubmitSyncCommitteeSelectionsResponse, + SlotDuration, + ViableNodeStatus, + {BeaconNodeRole.Duties}, + submitSyncCommitteeSelectionsPlain(it, data)): + if apiResponse.isErr(): + handleCommunicationError() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + apiResponse.error) + else: + let response = apiResponse.get() + case response.status + of 200: + let res = decodeBytes(SubmitSyncCommitteeSelectionsResponse, + response.data, response.contentType) + if res.isErr(): + handleUnexpectedData() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err($res.error) + else: + ApiResponse[SubmitSyncCommitteeSelectionsResponse].ok(res.get()) + of 400: + handle400() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + ResponseInvalidError) + of 500: + handle500() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + ResponseInternalError) + of 501: + handle501() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + ResponseNotImplementedError) + of 503: + handle503() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + ResponseNoSyncError) + else: + handleUnexpectedCode() + ApiResponse[SubmitSyncCommitteeSelectionsResponse].err( + ResponseUnexpectedError) + + if res.isErr(): + raise (ref ValidatorApiError)(msg: res.error, data: failures) + return res.get() + + of ApiStrategyKind.Priority: + vc.firstSuccessSequential(RestPlainResponse, + SlotDuration, + ViableNodeStatus, + {BeaconNodeRole.Duties}, + submitSyncCommitteeSelectionsPlain(it, data)): + if apiResponse.isErr(): + handleCommunicationError() + false + else: + let response = apiResponse.get() + case response.status + of 200: + let res = decodeBytes(SubmitSyncCommitteeSelectionsResponse, + response.data, response.contentType) + if res.isOk(): return res.get() + handleUnexpectedData() + false + of 400: + handle400() + false + of 500: + handle500() + false + of 501: + handle501() + false + of 503: + handle503() + false + else: + handleUnexpectedCode() + false + + raise (ref ValidatorApiError)( + msg: "Failed to submit sync committee selections", data: failures) diff --git a/beacon_chain/validator_client/common.nim b/beacon_chain/validator_client/common.nim index 2d6dd0767..b07db6149 100644 --- a/beacon_chain/validator_client/common.nim +++ b/beacon_chain/validator_client/common.nim @@ -239,7 +239,7 @@ type ApiFailure* {.pure.} = enum Communication, Invalid, NotFound, OptSynced, NotSynced, Internal, - UnexpectedCode, UnexpectedResponse, NoError + NotImplemented, UnexpectedCode, UnexpectedResponse, NoError ApiNodeFailure* = object node*: BeaconNodeServerRef @@ -255,22 +255,6 @@ type ValidatorApiError* = object of ValidatorClientError data*: seq[ApiNodeFailure] - FillSignaturesResult* = object - signaturesRequested*: int - signaturesReceived*: int - - AttestationSlotRequest* = object - validator*: AttachedValidator - fork*: Fork - slot*: Slot - - SyncCommitteeSlotRequest* = object - validator*: AttachedValidator - fork*: Fork - slot*: Slot - sync_committee_index*: IndexInSyncCommittee - duty*: SyncCommitteeDuty - const DefaultDutyAndProof* = DutyAndProof(epoch: FAR_FUTURE_EPOCH) DefaultSyncCommitteeDuty* = SyncCommitteeDuty() @@ -386,6 +370,7 @@ proc `$`*(failure: ApiFailure): string = of ApiFailure.NotSynced: "not-synced" of ApiFailure.OptSynced: "opt-synced" of ApiFailure.Internal: "internal-issue" + of ApiFailure.NotImplemented: "not-implemented" of ApiFailure.UnexpectedCode: "unexpected-code" of ApiFailure.UnexpectedResponse: "unexpected-data" of ApiFailure.NoError: "status-update" @@ -1465,240 +1450,6 @@ func `==`*(a, b: SyncCommitteeDuty): bool = compareUnsorted(a.validator_sync_committee_indices, b.validator_sync_committee_indices) -proc cmp(x, y: AttestationSlotRequest|SyncCommitteeSlotRequest): int = - cmp(x.slot, y.slot) - -func getIndex*(proof: SyncCommitteeSelectionProof, - inindex: IndexInSyncCommittee): Opt[int] = - if len(proof) == 0: - return Opt.none(int) - for index, value in proof.pairs(): - if value.sync_committee_index == inindex: - return Opt.some(index) - Opt.none(int) - -func hasSignature*(proof: SyncCommitteeSelectionProof, - inindex: IndexInSyncCommittee, - slot: Slot): bool = - let index = proof.getIndex(inindex).valueOr: return false - proof[index].signatures[int(slot.since_epoch_start())].isSome() - -proc setSignature*(proof: var SyncCommitteeSelectionProof, - inindex: IndexInSyncCommittee, slot: Slot, - signature: Opt[ValidatorSig]) = - let index = proof.getIndex(inindex).expect( - "EpochSelectionProof should be present at this moment") - proof[index].signatures[int(slot.since_epoch_start())] = signature - -proc setSyncSelectionProof*(vc: ValidatorClientRef, pubkey: ValidatorPubKey, - inindex: IndexInSyncCommittee, slot: Slot, - duty: SyncCommitteeDuty, - signature: Opt[ValidatorSig]) = - let - proof = - block: - let length = len(duty.validator_sync_committee_indices) - var res = newSeq[EpochSelectionProof](length) - for i in 0 ..< length: - res[i].sync_committee_index = duty.validator_sync_committee_indices[i] - res - - vc.syncCommitteeProofs. - mgetOrPut(slot.epoch(), default(SyncCommitteeProofs)).proofs. - mgetOrPut(pubkey, proof).setSignature(inindex, slot, signature) - -proc getSyncCommitteeSelectionProof*( - vc: ValidatorClientRef, - pubkey: ValidatorPubKey, - epoch: Epoch - ): Opt[SyncCommitteeSelectionProof] = - vc.syncCommitteeProofs.withValue(epoch, epochProofs): - epochProofs[].proofs.withValue(pubkey, validatorProofs): - return Opt.some(validatorProofs[]) - do: - return Opt.none(SyncCommitteeSelectionProof) - do: - return Opt.none(SyncCommitteeSelectionProof) - -proc getSyncCommitteeSelectionProof*( - vc: ValidatorClientRef, - pubkey: ValidatorPubKey, - slot: Slot, - inindex: IndexInSyncCommittee - ): Opt[ValidatorSig] = - vc.syncCommitteeProofs.withValue(slot.epoch(), epochProofs): - epochProofs[].proofs.withValue(pubkey, validatorProofs): - let index = getIndex(validatorProofs[], inindex).valueOr: - return Opt.none(ValidatorSig) - return validatorProofs[][index].signatures[int(slot.since_epoch_start())] - do: - return Opt.none(ValidatorSig) - do: - return Opt.none(ValidatorSig) - -proc fillSyncCommitteeSelectionProofs*( - service: DutiesServiceRef, - start, finish: Slot - ): Future[FillSignaturesResult] {.async.} = - let - vc = service.client - genesisRoot = vc.beaconGenesis.genesis_validators_root - var - requests = - block: - var res: seq[SyncCommitteeSlotRequest] - for epoch in start.epoch() .. finish.epoch(): - let - fork = vc.forkAtEpoch(epoch) - period = epoch.sync_committee_period() - for duty in vc.syncDutiesForPeriod(period): - let validator = vc.attachedValidators[]. - getValidator(duty.pubkey).valueOr: - # Ignore all the validators which are not here anymore - continue - if validator.index.isNone(): - # Ignore all the valididators which do not have index yet. - continue - let proof = vc.getSyncCommitteeSelectionProof(duty.pubkey, epoch). - get(default(SyncCommitteeSelectionProof)) - for inindex in duty.validator_sync_committee_indices: - for slot in epoch.slots(): - if slot < start: continue - if slot > finish: break - if not(proof.hasSignature(inindex, slot)): - res.add( - SyncCommitteeSlotRequest( - validator: validator, - fork: fork, - slot: slot, - duty: duty, - sync_committee_index: inindex)) - # We make requests sorted by slot number. - sorted(res, cmp, order = SortOrder.Ascending) - sigres = FillSignaturesResult(signaturesRequested: len(requests)) - pendingRequests = requests.mapIt( - FutureBase(getSyncCommitteeSelectionProof( - it.validator, it.fork, genesisRoot, it.slot, - getSubcommitteeIndex(it.sync_committee_index)))) - - while len(pendingRequests) > 0: - try: - discard await race(pendingRequests) - except CancelledError as exc: - let pending = pendingRequests - .filterIt(not(it.finished())).mapIt(it.cancelAndWait()) - await noCancel allFutures(pending) - raise exc - - (requests, pendingRequests) = - block: - var - res1: seq[SyncCommitteeSlotRequest] - res2: seq[FutureBase] - for index, fut in pendingRequests.pairs(): - if not(fut.finished()): - res1.add(requests[index]) - res2.add(fut) - else: - let - request = requests[index] - signature = - if fut.completed(): - let sres = Future[SignatureResult](fut).read() - if sres.isErr(): - warn "Unable to create slot signature using remote signer", - reason = sres.error(), epoch = request.slot.epoch(), - slot = request.slot - Opt.none(ValidatorSig) - else: - inc(sigres.signaturesReceived) - Opt.some(sres.get()) - else: - Opt.none(ValidatorSig) - vc.setSyncSelectionProof(request.validator.pubkey, - request.sync_committee_index, - request.slot, request.duty, - signature) - (res1, res2) - sigres - -proc fillAttestationSelectionProofs*( - service: DutiesServiceRef, - start, finish: Slot - ): Future[FillSignaturesResult] {.async.} = - let - vc = service.client - genesisRoot = vc.beaconGenesis.genesis_validators_root - var - requests = - block: - var res: seq[AttestationSlotRequest] - for epoch in start.epoch() .. finish.epoch(): - for duty in vc.attesterDutiesForEpoch(epoch): - if (duty.data.slot < start) or (duty.data.slot > finish): - # Ignore all the slots which are not in range. - continue - if duty.slotSig.isSome(): - # Ignore all the duties which already has selection proof. - continue - let validator = vc.attachedValidators[]. - getValidator(duty.data.pubkey).valueOr: - # Ignore all the validators which are not here anymore - continue - if validator.index.isNone(): - # Ignore all the valididators which do not have index yet. - continue - res.add(AttestationSlotRequest( - validator: validator, - slot: duty.data.slot, - fork: vc.forkAtEpoch(duty.data.slot.epoch()) - )) - # We make requests sorted by slot number. - sorted(res, cmp, order = SortOrder.Ascending) - sigres = FillSignaturesResult(signaturesRequested: len(requests)) - pendingRequests = requests.mapIt( - FutureBase(getSlotSignature(it.validator, it.fork, genesisRoot, it.slot))) - - while len(pendingRequests) > 0: - try: - discard await race(pendingRequests) - except CancelledError as exc: - let pending = pendingRequests - .filterIt(not(it.finished())).mapIt(it.cancelAndWait()) - await noCancel allFutures(pending) - raise exc - - (requests, pendingRequests) = - block: - var - res1: seq[AttestationSlotRequest] - res2: seq[FutureBase] - for index, fut in pendingRequests.pairs(): - if not(fut.finished()): - res1.add(requests[index]) - res2.add(fut) - else: - let - request = requests[index] - signature = - if fut.completed(): - let sres = Future[SignatureResult](fut).read() - if sres.isErr(): - warn "Unable to create slot signature using remote signer", - reason = sres.error(), epoch = request.slot.epoch(), - slot = request.slot - Opt.none(ValidatorSig) - else: - inc(sigres.signaturesReceived) - Opt.some(sres.get()) - else: - Opt.none(ValidatorSig) - vc.attesters.withValue(request.validator.pubkey, map): - map[].duties.withValue(request.slot.epoch(), dap): - dap[].slotSig = signature - (res1, res2) - sigres - proc updateRuntimeConfig*(vc: ValidatorClientRef, node: BeaconNodeServerRef, info: VCRuntimeConfig): Result[void, string] = diff --git a/beacon_chain/validator_client/duties_service.nim b/beacon_chain/validator_client/duties_service.nim index 561f1bb8a..de98baa16 100644 --- a/beacon_chain/validator_client/duties_service.nim +++ b/beacon_chain/validator_client/duties_service.nim @@ -6,8 +6,8 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. import std/[sets, sequtils] -import chronicles -import common, api, block_service +import chronicles, metrics +import common, api, block_service, selection_proofs const ServiceName = "duties_service" @@ -314,12 +314,23 @@ proc pollForAttesterDuties*(service: DutiesServiceRef) {.async.} = block: let moment = Moment.now() - sigres = await service.fillAttestationSelectionProofs( - currentSlot, currentSlot + Epoch(1)) - debug "Attestation selection proofs have been received", - signatures_requested = sigres.signaturesRequested, - signatures_received = sigres.signaturesReceived, - time = (Moment.now() - moment) + sigres = + await vc.fillAttestationSelectionProofs(currentSlot, + currentSlot + Epoch(AGGREGATION_PRE_COMPUTE_EPOCHS)) + + if vc.config.distributedEnabled: + debug "Attestation selection proofs have been received", + signatures_requested = sigres.signaturesRequested, + signatures_received = sigres.signaturesReceived, + selections_requested = sigres.selections_requested, + selections_received = sigres.selections_received, + selections_processed = sigres.selections_processed, + total_elapsed_time = (Moment.now() - moment) + else: + debug "Attestation selection proofs have been received", + signatures_requested = sigres.signaturesRequested, + signatures_received = sigres.signaturesReceived, + total_elapsed_time = (Moment.now() - moment) let subscriptions = block: @@ -393,12 +404,23 @@ proc pollForSyncCommitteeDuties*(service: DutiesServiceRef) {.async.} = block: let moment = Moment.now() - sigres = await service.fillSyncCommitteeSelectionProofs( - currentSlot, currentSlot + Epoch(AGGREGATION_PRE_COMPUTE_EPOCHS)) - debug "Sync committee selection proofs have been received", - signatures_requested = sigres.signaturesRequested, - signatures_received = sigres.signaturesReceived, - time = (Moment.now() - moment) + sigres = + await vc.fillSyncCommitteeSelectionProofs(currentSlot, + currentSlot + Epoch(AGGREGATION_PRE_COMPUTE_EPOCHS)) + + if vc.config.distributedEnabled: + debug "Sync committee selection proofs have been received", + signatures_requested = sigres.signaturesRequested, + signatures_received = sigres.signaturesReceived, + selections_requested = sigres.selections_requested, + selections_received = sigres.selections_received, + selections_processed = sigres.selections_processed, + total_elapsed_time = (Moment.now() - moment) + else: + debug "Sync committee selection proofs have been received", + signatures_requested = sigres.signaturesRequested, + signatures_received = sigres.signaturesReceived, + total_elapsed_time = (Moment.now() - moment) let periods = diff --git a/beacon_chain/validator_client/selection_proofs.nim b/beacon_chain/validator_client/selection_proofs.nim new file mode 100644 index 000000000..9018962e6 --- /dev/null +++ b/beacon_chain/validator_client/selection_proofs.nim @@ -0,0 +1,514 @@ +# beacon_chain +# Copyright (c) 2023 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. + +import std/[algorithm, sequtils] +import chronicles, chronos, metrics +import common, api + +{.push raises: [].} + +declareGauge client_slot_signatures_time, + "Time used to obtain slot signatures" + +declareGauge client_sync_committee_selection_proof_time, + "Time used to obtain sync committee selection proofs" + +declareGauge client_obol_aggregated_slot_signatures_time, + "Time used to obtain slot signatures" + +declareGauge client_obol_aggregated_sync_committee_selection_proof_time, + "Time used to obtain sync committee selection proofs" + +type + FillSignaturesResult* = object + signaturesRequested*: int + signaturesReceived*: int + selectionsRequested*: int + selectionsReceived*: int + selectionsProcessed*: int + + AttestationSlotRequest = object + validator: AttachedValidator + fork: Fork + slot: Slot + proof: Opt[ValidatorSig] + future: FutureBase + + SyncCommitteeSlotRequest* = object + validator: AttachedValidator + fork: Fork + slot: Slot + sync_committee_index: IndexInSyncCommittee + sub_committee_index: SyncSubcommitteeIndex + duty: SyncCommitteeDuty + proof: Opt[ValidatorSig] + future: FutureBase + +template withTimeMetric(metricName, body: untyped): untyped = + let momentTime = Moment.now() + try: + body + finally: + let elapsedTime = Moment.now() - momentTime + metrics.set(metricName, elapsedTime.milliseconds()) + +proc cmp(x, y: AttestationSlotRequest|SyncCommitteeSlotRequest): int = + cmp(x.slot, y.slot) + +proc getAttesterDutiesRequests( + vc: ValidatorClientRef, + start, finish: Slot, + genesisRoot: Eth2Digest + ): seq[AttestationSlotRequest] = + var res: seq[AttestationSlotRequest] + for epoch in start.epoch() .. finish.epoch(): + for duty in vc.attesterDutiesForEpoch(epoch): + if (duty.data.slot < start) or (duty.data.slot > finish): + # Ignore all the slots which are not in range. + continue + if duty.slotSig.isSome(): + # Ignore all the duties which already has selection proof. + continue + let validator = vc.attachedValidators[]. + getValidator(duty.data.pubkey).valueOr: + # Ignore all the validators which are not here anymore + continue + if validator.index.isNone(): + # Ignore all the validators which do not have index yet. + continue + + let + fork = vc.forkAtEpoch(duty.data.slot.epoch()) + future = getSlotSignature(validator, fork, genesisRoot, duty.data.slot) + + res.add( + AttestationSlotRequest(validator: validator, slot: duty.data.slot, + fork: fork, future: FutureBase(future))) + # We make requests sorted by slot number. + sorted(res, cmp, order = SortOrder.Ascending) + +proc fillAttestationSelectionProofs*( + vc: ValidatorClientRef, + start, finish: Slot + ): Future[FillSignaturesResult] {.async.} = + let genesisRoot = vc.beaconGenesis.genesis_validators_root + var + requests: seq[AttestationSlotRequest] + sigres: FillSignaturesResult + + withTimeMetric(client_slot_signatures_time): + requests = vc.getAttesterDutiesRequests(start, finish, genesisRoot) + sigres.signaturesRequested = len(requests) + var pendingRequests = requests.mapIt(it.future) + + while len(pendingRequests) > 0: + try: + discard await race(pendingRequests) + except CancelledError as exc: + var pending: seq[Future[void]] + for future in pendingRequests: + if not(future.finished()): pending.add(future.cancelAndWait()) + await noCancel allFutures(pending) + raise exc + + pendingRequests = + block: + var res: seq[FutureBase] + for mreq in requests.mitems(): + if isNil(mreq.future): continue + if not(mreq.future.finished()): + res.add(mreq.future) + else: + let signature = + if mreq.future.completed(): + let sres = Future[SignatureResult](mreq.future).read() + if sres.isErr(): + warn "Unable to create slot signature using remote signer", + reason = sres.error(), epoch = mreq.slot.epoch(), + slot = mreq.slot + Opt.none(ValidatorSig) + else: + inc(sigres.signaturesReceived) + Opt.some(sres.get()) + else: + Opt.none(ValidatorSig) + + mreq.future = nil + mreq.proof = signature + + if signature.isSome(): + vc.attesters.withValue(mreq.validator.pubkey, map): + map[].duties.withValue(mreq.slot.epoch(), dap): + dap[].slotSig = signature + res + + if vc.config.distributedEnabled: + withTimeMetric(client_obol_aggregated_slot_signatures_time): + let (indexToKey, selections) = + block: + var + res1: Table[ValidatorIndex, Opt[ValidatorPubKey]] + res2: seq[RestBeaconCommitteeSelection] + + for mreq in requests.mitems(): + if mreq.proof.isSome(): + res1[mreq.validator.index.get()] = Opt.some(mreq.validator.pubkey) + res2.add(RestBeaconCommitteeSelection( + validator_index: RestValidatorIndex(mreq.validator.index.get()), + slot: mreq.slot, selection_proof: mreq.proof.get())) + (res1, res2) + + sigres.selectionsRequested = len(selections) + + if len(selections) == 0: + return sigres + + let sresponse = + try: + # Query middleware for aggregated signatures. + await vc.submitBeaconCommitteeSelections(selections, + ApiStrategyKind.Best) + except ValidatorApiError as exc: + warn "Unable to submit beacon committee selections", + reason = exc.getFailureReason() + return sigres + except CancelledError as exc: + debug "Beacon committee selections processing was interrupted" + raise exc + except CatchableError as exc: + error "Unexpected error occured while trying to submit beacon " & + "committee selections", reason = exc.msg, error = exc.name + return sigres + + sigres.selectionsReceived = len(sresponse.data) + + for selection in sresponse.data: + let + vindex = selection.validator_index.toValidatorIndex().valueOr: + warn "Invalid validator_index value encountered while processing " & + "beacon committee selections", + validator_index = uint64(selection.validator_index), + reason = $error + continue + selectionProof = selection.selection_proof.load().valueOr: + warn "Invalid signature encountered while processing " & + "beacon committee selections", + validator_index = vindex, slot = selection.slot, + selection_proof = shortLog(selection.selection_proof) + continue + validator = + block: + # Selections operating using validator indices, so we should check + # if we have such validator index in our validator's pool and it + # still in place (not removed using keystore manager). + let key = indexToKey.getOrDefault(vindex) + if key.isNone(): + warn "Non-existing validator encountered while processing " & + "beacon committee selections", + validator_index = vindex, + slot = selection.slot, + selection_proof = shortLog(selection.selection_proof) + continue + vc.attachedValidators[].getValidator(key.get()).valueOr: + notice "Found missing validator while processing " & + "beacon committee selections", validator_index = vindex, + slot = selection.slot, + validator = shortLog(key.get()), + selection_proof = shortLog(selection.selection_proof) + continue + + vc.attesters.withValue(validator.pubkey, map): + map[].duties.withValue(selection.slot.epoch(), dap): + dap[].slotSig = Opt.some(selectionProof.toValidatorSig()) + inc(sigres.selectionsProcessed) + + sigres + +func getIndex*(proof: SyncCommitteeSelectionProof, + inindex: IndexInSyncCommittee): Opt[int] = + if len(proof) == 0: + return Opt.none(int) + for index, value in proof.pairs(): + if value.sync_committee_index == inindex: + return Opt.some(index) + Opt.none(int) + +func hasSignature*(proof: SyncCommitteeSelectionProof, + inindex: IndexInSyncCommittee, + slot: Slot): bool = + let index = proof.getIndex(inindex).valueOr: return false + proof[index].signatures[int(slot.since_epoch_start())].isSome() + +func getSignature*(proof: SyncCommitteeSelectionProof, + inindex: IndexInSyncCommittee, + slot: Slot): Opt[ValidatorSig] = + let index = proof.getIndex(inindex).valueOr: + return Opt.none(ValidatorSig) + proof[index].signatures[int(slot.since_epoch_start())] + +proc setSignature*(proof: var SyncCommitteeSelectionProof, + inindex: IndexInSyncCommittee, slot: Slot, + signature: Opt[ValidatorSig]) = + let index = proof.getIndex(inindex).expect( + "EpochSelectionProof should be present at this moment") + proof[index].signatures[int(slot.since_epoch_start())] = signature + +proc setSyncSelectionProof*(vc: ValidatorClientRef, pubkey: ValidatorPubKey, + inindex: IndexInSyncCommittee, slot: Slot, + duty: SyncCommitteeDuty, + signature: Opt[ValidatorSig]) = + let + proof = + block: + let length = len(duty.validator_sync_committee_indices) + var res = newSeq[EpochSelectionProof](length) + for i in 0 ..< length: + res[i].sync_committee_index = duty.validator_sync_committee_indices[i] + res + + vc.syncCommitteeProofs. + mgetOrPut(slot.epoch(), default(SyncCommitteeProofs)).proofs. + mgetOrPut(pubkey, proof).setSignature(inindex, slot, signature) + +proc getSyncCommitteeSelectionProof*( + vc: ValidatorClientRef, + pubkey: ValidatorPubKey, + epoch: Epoch + ): Opt[SyncCommitteeSelectionProof] = + vc.syncCommitteeProofs.withValue(epoch, epochProofs): + epochProofs[].proofs.withValue(pubkey, validatorProofs): + return Opt.some(validatorProofs[]) + do: + return Opt.none(SyncCommitteeSelectionProof) + do: + return Opt.none(SyncCommitteeSelectionProof) + +proc getSyncCommitteeSelectionProof*( + vc: ValidatorClientRef, + pubkey: ValidatorPubKey, + slot: Slot, + inindex: IndexInSyncCommittee + ): Opt[ValidatorSig] = + vc.syncCommitteeProofs.withValue(slot.epoch(), epochProofs): + epochProofs[].proofs.withValue(pubkey, validatorProofs): + let index = getIndex(validatorProofs[], inindex).valueOr: + return Opt.none(ValidatorSig) + return validatorProofs[][index].signatures[int(slot.since_epoch_start())] + do: + return Opt.none(ValidatorSig) + do: + return Opt.none(ValidatorSig) + +proc getSyncCommitteeDutiesRequests*( + vc: ValidatorClientRef, + start, finish: Slot, + genesisRoot: Eth2Digest + ): seq[SyncCommitteeSlotRequest] = + var res: seq[SyncCommitteeSlotRequest] + for epoch in start.epoch() .. finish.epoch(): + let + fork = vc.forkAtEpoch(epoch) + period = epoch.sync_committee_period() + + for duty in vc.syncDutiesForPeriod(period): + let validator = vc.attachedValidators[].getValidator(duty.pubkey).valueOr: + # Ignore all the validators which are not here anymore + continue + if validator.index.isNone(): + # Ignore all the valididators which do not have index yet. + continue + + let proof = vc.getSyncCommitteeSelectionProof(duty.pubkey, epoch). + get(default(SyncCommitteeSelectionProof)) + + for inindex in duty.validator_sync_committee_indices: + for slot in epoch.slots(): + if slot < start: continue + if slot > finish: break + if proof.hasSignature(inindex, slot): continue + let + future = + getSyncCommitteeSelectionProof(validator, fork, genesisRoot, slot, + getSubcommitteeIndex(inindex)) + req = + SyncCommitteeSlotRequest( + validator: validator, + fork: fork, + slot: slot, + duty: duty, + sync_committee_index: inindex, + sub_committee_index: getSubcommitteeIndex(inindex), + future: FutureBase(future)) + res.add(req) + # We make requests sorted by slot number. + sorted(res, cmp, order = SortOrder.Ascending) + +proc getSyncRequest*( + requests: var openArray[SyncCommitteeSlotRequest], + validator: AttachedValidator, + slot: Slot, + subcommittee_index: uint64 + ): Opt[SyncCommitteeSlotRequest] = + for mreq in requests.mitems(): + if mreq.validator.pubkey == validator.pubkey and + mreq.slot == slot and + mreq.sub_committee_index == subcommittee_index: + return Opt.some(mreq) + Opt.none(SyncCommitteeSlotRequest) + +proc fillSyncCommitteeSelectionProofs*( + vc: ValidatorClientRef, + start, finish: Slot + ): Future[FillSignaturesResult] {.async.} = + let genesisRoot = vc.beaconGenesis.genesis_validators_root + var + requests: seq[SyncCommitteeSlotRequest] + sigres: FillSignaturesResult + + withTimeMetric(client_sync_committee_selection_proof_time): + requests = vc.getSyncCommitteeDutiesRequests(start, finish, genesisRoot) + sigres.signaturesRequested = len(requests) + var pendingRequests = requests.mapIt(it.future) + + while len(pendingRequests) > 0: + try: + discard await race(pendingRequests) + except CancelledError as exc: + var pending: seq[Future[void]] + for future in pendingRequests: + if not(future.finished()): pending.add(future.cancelAndWait()) + await noCancel allFutures(pending) + raise exc + + pendingRequests = + block: + var res: seq[FutureBase] + for mreq in requests.mitems(): + if isNil(mreq.future): continue + if not(mreq.future.finished()): + res.add(mreq.future) + else: + let signature = + if mreq.future.completed(): + let sres = Future[SignatureResult](mreq.future).read() + if sres.isErr(): + warn "Unable to create slot signature using remote signer", + reason = sres.error(), epoch = mreq.slot.epoch(), + slot = mreq.slot + Opt.none(ValidatorSig) + else: + inc(sigres.signaturesReceived) + Opt.some(sres.get()) + else: + Opt.none(ValidatorSig) + + mreq.future = nil + mreq.proof = signature + + if signature.isSome(): + vc.setSyncSelectionProof(mreq.validator.pubkey, + mreq.sync_committee_index, + mreq.slot, mreq.duty, + signature) + res + + if vc.config.distributedEnabled: + withTimeMetric(client_obol_aggregated_sync_committee_selection_proof_time): + let (indexToKey, selections) = + block: + var + res1: Table[ValidatorIndex, Opt[ValidatorPubKey]] + res2: seq[RestSyncCommitteeSelection] + for mreq in requests.mitems(): + if mreq.proof.isSome(): + res1[mreq.validator.index.get()] = Opt.some(mreq.validator.pubkey) + res2.add(RestSyncCommitteeSelection( + validator_index: RestValidatorIndex(mreq.validator.index.get()), + subcommittee_index: uint64(mreq.sub_committee_index), + slot: mreq.slot, selection_proof: mreq.proof.get())) + (res1, res2) + + sigres.selectionsRequested = len(selections) + + if len(selections) == 0: + return sigres + + let sresponse = + try: + # Query middleware for aggregated signatures. + await vc.submitSyncCommitteeSelections(selections, + ApiStrategyKind.Best) + except ValidatorApiError as exc: + warn "Unable to submit sync committee selections", + reason = exc.getFailureReason() + return sigres + except CancelledError as exc: + debug "Sync committee selections processing was interrupted" + raise exc + except CatchableError as exc: + error "Unexpected error occured while trying to submit sync " & + "committee selections", reason = exc.msg, error = exc.name + return sigres + + sigres.selectionsReceived = len(sresponse.data) + + for selection in sresponse.data: + let + slot = selection.slot + subcommittee_index = selection.subcommittee_index + vindex = selection.validator_index.toValidatorIndex().valueOr: + warn "Invalid validator_index value encountered while processing " & + "sync committee selections", + validator_index = uint64(selection.validator_index), + reason = $error + continue + selectionProof = selection.selection_proof.load().valueOr: + warn "Invalid signature encountered while processing " & + "sync committee selections", + validator_index = vindex, slot = slot, + selection_proof = shortLog(selection.selection_proof) + continue + validator = + block: + # Selections operating using validator indices, so we should check + # if we have such validator index in our validator's pool and it + # still in place (not removed using keystore manager). + let key = indexToKey.getOrDefault(vindex) + if key.isNone(): + warn "Non-existing validator encountered while processing " & + "sync committee selections", + validator_index = vindex, + slot = slot, + selection_proof = shortLog(selection.selection_proof) + continue + vc.attachedValidators[].getValidator(key.get()).valueOr: + notice "Found missing validator while processing " & + "sync committee selections", validator_index = vindex, + slot = slot, + validator = shortLog(key.get()), + selection_proof = shortLog(selection.selection_proof) + continue + request = + block: + let res = getSyncRequest(requests, validator, slot, + subcommittee_index) + if res.isNone(): + warn "Found sync committee selection proof which was not " & + "requested", + slot = slot, subcommittee_index = subcommittee_index, + validator = shortLog(validator), + selection_proof = shortLog(selection.selection_proof) + continue + res.get() + + vc.syncCommitteeProofs.withValue(slot.epoch(), epochProofs): + epochProofs[].proofs.withValue(validator.pubkey, signatures): + signatures[].setSignature(request.sync_committee_index, + selection.slot, + Opt.some(selection.selectionProof)) + inc(sigres.selectionsProcessed) + sigres diff --git a/beacon_chain/validator_client/sync_committee_service.nim b/beacon_chain/validator_client/sync_committee_service.nim index 3906d94fd..b83f1752c 100644 --- a/beacon_chain/validator_client/sync_committee_service.nim +++ b/beacon_chain/validator_client/sync_committee_service.nim @@ -11,7 +11,7 @@ import ../spec/datatypes/[phase0, altair, bellatrix], ../spec/eth2_apis/rest_types, ../validators/activity_metrics, - "."/[common, api] + "."/[common, api, selection_proofs] const ServiceName = "sync_committee_service" diff --git a/tests/test_validator_client.nim b/tests/test_validator_client.nim index 6ea80b58f..c4d0f2850 100644 --- a/tests/test_validator_client.nim +++ b/tests/test_validator_client.nim @@ -144,7 +144,163 @@ const ("", "err(Missing hostname)") ] + ObolBeaconRequestTestVector = """ +[ + { + "validator_index": "1", + "slot": "1", + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "slot": "2", + "validator_index": "2", + "selection_proof": "0x2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "3", + "selection_proof": "0x3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "slot": "3" + }, + { + "selection_proof": "0x4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "validator_index": "4", + "slot": "4" + } +]""" + ObolBeaconResponseTestVector = """ +{ + "data": [ + { + "validator_index": "1", + "slot": "1", + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "2", + "slot": "2", + "selection_proof": "0x2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "3", + "slot": "3", + "selection_proof": "0x3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "4", + "slot": "4", + "selection_proof": "0x4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ] +}""" + ObolBeaconResponseTestVectorObject = [ + ( + validator_index: RestValidatorIndex(1), + slot: Slot(1), + selection_proof: "1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(2), + slot: Slot(2), + selection_proof: "2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(3), + slot: Slot(3), + selection_proof: "3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(4), + slot: Slot(4), + selection_proof: "4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ) + ] + ObolSyncRequestTestVector = """ +[ + { + "validator_index": "1", + "slot": "1", + "subcommittee_index": "1", + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "2", + "subcommittee_index": "2", + "slot": "2", + "selection_proof": "0x2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "subcommittee_index": "3", + "validator_index": "3", + "slot": "3", + "selection_proof": "0x3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "4", + "slot": "4", + "selection_proof": "0x4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "subcommittee_index": "4" + } +]""" + ObolSyncResponseTestVector = """ +{ + "data": [ + { + "validator_index": "1", + "slot": "1", + "subcommittee_index": "1", + "selection_proof": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "2", + "subcommittee_index": "2", + "slot": "2", + "selection_proof": "0x2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "subcommittee_index": "3", + "validator_index": "3", + "slot": "3", + "selection_proof": "0x3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + { + "validator_index": "4", + "slot": "4", + "selection_proof": "0x4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "subcommittee_index": "4" + } + ] +}""" + ObolSyncResponseTestVectorObject = [ + ( + validator_index: RestValidatorIndex(1), + slot: Slot(1), + subcommittee_index: 1'u64, + selection_proof: "1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(2), + slot: Slot(2), + subcommittee_index: 2'u64, + selection_proof: "2b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(3), + slot: Slot(3), + subcommittee_index: 3'u64, + selection_proof: "3b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ), + ( + validator_index: RestValidatorIndex(4), + slot: Slot(4), + subcommittee_index: 4'u64, + selection_proof: "4b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + ) + ] + type + TestDecodeTypes = seq[RestBeaconCommitteeSelection] | + seq[RestSyncCommitteeSelection] + AttestationDataTuple* = tuple[ slot: uint64, index: uint64, @@ -238,12 +394,227 @@ proc createRootsSeen( res suite "Validator Client test suite": + + proc decodeBytes[T: TestDecodeTypes]( + t: typedesc[T], + value: openArray[byte], + contentType: Opt[ContentTypeData] = Opt.none(ContentTypeData) + ): RestResult[T] = + let mediaType = + if contentType.isNone(): + ApplicationJsonMediaType + else: + if isWildCard(contentType.get().mediaType): + return err("Incorrect Content-Type") + contentType.get().mediaType + + if mediaType == ApplicationJsonMediaType: + try: + ok RestJson.decode(value, T, + requireAllFields = true, + allowUnknownFields = true) + except SerializationError as exc: + err("Serialization error") + else: + err("Content-Type not supported") + + proc submitBeaconCommitteeSelectionsPlain( + body: seq[RestBeaconCommitteeSelection] + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/beacon_committee_selections", + meth: MethodPost.} + ## https://ethereum.github.io/beacon-APIs/#/Validator/submitBeaconCommitteeSelections + + proc submitSyncCommitteeSelectionsPlain( + body: seq[RestSyncCommitteeSelection] + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/validator/sync_committee_selections", + meth: MethodPost.} + ## https://ethereum.github.io/beacon-APIs/#/Validator/submitSyncCommitteeSelections + + proc createServer(address: TransportAddress, + process: HttpProcessCallback, secure: bool): HttpServerRef = + let + socketFlags = {ServerFlags.TcpNoDelay, ServerFlags.ReuseAddr} + res = HttpServerRef.new(address, process, socketFlags = socketFlags) + res.get() + test "normalizeUri() test vectors": for hostname in HostNames: for vector in GoodTestVectors: let expect = vector[1] % (hostname) check $normalizeUri(parseUri(vector[0] % (hostname))) == expect + asyncTest "/eth/v1/validator/beacon_committee_selections " & + "serialization/deserialization test": + var clientRequest: seq[byte] + proc process(r: RequestFence): Future[HttpResponseRef] {.async.} = + if r.isOk(): + let request = r.get() + case request.uri.path + of "/eth/v1/validator/beacon_committee_selections": + clientRequest = await request.getBody() + let headers = HttpTable.init([("Content-Type", "application/json")]) + return await request.respond(Http200, ObolBeaconResponseTestVector, + headers) + else: + return await request.respond(Http404, "Page not found") + else: + return dumbResponse() + + let server = createServer(initTAddress("127.0.0.1:0"), process, false) + server.start() + defer: + await server.stop() + await server.closeWait() + + let + serverAddress = server.instance.localAddress + flags = {RestClientFlag.CommaSeparatedArray} + remoteUri = "http://" & $serverAddress + client = + block: + let res = RestClientRef.new(remoteUri, flags = flags) + check res.isOk() + res.get() + selections = + block: + let res = decodeBytes( + seq[RestBeaconCommitteeSelection], + ObolBeaconRequestTestVector.toOpenArrayByte( + 0, len(ObolBeaconRequestTestVector) - 1)) + check res.isOk() + res.get() + + defer: + await client.closeWait() + + let resp = await client.submitBeaconCommitteeSelectionsPlain(selections) + check: + resp.status == 200 + resp.contentType == MediaType.init("application/json") + + let request = + block: + let res = decodeBytes( + seq[RestBeaconCommitteeSelection], + clientRequest) + check res.isOk() + res.get() + + let response = block: + let res = decodeBytes(SubmitBeaconCommitteeSelectionsResponse, + resp.data, resp.contentType) + check res.isOk() + res.get() + + check: + len(request) == len(selections) + len(response.data) == len(ObolBeaconResponseTestVectorObject) + + # Checking response + for index, item in response.data.pairs(): + check: + item.validator_index == + ObolBeaconResponseTestVectorObject[index].validator_index + item.slot == + ObolBeaconResponseTestVectorObject[index].slot + item.selection_proof.toHex() == + ObolBeaconResponseTestVectorObject[index].selection_proof + + # Checking request + for index, item in selections.pairs(): + check: + item.validator_index == request[index].validator_index + item.slot == request[index].slot + item.selection_proof.toHex() == request[index].selection_proof.toHex() + + asyncTest "/eth/v1/validator/sync_committee_selections " & + "serialization/deserialization test": + var clientRequest: seq[byte] + proc process(r: RequestFence): Future[HttpResponseRef] {.async.} = + if r.isOk(): + let request = r.get() + case request.uri.path + of "/eth/v1/validator/sync_committee_selections": + clientRequest = await request.getBody() + let headers = HttpTable.init([("Content-Type", "application/json")]) + return await request.respond(Http200, ObolSyncResponseTestVector, + headers) + else: + return await request.respond(Http404, "Page not found") + else: + return dumbResponse() + + let server = createServer(initTAddress("127.0.0.1:0"), process, false) + server.start() + defer: + await server.stop() + await server.closeWait() + + let + serverAddress = server.instance.localAddress + flags = {RestClientFlag.CommaSeparatedArray} + remoteUri = "http://" & $serverAddress + client = + block: + let res = RestClientRef.new(remoteUri, flags = flags) + check res.isOk() + res.get() + selections = + block: + let res = decodeBytes( + seq[RestSyncCommitteeSelection], + ObolSyncRequestTestVector.toOpenArrayByte( + 0, len(ObolSyncRequestTestVector) - 1)) + check res.isOk() + res.get() + + defer: + await client.closeWait() + + let resp = await client.submitSyncCommitteeSelectionsPlain(selections) + check: + resp.status == 200 + resp.contentType == MediaType.init("application/json") + + let request = + block: + let res = decodeBytes( + seq[RestSyncCommitteeSelection], + clientRequest) + check res.isOk() + res.get() + + let response = block: + let res = decodeBytes(SubmitSyncCommitteeSelectionsResponse, + resp.data, resp.contentType) + check res.isOk() + res.get() + + check: + len(request) == len(selections) + len(response.data) == len(ObolSyncResponseTestVectorObject) + + # Checking response + for index, item in response.data.pairs(): + check: + item.validator_index == + ObolSyncResponseTestVectorObject[index].validator_index + item.slot == + ObolSyncResponseTestVectorObject[index].slot + item.selection_proof.toHex() == + ObolSyncResponseTestVectorObject[index].selection_proof + item.subcommittee_index == request[index].subcommittee_index + + # Checking request + for index, item in selections.pairs(): + check: + item.validator_index == request[index].validator_index + item.slot == request[index].slot + item.subcommittee_index == request[index].subcommittee_index + item.selection_proof.toHex() == request[index].selection_proof.toHex() + test "getAttestationDataScore() test vectors": for vector in AttestationDataVectors: let From c279bd447474c5635586f81cf633915ca721b8b8 Mon Sep 17 00:00:00 2001 From: Eugene Kabanov Date: Wed, 8 Nov 2023 15:42:50 +0200 Subject: [PATCH 37/45] Fix issue when peers was not disconnected on low score. (#5579) --- beacon_chain/networking/eth2_network.nim | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index 14b99488f..f2c008811 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -517,6 +517,17 @@ proc disconnect*(peer: Peer, reason: DisconnectionReason, trace "Exception while disconnecting peer", peer = peer.peerId, reason = reason +proc releasePeer*(peer: Peer) = + ## Checks for peer's score and disconnects peer if score is less than + ## `PeerScoreLowLimit`. + if peer.connectionState notin {ConnectionState.Disconnecting, + ConnectionState.Disconnected}: + if peer.score < PeerScoreLowLimit: + debug "Peer was disconnected due to low score", peer = peer, + peer_score = peer.score, score_low_limit = PeerScoreLowLimit, + score_high_limit = PeerScoreHighLimit + asyncSpawn(peer.disconnect(PeerScoreLow)) + include eth/p2p/p2p_backends_helpers include eth/p2p/p2p_tracing @@ -1233,7 +1244,7 @@ proc handleIncomingStream(network: Eth2Node, finally: await conn.closeWithEOF() - discard network.peerPool.checkPeerScore(peer) + releasePeer(peer) proc toPeerAddr*(r: enr.TypedRecord, proto: IpTransportProtocol): Result[PeerAddr, cstring] = @@ -1869,18 +1880,7 @@ proc new(T: type Eth2Node, peer.score >= PeerScoreLowLimit proc onDeletePeer(peer: Peer) = - if peer.connectionState notin {ConnectionState.Disconnecting, - ConnectionState.Disconnected}: - if peer.score < PeerScoreLowLimit: - debug "Peer was removed from PeerPool due to low score", peer = peer, - peer_score = peer.score, score_low_limit = PeerScoreLowLimit, - score_high_limit = PeerScoreHighLimit - asyncSpawn(peer.disconnect(PeerScoreLow)) - else: - debug "Peer was removed from PeerPool", peer = peer, - peer_score = peer.score, score_low_limit = PeerScoreLowLimit, - score_high_limit = PeerScoreHighLimit - asyncSpawn(peer.disconnect(FaultOrError)) # Shouldn't actually happen! + peer.releasePeer() node.peerPool.setScoreCheck(scoreCheck) node.peerPool.setOnDeletePeer(onDeletePeer) From 4399361bc7312d71c5b2613586b438af17a141fc Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 8 Nov 2023 16:08:13 +0100 Subject: [PATCH 38/45] bump `gnosis-chain-configs` to `c8b24c87e4cbea8a35b1be6ed5398b519a600928` (#5580) - fix: remove enr padding - Sync Deneb preset with Ethereum L1 --- vendor/gnosis-chain-configs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/gnosis-chain-configs b/vendor/gnosis-chain-configs index b90374a1c..c8b24c87e 160000 --- a/vendor/gnosis-chain-configs +++ b/vendor/gnosis-chain-configs @@ -1 +1 @@ -Subproject commit b90374a1c63703db8235fcdb65aff2e909bc42b5 +Subproject commit c8b24c87e4cbea8a35b1be6ed5398b519a600928 From d9031d97dcd1c5742b5c31e2f59a4f18f726abb2 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 9 Nov 2023 13:54:44 +0100 Subject: [PATCH 39/45] rename `_INDEX` generalized index constants to `_GINDEX` (#5583) Rename constants for consistency with upcoming spec adjustment: - https://github.com/ethereum/consensus-specs/pull/3537 --- .../blockchain_dag_light_client.nim | 14 +++++++------- beacon_chain/spec/datatypes/altair.nim | 14 +++++++------- beacon_chain/spec/datatypes/capella.nim | 8 ++++---- beacon_chain/spec/datatypes/deneb.nim | 6 +++--- beacon_chain/spec/forks_light_client.nim | 6 +++--- beacon_chain/spec/light_client_sync.nim | 12 ++++++------ .../test_fixture_light_client_sync_protocol.nim | 4 ++-- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim b/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim index b605f3e4e..e917f246d 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim @@ -222,7 +222,7 @@ proc initLightClientBootstrapForPeriod( forkyBlck.toLightClientHeader(lcDataFork)) dag.lcDataStore.db.putCurrentSyncCommitteeBranch( bid.slot, forkyState.data.build_proof( - altair.CURRENT_SYNC_COMMITTEE_INDEX).get) + altair.CURRENT_SYNC_COMMITTEE_GINDEX).get) else: raiseAssert "Unreachable" res @@ -371,10 +371,10 @@ proc initLightClientUpdateForPeriod( attested_header: forkyBlck.toLightClientHeader(lcDataFork), next_sync_committee: forkyState.data.next_sync_committee, next_sync_committee_branch: - forkyState.data.build_proof(altair.NEXT_SYNC_COMMITTEE_INDEX).get, + forkyState.data.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get, finality_branch: if finalizedBid.slot != FAR_FUTURE_SLOT: - forkyState.data.build_proof(altair.FINALIZED_ROOT_INDEX).get + forkyState.data.build_proof(altair.FINALIZED_ROOT_GINDEX).get else: default(FinalityBranch))) else: raiseAssert "Unreachable" @@ -442,13 +442,13 @@ proc cacheLightClientData( ## block and state. let cachedData = CachedLightClientData( current_sync_committee_branch: - state.data.build_proof(altair.CURRENT_SYNC_COMMITTEE_INDEX).get, + state.data.build_proof(altair.CURRENT_SYNC_COMMITTEE_GINDEX).get, next_sync_committee_branch: - state.data.build_proof(altair.NEXT_SYNC_COMMITTEE_INDEX).get, + state.data.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get, finalized_slot: state.data.finalized_checkpoint.epoch.start_slot, finality_branch: - state.data.build_proof(altair.FINALIZED_ROOT_INDEX).get) + state.data.build_proof(altair.FINALIZED_ROOT_GINDEX).get) if dag.lcDataStore.cache.data.hasKeyOrPut(bid, cachedData): doAssert false, "Redundant `cacheLightClientData` call" @@ -956,7 +956,7 @@ proc getLightClientBootstrap( dag.lcDataStore.db.putHeader(header) dag.lcDataStore.db.putCurrentSyncCommitteeBranch( slot, forkyState.data.build_proof( - altair.CURRENT_SYNC_COMMITTEE_INDEX).get) + altair.CURRENT_SYNC_COMMITTEE_GINDEX).get) else: raiseAssert "Unreachable" do: return default(ForkedLightClientBootstrap) diff --git a/beacon_chain/spec/datatypes/altair.nim b/beacon_chain/spec/datatypes/altair.nim index a32c9ae39..3a7aaf170 100644 --- a/beacon_chain/spec/datatypes/altair.nim +++ b/beacon_chain/spec/datatypes/altair.nim @@ -59,11 +59,11 @@ const # All of these indices are rooted in `BeaconState`. # The first member (`genesis_time`) is 32, subsequent members +1 each. # If there are ever more than 32 members in `BeaconState`, indices change! - # `FINALIZED_ROOT_INDEX` is one layer deeper, i.e., `52 * 2 + 1`. + # `FINALIZED_ROOT_GINDEX` is one layer deeper, i.e., `52 * 2 + 1`. # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/ssz/merkle-proofs.md - FINALIZED_ROOT_INDEX* = 105.GeneralizedIndex # `finalized_checkpoint` > `root` - CURRENT_SYNC_COMMITTEE_INDEX* = 54.GeneralizedIndex # `current_sync_committee` - NEXT_SYNC_COMMITTEE_INDEX* = 55.GeneralizedIndex # `next_sync_committee` + FINALIZED_ROOT_GINDEX* = 105.GeneralizedIndex # finalized_checkpoint > root + CURRENT_SYNC_COMMITTEE_GINDEX* = 54.GeneralizedIndex # current_sync_committee + NEXT_SYNC_COMMITTEE_GINDEX* = 55.GeneralizedIndex # next_sync_committee # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/beacon-chain.md#inactivity-penalties INACTIVITY_SCORE_BIAS* = 4 @@ -157,13 +157,13 @@ type ### Modified/overloaded FinalityBranch* = - array[log2trunc(FINALIZED_ROOT_INDEX), Eth2Digest] + array[log2trunc(FINALIZED_ROOT_GINDEX), Eth2Digest] CurrentSyncCommitteeBranch* = - array[log2trunc(CURRENT_SYNC_COMMITTEE_INDEX), Eth2Digest] + array[log2trunc(CURRENT_SYNC_COMMITTEE_GINDEX), Eth2Digest] NextSyncCommitteeBranch* = - array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] + array[log2trunc(NEXT_SYNC_COMMITTEE_GINDEX), Eth2Digest] # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/altair/light-client/sync-protocol.md#lightclientheader LightClientHeader* = object diff --git a/beacon_chain/spec/datatypes/capella.nim b/beacon_chain/spec/datatypes/capella.nim index cbfd1461d..83c89ac99 100644 --- a/beacon_chain/spec/datatypes/capella.nim +++ b/beacon_chain/spec/datatypes/capella.nim @@ -32,7 +32,7 @@ const # The first member (`randao_reveal`) is 16, subsequent members +1 each. # If there are ever more than 16 members in `BeaconBlockBody`, indices change! # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.3/ssz/merkle-proofs.md - EXECUTION_PAYLOAD_INDEX* = 25.GeneralizedIndex # `execution_payload` + EXECUTION_PAYLOAD_GINDEX* = 25.GeneralizedIndex # execution_payload type SignedBLSToExecutionChangeList* = @@ -120,7 +120,7 @@ type execution_payload: ExecutionPayload): bool {.gcsafe, raises: [].} ExecutionBranch* = - array[log2trunc(EXECUTION_PAYLOAD_INDEX), Eth2Digest] + array[log2trunc(EXECUTION_PAYLOAD_GINDEX), Eth2Digest] # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/sync-protocol.md#modified-lightclientheader LightClientHeader* = object @@ -673,8 +673,8 @@ func is_valid_light_client_header*( is_valid_merkle_branch( get_lc_execution_root(header, cfg), header.execution_branch, - log2trunc(EXECUTION_PAYLOAD_INDEX), - get_subtree_index(EXECUTION_PAYLOAD_INDEX), + log2trunc(EXECUTION_PAYLOAD_GINDEX), + get_subtree_index(EXECUTION_PAYLOAD_GINDEX), header.beacon.body_root) # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/capella/light-client/fork.md#upgrading-light-client-data diff --git a/beacon_chain/spec/datatypes/deneb.nim b/beacon_chain/spec/datatypes/deneb.nim index 1fc0b946a..a89cf0a30 100644 --- a/beacon_chain/spec/datatypes/deneb.nim +++ b/beacon_chain/spec/datatypes/deneb.nim @@ -574,7 +574,7 @@ func kzg_commitment_inclusion_proof_gindex*( # If there are ever more than 16 members in `BeaconBlockBody`, indices change! # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/ssz/merkle-proofs.md const - # `blob_kzg_commitments` + # blob_kzg_commitments BLOB_KZG_COMMITMENTS_GINDEX = 27.GeneralizedIndex # List + 0 = items, + 1 = len @@ -639,8 +639,8 @@ func is_valid_light_client_header*( is_valid_merkle_branch( get_lc_execution_root(header, cfg), header.execution_branch, - log2trunc(EXECUTION_PAYLOAD_INDEX), - get_subtree_index(EXECUTION_PAYLOAD_INDEX), + log2trunc(EXECUTION_PAYLOAD_GINDEX), + get_subtree_index(EXECUTION_PAYLOAD_GINDEX), header.beacon.body_root) # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/deneb/light-client/fork.md#upgrading-light-client-data diff --git a/beacon_chain/spec/forks_light_client.nim b/beacon_chain/spec/forks_light_client.nim index 863ad0929..090e54a2d 100644 --- a/beacon_chain/spec/forks_light_client.nim +++ b/beacon_chain/spec/forks_light_client.nim @@ -878,7 +878,7 @@ func toCapellaLightClientHeader( transactions_root: hash_tree_root(payload.transactions), withdrawals_root: hash_tree_root(payload.withdrawals)), execution_branch: blck.message.body.build_proof( - capella.EXECUTION_PAYLOAD_INDEX).get) + capella.EXECUTION_PAYLOAD_GINDEX).get) # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.0/specs/deneb/light-client/full-node.md#modified-block_to_light_client_header func toDenebLightClientHeader( @@ -920,7 +920,7 @@ func toDenebLightClientHeader( transactions_root: hash_tree_root(payload.transactions), withdrawals_root: hash_tree_root(payload.withdrawals)), execution_branch: blck.message.body.build_proof( - capella.EXECUTION_PAYLOAD_INDEX).get) + capella.EXECUTION_PAYLOAD_GINDEX).get) func toDenebLightClientHeader( blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6) @@ -947,7 +947,7 @@ func toDenebLightClientHeader( withdrawals_root: hash_tree_root(payload.withdrawals), excess_blob_gas: payload.excess_blob_gas), execution_branch: blck.message.body.build_proof( - capella.EXECUTION_PAYLOAD_INDEX).get) + capella.EXECUTION_PAYLOAD_GINDEX).get) func toLightClientHeader*( blck: # `SomeSignedBeaconBlock` doesn't work here (Nim 1.6) diff --git a/beacon_chain/spec/light_client_sync.nim b/beacon_chain/spec/light_client_sync.nim index a7282cea9..0c7b16e53 100644 --- a/beacon_chain/spec/light_client_sync.nim +++ b/beacon_chain/spec/light_client_sync.nim @@ -32,8 +32,8 @@ func initialize_light_client_store*( if not is_valid_merkle_branch( hash_tree_root(bootstrap.current_sync_committee), bootstrap.current_sync_committee_branch, - log2trunc(altair.CURRENT_SYNC_COMMITTEE_INDEX), - get_subtree_index(altair.CURRENT_SYNC_COMMITTEE_INDEX), + log2trunc(altair.CURRENT_SYNC_COMMITTEE_GINDEX), + get_subtree_index(altair.CURRENT_SYNC_COMMITTEE_GINDEX), bootstrap.header.beacon.state_root): return ResultType.err(VerifierError.Invalid) @@ -111,8 +111,8 @@ proc validate_light_client_update*( if not is_valid_merkle_branch( finalized_root, update.finality_branch, - log2trunc(altair.FINALIZED_ROOT_INDEX), - get_subtree_index(altair.FINALIZED_ROOT_INDEX), + log2trunc(altair.FINALIZED_ROOT_GINDEX), + get_subtree_index(altair.FINALIZED_ROOT_GINDEX), update.attested_header.beacon.state_root): return err(VerifierError.Invalid) @@ -130,8 +130,8 @@ proc validate_light_client_update*( if not is_valid_merkle_branch( hash_tree_root(update.next_sync_committee), update.next_sync_committee_branch, - log2trunc(altair.NEXT_SYNC_COMMITTEE_INDEX), - get_subtree_index(altair.NEXT_SYNC_COMMITTEE_INDEX), + log2trunc(altair.NEXT_SYNC_COMMITTEE_GINDEX), + get_subtree_index(altair.NEXT_SYNC_COMMITTEE_GINDEX), update.attested_header.beacon.state_root): return err(VerifierError.Invalid) diff --git a/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim b/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim index 9be052087..b99400da9 100644 --- a/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim +++ b/tests/consensus_spec/altair/test_fixture_light_client_sync_protocol.nim @@ -288,7 +288,7 @@ proc runTest(storeDataFork: static LightClientDataFork) = template next_sync_committee(): auto = state.next_sync_committee let next_sync_committee_branch = - state.build_proof(altair.NEXT_SYNC_COMMITTEE_INDEX).get + state.build_proof(altair.NEXT_SYNC_COMMITTEE_GINDEX).get # Finality is unchanged finality_header = default(storeDataFork.LightClientHeader) @@ -358,7 +358,7 @@ proc runTest(storeDataFork: static LightClientDataFork) = finalized_header.beacon.hash_tree_root() == state.finalized_checkpoint.root let - finality_branch = state.build_proof(altair.FINALIZED_ROOT_INDEX).get + finality_branch = state.build_proof(altair.FINALIZED_ROOT_GINDEX).get update = storeDataFork.LightClientUpdate( attested_header: attested_header, From 06e2ca52867a0d9c1a3359b070d29ace0b39e55c Mon Sep 17 00:00:00 2001 From: tersec Date: Thu, 9 Nov 2023 17:45:07 +0300 Subject: [PATCH 40/45] don't explicitly filter removed file parsedBeaconState.json from holesky (#5584) --- Makefile | 2 +- ci/Jenkinsfile.benchmarks | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 26c29d38a..dfd991c61 100644 --- a/Makefile +++ b/Makefile @@ -120,7 +120,7 @@ endif # We don't need these `vendor/holesky` files but fetching them # may trigger 'This repository is over its data quota' from GitHub -GIT_SUBMODULE_CONFIG := -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz,/custom_config_data/parsedBeaconState.json +GIT_SUBMODULE_CONFIG := -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz ifeq ($(NIM_PARAMS),) # "variables.mk" was not included, so we update the submodules. diff --git a/ci/Jenkinsfile.benchmarks b/ci/Jenkinsfile.benchmarks index 481b84b42..1e30eb54c 100644 --- a/ci/Jenkinsfile.benchmarks +++ b/ci/Jenkinsfile.benchmarks @@ -23,7 +23,7 @@ node("metal") { /* source code checkout */ checkout scm /* we need to update the submodules before caching kicks in */ - sh "git -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz,/custom_config_data/parsedBeaconState.json submodule update --init --recursive" + sh "git -c lfs.fetchexclude=/public-keys/all.txt,/custom_config_data/genesis.ssz submodule update --init --recursive" } stage("Build") { From 68a77926e87697c2fa7b8513b03d3f85ff36e327 Mon Sep 17 00:00:00 2001 From: tersec Date: Thu, 9 Nov 2023 23:35:40 +0300 Subject: [PATCH 41/45] rm ropsten and rinkleby chain IDs from EL manager (#5586) --- beacon_chain/el/el_manager.nim | 2 -- beacon_chain/networking/network_metadata.nim | 2 -- 2 files changed, 4 deletions(-) diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index 271afc47b..313d215f6 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -1380,8 +1380,6 @@ proc exchangeConfigWithSingleEL(m: ELManager, connection: ELConnection) {.async. # https://eips.ethereum.org/EIPS/eip-155#list-of-chain-ids expectedChain = case m.eth1Network.get of mainnet: 1.Quantity - of ropsten: 3.Quantity - of rinkeby: 4.Quantity of goerli: 5.Quantity of sepolia: 11155111.Quantity # https://chainid.network/ of holesky: 17000.Quantity diff --git a/beacon_chain/networking/network_metadata.nim b/beacon_chain/networking/network_metadata.nim index c56a13d30..2a852c0bd 100644 --- a/beacon_chain/networking/network_metadata.nim +++ b/beacon_chain/networking/network_metadata.nim @@ -41,8 +41,6 @@ type Eth1Network* = enum mainnet - ropsten - rinkeby goerli sepolia holesky From 101b723f52e837aaecc8feffeab7e566bafb980e Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Thu, 9 Nov 2023 21:41:17 +0100 Subject: [PATCH 42/45] make `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` configurable (#5582) * make `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` configurable Gnosis uses custom `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` to account for the faster slot timing, so that blobs still remain available for roughly the same amount of real time. Also extend REST config endpoint with full config form `v1.4.0-beta.4`, and extend compatibility checks when loading configs to reduce warnings. --- beacon_chain/nimbus_beacon_node.nim | 10 +- beacon_chain/rpc/rest_config_api.nim | 48 ++++- beacon_chain/spec/datatypes/base.nim | 6 +- beacon_chain/spec/datatypes/constants.nim | 9 +- beacon_chain/spec/presets.nim | 239 ++++++++++++++++++---- beacon_chain/sync/sync_manager.nim | 7 +- beacon_chain/sync/sync_protocol.nim | 4 +- ncli/resttest-rules.json | 2 +- 8 files changed, 269 insertions(+), 56 deletions(-) diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index cdb709527..eb1cfedd5 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -423,11 +423,15 @@ proc initFullNode( validatorChangePool, node.attachedValidators, syncCommitteeMsgPool, lightClientPool, quarantine, blobQuarantine, rng, getBeaconTime, taskpool) syncManager = newSyncManager[Peer, PeerId]( - node.network.peerPool, dag.cfg.DENEB_FORK_EPOCH, SyncQueueKind.Forward, getLocalHeadSlot, + node.network.peerPool, + dag.cfg.DENEB_FORK_EPOCH, dag.cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, + SyncQueueKind.Forward, getLocalHeadSlot, getLocalWallSlot, getFirstSlotAtFinalizedEpoch, getBackfillSlot, getFrontfillSlot, dag.tail.slot, blockVerifier) backfiller = newSyncManager[Peer, PeerId]( - node.network.peerPool, dag.cfg.DENEB_FORK_EPOCH, SyncQueueKind.Backward, getLocalHeadSlot, + node.network.peerPool, + dag.cfg.DENEB_FORK_EPOCH, dag.cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS, + SyncQueueKind.Backward, getLocalHeadSlot, getLocalWallSlot, getFirstSlotAtFinalizedEpoch, getBackfillSlot, getFrontfillSlot, dag.backfill.slot, blockVerifier, maxHeadAge = 0) @@ -1326,7 +1330,7 @@ proc updateGossipStatus(node: BeaconNode, slot: Slot) {.async.} = proc pruneBlobs(node: BeaconNode, slot: Slot) = let blobPruneEpoch = (slot.epoch - - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS - 1) + node.dag.cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS - 1) if slot.is_epoch() and blobPruneEpoch >= node.dag.cfg.DENEB_FORK_EPOCH: var blocks: array[SLOTS_PER_EPOCH.int, BlockId] var count = 0 diff --git a/beacon_chain/rpc/rest_config_api.nim b/beacon_chain/rpc/rest_config_api.nim index 17937a306..970c4a497 100644 --- a/beacon_chain/rpc/rest_config_api.nim +++ b/beacon_chain/rpc/rest_config_api.nim @@ -138,7 +138,7 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: Base10.toString(uint64(KZG_COMMITMENT_INCLUSION_PROOF_DEPTH)), - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/configs/mainnet.yaml + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/configs/mainnet.yaml PRESET_BASE: cfg.PRESET_BASE, CONFIG_NAME: @@ -197,12 +197,56 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = Base10.toString(cfg.MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT), PROPOSER_SCORE_BOOST: Base10.toString(PROPOSER_SCORE_BOOST), + REORG_HEAD_WEIGHT_THRESHOLD: + Base10.toString(REORG_HEAD_WEIGHT_THRESHOLD), + REORG_PARENT_WEIGHT_THRESHOLD: + Base10.toString(REORG_PARENT_WEIGHT_THRESHOLD), + REORG_MAX_EPOCHS_SINCE_FINALIZATION: + Base10.toString(uint64(REORG_MAX_EPOCHS_SINCE_FINALIZATION)), DEPOSIT_CHAIN_ID: Base10.toString(cfg.DEPOSIT_CHAIN_ID), DEPOSIT_NETWORK_ID: Base10.toString(cfg.DEPOSIT_NETWORK_ID), DEPOSIT_CONTRACT_ADDRESS: $cfg.DEPOSIT_CONTRACT_ADDRESS, + GOSSIP_MAX_SIZE: + Base10.toString(GOSSIP_MAX_SIZE), + MAX_REQUEST_BLOCKS: + Base10.toString(MAX_REQUEST_BLOCKS), + EPOCHS_PER_SUBNET_SUBSCRIPTION: + Base10.toString(EPOCHS_PER_SUBNET_SUBSCRIPTION), + MIN_EPOCHS_FOR_BLOCK_REQUESTS: + Base10.toString(cfg.MIN_EPOCHS_FOR_BLOCK_REQUESTS), + MAX_CHUNK_SIZE: + Base10.toString(MAX_CHUNK_SIZE), + TTFB_TIMEOUT: + Base10.toString(TTFB_TIMEOUT), + RESP_TIMEOUT: + Base10.toString(RESP_TIMEOUT), + ATTESTATION_PROPAGATION_SLOT_RANGE: + Base10.toString(ATTESTATION_PROPAGATION_SLOT_RANGE), + MAXIMUM_GOSSIP_CLOCK_DISPARITY: + Base10.toString(MAXIMUM_GOSSIP_CLOCK_DISPARITY.milliseconds.uint64), + MESSAGE_DOMAIN_INVALID_SNAPPY: + to0xHex(MESSAGE_DOMAIN_INVALID_SNAPPY), + MESSAGE_DOMAIN_VALID_SNAPPY: + to0xHex(MESSAGE_DOMAIN_VALID_SNAPPY), + SUBNETS_PER_NODE: + Base10.toString(SUBNETS_PER_NODE), + ATTESTATION_SUBNET_COUNT: + Base10.toString(ATTESTATION_SUBNET_COUNT), + ATTESTATION_SUBNET_EXTRA_BITS: + Base10.toString(ATTESTATION_SUBNET_EXTRA_BITS), + ATTESTATION_SUBNET_PREFIX_BITS: + Base10.toString(ATTESTATION_SUBNET_PREFIX_BITS), + MAX_REQUEST_BLOCKS_DENEB: + Base10.toString(MAX_REQUEST_BLOCKS_DENEB), + MAX_REQUEST_BLOB_SIDECARS: + Base10.toString(MAX_REQUEST_BLOB_SIDECARS), + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: + Base10.toString(cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS), + BLOB_SIDECAR_SUBNET_COUNT: + Base10.toString(BLOB_SIDECAR_SUBNET_COUNT), # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/beacon-chain.md#constants # GENESIS_SLOT @@ -265,8 +309,6 @@ proc installConfigApiHandlers*(router: var RestRouter, node: BeaconNode) = # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/phase0/validator.md#constants TARGET_AGGREGATORS_PER_COMMITTEE: Base10.toString(TARGET_AGGREGATORS_PER_COMMITTEE), - ATTESTATION_SUBNET_COUNT: - Base10.toString(ATTESTATION_SUBNET_COUNT), # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/altair/validator.md#constants TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE: diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index 7b9bec795..c7fe91a77 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -65,13 +65,12 @@ import stew/[assign2, byteutils, results], chronicles, json_serialization, - chronos/timer, ssz_serialization/types as sszTypes, ../../version, ".."/[beacon_time, crypto, digest, presets] export - tables, results, json_serialization, timer, sszTypes, beacon_time, crypto, + tables, results, json_serialization, sszTypes, beacon_time, crypto, digest, presets const SPEC_VERSION* = "1.4.0-beta.4" @@ -82,9 +81,6 @@ const ZERO_HASH* = Eth2Digest() MAX_GRAFFITI_SIZE* = 32 - # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.1/specs/phase0/p2p-interface.md#configuration - MAXIMUM_GOSSIP_CLOCK_DISPARITY* = 500.millis - SLOTS_PER_ETH1_VOTING_PERIOD* = EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH diff --git a/beacon_chain/spec/datatypes/constants.nim b/beacon_chain/spec/datatypes/constants.nim index 44306d2c7..630f86a10 100644 --- a/beacon_chain/spec/datatypes/constants.nim +++ b/beacon_chain/spec/datatypes/constants.nim @@ -5,6 +5,8 @@ # * 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. +import chronos/timer + type Slot* = distinct uint64 Epoch* = distinct uint64 @@ -54,8 +56,11 @@ const # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/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.4.0-beta.1/specs/phase0/fork-choice.md#configuration + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/fork-choice.md#configuration PROPOSER_SCORE_BOOST*: uint64 = 40 + REORG_HEAD_WEIGHT_THRESHOLD*: uint64 = 20 + REORG_PARENT_WEIGHT_THRESHOLD*: uint64 = 160 + REORG_MAX_EPOCHS_SINCE_FINALIZATION* = Epoch(2) # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#configuration BLOB_SIDECAR_SUBNET_COUNT*: uint64 = 6 @@ -64,11 +69,11 @@ const MAX_REQUEST_BLOCKS* = 1024'u64 RESP_TIMEOUT* = 10'u64 ATTESTATION_PROPAGATION_SLOT_RANGE*: uint64 = 32 + MAXIMUM_GOSSIP_CLOCK_DISPARITY* = 500.millis # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/bellatrix/p2p-interface.md#configuration GOSSIP_MAX_SIZE* = 10'u64 * 1024 * 1024 # bytes MAX_CHUNK_SIZE* = 10'u64 * 1024 * 1024 # bytes # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.2/specs/deneb/p2p-interface.md#configuration - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS*: uint64 = 4096 MAX_REQUEST_BLOCKS_DENEB*: uint64 = 128 # TODO Make use of in request code diff --git a/beacon_chain/spec/presets.nim b/beacon_chain/spec/presets.nim index a2b42b19c..74c4c98b3 100644 --- a/beacon_chain/spec/presets.nim +++ b/beacon_chain/spec/presets.nim @@ -9,6 +9,7 @@ import std/[strutils, parseutils, tables, typetraits], + chronos/timer, stew/[byteutils], stint, web3/[ethtypes], ./datatypes/constants @@ -26,21 +27,23 @@ const # Not used anywhere; only for network preset checking EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION: uint64 = 256 - MESSAGE_DOMAIN_INVALID_SNAPPY = 0'u64 - TTFB_TIMEOUT = 5'u64 + TTFB_TIMEOUT* = 5'u64 + MESSAGE_DOMAIN_INVALID_SNAPPY*: array[4, byte] = [0x00, 0x00, 0x00, 0x00] + MESSAGE_DOMAIN_VALID_SNAPPY*: array[4, byte] = [0x01, 0x00, 0x00, 0x00] type Version* = distinct array[4, byte] Eth1Address* = ethtypes.Address RuntimeConfig* = object - ## https://github.com/ethereum/consensus-specs/tree/v1.3.0/configs + ## https://github.com/ethereum/consensus-specs/tree/v1.4.0-beta.4/configs PRESET_BASE*: string CONFIG_NAME*: string # Transition TERMINAL_TOTAL_DIFFICULTY*: UInt256 TERMINAL_BLOCK_HASH*: BlockHash + TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH*: Epoch # Not actively used, but part of the spec # Genesis MIN_GENESIS_ACTIVE_VALIDATOR_COUNT*: uint64 @@ -75,14 +78,37 @@ type # Fork choice # TODO PROPOSER_SCORE_BOOST*: uint64 + # TODO REORG_HEAD_WEIGHT_THRESHOLD*: uint64 + # TODO REORG_PARENT_WEIGHT_THRESHOLD*: uint64 + # TODO REORG_MAX_EPOCHS_SINCE_FINALIZATION*: uint64 # Deposit contract DEPOSIT_CHAIN_ID*: uint64 DEPOSIT_NETWORK_ID*: uint64 DEPOSIT_CONTRACT_ADDRESS*: Eth1Address - # Not actively used, but part of the spec - TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH*: Epoch + # Networking + # TODO GOSSIP_MAX_SIZE*: uint64 + # TODO MAX_REQUEST_BLOCKS*: uint64 + # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION*: uint64 + # TODO MIN_EPOCHS_FOR_BLOCK_REQUESTS*: uint64 + # TODO MAX_CHUNK_SIZE*: uint64 + # TODO TTFB_TIMEOUT*: uint64 + # TODO RESP_TIMEOUT*: uint64 + # TODO ATTESTATION_PROPAGATION_SLOT_RANGE*: uint64 + # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY*: uint64 + # TODO MESSAGE_DOMAIN_INVALID_SNAPPY*: array[4, byte] + # TODO MESSAGE_DOMAIN_VALID_SNAPPY*: array[4, byte] + # TODO SUBNETS_PER_NODE*: uint64 + # TODO ATTESTATION_SUBNET_COUNT*: uint64 + # TODO ATTESTATION_SUBNET_EXTRA_BITS*: uint64 + # TODO ATTESTATION_SUBNET_PREFIX_BITS*: uint64 + + # Deneb + # TODO MAX_REQUEST_BLOCKS_DENEB*: uint64 + # TODO MAX_REQUEST_BLOB_SIDECARS*: uint64 + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS*: uint64 + # TODO BLOB_SIDECAR_SUBNET_COUNT*: uint64 PresetFile* = object values*: Table[string, string] @@ -203,7 +229,46 @@ when const_preset == "mainnet": # Ethereum PoW Mainnet DEPOSIT_CHAIN_ID: 1, DEPOSIT_NETWORK_ID: 1, - DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address) + DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), + + # Networking + # --------------------------------------------------------------- + # `10 * 2**20` (= 10485760, 10 MiB) + # TODO GOSSIP_MAX_SIZE: 10485760, + # `2**10` (= 1024) + # TODO MAX_REQUEST_BLOCKS: 1024, + # `2**8` (= 256) + # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, + # `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) + # TODO MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024, + # `10 * 2**20` (=10485760, 10 MiB) + # TODO MAX_CHUNK_SIZE: 10485760, + # 5s + # TODO TTFB_TIMEOUT: 5, + # 10s + # TODO RESP_TIMEOUT: 10, + # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, + # 500ms + # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, + # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], + # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], + # 2 subnets per node + # TODO SUBNETS_PER_NODE: 2, + # 2**8 (= 64) + # TODO ATTESTATION_SUBNET_COUNT: 64, + # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, + # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS + # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, + + # Deneb + # `2**7` (=128) + # TODO MAX_REQUEST_BLOCKS_DENEB: 128, + # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK + # TODO MAX_REQUEST_BLOB_SIDECARS: 768, + # `2**12` (= 4096 epochs, ~18 days) + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 4096, + # `6` + # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) elif const_preset == "gnosis": @@ -309,7 +374,46 @@ elif const_preset == "gnosis": # Gnosis PoW Mainnet DEPOSIT_CHAIN_ID: 100, DEPOSIT_NETWORK_ID: 100, - DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address) + DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), + + # Networking + # --------------------------------------------------------------- + # `10 * 2**20` (= 10485760, 10 MiB) + # TODO GOSSIP_MAX_SIZE: 10485760, + # `2**10` (= 1024) + # TODO MAX_REQUEST_BLOCKS: 1024, + # `2**8` (= 256) + # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, + # `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 33024, ~5 months) + # TODO MIN_EPOCHS_FOR_BLOCK_REQUESTS: 33024, + # `10 * 2**20` (=10485760, 10 MiB) + # TODO MAX_CHUNK_SIZE: 10485760, + # 5s + # TODO TTFB_TIMEOUT: 5, + # 10s + # TODO RESP_TIMEOUT: 10, + # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, + # 500ms + # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, + # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], + # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], + # 2 subnets per node + # TODO SUBNETS_PER_NODE: 2, + # 2**8 (= 64) + # TODO ATTESTATION_SUBNET_COUNT: 64, + # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, + # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS + # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, + + # Deneb + # `2**7` (=128) + # TODO MAX_REQUEST_BLOCKS_DENEB: 128, + # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK + # TODO MAX_REQUEST_BLOB_SIDECARS: 768, + # `2**12` (= 4096 epochs, ~18 days) + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 16384, + # `6` + # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) elif const_preset == "minimal": @@ -412,7 +516,46 @@ elif const_preset == "minimal": DEPOSIT_CHAIN_ID: 5, DEPOSIT_NETWORK_ID: 5, # Configured on a per testnet basis - DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address) + DEPOSIT_CONTRACT_ADDRESS: default(Eth1Address), + + # Networking + # --------------------------------------------------------------- + # `10 * 2**20` (= 10485760, 10 MiB) + # TODO GOSSIP_MAX_SIZE: 10485760, + # `2**10` (= 1024) + # TODO MAX_REQUEST_BLOCKS: 1024, + # `2**8` (= 256) + # TODO EPOCHS_PER_SUBNET_SUBSCRIPTION: 256, + # [customized] `MIN_VALIDATOR_WITHDRAWABILITY_DELAY + CHURN_LIMIT_QUOTIENT // 2` (= 272) + # TODO MIN_EPOCHS_FOR_BLOCK_REQUESTS: 272, + # `10 * 2**20` (=10485760, 10 MiB) + # TODO MAX_CHUNK_SIZE: 10485760, + # 5s + # TODO TTFB_TIMEOUT: 5, + # 10s + # TODO RESP_TIMEOUT: 10, + # TODO ATTESTATION_PROPAGATION_SLOT_RANGE: 32, + # 500ms + # TODO MAXIMUM_GOSSIP_CLOCK_DISPARITY: 500, + # TODO MESSAGE_DOMAIN_INVALID_SNAPPY: [byte 0x00, 0x00, 0x00, 0x00], + # TODO MESSAGE_DOMAIN_VALID_SNAPPY: [byte 0x01, 0x00, 0x00, 0x00], + # 2 subnets per node + # TODO SUBNETS_PER_NODE: 2, + # 2**8 (= 64) + # TODO ATTESTATION_SUBNET_COUNT: 64, + # TODO ATTESTATION_SUBNET_EXTRA_BITS: 0, + # ceillog2(ATTESTATION_SUBNET_COUNT) + ATTESTATION_SUBNET_EXTRA_BITS + # TODO ATTESTATION_SUBNET_PREFIX_BITS: 6, + + # Deneb + # `2**7` (=128) + # TODO MAX_REQUEST_BLOCKS_DENEB: 128, + # MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK + # TODO MAX_REQUEST_BLOB_SIDECARS: 768, + # `2**12` (= 4096 epochs, ~18 days) + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: 4096, + # `6` + # TODO BLOB_SIDECAR_SUBNET_COUNT: 6, ) else: @@ -443,6 +586,10 @@ else: const SLOTS_PER_SYNC_COMMITTEE_PERIOD* = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD +# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/p2p-interface.md#configuration +func MIN_EPOCHS_FOR_BLOCK_REQUESTS*(cfg: RuntimeConfig): uint64 = + cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + cfg.CHURN_LIMIT_QUOTIENT div 2 + func parse(T: type uint64, input: string): T {.raises: [ValueError].} = var res: BiggestUInt if input.len > 2 and input[0] == '0' and input[1] == 'x': @@ -457,6 +604,10 @@ func parse(T: type uint64, input: string): T {.raises: [ValueError].} = template parse(T: type byte, input: string): T = byte parse(uint64, input) +func parse(T: type array[4, byte], input: string): T + {.raises: [ValueError].} = + hexToByteArray(input, 4) + func parse(T: type Version, input: string): T {.raises: [ValueError].} = Version hexToByteArray(input, 4) @@ -517,27 +668,30 @@ proc readRuntimeConfig*( # Certain config keys are baked into the binary at compile-time # and cannot be overridden via config. + template checkCompatibility(constValue: untyped, name: string): untyped = + if values.hasKey(name): + try: + let value = parse(typeof(constValue), values[name]) + when constValue is distinct: + if distinctBase(value) != distinctBase(constValue): + raise (ref PresetFileError)(msg: + "Cannot override config" & + " (compiled: " & name & "=" & $distinctBase(constValue) & + " - config: " & name & "=" & values[name] & ")") + else: + if value != constValue: + raise (ref PresetFileError)(msg: + "Cannot override config" & + " (compiled: " & name & "=" & $constValue & + " - config: " & name & "=" & values[name] & ")") + values.del name + except ValueError: + raise (ref PresetFileError)(msg: "Unable to parse " & name) + template checkCompatibility(constValue: untyped): untyped = block: const name = astToStr(constValue) - if values.hasKey(name): - try: - let value = parse(typeof(constValue), values[name]) - when constValue is distinct: - if distinctBase(value) != distinctBase(constValue): - raise (ref PresetFileError)(msg: - "Cannot override config" & - " (compiled: " & name & "=" & $distinctBase(constValue) & - " - config: " & name & "=" & values[name] & ")") - else: - if value != constValue: - raise (ref PresetFileError)(msg: - "Cannot override config" & - " (compiled: " & name & "=" & $constValue & - " - config: " & name & "=" & values[name] & ")") - values.del name - except ValueError: - raise (ref PresetFileError)(msg: "Unable to parse " & name) + checkCompatibility(constValue, name) checkCompatibility SECONDS_PER_SLOT @@ -578,7 +732,6 @@ proc readRuntimeConfig*( checkCompatibility TARGET_AGGREGATORS_PER_COMMITTEE checkCompatibility EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION - checkCompatibility ATTESTATION_SUBNET_COUNT checkCompatibility DOMAIN_BEACON_PROPOSER checkCompatibility DOMAIN_BEACON_ATTESTER @@ -595,19 +748,29 @@ proc readRuntimeConfig*( checkCompatibility MAX_REQUEST_BLOCKS checkCompatibility EPOCHS_PER_SUBNET_SUBSCRIPTION checkCompatibility MAX_CHUNK_SIZE + checkCompatibility TTFB_TIMEOUT + checkCompatibility RESP_TIMEOUT + checkCompatibility ATTESTATION_PROPAGATION_SLOT_RANGE + checkCompatibility MAXIMUM_GOSSIP_CLOCK_DISPARITY.milliseconds.uint64, + "MAXIMUM_GOSSIP_CLOCK_DISPARITY" + checkCompatibility MESSAGE_DOMAIN_INVALID_SNAPPY + checkCompatibility MESSAGE_DOMAIN_VALID_SNAPPY checkCompatibility SUBNETS_PER_NODE + checkCompatibility ATTESTATION_SUBNET_COUNT checkCompatibility ATTESTATION_SUBNET_EXTRA_BITS checkCompatibility ATTESTATION_SUBNET_PREFIX_BITS - checkCompatibility BLOB_SIDECAR_SUBNET_COUNT - checkCompatibility MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS - checkCompatibility RESP_TIMEOUT - checkCompatibility TTFB_TIMEOUT - checkCompatibility MESSAGE_DOMAIN_INVALID_SNAPPY - checkCompatibility MAX_REQUEST_BLOCKS_DENEB - checkCompatibility ATTESTATION_PROPAGATION_SLOT_RANGE + checkCompatibility MAX_REQUEST_BLOCKS_DENEB + checkCompatibility MAX_REQUEST_BLOCKS_DENEB * MAX_BLOBS_PER_BLOCK, + "MAX_REQUEST_BLOB_SIDECARS" + checkCompatibility BLOB_SIDECAR_SUBNET_COUNT + + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-beta.4/specs/phase0/fork-choice.md#configuration # Isn't being used as a preset in the usual way: at any time, there's one correct value checkCompatibility PROPOSER_SCORE_BOOST + checkCompatibility REORG_HEAD_WEIGHT_THRESHOLD + checkCompatibility REORG_PARENT_WEIGHT_THRESHOLD + checkCompatibility REORG_MAX_EPOCHS_SINCE_FINALIZATION for name, field in cfg.fieldPairs(): if name in values: @@ -621,6 +784,10 @@ proc readRuntimeConfig*( raise (ref PresetIncompatibleError)( msg: "Config not compatible with binary, compile with -d:const_preset=" & cfg.PRESET_BASE) + # Requires initialized `cfg` + checkCompatibility cfg.MIN_EPOCHS_FOR_BLOCK_REQUESTS, + "MIN_EPOCHS_FOR_BLOCK_REQUESTS" + var unknowns: seq[string] for name in values.keys: unknowns.add name @@ -638,10 +805,6 @@ template name*(cfg: RuntimeConfig): string = else: const_preset -# https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.3/specs/phase0/p2p-interface.md#configuration -func MIN_EPOCHS_FOR_BLOCK_REQUESTS*(cfg: RuntimeConfig): uint64 = - cfg.MIN_VALIDATOR_WITHDRAWABILITY_DELAY + cfg.CHURN_LIMIT_QUOTIENT div 2 - func defaultLightClientDataMaxPeriods*(cfg: RuntimeConfig): uint64 = const epochsPerPeriod = EPOCHS_PER_SYNC_COMMITTEE_PERIOD let maxEpochs = cfg.MIN_EPOCHS_FOR_BLOCK_REQUESTS diff --git a/beacon_chain/sync/sync_manager.nim b/beacon_chain/sync/sync_manager.nim index c0c35567e..4200bc9bc 100644 --- a/beacon_chain/sync/sync_manager.nim +++ b/beacon_chain/sync/sync_manager.nim @@ -49,6 +49,7 @@ type SyncManager*[A, B] = ref object pool: PeerPool[A, B] DENEB_FORK_EPOCH: Epoch + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: uint64 responseTimeout: chronos.Duration maxHeadAge: uint64 getLocalHeadSlot: GetSlotCallback @@ -116,6 +117,7 @@ proc initQueue[A, B](man: SyncManager[A, B]) = proc newSyncManager*[A, B](pool: PeerPool[A, B], denebEpoch: Epoch, + minEpochsForBlobSidecarsRequests: uint64, direction: SyncQueueKind, getLocalHeadSlotCb: GetSlotCallback, getLocalWallSlotCb: GetSlotCallback, @@ -138,6 +140,7 @@ proc newSyncManager*[A, B](pool: PeerPool[A, B], var res = SyncManager[A, B]( pool: pool, DENEB_FORK_EPOCH: denebEpoch, + MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS: minEpochsForBlobSidecarsRequests, getLocalHeadSlot: getLocalHeadSlotCb, getLocalWallSlot: getLocalWallSlotCb, getSafeSlot: getSafeSlot, @@ -187,8 +190,8 @@ proc getBlocks*[A, B](man: SyncManager[A, B], peer: A, proc shouldGetBlobs[A, B](man: SyncManager[A, B], e: Epoch): bool = let wallEpoch = man.getLocalWallSlot().epoch e >= man.DENEB_FORK_EPOCH and - (wallEpoch < MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS or - e >= wallEpoch - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS) + (wallEpoch < man.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS or + e >= wallEpoch - man.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS) proc getBlobSidecars*[A, B](man: SyncManager[A, B], peer: A, req: SyncRequest): Future[BlobSidecarsRes] {.async.} = diff --git a/beacon_chain/sync/sync_protocol.nim b/beacon_chain/sync/sync_protocol.nim index 150cea622..02ae89caf 100644 --- a/beacon_chain/sync/sync_protocol.nim +++ b/beacon_chain/sync/sync_protocol.nim @@ -498,10 +498,10 @@ p2pProtocol BeaconSync(version = 1, let dag = peer.networkState.dag epochBoundary = - if MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS >= dag.head.slot.epoch: + if dag.cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS >= dag.head.slot.epoch: GENESIS_EPOCH else: - dag.head.slot.epoch - MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS + dag.head.slot.epoch - dag.cfg.MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS if startSlot.epoch < epochBoundary: raise newException(ResourceUnavailableError, BlobsOutOfRange) diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 032bd9841..ec19ceb58 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -2826,7 +2826,7 @@ "response": { "status": {"operator": "equals", "value": "200"}, "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], - "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","FIELD_ELEMENTS_PER_BLOB":"","MAX_BLOB_COMMITMENTS_PER_BLOCK":"","MAX_BLOBS_PER_BLOCK":"","KZG_COMMITMENT_INCLUSION_PROOF_DEPTH":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","ATTESTATION_SUBNET_COUNT":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":""}}] + "body": [{"operator": "jstructcmps", "start": ["data"], "value": {"MAX_COMMITTEES_PER_SLOT":"","TARGET_COMMITTEE_SIZE":"","MAX_VALIDATORS_PER_COMMITTEE":"","SHUFFLE_ROUND_COUNT":"","HYSTERESIS_QUOTIENT":"","HYSTERESIS_DOWNWARD_MULTIPLIER":"","HYSTERESIS_UPWARD_MULTIPLIER":"","MIN_DEPOSIT_AMOUNT":"","MAX_EFFECTIVE_BALANCE":"","EFFECTIVE_BALANCE_INCREMENT":"","MIN_ATTESTATION_INCLUSION_DELAY":"","SLOTS_PER_EPOCH":"","MIN_SEED_LOOKAHEAD":"","MAX_SEED_LOOKAHEAD":"","EPOCHS_PER_ETH1_VOTING_PERIOD":"","SLOTS_PER_HISTORICAL_ROOT":"","MIN_EPOCHS_TO_INACTIVITY_PENALTY":"","EPOCHS_PER_HISTORICAL_VECTOR":"","EPOCHS_PER_SLASHINGS_VECTOR":"","HISTORICAL_ROOTS_LIMIT":"","VALIDATOR_REGISTRY_LIMIT":"","BASE_REWARD_FACTOR":"","WHISTLEBLOWER_REWARD_QUOTIENT":"","PROPOSER_REWARD_QUOTIENT":"","INACTIVITY_PENALTY_QUOTIENT":"","MIN_SLASHING_PENALTY_QUOTIENT":"","PROPORTIONAL_SLASHING_MULTIPLIER":"","MAX_PROPOSER_SLASHINGS":"","MAX_ATTESTER_SLASHINGS":"","MAX_ATTESTATIONS":"","MAX_DEPOSITS":"","MAX_VOLUNTARY_EXITS":"","INACTIVITY_PENALTY_QUOTIENT_ALTAIR":"","MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR":"","PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR":"","SYNC_COMMITTEE_SIZE":"","EPOCHS_PER_SYNC_COMMITTEE_PERIOD":"","MIN_SYNC_COMMITTEE_PARTICIPANTS":"","UPDATE_TIMEOUT":"","INACTIVITY_PENALTY_QUOTIENT_BELLATRIX":"","MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX":"","PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX":"","MAX_BYTES_PER_TRANSACTION":"","MAX_TRANSACTIONS_PER_PAYLOAD":"","BYTES_PER_LOGS_BLOOM":"","MAX_EXTRA_DATA_BYTES":"","MAX_BLS_TO_EXECUTION_CHANGES":"","MAX_WITHDRAWALS_PER_PAYLOAD":"","MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP":"","PRESET_BASE":"","CONFIG_NAME":"","TERMINAL_TOTAL_DIFFICULTY":"","TERMINAL_BLOCK_HASH":"","TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":"","MIN_GENESIS_ACTIVE_VALIDATOR_COUNT":"","MIN_GENESIS_TIME":"","GENESIS_FORK_VERSION":"","GENESIS_DELAY":"","ALTAIR_FORK_VERSION":"","ALTAIR_FORK_EPOCH":"","BELLATRIX_FORK_VERSION":"","BELLATRIX_FORK_EPOCH":"","CAPELLA_FORK_VERSION":"","CAPELLA_FORK_EPOCH":"","DENEB_FORK_VERSION":"","DENEB_FORK_EPOCH":"","SECONDS_PER_SLOT":"","SECONDS_PER_ETH1_BLOCK":"","MIN_VALIDATOR_WITHDRAWABILITY_DELAY":"","FIELD_ELEMENTS_PER_BLOB":"","MAX_BLOB_COMMITMENTS_PER_BLOCK":"","MAX_BLOBS_PER_BLOCK":"","KZG_COMMITMENT_INCLUSION_PROOF_DEPTH":"","SHARD_COMMITTEE_PERIOD":"","ETH1_FOLLOW_DISTANCE":"","INACTIVITY_SCORE_BIAS":"","INACTIVITY_SCORE_RECOVERY_RATE":"","EJECTION_BALANCE":"","MIN_PER_EPOCH_CHURN_LIMIT":"","CHURN_LIMIT_QUOTIENT":"","MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":"","PROPOSER_SCORE_BOOST":"","REORG_HEAD_WEIGHT_THRESHOLD":"","REORG_PARENT_WEIGHT_THRESHOLD":"","REORG_MAX_EPOCHS_SINCE_FINALIZATION":"","DEPOSIT_CHAIN_ID":"","DEPOSIT_NETWORK_ID":"","DEPOSIT_CONTRACT_ADDRESS":"","GOSSIP_MAX_SIZE":"","MAX_REQUEST_BLOCKS":"","EPOCHS_PER_SUBNET_SUBSCRIPTION":"","MIN_EPOCHS_FOR_BLOCK_REQUESTS":"","MAX_CHUNK_SIZE":"","TTFB_TIMEOUT":"","RESP_TIMEOUT":"","ATTESTATION_PROPAGATION_SLOT_RANGE":"","MAXIMUM_GOSSIP_CLOCK_DISPARITY":"","MESSAGE_DOMAIN_INVALID_SNAPPY":"","MESSAGE_DOMAIN_VALID_SNAPPY":"","SUBNETS_PER_NODE":"","ATTESTATION_SUBNET_COUNT":"","ATTESTATION_SUBNET_EXTRA_BITS":"","ATTESTATION_SUBNET_PREFIX_BITS":"","MAX_REQUEST_BLOCKS_DENEB":"","MAX_REQUEST_BLOB_SIDECARS":"","MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS":"","BLOB_SIDECAR_SUBNET_COUNT":"","BLS_WITHDRAWAL_PREFIX":"","ETH1_ADDRESS_WITHDRAWAL_PREFIX":"","DOMAIN_BEACON_PROPOSER":"","DOMAIN_BEACON_ATTESTER":"","DOMAIN_RANDAO":"","DOMAIN_DEPOSIT":"","DOMAIN_VOLUNTARY_EXIT":"","DOMAIN_SELECTION_PROOF":"","DOMAIN_AGGREGATE_AND_PROOF":"","TIMELY_SOURCE_FLAG_INDEX":"","TIMELY_TARGET_FLAG_INDEX":"","TIMELY_HEAD_FLAG_INDEX":"","TIMELY_SOURCE_WEIGHT":"","TIMELY_TARGET_WEIGHT":"","TIMELY_HEAD_WEIGHT":"","SYNC_REWARD_WEIGHT":"","PROPOSER_WEIGHT":"","WEIGHT_DENOMINATOR":"","DOMAIN_SYNC_COMMITTEE":"","DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF":"","DOMAIN_CONTRIBUTION_AND_PROOF":"","DOMAIN_BLS_TO_EXECUTION_CHANGE":"","TARGET_AGGREGATORS_PER_COMMITTEE":"","TARGET_AGGREGATORS_PER_SYNC_SUBCOMMITTEE":"","SYNC_COMMITTEE_SUBNET_COUNT":""}}] } }, { From 2db2442580ec9af856a7fef9ff535af37a72d1ab Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 10 Nov 2023 08:40:04 +0100 Subject: [PATCH 43/45] update mdbook versions --- Makefile | 8 ++++---- docs/README.md | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index dfd991c61..cae878854 100644 --- a/Makefile +++ b/Makefile @@ -841,10 +841,10 @@ book: "$(MAKE)" -C docs book auditors-book: - [[ "$$(mdbook --version)" = "mdbook v0.4.28" ]] || { echo "'mdbook v0.4.28' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } - [[ "$$(mdbook-toc --version)" == "mdbook-toc 0.8.0" ]] || { echo "'mdbook-toc 0.8.0' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } - [[ "$$(mdbook-open-on-gh --version)" == "mdbook-open-on-gh 2.3.3" ]] || { echo "'mdbook-open-on-gh 2.3.3' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } - [[ "$$(mdbook-admonish --version)" == "mdbook-admonish 1.7.0" ]] || { echo "'mdbook-open-on-gh 1.7.0' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } + [[ "$$(mdbook --version)" = "mdbook v0.4.35" ]] || { echo "'mdbook v0.4.28' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } + [[ "$$(mdbook-toc --version)" == "mdbook-toc 0.14.1" ]] || { echo "'mdbook-toc 0.14.1' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } + [[ "$$(mdbook-open-on-gh --version)" == "mdbook-open-on-gh 2.4.1" ]] || { echo "'mdbook-open-on-gh 2.4.1' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } + [[ "$$(mdbook-admonish --version)" == "mdbook-admonish 1.13.1" ]] || { echo "'mdbook-open-on-gh 1.13.1' not found in PATH. See 'docs/README.md'. Aborting."; exit 1; } cd docs/the_auditors_handbook && \ mdbook build diff --git a/docs/README.md b/docs/README.md index a335d559b..948686931 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,13 +10,13 @@ Some books in this folder were produced using [mdBook](https://github.com/rust-l ```bash # Install or update tooling (make sure you add "~/.cargo/bin" to PATH): -cargo install mdbook --version 0.4.28 -cargo install mdbook-toc --version 0.8.0 -cargo install mdbook-open-on-gh --version 2.3.3 -cargo install mdbook-admonish --version 1.7.0 +cargo install mdbook --version 0.4.35 +cargo install mdbook-toc --version 0.14.1 +cargo install mdbook-open-on-gh --version 2.4.1 +cargo install mdbook-admonish --version 1.13.1 # Work on the book locally - open "http://localhost:4000" for live version -cd docs/the_nimbus_book +cd docs/the_auditors_handbook mdbook serve -p 4000 # Create a local copy of the book From f388d76e4915bc6e5664f4cfa4a76b0d218157ec Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Fri, 10 Nov 2023 10:16:30 +0100 Subject: [PATCH 44/45] bump `gnosis-chain-configs` to `b8ae3091439131949a994d638d730b5a5cb60f7a` (#5581) - fix(ci): specify enr-cli version - Update deneb config vars --- beacon_chain/spec/presets/gnosis/altair_preset.nim | 4 ++-- beacon_chain/spec/presets/gnosis/bellatrix_preset.nim | 2 +- beacon_chain/spec/presets/gnosis/capella_preset.nim | 2 +- beacon_chain/spec/presets/gnosis/deneb_preset.nim | 6 +++--- beacon_chain/spec/presets/gnosis/phase0_preset.nim | 2 +- vendor/gnosis-chain-configs | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/beacon_chain/spec/presets/gnosis/altair_preset.nim b/beacon_chain/spec/presets/gnosis/altair_preset.nim index 8841c8f41..a78b4a2ec 100644 --- a/beacon_chain/spec/presets/gnosis/altair_preset.nim +++ b/beacon_chain/spec/presets/gnosis/altair_preset.nim @@ -5,8 +5,8 @@ # * 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. -# Mainnet preset - Altair -# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/altair.yaml +# Gnosis preset - Altair +# https://github.com/gnosischain/configs/blob/b8ae3091439131949a994d638d730b5a5cb60f7a/presets/gnosis/altair.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim b/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim index 6b6fe445c..30bb838d6 100644 --- a/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim +++ b/beacon_chain/spec/presets/gnosis/bellatrix_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Bellatrix -# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/bellatrix.yaml +# https://github.com/gnosischain/configs/blob/b8ae3091439131949a994d638d730b5a5cb60f7a/presets/gnosis/bellatrix.yaml const # Updated penalty values # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/capella_preset.nim b/beacon_chain/spec/presets/gnosis/capella_preset.nim index 6807c16b6..aa965e7cc 100644 --- a/beacon_chain/spec/presets/gnosis/capella_preset.nim +++ b/beacon_chain/spec/presets/gnosis/capella_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Capella -# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/capella.yaml +# https://github.com/gnosischain/configs/blob/b8ae3091439131949a994d638d730b5a5cb60f7a/presets/gnosis/capella.yaml const # Max operations per block # --------------------------------------------------------------- diff --git a/beacon_chain/spec/presets/gnosis/deneb_preset.nim b/beacon_chain/spec/presets/gnosis/deneb_preset.nim index 3e34a87f5..403ff5da5 100644 --- a/beacon_chain/spec/presets/gnosis/deneb_preset.nim +++ b/beacon_chain/spec/presets/gnosis/deneb_preset.nim @@ -6,13 +6,13 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Deneb -# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/deneb.yaml +# https://github.com/gnosischain/configs/blob/b8ae3091439131949a994d638d730b5a5cb60f7a/presets/gnosis/deneb.yaml const # `uint64(4096)` FIELD_ELEMENTS_PER_BLOB*: uint64 = 4096 # `uint64(2**12)` (= 4096) MAX_BLOB_COMMITMENTS_PER_BLOCK*: uint64 = 4096 - # `uint64(2**2)` (= 4) - MAX_BLOBS_PER_BLOCK*: uint64 = 4 + # `uint64(6)` + MAX_BLOBS_PER_BLOCK*: uint64 = 6 # `floorlog2(get_generalized_index(BeaconBlockBody, 'blob_kzg_commitments')) + 1 + ceillog2(MAX_BLOB_COMMITMENTS_PER_BLOCK)` = 4 + 1 + 12 = 17 KZG_COMMITMENT_INCLUSION_PROOF_DEPTH* = 17 diff --git a/beacon_chain/spec/presets/gnosis/phase0_preset.nim b/beacon_chain/spec/presets/gnosis/phase0_preset.nim index cd6f9f784..ae77abd55 100644 --- a/beacon_chain/spec/presets/gnosis/phase0_preset.nim +++ b/beacon_chain/spec/presets/gnosis/phase0_preset.nim @@ -6,7 +6,7 @@ # at your option. This file may not be copied, modified, or distributed except according to those terms. # Gnosis preset - Phase0 -# https://github.com/gnosischain/configs/blob/b90374a1c63703db8235fcdb65aff2e909bc42b5/presets/gnosis/phase0.yaml +# https://github.com/gnosischain/configs/blob/b8ae3091439131949a994d638d730b5a5cb60f7a/presets/gnosis/phase0.yaml const # diff --git a/vendor/gnosis-chain-configs b/vendor/gnosis-chain-configs index c8b24c87e..b8ae30914 160000 --- a/vendor/gnosis-chain-configs +++ b/vendor/gnosis-chain-configs @@ -1 +1 @@ -Subproject commit c8b24c87e4cbea8a35b1be6ed5398b519a600928 +Subproject commit b8ae3091439131949a994d638d730b5a5cb60f7a From 1bbd6283a694a1235a75ee11d5adc1a2a3657563 Mon Sep 17 00:00:00 2001 From: Miran Date: Fri, 10 Nov 2023 13:53:32 +0100 Subject: [PATCH 45/45] add dark theme for nimbus.guide (#5564) --- docs/the_nimbus_book/mkdocs.yml | 18 ++++++++++++++---- docs/the_nimbus_book/src/stylesheets/extra.css | 6 ++++++ 2 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 docs/the_nimbus_book/src/stylesheets/extra.css diff --git a/docs/the_nimbus_book/mkdocs.yml b/docs/the_nimbus_book/mkdocs.yml index 2b6abe5e8..952f0b298 100644 --- a/docs/the_nimbus_book/mkdocs.yml +++ b/docs/the_nimbus_book/mkdocs.yml @@ -16,9 +16,20 @@ theme: - navigation.top - content.tabs.link palette: - scheme: default - primary: orange - accent: amber + - scheme: default + primary: orange + accent: amber + toggle: + icon: material/brightness-7 + name: Switch to dark mode + - scheme: slate + primary: black + accent: light blue + toggle: + icon: material/brightness-4 + name: Switch to light mode +extra_css: + - stylesheets/extra.css # Support urls previously used by mdbook use_directory_urls: false @@ -29,7 +40,6 @@ docs_dir: src markdown_extensions: - admonition - - meta - pymdownx.details - pymdownx.highlight: anchor_linenums: true diff --git a/docs/the_nimbus_book/src/stylesheets/extra.css b/docs/the_nimbus_book/src/stylesheets/extra.css new file mode 100644 index 000000000..e49c731ca --- /dev/null +++ b/docs/the_nimbus_book/src/stylesheets/extra.css @@ -0,0 +1,6 @@ +[data-md-color-scheme="slate"] { + --md-hue: 180; + --md-default-bg-color: hsla(var(--md-hue), 0%, 0%, 1); + --md-footer-bg-color: hsla(var(--md-hue), 0%, 0%, 1); + --md-footer-bg-color--dark: hsla(var(--md-hue), 0%, 0%, 1); + }