From 9e14d904acc3cb0706177096671719273a34260f Mon Sep 17 00:00:00 2001 From: tersec Date: Sat, 10 Jun 2023 05:39:10 +0000 Subject: [PATCH] https://github.com/ethereum/consensus-specs/pull/3359 (#5047) --- beacon_chain/beacon_node_light_client.nim | 3 +- beacon_chain/el/el_manager.nim | 25 ++++++++++++---- .../gossip_processing/block_processor.nim | 18 ++++++++---- beacon_chain/nimbus_light_client.nim | 4 +-- beacon_chain/spec/state_transition_block.nim | 29 +++++++++---------- vendor/nim-web3 | 2 +- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/beacon_chain/beacon_node_light_client.nim b/beacon_chain/beacon_node_light_client.nim index 66596f451..337b9ed6d 100644 --- a/beacon_chain/beacon_node_light_client.nim +++ b/beacon_chain/beacon_node_light_client.nim @@ -51,7 +51,8 @@ proc initLightClient*( if not blckPayload.block_hash.isZero: # engine_newPayloadV1 - discard await node.elManager.newExecutionPayload(blckPayload) + discard await node.elManager.newExecutionPayload( + blck.message.body) # Retain optimistic head for other `forkchoiceUpdated` callers. # May temporarily block `forkchoiceUpdatedV1` calls, e.g., Geth: diff --git a/beacon_chain/el/el_manager.nim b/beacon_chain/el/el_manager.nim index edbaaea11..8470c295f 100644 --- a/beacon_chain/el/el_manager.nim +++ b/beacon_chain/el/el_manager.nim @@ -25,6 +25,7 @@ import from std/times import getTime, inSeconds, initTime, `-` from ../spec/engine_authentication import getSignedIatToken +from ../spec/state_transition_block import kzg_commitment_to_versioned_hash export el_conf, engine_api, deques, base, DepositTreeSnapshot @@ -1064,10 +1065,11 @@ proc sendNewPayloadToSingleEL(connection: ELConnection, return await rpcClient.engine_newPayloadV2(payload) proc sendNewPayloadToSingleEL(connection: ELConnection, - payload: engine_api.ExecutionPayloadV3): + payload: engine_api.ExecutionPayloadV3, + versioned_hashes: seq[engine_api.VersionedHash]): Future[PayloadStatusV1] {.async.} = let rpcClient = await connection.connectedRpcClient() - return await rpcClient.engine_newPayloadV3(payload) + return await rpcClient.engine_newPayloadV3(payload, versioned_hashes) type StatusRelation = enum @@ -1159,15 +1161,28 @@ proc processResponse[ELResponseType]( url2 = connections[idx].engineUrl.url, status2 = status -proc sendNewPayload*(m: ELManager, - payload: engine_api.ExecutionPayloadV1 | engine_api.ExecutionPayloadV2 | engine_api.ExecutionPayloadV3): +proc sendNewPayload*(m: ELManager, blockBody: SomeForkyBeaconBlockBody): Future[PayloadExecutionStatus] {.async.} = let earlyDeadline = sleepAsync(chronos.seconds 1) startTime = Moment.now deadline = sleepAsync(NEWPAYLOAD_TIMEOUT) + payload = blockBody.execution_payload.asEngineExecutionPayload requests = m.elConnections.mapIt: - let req = sendNewPayloadToSingleEL(it, payload) + let req = + when payload is engine_api.ExecutionPayloadV3: + # 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 + # [Modified in Deneb] Pass `versioned_hashes` to Execution Engine + let versioned_hashes = mapIt( + blockBody.blob_kzg_commitments, + engine_api.VersionedHash(kzg_commitment_to_versioned_hash(it))) + sendNewPayloadToSingleEL(it, payload, versioned_hashes) + elif payload is engine_api.ExecutionPayloadV1 or + payload is engine_api.ExecutionPayloadV2: + sendNewPayloadToSingleEL(it, payload) + else: + static: doAssert false trackEngineApiRequest(it, req, "newPayload", startTime, deadline) req diff --git a/beacon_chain/gossip_processing/block_processor.nim b/beacon_chain/gossip_processing/block_processor.nim index f1c732c95..a4f6be7f8 100644 --- a/beacon_chain/gossip_processing/block_processor.nim +++ b/beacon_chain/gossip_processing/block_processor.nim @@ -245,8 +245,8 @@ from web3/engine_api_types import PayloadAttributesV1, PayloadAttributesV2, PayloadExecutionStatus, PayloadStatusV1 from ../el/el_manager import - ELManager, asEngineExecutionPayload, forkchoiceUpdated, hasConnection, - hasProperlyConfiguredConnection, sendNewPayload + ELManager, forkchoiceUpdated, hasConnection, hasProperlyConfiguredConnection, + sendNewPayload proc expectValidForkchoiceUpdated( elManager: ELManager, headBlockPayloadAttributesType: typedesc, @@ -304,9 +304,11 @@ from ../spec/datatypes/deneb import SignedBeaconBlock, asTrusted, shortLog proc newExecutionPayload*( elManager: ELManager, - executionPayload: ForkyExecutionPayload): + blockBody: SomeForkyBeaconBlockBody): Future[Opt[PayloadExecutionStatus]] {.async.} = + template executionPayload: untyped = blockBody.execution_payload + if not elManager.hasProperlyConfiguredConnection: if elManager.hasConnection: info "No execution client connected; cannot process block payloads", @@ -320,8 +322,7 @@ proc newExecutionPayload*( executionPayload = shortLog(executionPayload) try: - let payloadStatus = await elManager.sendNewPayload( - executionPayload.asEngineExecutionPayload) + let payloadStatus = await elManager.sendNewPayload(blockBody) debug "newPayload: succeeded", parentHash = executionPayload.parent_hash, @@ -348,7 +349,7 @@ proc getExecutionValidity( try: let executionPayloadStatus = await elManager.newExecutionPayload( - blck.message.body.execution_payload) + blck.message.body) if executionPayloadStatus.isNone: return NewPayloadStatus.noResponse @@ -442,6 +443,10 @@ proc storeBlock*( # When the execution layer is not available to verify the payload, we do the # required check on the CL side instead and proceed as if the EL was syncing + # TODO run https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#blob-kzg-commitments + # https://github.com/ethereum/execution-apis/blob/main/src/engine/experimental/blob-extension.md#specification + # "This validation MUST be instantly run in all cases even during active sync process." + # # Client software MUST validate `blockHash` value as being equivalent to # `Keccak256(RLP(ExecutionBlockHeader))` # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.3/src/engine/paris.md#specification @@ -462,6 +467,7 @@ proc storeBlock*( # be re-added later self.consensusManager.quarantine[].removeOrphan(signedBlock) + # TODO with v1.4.0, not sure this is still relevant # Establish blob viability before calling addHeadBlock to avoid # writing the block in case of blob error. when typeof(signedBlock).toFork() >= ConsensusFork.Deneb: diff --git a/beacon_chain/nimbus_light_client.nim b/beacon_chain/nimbus_light_client.nim index c8d1f12f8..ff9e6ad9b 100644 --- a/beacon_chain/nimbus_light_client.nim +++ b/beacon_chain/nimbus_light_client.nim @@ -113,7 +113,7 @@ programMain: template payload(): auto = blck.message.body.execution_payload if elManager != nil and not payload.block_hash.isZero: - discard await elManager.newExecutionPayload(payload) + discard await elManager.newExecutionPayload(blck.message.body) discard await elManager.forkchoiceUpdated( headBlockHash = payload.block_hash, safeBlockHash = payload.block_hash, # stub value @@ -124,7 +124,7 @@ programMain: template payload(): auto = blck.message.body.execution_payload if elManager != nil and not payload.block_hash.isZero: - discard await elManager.newExecutionPayload(payload) + discard await elManager.newExecutionPayload(blck.message.body) discard await elManager.forkchoiceUpdated( headBlockHash = payload.block_hash, safeBlockHash = payload.block_hash, # stub value diff --git a/beacon_chain/spec/state_transition_block.nim b/beacon_chain/spec/state_transition_block.nim index bf88b2b2a..a1a9de02b 100644 --- a/beacon_chain/spec/state_transition_block.nim +++ b/beacon_chain/spec/state_transition_block.nim @@ -727,9 +727,9 @@ func tx_peek_blob_versioned_hashes(opaque_tx: Transaction): ok res # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash -func kzg_commitment_to_versioned_hash( +func kzg_commitment_to_versioned_hash*( kzg_commitment: KzgCommitment): VersionedHash = - # https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#blob + # https://github.com/ethereum/consensus-specs/blob/v1.4.0-alpha.1/specs/deneb/beacon-chain.md#blob const VERSIONED_HASH_VERSION_KZG = 0x01'u8 var res: VersionedHash @@ -752,20 +752,15 @@ func verify_kzg_commitments_against_transactions*( #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) + all_versioned_hashes == mapIt( + kzg_commitments, it.kzg_commitment_to_versioned_hash) -# https://github.com/ethereum/consensus-specs/blob/v1.3.0/specs/deneb/beacon-chain.md#blob-kzg-commitments func process_blob_kzg_commitments( - state: var deneb.BeaconState, body: deneb.BeaconBlockBody | deneb.TrustedBeaconBlockBody | - deneb.SigVerifiedBeaconBlockBody): - Result[void, cstring] = - if verify_kzg_commitments_against_transactions( - body.execution_payload.transactions.asSeq, - body.blob_kzg_commitments.asSeq): - return ok() - else: - return err("process_blob_kzg_commitments: verify_kzg_commitments_against_transactions failed") + 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], @@ -875,6 +870,9 @@ proc process_block*( ## block application fails (!) ? process_block_header(state, blck, flags, cache) + + # Consensus specs v1.4.0 unconditionally assume is_execution_enabled is + # true, but intentionally keep such a check. if is_execution_enabled(state, blck.body): ? process_withdrawals( state, blck.body.execution_payload) # [New in Capella] @@ -909,6 +907,9 @@ proc process_block*( ## block application fails (!) ? process_block_header(state, blck, flags, cache) + + # Consensus specs v1.4.0 unconditionally assume is_execution_enabled is + # true, but intentionally keep such a check. if is_execution_enabled(state, blck.body): ? process_withdrawals(state, blck.body.execution_payload) ? process_execution_payload( @@ -926,6 +927,4 @@ proc process_block*( ? process_sync_aggregate( state, blck.body.sync_aggregate, total_active_balance, cache) - ? process_blob_kzg_commitments(state, blck.body) # [New in Deneb] - ok() diff --git a/vendor/nim-web3 b/vendor/nim-web3 index 18e37f7e0..ebd1d8913 160000 --- a/vendor/nim-web3 +++ b/vendor/nim-web3 @@ -1 +1 @@ -Subproject commit 18e37f7e0110f4400d1a19a9b925e4ac6e349e5f +Subproject commit ebd1d8913b938f1050ada408b9ceaecb2c39e666