diff --git a/AllTests-mainnet.md b/AllTests-mainnet.md index 5ea840b375..ca9814fa8e 100644 --- a/AllTests-mainnet.md +++ b/AllTests-mainnet.md @@ -725,18 +725,6 @@ AllTests-mainnet + Invalid Authorization Token [Beacon Node] [Preset: mainnet] OK + Missing Authorization header [Beacon Node] [Preset: mainnet] OK ``` -## MEV calls serialization/deserialization and behavior test suite -```diff -+ /eth/v1/builder/blinded_blocks [json/json] test OK -+ /eth/v1/builder/blinded_blocks [json/ssz] test OK -+ /eth/v1/builder/blinded_blocks [ssz/json] test OK -+ /eth/v1/builder/blinded_blocks [ssz/ssz] test OK -+ /eth/v1/builder/header [json] test OK -+ /eth/v1/builder/header [ssz] test OK -+ /eth/v1/builder/status test OK -+ /eth/v1/builder/validators [json] test OK -+ /eth/v1/builder/validators [ssz] test OK -``` ## Message signatures ```diff + Aggregate and proof signatures OK diff --git a/beacon_chain/rpc/rest_constants.nim b/beacon_chain/rpc/rest_constants.nim index dfa155d102..ae6db4738f 100644 --- a/beacon_chain/rpc/rest_constants.nim +++ b/beacon_chain/rpc/rest_constants.nim @@ -279,3 +279,4 @@ const "Unable to load state for parent block, database corrupt?" RewardOverflowError* = "Reward value overflow" + InvalidContentTypeError* = "Invalid content type" diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 0660033c54..da85d28920 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -26,7 +26,6 @@ export jsonSerializationResults, rest_keymanager_types from web3/primitives import Hash32, Quantity -from json import getStr, newJString export primitives.Hash32, primitives.Quantity func decodeMediaType*( @@ -83,6 +82,8 @@ RestJson.useDefaultSerializationFor( GetForkChoiceResponse, GetForkScheduleResponse, GetGenesisResponse, + GetHeaderResponseDeneb, + GetHeaderResponseElectra, GetKeystoresResponse, GetNextWithdrawalsResponse, GetPoolAttesterSlashingsResponse, @@ -167,6 +168,8 @@ RestJson.useDefaultSerializationFor( SignedContributionAndProof, SignedValidatorRegistrationV1, SignedVoluntaryExit, + SubmitBlindedBlockResponseDeneb, + SubmitBlindedBlockResponseElectra, SyncAggregate, SyncAggregatorSelectionData, SyncCommittee, @@ -338,8 +341,6 @@ const UnableDecodeVersionError = "Unable to decode version" UnableDecodeError = "Unable to decode data" UnexpectedDecodeError = "Unexpected decoding error" - InvalidContentTypeError* = "Invalid content type" - UnexpectedForkVersionError* = "Unexpected fork version received" type EncodeTypes* = @@ -355,6 +356,9 @@ type SetGasLimitRequest | bellatrix_mev.SignedBlindedBeaconBlock | capella_mev.SignedBlindedBeaconBlock | + deneb_mev.SignedBlindedBeaconBlock | + electra_mev.SignedBlindedBeaconBlock | + fulu_mev.SignedBlindedBeaconBlock | phase0.AttesterSlashing | SignedValidatorRegistrationV1 | SignedVoluntaryExit | @@ -370,10 +374,7 @@ type DenebSignedBlockContents | ElectraSignedBlockContents | FuluSignedBlockContents | - ForkedMaybeBlindedBeaconBlock | - deneb_mev.SignedBlindedBeaconBlock | - electra_mev.SignedBlindedBeaconBlock | - fulu_mev.SignedBlindedBeaconBlock + ForkedMaybeBlindedBeaconBlock EncodeArrays* = seq[phase0.Attestation] | @@ -391,14 +392,6 @@ type seq[RestBeaconCommitteeSelection] | seq[RestSyncCommitteeSelection] - MevDecodeTypes* = - GetHeaderResponseDeneb | - GetHeaderResponseElectra | - GetHeaderResponseFulu | - SubmitBlindedBlockResponseDeneb | - SubmitBlindedBlockResponseElectra | - SubmitBlindedBlockResponseFulu - DecodeTypes* = DataEnclosedObject | DataMetaEnclosedObject | @@ -3273,67 +3266,11 @@ proc decodeBodyJsonOrSsz*( return err( RestErrorMessage.init(Http400, UnableDecodeError, [exc.formatMsg("")])) - ok(data.asSeq) + ok(data.toSeq) else: err(RestErrorMessage.init(Http415, InvalidContentTypeError, [$body.contentType])) -proc decodeBytesJsonOrSsz*( - T: typedesc[MevDecodeTypes], - data: openArray[byte], - contentType: Opt[ContentTypeData], - version: string -): Result[T, RestErrorMessage] = - var res {.noinit.}: T - - let - typeFork = kind(typeof(res.data)) - consensusFork = ConsensusFork.decodeString(version).valueOr: - return err(RestErrorMessage.init(Http400, UnableDecodeVersionError, - [version, $error])) - if typeFork != consensusFork: - return err( - RestErrorMessage.init(Http400, UnexpectedForkVersionError, - ["eth-consensus-version", consensusFork.toString(), - typeFork.toString()])) - - if contentType == ApplicationJsonMediaType: - res = - try: - RestJson.decode( - data, - T, - requireAllFields = true, - allowUnknownFields = true) - except SerializationError as exc: - debug "Failed to deserialize REST JSON data", - err = exc.formatMsg("") - return err( - RestErrorMessage.init(Http400, UnableDecodeError, - [exc.formatMsg("")])) - let jsonFork = ConsensusFork.decodeString(res.version.getStr()).valueOr: - return err(RestErrorMessage.init(Http400, UnableDecodeVersionError, - [res.version.getStr(), $error])) - if typeFork != jsonFork: - return err( - RestErrorMessage.init(Http400, UnexpectedForkVersionError, - ["json-version", res.version.getStr(), - typeFork.toString()])) - ok(res) - elif contentType == OctetStreamMediaType: - ok(T( - version: newJString(typeFork.toString()), - data: - try: - SSZ.decode(data, typeof(res.data)) - except SerializationError as exc: - return err( - RestErrorMessage.init(Http400, UnableDecodeError, - [exc.formatMsg("")])))) - else: - err(RestErrorMessage.init(Http415, InvalidContentTypeError, - [$contentType])) - proc decodeBody*[T](t: typedesc[T], body: ContentBody): Result[T, cstring] = if body.contentType != ApplicationJsonMediaType: @@ -3387,31 +3324,6 @@ proc decodeBodyJsonOrSsz*[T](t: typedesc[T], err(RestErrorMessage.init(Http415, InvalidContentTypeError, [$body.contentType])) -proc encodeBytes*(value: seq[SignedValidatorRegistrationV1], - contentType: string): RestResult[seq[byte]] = - case contentType - of "application/json": - try: - var - stream = memoryOutput() - writer = JsonWriter[RestJson].init(stream) - writer.writeArray(value) - ok(stream.getOutput(seq[byte])) - except IOError: - return err("Input/output error") - except SerializationError: - return err("Serialization error") - of "application/octet-stream": - try: - ok(SSZ.encode( - init( - List[SignedValidatorRegistrationV1, Limit VALIDATOR_REGISTRY_LIMIT], - value))) - except SerializationError: - return err("Serialization error") - else: - err("Content-Type not supported") - proc encodeBytes*[T: EncodeTypes](value: T, contentType: string): RestResult[seq[byte]] = case contentType @@ -3451,26 +3363,29 @@ proc encodeBytes*[T: EncodeArrays](value: T, err("Content-Type not supported") proc encodeBytes*[T: EncodeOctetTypes]( - value: T, - contentType: string -): RestResult[seq[byte]] = + value: T, + contentType: string + ): RestResult[seq[byte]] = case contentType of "application/json": - try: - var - stream = memoryOutput() - writer = JsonWriter[RestJson].init(stream) - writer.writeValue(value) - ok(stream.getOutput(seq[byte])) - except IOError: - err("Input/output error") - except SerializationError: - err("Serialization error") + let data = + try: + var stream = memoryOutput() + var writer = JsonWriter[RestJson].init(stream) + writer.writeValue(value) + stream.getOutput(seq[byte]) + except IOError: + return err("Input/output error") + except SerializationError: + return err("Serialization error") + ok(data) of "application/octet-stream": - try: - ok(SSZ.encode(value)) - except CatchableError: - err("Serialization error") + let data = + try: + SSZ.encode(value) + except CatchableError: + return err("Serialization error") + ok(data) else: err("Content-Type not supported") diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index 3f8abe45b4..b995948ac8 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -518,6 +518,9 @@ type GetEpochCommitteesResponse* = DataEnclosedObject[seq[RestBeaconStatesCommittees]] GetForkScheduleResponse* = DataEnclosedObject[seq[Fork]] GetGenesisResponse* = DataEnclosedObject[RestGenesis] + GetHeaderResponseDeneb* = DataVersionEnclosedObject[deneb_mev.SignedBuilderBid] + GetHeaderResponseElectra* = DataVersionEnclosedObject[electra_mev.SignedBuilderBid] + GetHeaderResponseFulu* = DataVersionEnclosedObject[fulu_mev.SignedBuilderBid] GetNetworkIdentityResponse* = DataEnclosedObject[RestNetworkIdentity] GetPeerCountResponse* = DataMetaEnclosedObject[RestPeerCount] GetPeerResponse* = DataMetaEnclosedObject[RestNodePeer] @@ -543,18 +546,14 @@ type GetEpochSyncCommitteesResponse* = DataEnclosedObject[RestEpochSyncCommittee] ProduceAttestationDataResponse* = DataEnclosedObject[AttestationData] ProduceSyncCommitteeContributionResponse* = DataEnclosedObject[SyncCommitteeContribution] + SubmitBlindedBlockResponseDeneb* = DataEnclosedObject[deneb_mev.ExecutionPayloadAndBlobsBundle] + SubmitBlindedBlockResponseElectra* = DataEnclosedObject[electra_mev.ExecutionPayloadAndBlobsBundle] + SubmitBlindedBlockResponseFulu* = DataEnclosedObject[fulu_mev.ExecutionPayloadAndBlobsBundle] GetValidatorsActivityResponse* = DataEnclosedObject[seq[RestActivityItem]] GetValidatorsLivenessResponse* = DataEnclosedObject[seq[RestLivenessItem]] SubmitBeaconCommitteeSelectionsResponse* = DataEnclosedObject[seq[RestBeaconCommitteeSelection]] SubmitSyncCommitteeSelectionsResponse* = DataEnclosedObject[seq[RestSyncCommitteeSelection]] - GetHeaderResponseDeneb* = DataVersionEnclosedObject[deneb_mev.SignedBuilderBid] - GetHeaderResponseElectra* = DataVersionEnclosedObject[electra_mev.SignedBuilderBid] - GetHeaderResponseFulu* = DataVersionEnclosedObject[fulu_mev.SignedBuilderBid] - SubmitBlindedBlockResponseDeneb* = DataVersionEnclosedObject[deneb_mev.ExecutionPayloadAndBlobsBundle] - SubmitBlindedBlockResponseElectra* = DataVersionEnclosedObject[electra_mev.ExecutionPayloadAndBlobsBundle] - SubmitBlindedBlockResponseFulu* = DataVersionEnclosedObject[fulu_mev.ExecutionPayloadAndBlobsBundle] - RestNodeValidity* {.pure.} = enum valid = "VALID", invalid = "INVALID", diff --git a/beacon_chain/spec/forks.nim b/beacon_chain/spec/forks.nim index 040c0ddd0d..3b4d518e0f 100644 --- a/beacon_chain/spec/forks.nim +++ b/beacon_chain/spec/forks.nim @@ -441,9 +441,7 @@ template kind*( deneb.SigVerifiedSignedBeaconBlock | deneb.MsgTrustedSignedBeaconBlock | deneb.TrustedSignedBeaconBlock | - deneb_mev.SignedBlindedBeaconBlock | - deneb_mev.SignedBuilderBid | - deneb_mev.ExecutionPayloadAndBlobsBundle]): ConsensusFork = + deneb_mev.SignedBlindedBeaconBlock]): ConsensusFork = ConsensusFork.Deneb template kind*( @@ -466,9 +464,7 @@ template kind*( electra.SingleAttestation | electra.AggregateAndProof | electra.SignedAggregateAndProof | - electra_mev.SignedBlindedBeaconBlock | - electra_mev.SignedBuilderBid | - electra_mev.ExecutionPayloadAndBlobsBundle]): ConsensusFork = + electra_mev.SignedBlindedBeaconBlock]): ConsensusFork = ConsensusFork.Electra template kind*( @@ -487,9 +483,7 @@ template kind*( fulu.SigVerifiedSignedBeaconBlock | fulu.MsgTrustedSignedBeaconBlock | fulu.TrustedSignedBeaconBlock | - fulu_mev.SignedBlindedBeaconBlock | - fulu_mev.SignedBuilderBid | - fulu_mev.ExecutionPayloadAndBlobsBundle]): ConsensusFork = + fulu_mev.SignedBlindedBeaconBlock]): ConsensusFork = ConsensusFork.Fulu template BeaconState*(kind: static ConsensusFork): auto = diff --git a/beacon_chain/spec/mev/rest_deneb_mev_calls.nim b/beacon_chain/spec/mev/rest_deneb_mev_calls.nim index 8074bef942..327144d220 100644 --- a/beacon_chain/spec/mev/rest_deneb_mev_calls.nim +++ b/beacon_chain/spec/mev/rest_deneb_mev_calls.nim @@ -1,5 +1,5 @@ # beacon_chain -# Copyright (c) 2023-2025 Status Research & Development GmbH +# Copyright (c) 2023-2024 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). @@ -13,11 +13,6 @@ import export chronos, client, rest_types, eth2_rest_serialization -proc getStatus*(): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/status", - meth: MethodGet.} - ## https://ethereum.github.io/builder-specs/#/Builder/status - proc registerValidator*(body: seq[SignedValidatorRegistrationV1] ): RestPlainResponse {. rest, endpoint: "/eth/v1/builder/validators", @@ -25,33 +20,19 @@ proc registerValidator*(body: seq[SignedValidatorRegistrationV1] ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/validators.yaml ## https://github.com/ethereum/beacon-APIs/blob/v2.3.0/apis/validator/register_validator.yaml -proc getHeaderDenebPlain*( - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", - meth: MethodGet, connection: {Dedicated, Close}.} +proc getHeaderDeneb*(slot: Slot, + parent_hash: Eth2Digest, + pubkey: ValidatorPubKey + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", + meth: MethodGet, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/header.yaml -proc getHeaderDeneb*( - client: RestClientRef, - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): Future[RestPlainResponse] {. - async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = - client.getHeaderDenebPlain( - slot, parent_hash, pubkey, - restAcceptType = "application/octet-stream,application/json;q=0.5", - ) - proc submitBlindedBlockPlain*( body: deneb_mev.SignedBlindedBeaconBlock ): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/blinded_blocks", - meth: MethodPost, connection: {Dedicated, Close}.} + rest, endpoint: "/eth/v1/builder/blinded_blocks", + meth: MethodPost, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml proc submitBlindedBlock*( @@ -59,10 +40,9 @@ proc submitBlindedBlock*( body: deneb_mev.SignedBlindedBeaconBlock ): Future[RestPlainResponse] {. async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = + RestCommunicationError]).} = ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml - client.submitBlindedBlockPlain( + await client.submitBlindedBlockPlain( body, - restAcceptType = "application/octet-stream,application/json;q=0.5", extraHeaders = @[("eth-consensus-version", toString(ConsensusFork.Deneb))] ) diff --git a/beacon_chain/spec/mev/rest_electra_mev_calls.nim b/beacon_chain/spec/mev/rest_electra_mev_calls.nim index 6984c5571c..2b92d8a55d 100644 --- a/beacon_chain/spec/mev/rest_electra_mev_calls.nim +++ b/beacon_chain/spec/mev/rest_electra_mev_calls.nim @@ -1,5 +1,5 @@ # beacon_chain -# Copyright (c) 2024-2025 Status Research & Development GmbH +# Copyright (c) 2024 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). @@ -13,44 +13,29 @@ import export chronos, client, rest_types, eth2_rest_serialization -proc getHeaderElectraPlain*( - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", - meth: MethodGet, connection: {Dedicated, Close}.} +proc getHeaderElectra*(slot: Slot, + parent_hash: Eth2Digest, + pubkey: ValidatorPubKey + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", + meth: MethodGet, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/header.yaml -proc getHeaderElectra*( - client: RestClientRef, - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): Future[RestPlainResponse] {. - async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = - client.getHeaderElectraPlain( - slot, parent_hash, pubkey, - restAcceptType = "application/octet-stream,application/json;q=0.5", - ) - proc submitBlindedBlockPlain*( body: electra_mev.SignedBlindedBeaconBlock ): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/blinded_blocks", - meth: MethodPost, connection: {Dedicated, Close}.} + rest, endpoint: "/eth/v1/builder/blinded_blocks", + meth: MethodPost, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml proc submitBlindedBlock*( - client: RestClientRef, - body: electra_mev.SignedBlindedBeaconBlock + client: RestClientRef, + body: electra_mev.SignedBlindedBeaconBlock ): Future[RestPlainResponse] {. async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = + RestCommunicationError]).} = ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml - client.submitBlindedBlockPlain( + await client.submitBlindedBlockPlain( body, - restAcceptType = "application/octet-stream,application/json;q=0.5", extraHeaders = @[("eth-consensus-version", toString(ConsensusFork.Electra))] ) diff --git a/beacon_chain/spec/mev/rest_fulu_mev_calls.nim b/beacon_chain/spec/mev/rest_fulu_mev_calls.nim index 61bd649bcd..8be08ae3c5 100644 --- a/beacon_chain/spec/mev/rest_fulu_mev_calls.nim +++ b/beacon_chain/spec/mev/rest_fulu_mev_calls.nim @@ -1,5 +1,5 @@ # beacon_chain -# Copyright (c) 2024-2025 Status Research & Development GmbH +# Copyright (c) 2024 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). @@ -13,33 +13,19 @@ import export chronos, client, rest_types, eth2_rest_serialization -proc getHeaderFuluPlain*( - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", - meth: MethodGet, connection: {Dedicated, Close}.} +proc getHeaderFulu*(slot: Slot, + parent_hash: Eth2Digest, + pubkey: ValidatorPubKey + ): RestPlainResponse {. + rest, endpoint: "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}", + meth: MethodGet, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/header.yaml -proc getHeaderFulu*( - client: RestClientRef, - slot: Slot, - parent_hash: Eth2Digest, - pubkey: ValidatorPubKey -): Future[RestPlainResponse] {. - async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = - client.getHeaderFuluPlain( - slot, parent_hash, pubkey, - restAcceptType = "application/octet-stream,application/json;q=0.5", - ) - proc submitBlindedBlockPlain*( body: fulu_mev.SignedBlindedBeaconBlock ): RestPlainResponse {. - rest, endpoint: "/eth/v1/builder/blinded_blocks", - meth: MethodPost, connection: {Dedicated, Close}.} + rest, endpoint: "/eth/v1/builder/blinded_blocks", + meth: MethodPost, connection: {Dedicated, Close}.} ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml proc submitBlindedBlock*( @@ -47,10 +33,9 @@ proc submitBlindedBlock*( body: fulu_mev.SignedBlindedBeaconBlock ): Future[RestPlainResponse] {. async: (raises: [CancelledError, RestEncodingError, RestDnsResolveError, - RestCommunicationError], raw: true).} = + RestCommunicationError]).} = ## https://github.com/ethereum/builder-specs/blob/v0.4.0/apis/builder/blinded_blocks.yaml - client.submitBlindedBlockPlain( + await client.submitBlindedBlockPlain( body, - restAcceptType = "application/octet-stream,application/json;q=0.5", extraHeaders = @[("eth-consensus-version", toString(ConsensusFork.Fulu))] ) diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 726c1b42ee..075f756348 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -391,7 +391,7 @@ proc get_builder_signature*( proc verify_builder_signature*( fork: Fork, msg: deneb_mev.BuilderBid | electra_mev.BuilderBid | - fulu_mev.BuilderBid | ValidatorRegistrationV1, + fulu_mev.BuilderBid, pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool = let signing_root = compute_builder_signing_root(fork, msg) blsVerify(pubkey, signing_root.data, signature) diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index e5453eb850..c43034be7b 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -646,9 +646,8 @@ proc getBlindedExecutionPayload[ BUILDER_PROPOSAL_DELAY_TOLERANCE): return err "Timeout obtaining Deneb blinded header from builder" - res = decodeBytesJsonOrSsz( - GetHeaderResponseDeneb, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + res = decodeBytes( + GetHeaderResponseDeneb, response.data, response.contentType) blindedHeader = res.valueOr: return err( @@ -663,9 +662,8 @@ proc getBlindedExecutionPayload[ BUILDER_PROPOSAL_DELAY_TOLERANCE): return err "Timeout obtaining Electra blinded header from builder" - res = decodeBytesJsonOrSsz( - GetHeaderResponseElectra, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + res = decodeBytes( + GetHeaderResponseElectra, response.data, response.contentType) blindedHeader = res.valueOr: return err( @@ -682,9 +680,8 @@ proc getBlindedExecutionPayload[ BUILDER_PROPOSAL_DELAY_TOLERANCE): return err "Timeout obtaining Fulu blinded header from builder" - res = decodeBytesJsonOrSsz( - GetHeaderResponseFulu, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + res = decodeBytes( + GetHeaderResponseFulu, response.data, response.contentType) blindedHeader = res.valueOr: return err( diff --git a/beacon_chain/validators/message_router_mev.nim b/beacon_chain/validators/message_router_mev.nim index b6bf3951cc..d8633e46c3 100644 --- a/beacon_chain/validators/message_router_mev.nim +++ b/beacon_chain/validators/message_router_mev.nim @@ -1,5 +1,5 @@ # beacon_chain -# Copyright (c) 2022-2025 Status Research & Development GmbH +# Copyright (c) 2022-2024 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). @@ -87,17 +87,14 @@ proc unblindAndRouteBlockMEV*( $response.status & ": " & $shortLog(blindedBlock)) when blindedBlock is deneb_mev.SignedBlindedBeaconBlock: - let res = decodeBytesJsonOrSsz( - SubmitBlindedBlockResponseDeneb, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + let res = decodeBytes( + SubmitBlindedBlockResponseDeneb, response.data, response.contentType) elif blindedBlock is electra_mev.SignedBlindedBeaconBlock: - let res = decodeBytesJsonOrSsz( - SubmitBlindedBlockResponseElectra, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + let res = decodeBytes( + SubmitBlindedBlockResponseElectra, response.data, response.contentType) elif blindedBlock is fulu_mev.SignedBlindedBeaconBlock: - let res = decodeBytesJsonOrSsz( - SubmitBlindedBlockResponseFulu, response.data, response.contentType, - response.headers.getString("eth-consensus-version")) + let res = decodeBytes( + SubmitBlindedBlockResponseFulu, response.data, response.contentType) else: static: doAssert false diff --git a/tests/all_tests.nim b/tests/all_tests.nim index b3f86ada9b..303d032031 100644 --- a/tests/all_tests.nim +++ b/tests/all_tests.nim @@ -63,7 +63,6 @@ import # Unit test ./test_validator_client, ./test_beacon_validators, ./test_beacon_chain_file, - ./test_mev_calls, ./test_keymanager_api # currently has to run after test_remote_keystore summarizeLongTests("AllTests") diff --git a/tests/test_mev_calls.nim b/tests/test_mev_calls.nim deleted file mode 100644 index cba58f1124..0000000000 --- a/tests/test_mev_calls.nim +++ /dev/null @@ -1,627 +0,0 @@ -# beacon_chain -# Copyright (c) 2025 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: [].} -{.used.} - -import - stew/[bitseqs, endians2, objects], - blscurve, bearssl/rand, - results, chronos, presto, unittest2, - chronos/unittest2/asynctests, - ../beacon_chain/spec/[presets, crypto, signatures, eth2_ssz_serialization, - helpers, forks], - ../beacon_chain/spec/mev/[deneb_mev, electra_mev, fulu_mev, - rest_deneb_mev_calls, rest_electra_mev_calls, - rest_fulu_mev_calls], - ../beacon_chain/rpc/rest_utils - -from std/times import Time, toUnix, fromUnix, getTime - -const - DenebSlot = Slot(32000) - ElectraSlot = Slot(64000) - FuluSlot = Slot(96000) - emptyFork = Fork() - emptyRoot = Eth2Digest() - -type - MevBlocks = deneb_mev.SignedBlindedBeaconBlock | - electra_mev.SignedBlindedBeaconBlock | - fulu_mev.SignedBlindedBeaconBlock - - TestNodeRef* = ref object - validators: seq[ValidatorPubKey] - - TestKind* {.pure.} = enum - Json, Ssz - -proc keyGen(rng: var HmacDrbgContext): BlsResult[ValidatorPrivKey] = - var - pubkey: blscurve.PublicKey - seckey: blscurve.SecretKey - let bytes = rng.generate(array[32, byte]) - if not keyGen(bytes, pubkey, seckey): - return err "key generation failed" - ok(ValidatorPrivKey(seckey)) - -func specifiedFeeRecipient(x: int): Eth1Address = - copyMem(addr result, unsafeAddr x, sizeof x) - -proc prepareRegistration( - fork: Fork, - key: ValidatorPrivKey, - gas_limit: uint64 = 0'u64, - timestamp: Time, - feeRecipient: Eth1Address -): SignedValidatorRegistrationV1 = - var msg = - SignedValidatorRegistrationV1( - message: ValidatorRegistrationV1( - fee_recipient: ExecutionAddress(data: distinctBase(feeRecipient)), - gas_limit: gas_limit, - timestamp: uint64(timestamp.toUnix()), - pubkey: key.toPubKey().toPubKey() - )) - msg.signature = get_builder_signature(fork, msg.message, key).toValidatorSig() - msg - -proc generateRegistrations( - rng: var HmacDrbgContext, - count: int -): seq[SignedValidatorRegistrationV1] = - var res: seq[SignedValidatorRegistrationV1] - for index in 0 ..< count: - let - privateKey = keyGen(rng).valueOr: - raiseAssert "Unable to generate private key" - feeRecipient = specifiedFeeRecipient(index) - res.add(prepareRegistration( - emptyFork, privateKey, 30_000_000'u64, getTime(), feeRecipient)) - res - -proc prepare( - T: typedesc[MevBlocks], - slot: Slot, - parent_hash: Eth2Digest, - proposer_index: uint64, - privateKey: ValidatorPrivKey -): T = - var tmp: T - let - blindedBlock = typeof(tmp.message)( - slot: slot, - proposer_index: proposer_index, - body: typeof(tmp.message.body)( - execution_payload_header: - typeof(tmp.message.body.execution_payload_header)( - parent_hash: parent_hash - ))) - block_root = hash_tree_root(blindedBlock) - T(message: blindedBlock, - signature: get_block_signature(emptyFork, emptyRoot, slot, block_root, - privateKey).toValidatorSig()) - -proc jsonResponseSignedBuilderBid( - t: typedesc[RestApiResponse], - bid: deneb_mev.SignedBuilderBid | electra_mev.SignedBuilderBid | - fulu_mev.SignedBuilderBid -): RestApiResponse = - let - consensusFork = typeof(bid).kind() - headers = [("eth-consensus-version", consensusFork.toString())] - res = - try: - var stream = memoryOutput() - var writer = JsonWriter[RestJson].init(stream) - writer.beginRecord() - writer.writeField("version", consensusFork.toString()) - writer.writeField("data", bid) - writer.endRecord() - stream.getOutput(seq[byte]) - except IOError: - default(seq[byte]) - RestApiResponse.response(res, Http200, "application/json", headers = headers) - -proc jsonResponseExecutionPayloadAndBlobsBundle( - t: typedesc[RestApiResponse], - payload: deneb_mev.ExecutionPayloadAndBlobsBundle | - electra_mev.ExecutionPayloadAndBlobsBundle | - fulu_mev.ExecutionPayloadAndBlobsBundle -): RestApiResponse = - let - consensusFork = typeof(payload).kind() - headers = [("eth-consensus-version", consensusFork.toString())] - res = - try: - var stream = memoryOutput() - var writer = JsonWriter[RestJson].init(stream) - writer.beginRecord() - writer.writeField("version", consensusFork.toString()) - writer.writeField("data", payload) - writer.endRecord() - stream.getOutput(seq[byte]) - except IOError: - default(seq[byte]) - RestApiResponse.response(res, Http200, "application/json", headers = headers) - -proc sszResponseSignedBuilderBid*( - t: typedesc[RestApiResponse], - bid: deneb_mev.SignedBuilderBid | electra_mev.SignedBuilderBid | - fulu_mev.SignedBuilderBid, -): RestApiResponse = - mixin kind - let - consensusFork = typeof(bid).kind() - headers = [("eth-consensus-version", consensusFork.toString())] - res = - try: - var stream = memoryOutput() - var writer = SszWriter.init(stream) - writer.writeValue(bid) - stream.getOutput(seq[byte]) - except IOError: - default(seq[byte]) - RestApiResponse.response(res, Http200, "application/octet-stream", - headers = headers) - -proc sszResponseExecutionPayloadAndBlobsBundle*( - t: typedesc[RestApiResponse], - payload: deneb_mev.ExecutionPayloadAndBlobsBundle | - electra_mev.ExecutionPayloadAndBlobsBundle | - fulu_mev.ExecutionPayloadAndBlobsBundle, -): RestApiResponse = - mixin kind - let - consensusFork = typeof(payload).kind() - headers = [("eth-consensus-version", consensusFork.toString())] - res = - try: - var stream = memoryOutput() - var writer = SszWriter.init(stream) - writer.writeValue(payload) - stream.getOutput(seq[byte]) - except IOError: - default(seq[byte]) - RestApiResponse.response(res, Http200, "application/octet-stream", - headers = headers) - -proc setupEngineAPI*(router: var RestRouter, node: TestNodeRef) = - router.api2(MethodPost, "/eth/v1/builder/validators") do ( - contentBody: Option[ContentBody]) -> RestApiResponse: - - if contentBody.isNone: - return RestApiResponse.jsonError(Http400, EmptyRequestBodyError) - - let registrations = - decodeBodyJsonOrSsz(seq[SignedValidatorRegistrationV1], - contentBody.get()).valueOr: - return RestApiResponse.jsonError(error) - - for item in registrations: - if not(verify_builder_signature(emptyFork, item.message, - item.message.pubkey, item.signature)): - return RestApiResponse.jsonError(Http400, - "Signature verification failed") - RestApiResponse.jsonResponse(Http200) - - router.api2(MethodGet, - "/eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}") do ( - slot: Slot, parent_hash: Eth2Digest, - pubkey: ValidatorPubKey) -> RestApiResponse: - let - qslot = slot.valueOr: - return RestApiResponse.jsonError(Http400, "Invalid slot", $error) - qhash = parent_hash.valueOr: - return RestApiResponse.jsonError(Http400, "Invalid parent_hash", $error) - qpubkey {.used.} = pubkey.valueOr: - return RestApiResponse.jsonError(Http400, "Invalid pubkey", $error) - contentType = preferredContentType(jsonMediaType, - sszMediaType).valueOr: - return RestApiResponse.jsonError(Http406, "Content is not acceptable") - - template respondSszOrJson(contentType, bid: auto): RestApiResponse = - if contentType == sszMediaType: - RestApiResponse.sszResponseSignedBuilderBid(bid) - elif contentType == jsonMediaType: - RestApiResponse.jsonResponseSignedBuilderBid(bid) - else: - RestApiResponse.jsonError(Http415, "Invalid Accept") - - if qslot == DenebSlot: - let bid = deneb_mev.SignedBuilderBid( - message: deneb_mev.BuilderBid( - header: deneb.ExecutionPayloadHeader(parent_hash: qhash)) - ) - respondSszOrJson(contentType, bid) - elif qslot == ElectraSlot: - let bid = electra_mev.SignedBuilderBid( - message: electra_mev.BuilderBid( - header: electra.ExecutionPayloadHeader(parent_hash: qhash)) - ) - respondSszOrJson(contentType, bid) - elif qslot == FuluSlot: - let bid = fulu_mev.SignedBuilderBid( - message: fulu_mev.BuilderBid( - header: fulu.ExecutionPayloadHeader(parent_hash: qhash)) - ) - respondSszOrJson(contentType, bid) - else: - RestApiResponse.jsonError(Http500, "Unsupported slot number") - - router.api2(MethodPost, "/eth/v1/builder/blinded_blocks") do ( - contentBody: Option[ContentBody]) -> RestApiResponse: - - if contentBody.isNone: - return RestApiResponse.jsonError(Http400, EmptyRequestBodyError) - - let - rawVersion = request.headers.getString("eth-consensus-version") - consensusFork = ConsensusFork.decodeString(rawVersion).valueOr: - return RestApiResponse.jsonError(Http400, "Invalid consensus version") - contentType = preferredContentType(jsonMediaType, - sszMediaType).valueOr: - return RestApiResponse.jsonError(Http406, "Content type not acceptable") - - if consensusFork < ConsensusFork.Deneb: - return RestApiResponse.jsonError(Http400, "Unsupported fork version") - - template respondSszOrJson(contentType, payload: auto): RestApiResponse = - if contentType == sszMediaType: - RestApiResponse.sszResponseExecutionPayloadAndBlobsBundle(payload) - elif contentType == jsonMediaType: - RestApiResponse.jsonResponseExecutionPayloadAndBlobsBundle(payload) - else: - RestApiResponse.jsonError(Http415, "Invalid Accept") - - if consensusFork == ConsensusFork.Deneb: - let - blck = - decodeBodyJsonOrSsz(deneb_mev.SignedBlindedBeaconBlock, - contentBody.get()).valueOr: - return RestApiResponse.jsonError(error) - proposerKey = - if int(blck.message.proposer_index) < len(node.validators): - node.validators[int(blck.message.proposer_index)] - else: - ValidatorPubKey() - slot = blck.message.slot - blockRoot = hash_tree_root(blck.message) - - if not(verify_block_signature(emptyFork, emptyRoot, slot, blockRoot, - proposerKey, blck.signature)): - return RestApiResponse.jsonError(Http400, "Invalid signature") - - let - payload = deneb_mev.ExecutionPayloadAndBlobsBundle( - execution_payload: deneb.ExecutionPayload( - parent_hash: blck.message.body.execution_payload_header.parent_hash - ), - blobs_bundle: BlobsBundle() - ) - respondSszOrJson(contentType, payload) - elif consensusFork == ConsensusFork.Electra: - let - blck = - decodeBodyJsonOrSsz(electra_mev.SignedBlindedBeaconBlock, - contentBody.get()).valueOr: - return RestApiResponse.jsonError(error) - payload = electra_mev.ExecutionPayloadAndBlobsBundle( - execution_payload: electra.ExecutionPayload( - parent_hash: blck.message.body.execution_payload_header.parent_hash - ), - blobs_bundle: BlobsBundle() - ) - respondSszOrJson(contentType, payload) - elif consensusFork == ConsensusFork.Fulu: - let - blck = - decodeBodyJsonOrSsz(fulu_mev.SignedBlindedBeaconBlock, - contentBody.get()).valueOr: - return RestApiResponse.jsonError(error) - payload = fulu_mev.ExecutionPayloadAndBlobsBundle( - execution_payload: fulu.ExecutionPayload( - parent_hash: blck.message.body.execution_payload_header.parent_hash - ), - blobs_bundle: BlobsBundle() - ) - respondSszOrJson(contentType, payload) - else: - raiseAssert "Unsupported fork version" - - router.api2(MethodGet, "/eth/v1/builder/status") do () -> RestApiResponse: - RestApiResponse.response(Http200) - -proc testSuite() = - - suite "MEV calls serialization/deserialization and behavior test suite": - let - rng = HmacDrbgContext.new() - node = TestNodeRef() - var router = RestRouter.init(proc(pattern: string, value: string): int = 0) - setupEngineAPI(router, node) - - let - bindAddress = try: - initTAddress("127.0.0.1", Port(0)) - except TransportAddressError as exc: - raiseAssert "Unexpected error, reason " & $exc.msg - - server = RestServerRef.new(router, bindAddress).valueOr: - raiseAssert "Unable to establish REST server, reason " & $error - address = server.localAddress() - - server.start() - - setup: - let - httpFlags: set[HttpClientFlag] = {} - prestoFlags = {RestClientFlag.CommaSeparatedArray} - socketFlags = {SocketFlags.TcpNoDelay} - remoteUri = "http://" & $address & "/" - client = RestClientRef.new( - remoteUri, prestoFlags, httpFlags, socketFlags = socketFlags).valueOr: - raiseAssert "Unable to resolve distributed signer address " & $address - - teardown: - waitFor client.closeWait() - - template getHeaderTest(responseKind: TestKind): untyped = - let - bytes = rng[].generate(array[32, byte]) - parent_hash = Eth2Digest(data: bytes) - privateKey = keyGen(rng[]).valueOr: - raiseAssert "Unable to generate private key" - publicKey = privateKey.toPubKey().toPubKey() - (restAcceptType1, responseMediaType1) = - if responseKind == TestKind.Ssz: - ("application/octet-stream", OctetStreamMediaType) - else: - ("application/json", ApplicationJsonMediaType) - (restAcceptType2, responseMediaType2) = - if responseKind == TestKind.Ssz: - ("application/json;q=0.9,application/octet-stream", - OctetStreamMediaType) - else: - ("application/octet-stream;q=0.9,application/json", - ApplicationJsonMediaType) - (restAcceptType3, responseMediaType3) = - if responseKind == TestKind.Ssz: - ("application/json;q=0.5,application/octet-stream;q=1.0", - OctetStreamMediaType) - else: - ("application/octet-stream;q=0.5,application/json;q=1.0", - ApplicationJsonMediaType) - - let - response1 = - await client.getHeaderDenebPlain(DenebSlot, parent_hash, - publicKey, restAcceptType = restAcceptType1) - response2 = - await client.getHeaderElectraPlain(ElectraSlot, parent_hash, - publicKey, restAcceptType = restAcceptType2) - response3 = - await client.getHeaderFuluPlain(FuluSlot, parent_hash, - publicKey, restAcceptType = restAcceptType3) - - check: - response1.status == 200 - response2.status == 200 - response3.status == 200 - response1.contentType.isSome() - response2.contentType.isSome() - response3.contentType.isSome() - response1.contentType.get().mediaType == responseMediaType1 - response2.contentType.get().mediaType == responseMediaType2 - response3.contentType.get().mediaType == responseMediaType3 - - let - version1 = response1.headers.getString("eth-consensus-version") - version2 = response2.headers.getString("eth-consensus-version") - version3 = response3.headers.getString("eth-consensus-version") - - check: - version1 == ConsensusFork.Deneb.toString() - version2 == ConsensusFork.Electra.toString() - version3 == ConsensusFork.Fulu.toString() - - let - bid1res = - decodeBytesJsonOrSsz(GetHeaderResponseDeneb, response1.data, - response1.contentType, version1) - bid2res = - decodeBytesJsonOrSsz(GetHeaderResponseElectra, response2.data, - response2.contentType, version2) - bid3res = - decodeBytesJsonOrSsz(GetHeaderResponseFulu, response3.data, - response3.contentType, version3) - - check: - bid1res.isOk() - bid2res.isOk() - bid3res.isOk() - bid1res.get().data.message.header.parent_hash == parent_hash - bid2res.get().data.message.header.parent_hash == parent_hash - bid3res.get().data.message.header.parent_hash == parent_hash - - template submitBlindedBlockTest( - requestKind: TestKind, - responseKind: TestKind - ): untyped = - let - parent_hash1 = Eth2Digest(data: rng[].generate(array[32, byte])) - parent_hash2 = Eth2Digest(data: rng[].generate(array[32, byte])) - parent_hash3 = Eth2Digest(data: rng[].generate(array[32, byte])) - privateKey1 = keyGen(rng[]).valueOr: - raiseAssert "Unable to generate private key" - privateKey2 = keyGen(rng[]).valueOr: - raiseAssert "Unable to generate private key" - privateKey3 = keyGen(rng[]).valueOr: - raiseAssert "Unable to generate private key" - publicKey1 = privateKey1.toPubKey().toPubKey() - publicKey2 = privateKey1.toPubKey().toPubKey() - publicKey3 = privateKey1.toPubKey().toPubKey() - - node.validators.reset() - node.validators.add(publicKey1) - node.validators.add(publicKey2) - node.validators.add(publicKey3) - - let - blck1 = - prepare(deneb_mev.SignedBlindedBeaconBlock, DenebSlot, parent_hash1, - 0'u64, privateKey1) - blck2 = - prepare(electra_mev.SignedBlindedBeaconBlock, ElectraSlot, parent_hash2, - 1'u64, privateKey2) - blck3 = - prepare(fulu_mev.SignedBlindedBeaconBlock, FuluSlot, parent_hash3, - 2'u64, privateKey3) - - restContentType1 = - if requestKind == TestKind.Ssz: - "application/octet-stream" - else: - "application/json" - restContentType2 = - if requestKind == TestKind.Ssz: - "application/octet-stream" - else: - "application/json" - restContentType3 = - if requestKind == TestKind.Ssz: - "application/octet-stream" - else: - "application/json" - (restAcceptType1, responseMediaType1) = - if responseKind == TestKind.Ssz: - ("application/octet-stream", OctetStreamMediaType) - else: - ("application/json", ApplicationJsonMediaType) - (restAcceptType2, responseMediaType2) = - if responseKind == TestKind.Ssz: - ("application/octet-stream,application/json;q=0.9", - OctetStreamMediaType) - else: - ("application/json,application/octet-stream;q=0.9", - ApplicationJsonMediaType) - (restAcceptType3, responseMediaType3) = - if responseKind == TestKind.Ssz: - ("application/json;q=0.5,application/octet-stream;q=1.0", - OctetStreamMediaType) - else: - ("application/octet-stream;q=0.5,application/json;q=1.0", - ApplicationJsonMediaType) - - response1 = - await client.submitBlindedBlockPlain( - blck1, - restContentType = restContentType1, - restAcceptType = restAcceptType1, - extraHeaders = @[("eth-consensus-version", - toString(ConsensusFork.Deneb))]) - response2 = - await client.submitBlindedBlockPlain( - blck2, - restContentType = restContentType2, - restAcceptType = restAcceptType2, - extraHeaders = @[("eth-consensus-version", - toString(ConsensusFork.Electra))]) - response3 = - await client.submitBlindedBlockPlain( - blck3, - restContentType = restContentType3, - restAcceptType = restAcceptType3, - extraHeaders = @[("eth-consensus-version", - toString(ConsensusFork.Fulu))]) - check: - response1.status == 200 - response2.status == 200 - response3.status == 200 - - let - version1 = response1.headers.getString("eth-consensus-version") - version2 = response2.headers.getString("eth-consensus-version") - version3 = response3.headers.getString("eth-consensus-version") - - check: - response1.contentType.isSome() - response2.contentType.isSome() - response3.contentType.isSome() - response1.contentType.get().mediaType == responseMediaType1 - response2.contentType.get().mediaType == responseMediaType2 - response3.contentType.get().mediaType == responseMediaType3 - version1 == ConsensusFork.Deneb.toString() - version2 == ConsensusFork.Electra.toString() - version3 == ConsensusFork.Fulu.toString() - - let - payload1res = - decodeBytesJsonOrSsz(SubmitBlindedBlockResponseDeneb, - response1.data, response1.contentType, version1) - payload2res = - decodeBytesJsonOrSsz(SubmitBlindedBlockResponseElectra, - response2.data, response2.contentType, version2) - payload3res = - decodeBytesJsonOrSsz(SubmitBlindedBlockResponseFulu, - response3.data, response3.contentType, version3) - - check: - payload1res.isOk() - payload2res.isOk() - payload3res.isOk() - payload1res.get().data.execution_payload.parent_hash == parent_hash1 - payload2res.get().data.execution_payload.parent_hash == parent_hash2 - payload3res.get().data.execution_payload.parent_hash == parent_hash3 - - asyncTest "/eth/v1/builder/status test": - let response = await client.getStatus() - check response.status == 200 - - asyncTest "/eth/v1/builder/validators [json] test": - let - response1 = - await client.registerValidator( - generateRegistrations(rng[], 5)) - response2 = - await client.registerValidator( - generateRegistrations(rng[], 5), - restContentType = "application/json") - check: - response1.status == 200 - response2.status == 200 - - asyncTest "/eth/v1/builder/validators [ssz] test": - let - response = - await client.registerValidator( - generateRegistrations(rng[], 5), - restContentType = "application/octet-stream") - check response.status == 200 - - asyncTest "/eth/v1/builder/header [json] test": - getHeaderTest(TestKind.Json) - - asyncTest "/eth/v1/builder/header [ssz] test": - getHeaderTest(TestKind.Ssz) - - asyncTest "/eth/v1/builder/blinded_blocks [json/json] test": - submitBlindedBlockTest(TestKind.Json, TestKind.Json) - - asyncTest "/eth/v1/builder/blinded_blocks [json/ssz] test": - submitBlindedBlockTest(TestKind.Json, TestKind.Ssz) - - asyncTest "/eth/v1/builder/blinded_blocks [ssz/ssz] test": - submitBlindedBlockTest(TestKind.Ssz, TestKind.Ssz) - - asyncTest "/eth/v1/builder/blinded_blocks [ssz/json] test": - submitBlindedBlockTest(TestKind.Ssz, TestKind.Json) - - suiteTeardown: - waitFor server.stop() - -testSuite()