diff --git a/beacon_chain/rpc/rest_beacon_api.nim b/beacon_chain/rpc/rest_beacon_api.nim index 8fd2a1e7b..c70d15c9f 100644 --- a/beacon_chain/rpc/rest_beacon_api.nim +++ b/beacon_chain/rpc/rest_beacon_api.nim @@ -856,7 +856,8 @@ proc installBeaconApiHandlers*(router: var RestRouter, node: BeaconNode) = of ConsensusFork.Bellatrix: let res = block: - let restBlock = decodeBodyJsonOrSsz(SignedBlindedBeaconBlock, body).valueOr: + let restBlock = decodeBodyJsonOrSsz( + bellatrix_mev.SignedBlindedBeaconBlock, body).valueOr: return RestApiResponse.jsonError(Http400, InvalidBlockObjectError, $error) await node.unblindAndRouteBlockMEV(restBlock) diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index a4bc3dbb9..3cba7eec9 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -13,7 +13,7 @@ import stew/[assign2, results, base10, byteutils], presto/common, import ".."/[eth2_ssz_serialization, forks, keystore], ".."/../consensus_object_pools/block_pools_types, ".."/datatypes/[phase0, altair, bellatrix], - ".."/mev/bellatrix_mev, + ".."/mev/[bellatrix_mev, capella_mev], ".."/../validators/slashing_protection_common, "."/[rest_types, rest_keymanager_types] import nimcrypto/utils as ncrutils @@ -85,7 +85,8 @@ type PrepareBeaconProposer | ProposerSlashing | SetFeeRecipientRequest | - SignedBlindedBeaconBlock | + bellatrix_mev.SignedBlindedBeaconBlock | + capella_mev.SignedBlindedBeaconBlock | SignedValidatorRegistrationV1 | SignedVoluntaryExit | Web3SignerRequest diff --git a/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim index 4941bafc1..1e3bd3711 100644 --- a/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim +++ b/beacon_chain/spec/eth2_apis/rest_beacon_calls.nim @@ -143,7 +143,8 @@ proc publishBlindedBlock*(body: altair.SignedBeaconBlock): RestPlainResponse {. meth: MethodPost.} ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock -proc publishBlindedBlock*(body: SignedBlindedBeaconBlock): RestPlainResponse {. +proc publishBlindedBlock*(body: bellatrix_mev.SignedBlindedBeaconBlock): + RestPlainResponse {. rest, endpoint: "/eth/v1/beacon/blinded_blocks", meth: MethodPost.} ## https://ethereum.github.io/beacon-APIs/#/Beacon/publishBlindedBlock diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index 042db48cf..381f16768 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -18,11 +18,11 @@ import stew/base10, web3/ethtypes, ".."/forks, ".."/datatypes/[phase0, altair, bellatrix, eip4844], - ".."/mev/bellatrix_mev + ".."/mev/[bellatrix_mev, capella_mev] from ".."/datatypes/capella import BeaconBlockBody -export forks, phase0, altair, bellatrix, capella, bellatrix_mev +export forks, phase0, altair, bellatrix, capella, bellatrix_mev, capella_mev const # https://github.com/ethereum/eth2.0-APIs/blob/master/apis/beacon/states/validator_balances.yaml#L17 @@ -633,7 +633,7 @@ type GetEpochCommitteesResponse* = DataEnclosedObject[seq[RestBeaconStatesCommittees]] GetForkScheduleResponse* = DataEnclosedObject[seq[Fork]] GetGenesisResponse* = DataEnclosedObject[RestGenesis] - GetHeaderResponse* = DataVersionEnclosedObject[SignedBuilderBid] + GetHeaderResponse* = DataVersionEnclosedObject[bellatrix_mev.SignedBuilderBid] GetNetworkIdentityResponse* = DataEnclosedObject[RestNetworkIdentity] GetPeerCountResponse* = DataMetaEnclosedObject[RestPeerCount] GetPeerResponse* = DataMetaEnclosedObject[RestNodePeer] @@ -659,7 +659,8 @@ type ProduceBlockResponseV2* = ForkedBeaconBlock ProduceBlindedBlockResponse* = ForkedBlindedBeaconBlock ProduceSyncCommitteeContributionResponse* = DataEnclosedObject[SyncCommitteeContribution] - SubmitBlindedBlockResponse* = DataEnclosedObject[bellatrix.ExecutionPayload] + SubmitBlindedBlockResponseBellatrix* = DataEnclosedObject[bellatrix.ExecutionPayload] + SubmitBlindedBlockResponseCapella* = DataEnclosedObject[capella.ExecutionPayload] GetValidatorsActivityResponse* = DataEnclosedObject[seq[RestActivityItem]] GetValidatorsLivenessResponse* = DataEnclosedObject[seq[RestLivenessItem]] diff --git a/beacon_chain/spec/mev/capella_mev.nim b/beacon_chain/spec/mev/capella_mev.nim new file mode 100644 index 000000000..f21b6527e --- /dev/null +++ b/beacon_chain/spec/mev/capella_mev.nim @@ -0,0 +1,79 @@ +# 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 ".."/datatypes/[altair, capella] +from stew/byteutils import to0xHex + +{.push raises: [].} + +type + # https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/specs/builder.md#builderbid-1 + BuilderBid* = object + header*: capella.ExecutionPayloadHeader # [Modified in Capella] + value*: UInt256 + pubkey*: ValidatorPubKey + + # https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/specs/builder.md#signedbuilderbid-1 + SignedBuilderBid* = object + message*: BuilderBid # [Modified in Capella] + signature*: ValidatorSig + + # https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/specs/builder.md#blindedbeaconblockbody-1 + BlindedBeaconBlockBody = object + randao_reveal*: ValidatorSig + eth1_data*: Eth1Data + graffiti*: GraffitiBytes + proposer_slashings*: List[ProposerSlashing, Limit MAX_PROPOSER_SLASHINGS] + attester_slashings*: List[AttesterSlashing, Limit MAX_ATTESTER_SLASHINGS] + attestations*: List[Attestation, Limit MAX_ATTESTATIONS] + deposits*: List[Deposit, Limit MAX_DEPOSITS] + voluntary_exits*: List[SignedVoluntaryExit, Limit MAX_VOLUNTARY_EXITS] + sync_aggregate*: SyncAggregate + execution_payload_header*: + capella.ExecutionPayloadHeader # [Modified in Capella] + bls_to_execution_changes*: + List[SignedBLSToExecutionChange, + Limit MAX_BLS_TO_EXECUTION_CHANGES] # [New in Capella] + + # https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/specs/builder.md#blindedbeaconblock-1 + BlindedBeaconBlock* = object + slot*: Slot + proposer_index*: uint64 + parent_root*: Eth2Digest + state_root*: Eth2Digest + body*: BlindedBeaconBlockBody # [Modified in Capella] + + # https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/specs/builder.md#signedblindedbeaconblock-1 + SignedBlindedBeaconBlock* = object + message*: BlindedBeaconBlock + signature*: ValidatorSig + +func shortLog*(v: BlindedBeaconBlock): auto = + ( + slot: shortLog(v.slot), + proposer_index: v.proposer_index, + parent_root: shortLog(v.parent_root), + state_root: shortLog(v.state_root), + eth1data: v.body.eth1_data, + graffiti: $v.body.graffiti, + proposer_slashings_len: v.body.proposer_slashings.len(), + attester_slashings_len: v.body.attester_slashings.len(), + attestations_len: v.body.attestations.len(), + deposits_len: v.body.deposits.len(), + voluntary_exits_len: v.body.voluntary_exits.len(), + sync_committee_participants: v.body.sync_aggregate.num_active_participants, + block_number: v.body.execution_payload_header.block_number, + # TODO checksum hex? shortlog? + fee_recipient: to0xHex(v.body.execution_payload_header.fee_recipient.data), + bls_to_execution_changes_len: v.body.bls_to_execution_changes.len() + ) + +func shortLog*(v: SignedBlindedBeaconBlock): auto = + ( + blck: shortLog(v.message), + signature: shortLog(v.signature) + ) diff --git a/beacon_chain/spec/mev/rest_bellatrix_mev_calls.nim b/beacon_chain/spec/mev/rest_bellatrix_mev_calls.nim index eae638843..f609b0a79 100644 --- a/beacon_chain/spec/mev/rest_bellatrix_mev_calls.nim +++ b/beacon_chain/spec/mev/rest_bellatrix_mev_calls.nim @@ -27,8 +27,8 @@ proc getHeader*(slot: Slot, meth: MethodGet, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.2.0/apis/builder/header.yaml -proc submitBlindedBlock*(body: SignedBlindedBeaconBlock - ): RestResponse[SubmitBlindedBlockResponse] {. +proc submitBlindedBlock*(body: bellatrix_mev.SignedBlindedBeaconBlock + ): RestResponse[SubmitBlindedBlockResponseBellatrix] {. rest, endpoint: "/eth/v1/builder/blinded_blocks", meth: MethodPost, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.2.0/apis/builder/blinded_blocks.yaml diff --git a/beacon_chain/spec/mev/rest_capella_mev_calls.nim b/beacon_chain/spec/mev/rest_capella_mev_calls.nim new file mode 100644 index 000000000..0b9c8c944 --- /dev/null +++ b/beacon_chain/spec/mev/rest_capella_mev_calls.nim @@ -0,0 +1,28 @@ +# 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. + +{.push raises: [].} + +import + chronos, presto/client, + ".."/eth2_apis/[rest_types, eth2_rest_serialization] + +export chronos, client, rest_types, eth2_rest_serialization + +# TODO +#proc getHeader*(slot: Slot, +# parent_hash: Eth2Digest, +# pubkey: ValidatorPubKey +# ): RestResponse[GetHeaderResponse] {. +# rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", +# meth: MethodGet, connection: {Dedicated, Close}.} +# ## https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/apis/builder/header.yaml + +proc submitBlindedBlock*(body: capella_mev.SignedBlindedBeaconBlock + ): RestResponse[SubmitBlindedBlockResponseCapella] {. + rest, endpoint: "/eth/v1/builder/blinded_blocks", + meth: MethodPost, connection: {Dedicated, Close}.} + ## https://github.com/jimmygchen/builder-specs/blob/0e15394bc239d3fee1ba9e42f4ce67ff6565537b/apis/builder/blinded_blocks.yaml diff --git a/beacon_chain/validators/message_router_mev.nim b/beacon_chain/validators/message_router_mev.nim index a6492b225..b39b9792b 100644 --- a/beacon_chain/validators/message_router_mev.nim +++ b/beacon_chain/validators/message_router_mev.nim @@ -14,6 +14,7 @@ import ../beacon_node from eth/async_utils import awaitWithTimeout from ../spec/datatypes/bellatrix import SignedBeaconBlock from ../spec/mev/rest_bellatrix_mev_calls import submitBlindedBlock +from ../spec/mev/rest_capella_mev_calls import submitBlindedBlock const BUILDER_BLOCK_SUBMISSION_DELAY_TOLERANCE = 4.seconds @@ -41,7 +42,7 @@ macro copyFields*( newDotExpr(dst, ident(name)), newDotExpr(src, ident(name))) proc unblindAndRouteBlockMEV*( - node: BeaconNode, blindedBlock: SignedBlindedBeaconBlock): + node: BeaconNode, blindedBlock: bellatrix_mev.SignedBlindedBeaconBlock): Future[Result[Opt[BlockRef], string]] {.async.} = # By time submitBlindedBlock is called, must already have done slashing # protection check diff --git a/beacon_chain/validators/validator_duties.nim b/beacon_chain/validators/validator_duties.nim index b850e8cda..d4ef279b8 100644 --- a/beacon_chain/validators/validator_duties.nim +++ b/beacon_chain/validators/validator_duties.nim @@ -38,7 +38,7 @@ import ../gossip_processing/block_processor, ".."/[conf, beacon_clock, beacon_node], "."/[slashing_protection, validator_pool, keystore_management], - ".."/spec/mev/rest_bellatrix_mev_calls + ".."/spec/mev/[rest_bellatrix_mev_calls, rest_capella_mev_calls] from eth/async_utils import awaitWithTimeout @@ -86,7 +86,7 @@ logScope: topics = "beacval" type ForkedBlockResult* = Result[ForkedBeaconBlock, string] - BlindedBlockResult* = Result[BlindedBeaconBlock, string] + BlindedBlockResult* = Result[bellatrix_mev.BlindedBeaconBlock, string] SyncStatus* {.pure.} = enum synced @@ -749,11 +749,12 @@ proc proposeBlockMEV( # This is only substantively asynchronous with a remote key signer let blindedBlock = awaitWithTimeout( - getBlindedBeaconBlock[SignedBlindedBeaconBlock]( + getBlindedBeaconBlock[bellatrix_mev.SignedBlindedBeaconBlock]( node, slot, validator, validator_index, forkedBlck, executionPayloadHeader), 500.milliseconds): - Result[SignedBlindedBeaconBlock, string].err "getBlindedBlock timed out" + Result[bellatrix_mev.SignedBlindedBeaconBlock, string].err( + "getBlindedBlock timed out") if blindedBlock.isErr: info "proposeBlockMEV: getBlindedBeaconBlock failed", @@ -815,7 +816,7 @@ proc makeBlindedBeaconBlockForHeadAndSlot*( return err("Unable to create blinded block") let (executionPayloadHeader, forkedBlck) = blindedBlockParts.get - return ok constructPlainBlindedBlock[BlindedBeaconBlock]( + return ok constructPlainBlindedBlock[bellatrix_mev.BlindedBeaconBlock]( forkedBlck, executionPayloadHeader) from ../spec/datatypes/eip4844 import shortLog diff --git a/beacon_chain/validators/validator_pool.nim b/beacon_chain/validators/validator_pool.nim index a44b5e502..200d8d322 100644 --- a/beacon_chain/validators/validator_pool.nim +++ b/beacon_chain/validators/validator_pool.nim @@ -355,7 +355,7 @@ proc getBlockSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, slot: Slot, block_root: Eth2Digest, blck: ForkedBeaconBlock | ForkedBlindedBeaconBlock | - BlindedBeaconBlock + bellatrix_mev.BlindedBeaconBlock ): Future[SignatureResult] {.async.} = return case v.kind