From 7eb6ea72de184486eff5db8da2ddccbb49af929e Mon Sep 17 00:00:00 2001 From: tersec Date: Mon, 16 Dec 2024 13:26:56 +0000 Subject: [PATCH] update to current EIP-7685 engine API request format --- beacon_chain/el/el_manager.nim | 31 ++++++++++---- beacon_chain/networking/eth2_network.nim | 15 +++---- beacon_chain/spec/datatypes/electra.nim | 2 +- beacon_chain/spec/datatypes/fulu.nim | 4 +- beacon_chain/validators/beacon_validators.nim | 42 ++++++++++++++----- vendor/nim-web3 | 2 +- 6 files changed, 64 insertions(+), 32 deletions(-) diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index 2e4425bd0b..ff2205c97b 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -855,7 +855,7 @@ proc sendNewPayloadToSingleEL( payload: engine_api.ExecutionPayloadV3, versioned_hashes: seq[engine_api.VersionedHash], parent_beacon_block_root: FixedBytes[32], - executionRequests: array[3, seq[byte]] + executionRequests: seq[seq[byte]] ): Future[PayloadStatusV1] {.async: (raises: [CatchableError]).} = let rpcClient = await connection.connectedRpcClient() await rpcClient.engine_newPayloadV4( @@ -995,15 +995,30 @@ proc sendNewPayload*( let req = when typeof(blck).kind >= ConsensusFork.Electra: # https://github.com/ethereum/execution-apis/blob/4140e528360fea53c34a766d86a000c6c039100e/src/engine/prague.md#engine_newpayloadv4 - let versioned_hashes = mapIt( - blck.body.blob_kzg_commitments, - engine_api.VersionedHash(kzg_commitment_to_versioned_hash(it))) + let + versioned_hashes = mapIt( + blck.body.blob_kzg_commitments, + engine_api.VersionedHash(kzg_commitment_to_versioned_hash(it))) + # https://github.com/ethereum/execution-apis/blob/7c9772f95c2472ccfc6f6128dc2e1b568284a2da/src/engine/prague.md#request + # "Each list element is a `requests` byte array as defined by + # EIP-7685. The first byte of each element is the `request_type` + # and the remaining bytes are the `request_data`. Elements of + # the list MUST be ordered by `request_type` in ascending order. + # Elements with empty `request_data` MUST be excluded from the + # list." + execution_requests = block: + var requests: seq[seq[byte]] + for request_type, request_data in + [SSZ.encode(blck.body.execution_requests.deposits), + SSZ.encode(blck.body.execution_requests.withdrawals), + SSZ.encode(blck.body.execution_requests.consolidations)]: + if request_data.len > 0: + requests.add @[request_type.byte] & request_data + requests + sendNewPayloadToSingleEL( it, payload, versioned_hashes, - FixedBytes[32] blck.parent_root.data, - [SSZ.encode(blck.body.execution_requests.deposits), - SSZ.encode(blck.body.execution_requests.withdrawals), - SSZ.encode(blck.body.execution_requests.consolidations)]) + FixedBytes[32] blck.parent_root.data, execution_requests) elif typeof(blck).kind == ConsensusFork.Deneb: # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/deneb/beacon-chain.md#process_execution_payload # Verify the execution payload is valid diff --git a/beacon_chain/networking/eth2_network.nim b/beacon_chain/networking/eth2_network.nim index 2d421c89ef..6248a5f6fa 100644 --- a/beacon_chain/networking/eth2_network.nim +++ b/beacon_chain/networking/eth2_network.nim @@ -284,9 +284,6 @@ declareGauge nbc_peers, declareCounter nbc_successful_discoveries, "Number of successful discoveries" -declareCounter nbc_failed_discoveries, - "Number of failed discoveries" - declareCounter nbc_cycling_kicked_peers, "Number of peers kicked for peer cycling" @@ -2091,21 +2088,21 @@ proc p2pProtocolBackendImpl*(p: P2PProtocol): Backend = import ./peer_protocol export peer_protocol -proc updateMetadataV2ToV3(metadataRes: NetRes[altair.MetaData]): +func updateMetadataV2ToV3(metadataRes: NetRes[altair.MetaData]): NetRes[fulu.MetaData] = if metadataRes.isOk: let metadata = metadataRes.get ok(fulu.MetaData(seq_number: metadata.seq_number, - attnets: metadata.attnets, - syncnets: metadata.syncnets)) + attnets: metadata.attnets, + syncnets: metadata.syncnets)) else: err(metadataRes.error) -proc getMetadata_vx(node: Eth2Node, peer: Peer): +proc getMetadata_vx(node: Eth2Node, peer: Peer): Future[NetRes[fulu.MetaData]] {.async: (raises: [CancelledError]).} = let - res = + res = if node.getBeaconTime().slotOrZero.epoch >= node.cfg.FULU_FORK_EPOCH: # Directly fetch fulu metadata if available await getMetadata_v3(peer) @@ -2438,7 +2435,7 @@ proc lookupCscFromPeer*(peer: Peer): uint64 = return metadata.get.custody_subnet_count # Try getting the custody count from ENR if metadata fetch fails. - debug "Could not get csc from metadata, trying from ENR", + debug "Could not get csc from metadata, trying from ENR", peer_id = peer.peerId let enrOpt = peer.enr if not enrOpt.isNone: diff --git a/beacon_chain/spec/datatypes/electra.nim b/beacon_chain/spec/datatypes/electra.nim index 5c871bc8db..278d49ad17 100644 --- a/beacon_chain/spec/datatypes/electra.nim +++ b/beacon_chain/spec/datatypes/electra.nim @@ -119,7 +119,7 @@ type executionPayload*: ExecutionPayload blockValue*: Wei blobsBundle*: BlobsBundle - executionRequests*: array[3, seq[byte]] + executionRequests*: seq[seq[byte]] # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/deneb/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object diff --git a/beacon_chain/spec/datatypes/fulu.nim b/beacon_chain/spec/datatypes/fulu.nim index 6ef03ac240..5235b416ed 100644 --- a/beacon_chain/spec/datatypes/fulu.nim +++ b/beacon_chain/spec/datatypes/fulu.nim @@ -149,7 +149,7 @@ type executionPayload*: ExecutionPayload blockValue*: Wei blobsBundle*: BlobsBundle - executionRequests*: array[3, seq[byte]] + executionRequests*: seq[seq[byte]] # https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/deneb/beacon-chain.md#executionpayloadheader ExecutionPayloadHeader* = object @@ -684,4 +684,4 @@ template asTrusted*( x: SignedBeaconBlock | SigVerifiedSignedBeaconBlock | MsgTrustedSignedBeaconBlock): TrustedSignedBeaconBlock = - isomorphicCast[TrustedSignedBeaconBlock](x) \ No newline at end of file + isomorphicCast[TrustedSignedBeaconBlock](x) diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 23b1f41984..4a68ca8a7e 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -43,7 +43,7 @@ import keystore_management, slashing_protection, validator_duties, validator_pool], ".."/spec/mev/[rest_deneb_mev_calls, rest_electra_mev_calls, rest_fulu_mev_calls] -from std/sequtils import countIt, foldl, mapIt +from std/sequtils import countIt, deduplicate, foldl, mapIt from eth/async_utils import awaitWithTimeout # Metrics for tracking attestation and beacon block loss @@ -443,6 +443,8 @@ proc getExecutionPayload( PayloadType, beaconHead.blck.bid.root, executionHead, latestSafe, latestFinalized, timestamp, random, feeRecipient, withdrawals) +from std/algorithm import isSorted + # BlockRewards has issues resolving somehow otherwise import ".."/spec/state_transition_block @@ -541,19 +543,37 @@ proc makeBeaconBlockForHeadAndSlot*( let execution_requests_actual = when PayloadType.kind >= ConsensusFork.Electra: # Don't want un-decoded SSZ going any further/deeper + var execution_requests_buffer: ExecutionRequests + block: + let request_types = mapIt(payload.executionRequests, it[0]) + if not isSorted(request_types): + return err("Execution layer request types not sorted") + if payload.executionRequests.len != + deduplicate(request_types, isSorted = true).len: + return err("Execution layer request types duplicated") try: - ExecutionRequests( - deposits: SSZ.decode( - payload.executionRequests[0], - List[DepositRequest, Limit MAX_DEPOSIT_REQUESTS_PER_PAYLOAD]), - withdrawals: SSZ.decode( - payload.executionRequests[1], - List[WithdrawalRequest, Limit MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]), - consolidations: SSZ.decode( - payload.executionRequests[2], - List[ConsolidationRequest, Limit MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD])) + for request_type_and_payload in payload.executionRequests: + if request_type_and_payload.len < 2: + return err("Execution layer request too short") + template request_payload: untyped = + request_type_and_payload.toOpenArray( + 1, request_type_and_payload.len - 1) + case request_type_and_payload[0] + of 0'u8: execution_requests_buffer.deposits = SSZ.decode( + request_payload, + List[DepositRequest, Limit MAX_DEPOSIT_REQUESTS_PER_PAYLOAD]) + of 1'u8: execution_requests_buffer.withdrawals = SSZ.decode( + request_payload, + List[WithdrawalRequest, Limit MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]) + of 2'u8: execution_requests_buffer.consolidations = SSZ.decode( + request_payload, + List[ConsolidationRequest, Limit MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]) + else: + return err("Execution layer invalid request type") except CatchableError: return err("Unable to deserialize execution layer requests") + + execution_requests_buffer else: default(ExecutionRequests) # won't be used by block builder diff --git a/vendor/nim-web3 b/vendor/nim-web3 index 2bdffd6112..2d8419dc7d 160000 --- a/vendor/nim-web3 +++ b/vendor/nim-web3 @@ -1 +1 @@ -Subproject commit 2bdffd61128f9142a0d19a9f3b6e6503b974929b +Subproject commit 2d8419dc7d2898ca6efd7d3299afc7292b664d96