diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 081f44120..5b62e10f0 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -921,7 +921,7 @@ proc getBlockSSZ*( of BeaconBlockFork.Bellatrix: getBlockSSZ(db, key, data, bellatrix.TrustedSignedBeaconBlock) of BeaconBlockFork.Capella: - raiseAssert $capellaImplementationMissing + getBlockSSZ(db, key, data, capella.TrustedSignedBeaconBlock) proc getBlockSZ*( db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], diff --git a/beacon_chain/consensus_object_pools/block_clearance.nim b/beacon_chain/consensus_object_pools/block_clearance.nim index 77704f81e..0ac937638 100644 --- a/beacon_chain/consensus_object_pools/block_clearance.nim +++ b/beacon_chain/consensus_object_pools/block_clearance.nim @@ -107,9 +107,8 @@ proc addResolvedHeadBlock( var unrealized: FinalityCheckpoints if enableTestFeatures in dag.updateFlags: unrealized = withState(state): - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + static: doAssert high(BeaconStateFork) == BeaconStateFork.Capella + when stateFork >= BeaconStateFork.Altair: forkyState.data.compute_unrealized_finality() else: forkyState.data.compute_unrealized_finality(cache) 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 e6a3ce2fe..23c29a859 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag_light_client.nim @@ -122,9 +122,7 @@ proc syncCommitteeRootForPeriod( bsi = ? dag.getExistingBlockIdAtSlot(syncCommitteeSlot) dag.withUpdatedExistingState(tmpState, bsi) do: withState(state): - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + when stateFork >= BeaconStateFork.Altair: ok forkyState.syncCommitteeRoot else: raiseAssert "Unreachable" do: err() @@ -359,9 +357,7 @@ proc initLightClientUpdateForPeriod( dag.handleUnexpectedLightClientError(bid.slot) return err() withStateAndBlck(state, bdata): - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + when stateFork >= BeaconStateFork.Altair: update.attested_header = blck.toBeaconBlockHeader() update.next_sync_committee = forkyState.data.next_sync_committee update.next_sync_committee_branch = @@ -387,7 +383,6 @@ proc initLightClientUpdateForPeriod( dag.handleUnexpectedLightClientError(signatureBid.slot) return err() withBlck(bdata): - static: doAssert high(BeaconStateFork) == BeaconStateFork.Capella when stateFork >= BeaconStateFork.Altair: update.sync_aggregate = blck.asSigned().message.body.sync_aggregate else: raiseAssert "Unreachable" @@ -623,9 +618,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) = if dag.head.slot < dag.lcDataStore.cache.tailSlot: return withState(dag.headState): - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + when stateFork >= BeaconStateFork.Altair: dag.cacheLightClientData(forkyState, dag.head.bid) else: raiseAssert "Unreachable" # `tailSlot` cannot be before Altair if dag.lcDataStore.importMode == LightClientDataImportMode.OnlyNew: @@ -676,9 +669,7 @@ proc initLightClientDataCache*(dag: ChainDAGRef) = res.err() continue withStateAndBlck(dag.headState, bdata): - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + when stateFork >= BeaconStateFork.Altair: # Cache light client data (non-finalized blocks may refer to this) if i != blocks.low: dag.cacheLightClientData(forkyState, bid) # `dag.head` already cached @@ -764,9 +755,7 @@ proc processHeadChangeForLightClient*(dag: ChainDAGRef) = dag.lcDataStore.db.putBestUpdate( period, dag.lcDataStore.cache.pendingBest.getOrDefault(key)) withState(dag.headState): # Common case separate to avoid `tmpState` copy - when stateFork >= BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing - elif stateFork >= BeaconStateFork.Altair: + when stateFork >= BeaconStateFork.Altair: let key = (headPeriod, forkyState.syncCommitteeRoot) dag.lcDataStore.db.putBestUpdate( headPeriod, dag.lcDataStore.cache.pendingBest.getOrDefault(key)) diff --git a/beacon_chain/rpc/rest_constants.nim b/beacon_chain/rpc/rest_constants.nim index 1c4a7e4cc..8799c4ff4 100644 --- a/beacon_chain/rpc/rest_constants.nim +++ b/beacon_chain/rpc/rest_constants.nim @@ -235,3 +235,5 @@ const "https://github.com/ethereum/beacon-APIs/pull/220" BlockIncorrectFork* = "Block has incorrect fork" + ValidatorNotActive* = + "Validator inactive" diff --git a/beacon_chain/rpc/rest_utils.nim b/beacon_chain/rpc/rest_utils.nim index 17c2c13f5..1dc9fa045 100644 --- a/beacon_chain/rpc/rest_utils.nim +++ b/beacon_chain/rpc/rest_utils.nim @@ -266,7 +266,7 @@ proc getStateOptimistic*(node: BeaconNode, case state.kind of BeaconStateFork.Phase0, BeaconStateFork.Altair: some[bool](false) - of BeaconStateFork.Bellatrix: + of BeaconStateFork.Bellatrix, BeaconStateFork.Capella: # A state is optimistic iff the block which created it is withState(state): # The block root which created the state at slot `n` is at slot `n-1` @@ -276,9 +276,6 @@ proc getStateOptimistic*(node: BeaconNode, doAssert forkyState.data.slot > 0 some[bool](node.dag.is_optimistic( get_block_root_at_slot(forkyState.data, forkyState.data.slot - 1))) - of BeaconStateFork.Capella: - if true: raiseAssert $capellaImplementationMissing - none[bool]() else: none[bool]() diff --git a/beacon_chain/rpc/rest_validator_api.nim b/beacon_chain/rpc/rest_validator_api.nim index 506de9edb..0ce1cf97a 100644 --- a/beacon_chain/rpc/rest_validator_api.nim +++ b/beacon_chain/rpc/rest_validator_api.nim @@ -637,6 +637,12 @@ proc installValidatorApiHandlers*(router: var RestRouter, node: BeaconNode) = get_committee_count_per_slot(shufflingRef), request.slot, request.committee_index) + if not is_active_validator( + getStateField( + node.dag.headState, validators).item(request.validator_index), + request.slot.epoch): + return RestApiResponse.jsonError(Http400, ValidatorNotActive) + node.consensusManager[].actionTracker.registerDuty( request.slot, subnet_id, request.validator_index, request.is_aggregator) diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 51a425d73..8378f07d8 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -18,6 +18,8 @@ import ".."/[eth2_ssz_serialization, forks, keystore], "."/[rest_types, rest_keymanager_types] import nimcrypto/utils as ncrutils +from ".."/datatypes/capella import SignedBeaconBlock + export eth2_ssz_serialization, results, peerid, common, serialization, chronicles, json_serialization, options, net, sets, rest_types, slashing_protection_common @@ -90,6 +92,7 @@ type EncodeOctetTypes* = altair.SignedBeaconBlock | bellatrix.SignedBeaconBlock | + capella.SignedBeaconBlock | phase0.SignedBeaconBlock EncodeArrays* = @@ -898,6 +901,8 @@ template prepareForkedBlockReading( version = some(BeaconBlockFork.Altair) of "BELLATRIX", "bellatrix": version = some(BeaconBlockFork.Bellatrix) + of "CAPELLA", "capella": + version = some(BeaconBlockFork.Bellatrix) else: reader.raiseUnexpectedValue("Incorrect version field value") of "block", "block_header", "data": @@ -1040,7 +1045,8 @@ proc writeValue*[ writer.writeField("version", forkIdentifier "bellatrix") writer.writeField("data", value.bellatrixData) of BeaconBlockFork.Capella: - raiseAssert $capellaImplementationMissing + writer.writeField("version", forkIdentifier "capella") + writer.writeField("data", value.capellaData) writer.endRecord() ## RestPublishedBeaconBlockBody @@ -1337,7 +1343,12 @@ proc readValue*(reader: var JsonReader[RestJson], ) ) of BeaconBlockFork.Capella: - reader.raiseUnexpectedValue($capellaImplementationMissing) + ForkedSignedBeaconBlock.init( + capella.SignedBeaconBlock( + message: blck.capellaData, + signature: signature.get() + ) + ) ) ## ForkedSignedBeaconBlock @@ -1362,6 +1373,8 @@ proc readValue*(reader: var JsonReader[RestJson], version = some(BeaconBlockFork.Altair) of "bellatrix": version = some(BeaconBlockFork.Bellatrix) + of "capella": + version = some(BeaconBlockFork.Capella) else: reader.raiseUnexpectedValue("Incorrect version field value") of "data": @@ -1434,7 +1447,8 @@ proc writeValue*(writer: var JsonWriter[RestJson], writer.writeField("version", "bellatrix") writer.writeField("data", value.bellatrixData) of BeaconBlockFork.Capella: - raiseAssert $capellaImplementationMissing + writer.writeField("version", "capella") + writer.writeField("data", value.capellaData) writer.endRecord() # ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would @@ -1457,6 +1471,7 @@ proc readValue*(reader: var JsonReader[RestJson], of "phase0": some(BeaconStateFork.Phase0) of "altair": some(BeaconStateFork.Altair) of "bellatrix": some(BeaconStateFork.Bellatrix) + of "capella": some(BeaconStateFork.Capella) else: reader.raiseUnexpectedValue("Incorrect version field value") of "data": if data.isSome(): @@ -1533,7 +1548,8 @@ proc writeValue*(writer: var JsonWriter[RestJson], value: ForkedHashedBeaconStat writer.writeField("version", "bellatrix") writer.writeField("data", value.bellatrixData.data) of BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing + writer.writeField("version", "capella") + writer.writeField("data", value.capellaData.data) writer.endRecord() ## Web3SignerRequest @@ -2915,6 +2931,7 @@ proc decodeString*(t: typedesc[BeaconBlockFork], of "phase0": ok(BeaconBlockFork.Phase0) of "altair": ok(BeaconBlockFork.Altair) of "bellatrix": ok(BeaconBlockFork.Bellatrix) + of "capella": ok(BeaconBlockFork.Capella) else: err("Unsupported or invalid beacon block fork version") proc decodeString*(t: typedesc[BeaconStateFork], @@ -2923,4 +2940,5 @@ proc decodeString*(t: typedesc[BeaconStateFork], of "phase0": ok(BeaconStateFork.Phase0) of "altair": ok(BeaconStateFork.Altair) of "bellatrix": ok(BeaconStateFork.Bellatrix) + of "capella": ok(BeaconStateFork.Capella) else: err("Unsupported or invalid beacon state fork version") diff --git a/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim index 24eefcf70..2fa19255a 100644 --- a/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim +++ b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim @@ -16,6 +16,8 @@ import ".."/[helpers, forks, keystore, eth2_ssz_serialization], "."/[rest_types, rest_common, eth2_rest_serialization] +from ".."/datatypes/capella import SignedBeaconBlock + export chronos, client, rest_types, eth2_rest_serialization proc getGenesis*(): RestResponse[GetGenesisResponse] {. @@ -116,6 +118,11 @@ proc publishBlock*(body: bellatrix.SignedBeaconBlock): RestPlainResponse {. meth: MethodPost.} ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock +proc publishBlock*(body: capella.SignedBeaconBlock): RestPlainResponse {. + rest, endpoint: "/eth/v1/beacon/blocks", + meth: MethodPost.} + ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlock + proc publishSszBlock*( client: RestClientRef, blck: ForkySignedBeaconBlock diff --git a/beacon_chain/validator_client/api.nim b/beacon_chain/validator_client/api.nim index a73562924..5546dc7b2 100644 --- a/beacon_chain/validator_client/api.nim +++ b/beacon_chain/validator_client/api.nim @@ -1686,7 +1686,7 @@ proc publishBlock*( of BeaconBlockFork.Bellatrix: publishBlock(it, data.bellatrixData) of BeaconBlockFork.Capella: - raiseAssert $capellaImplementationMissing + publishBlock(it, data.capellaData) do: if apiResponse.isErr(): debug ErrorMessage, endpoint = node, error = apiResponse.error()