From 4ffe056a2500751a4e4c2348cc5dab228e93a7ce Mon Sep 17 00:00:00 2001 From: andri lim Date: Sat, 2 Nov 2024 16:58:18 +0700 Subject: [PATCH] Engine API simulator: simplify versioned method call (#2821) * Engine API simulator: simplify versioned method call * More cleanup --- .../engine/cancun/step_newpayloads.nim | 8 +- .../engine/cancun/step_sendmodpayload.nim | 4 +- hive_integration/nodocker/engine/clmock.nim | 63 +++------- .../nodocker/engine/engine/bad_hash.nim | 11 +- .../nodocker/engine/engine/forkchoice.nim | 21 ++-- .../engine/engine/invalid_ancestor.nim | 28 ++--- .../engine/engine/invalid_payload.nim | 42 +++---- .../engine/engine/payload_attributes.nim | 6 +- .../engine/engine/payload_execution.nim | 43 ++++--- .../nodocker/engine/engine/payload_id.nim | 4 +- .../nodocker/engine/engine/reorg.nim | 110 +++++++++--------- .../nodocker/engine/engine/versioning.nim | 2 +- .../nodocker/engine/engine_client.nim | 102 +++------------- .../nodocker/engine/engine_env.nim | 59 +++++++++- hive_integration/nodocker/engine/types.nim | 30 ++++- .../engine/withdrawals/wd_reorg_spec.nim | 30 ++--- .../nodocker/pyspec/pyspec_sim.nim | 12 +- tests/test_engine_api.nim | 14 +-- 18 files changed, 284 insertions(+), 305 deletions(-) diff --git a/hive_integration/nodocker/engine/cancun/step_newpayloads.nim b/hive_integration/nodocker/engine/cancun/step_newpayloads.nim index 35ea1c7cb..da41a0397 100644 --- a/hive_integration/nodocker/engine/cancun/step_newpayloads.nim +++ b/hive_integration/nodocker/engine/cancun/step_newpayloads.nim @@ -228,7 +228,7 @@ method execute*(step: NewPayloads, ctx: CancunTestContext): bool = if step.fcUOnPayloadRequest.getExpectInvalidStatus(): expectedStatus = PayloadExecutionStatus.invalid - let r = env.engine.client.forkchoiceUpdated(version, forkchoiceState, Opt.some(payloadAttributes)) + let r = env.engine.forkchoiceUpdated(version, forkchoiceState, payloadAttributes) if expectedError != 0: r.expectErrorCode(expectedError, step.expectationDescription) else: @@ -258,7 +258,7 @@ method execute*(step: NewPayloads, ctx: CancunTestContext): bool = let period = chronos.seconds(step.getPayloadDelay) waitFor sleepAsync(period) - let r = env.engine.client.getPayload(payloadID, version) + let r = env.engine.getPayload(version, payloadID) if expectedError != 0: r.expectErrorCode(expectedError, step.expectationDescription) else: @@ -310,7 +310,7 @@ method execute*(step: NewPayloads, ctx: CancunTestContext): bool = if step.newPayloadCustomizer.getExpectInvalidStatus(): expectedStatus = PayloadExecutionStatus.invalid - let r = env.client.newPayload(version, payload) + let r = env.engine.newPayload(version, payload) if expectedError != 0: r.expectErrorCode(expectedError, step.expectationDescription) else: @@ -332,7 +332,7 @@ method execute*(step: NewPayloads, ctx: CancunTestContext): bool = forkchoiceState.headBlockHash = env.clMock.latestPayloadBuilt.blockHash - let r = env.engine.client.forkchoiceUpdated(version, forkchoiceState) + let r = env.engine.forkchoiceUpdated(version, forkchoiceState) if expectedError != 0: r.expectErrorCode(expectedError, step.expectationDescription) else: diff --git a/hive_integration/nodocker/engine/cancun/step_sendmodpayload.nim b/hive_integration/nodocker/engine/cancun/step_sendmodpayload.nim index 27436d5bf..12cbda12f 100644 --- a/hive_integration/nodocker/engine/cancun/step_sendmodpayload.nim +++ b/hive_integration/nodocker/engine/cancun/step_sendmodpayload.nim @@ -1,5 +1,5 @@ # Nimbus -# Copyright (c) 2023 Status Research & Development GmbH +# Copyright (c) 2023-2024 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or # http://www.apache.org/licenses/LICENSE-2.0) @@ -47,7 +47,7 @@ method execute*(step: SendModifiedLatestPayload, ctx: CancunTestContext): bool = doAssert(step.clientID < env.numEngines(), "invalid client index " & $step.clientID) let eng = env.engines(step.clientID) - let r = eng.client.newPayload(version, payload) + let r = eng.newPayload(version, payload) if expectedError != 0: r.expectErrorCode(expectedError) else: diff --git a/hive_integration/nodocker/engine/clmock.nim b/hive_integration/nodocker/engine/clmock.nim index 570eca422..62ba20684 100644 --- a/hive_integration/nodocker/engine/clmock.nim +++ b/hive_integration/nodocker/engine/clmock.nim @@ -56,7 +56,7 @@ type # PoS Chain History Information prevRandaoHistory* : Table[uint64, Bytes32] - executedPayloadHistory* : Table[uint64, ExecutionPayload] + executedPayloadHistory* : Table[uint64, ExecutableData] headHashHistory : seq[Hash32] # Latest broadcasted data using the PoS Engine API @@ -91,11 +91,7 @@ type onFinalizedBlockChange* : proc(): bool {.gcsafe.} -proc collectBlobHashes(list: openArray[Web3Tx]): seq[Hash32] = - for w3tx in list: - let tx = ethTx(w3tx) - for h in tx.versionedHashes: - result.add h + func latestExecutableData*(cl: CLMocker): ExecutableData = ExecutableData( @@ -237,6 +233,10 @@ func isCancun(cl: CLMocker, timestamp: Quantity): bool = let ts = EthTime(timestamp.uint64) cl.com.isCancunOrLater(ts) +func isPrague(cl: CLMocker, timestamp: Quantity): bool = + let ts = EthTime(timestamp.uint64) + cl.com.isPragueOrLater(ts) + # Picks the next payload producer from the set of clients registered proc pickNextPayloadProducer(cl: CLMocker): bool = doAssert cl.clients.len != 0 @@ -287,6 +287,8 @@ proc generatePayloadAttributes(cl: CLMocker) = let beaconRoot = timestampToBeaconRoot(timestamp) cl.latestPayloadAttributes.parentBeaconBlockRoot = Opt.some(beaconRoot) + #if cl.isPrague(timestamp): + # Save random value let number = cl.latestHeader.number + 1 cl.prevRandaoHistory[number] = nextPrevRandao @@ -318,12 +320,14 @@ proc requestNextPayload(cl: CLMocker): bool = proc getPayload(cl: CLMocker, payloadId: Bytes8): Result[GetPayloadResponse, string] = let ts = cl.latestPayloadAttributes.timestamp let client = cl.nextBlockProducer.client - if cl.isCancun(ts): - client.getPayload(payloadId, Version.V3) + if cl.isPrague(ts): + client.getPayload(Version.V4, payloadId) + elif cl.isCancun(ts): + client.getPayload(Version.V3, payloadId) elif cl.isShanghai(ts): - client.getPayload(payloadId, Version.V2) + client.getPayload(Version.V2, payloadId) else: - client.getPayload(payloadId, Version.V1) + client.getPayload(Version.V1, payloadId) proc getNextPayload(cl: CLMocker): bool = let res = cl.getPayload(cl.nextPayloadID) @@ -381,32 +385,9 @@ proc getNextPayload(cl: CLMocker): bool = return true -func versionedHashes(payload: ExecutionPayload): seq[Hash32] = - result = newSeqOfCap[Hash32](payload.transactions.len) - for x in payload.transactions: - let tx = rlp.decode(distinctBase(x), Transaction) - for vs in tx.versionedHashes: - result.add vs - -proc broadcastNewPayload(cl: CLMocker, - eng: EngineEnv, - payload: ExecutableData): Result[PayloadStatusV1, string] = - let version = eng.version(payload.basePayload.timestamp) - case version - of Version.V1: return eng.client.newPayloadV1(payload.basePayload.V1) - of Version.V2: return eng.client.newPayloadV2(payload.basePayload.V2) - of Version.V3: return eng.client.newPayloadV3(payload.basePayload.V3, - versionedHashes(payload.basePayload), - cl.latestPayloadAttributes.parentBeaconBlockRoot.get) - of Version.V4: - return eng.client.newPayloadV4(payload.basePayload.V3, - versionedHashes(payload.basePayload), - cl.latestPayloadAttributes.parentBeaconBlockRoot.get, - payload.executionRequests.get) - proc broadcastNextNewPayload(cl: CLMocker): bool = for eng in cl.clients: - let res = cl.broadcastNewPayload(eng, cl.latestExecutedPayload) + let res = eng.newPayload(cl.latestExecutedPayload) if res.isErr: error "CLMocker: broadcastNewPayload Error", msg=res.error return false @@ -456,21 +437,19 @@ proc broadcastNextNewPayload(cl: CLMocker): bool = cl.latestExecutedPayload = cl.latestExecutableData() let number = uint64 cl.latestPayloadBuilt.blockNumber - cl.executedPayloadHistory[number] = cl.latestPayloadBuilt + cl.executedPayloadHistory[number] = cl.latestExecutedPayload return true proc broadcastForkchoiceUpdated(cl: CLMocker, eng: EngineEnv, - version: Version, update: ForkchoiceStateV1): Result[ForkchoiceUpdatedResponse, string] = + let version = eng.version(cl.latestExecutedPayload.basePayload.timestamp) eng.client.forkchoiceUpdated(version, update, Opt.none(PayloadAttributes)) -proc broadcastForkchoiceUpdated*(cl: CLMocker, - version: Version, - update: ForkchoiceStateV1): bool = +proc broadcastLatestForkchoice*(cl: CLMocker): bool = for eng in cl.clients: - let res = cl.broadcastForkchoiceUpdated(eng, version, update) + let res = cl.broadcastForkchoiceUpdated(eng, cl.latestForkchoice) if res.isErr: error "CLMocker: broadcastForkchoiceUpdated Error", msg=res.error return false @@ -500,10 +479,6 @@ proc broadcastForkchoiceUpdated*(cl: CLMocker, return true -proc broadcastLatestForkchoice(cl: CLMocker): bool = - let version = cl.latestExecutedPayload.version - cl.broadcastForkchoiceUpdated(version, cl.latestForkchoice) - func w3Address(x: int): Address = var res: array[20, byte] res[^1] = x.byte diff --git a/hive_integration/nodocker/engine/engine/bad_hash.nim b/hive_integration/nodocker/engine/engine/bad_hash.nim index 7d0c2c06c..b359ab042 100644 --- a/hive_integration/nodocker/engine/engine/bad_hash.nim +++ b/hive_integration/nodocker/engine/engine/bad_hash.nim @@ -91,8 +91,8 @@ method execute(cs: BadHashOnNewPayload, env: TestEnv): bool = safeblockHash: latestHash, finalizedblockHash: latestHash, ) - version = env.engine.version(env.clMock.latestHeader.timestamp) - r = env.engine.client.forkchoiceUpdated(version, fcU) + timeVer = env.clMock.latestHeader.timestamp + r = env.engine.forkchoiceUpdated(timeVer, fcU) r.expectPayloadStatus(PayloadExecutionStatus.syncing) @@ -111,7 +111,7 @@ method execute(cs: BadHashOnNewPayload, env: TestEnv): bool = # Starting from Shanghai, INVALID should be returned instead (https:#githucs.com/ethereum/execution-apis/pull/338) let version = env.engine.version(shadow.payload.timestamp) - r = env.engine.client.newPayload(version, shadow.payload) + r = env.engine.newPayload(shadow.payload) if version >= Version.V2: r.expectStatus(PayloadExecutionStatus.invalid) @@ -136,8 +136,7 @@ method execute(cs: BadHashOnNewPayload, env: TestEnv): bool = # or INVALID (client still has the payload and can verify that this payload is incorrectly building on top of it), # but a VALID response is incorrect. let - version = env.engine.version(shadow.payload.timestamp) - r = env.engine.client.newPayload(version, shadow.payload) + r = env.engine.newPayload(shadow.payload) r.expectStatusEither([PayloadExecutionStatus.accepted, PayloadExecutionStatus.invalid, PayloadExecutionStatus.syncing]) return true )) @@ -185,7 +184,7 @@ method execute(cs: ParentHashOnNewPayload, env: TestEnv): bool = # Starting from Shanghai, INVALID should be returned instead (https:#githucs.com/ethereum/execution-apis/pull/338) let version = env.engine.version(payload.timestamp) - r = env.engine.client.newPayload(version, payload) + r = env.engine.newPayload(payload) if version >= Version.V2: r.expectStatus(PayloadExecutionStatus.invalid) diff --git a/hive_integration/nodocker/engine/engine/forkchoice.nim b/hive_integration/nodocker/engine/engine/forkchoice.nim index 6adcb4092..0635fea64 100644 --- a/hive_integration/nodocker/engine/engine/forkchoice.nim +++ b/hive_integration/nodocker/engine/engine/forkchoice.nim @@ -61,8 +61,7 @@ method execute(cs: InconsistentForkchoiceTest, env: TestEnv): bool = shadow.canon.add env.clMock.latestExecutableData # Send the alternative payload - let version = env.engine.version(altPayload.timestamp) - let r = env.engine.client.newPayload(version, altPayload) + let r = env.engine.newPayload(altPayload) r.expectStatusEither([PayloadExecutionStatus.valid, PayloadExecutionStatus.accepted]) return true )) @@ -84,12 +83,12 @@ method execute(cs: InconsistentForkchoiceTest, env: TestEnv): bool = of FinalizedBlockHash: inconsistentFcU.finalizedBlockHash = shadow.alt[len(shadow.canon)-3].blockHash - let version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - var r = env.engine.client.forkchoiceUpdated(version, inconsistentFcU) + let timeVer = env.clMock.latestPayloadBuilt.timestamp + var r = env.engine.forkchoiceUpdated(timeVer, inconsistentFcU) r.expectErrorCode(engineApiInvalidForkchoiceState) # Return to the canonical chain - r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectPayloadStatus(PayloadExecutionStatus.valid) return true @@ -133,15 +132,15 @@ method execute(cs: ForkchoiceUpdatedUnknownBlockHashTest, env: TestEnv): bool = # - (payloadStatus: (status: SYNCING, latestValidHash: null, validationError: null), payloadId: null) # if forkchoiceState.headblockHash references an unknown payload or a payload that can't be validated # because requisite data for the validation is missing - let version = env.engine.version(env.clMock.latestExecutedPayload.timestamp) - var r = env.engine.client.forkchoiceUpdated(version, fcu) + let timeVer = env.clMock.latestExecutedPayload.timestamp + var r = env.engine.forkchoiceUpdated(timeVer, fcu) r.expectPayloadStatus(PayloadExecutionStatus.syncing) var payloadAttributes = env.clMock.latestPayloadAttributes payloadAttributes.timestamp = w3Qty(payloadAttributes.timestamp, 1) # Test again using PayloadAttributes, should also return SYNCING and no PayloadID - r = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(payloadAttributes)) + r = env.engine.forkchoiceUpdated(timeVer, fcu, Opt.some(payloadAttributes)) r.expectPayloadStatus(PayloadExecutionStatus.syncing) r.expectPayloadID(Opt.none(Bytes8)) else: @@ -159,8 +158,8 @@ method execute(cs: ForkchoiceUpdatedUnknownBlockHashTest, env: TestEnv): bool = elif cs.field == FinalizedBlockHash: fcu.finalizedBlockHash = randomblockHash - let version = env.engine.version(env.clMock.latestExecutedPayload.timestamp) - var r = env.engine.client.forkchoiceUpdated(version, fcu) + let timeVer = env.clMock.latestExecutedPayload.timestamp + var r = env.engine.forkchoiceUpdated(timeVer, fcu) r.expectError() var payloadAttributes = env.clMock.latestPayloadAttributes @@ -168,7 +167,7 @@ method execute(cs: ForkchoiceUpdatedUnknownBlockHashTest, env: TestEnv): bool = payloadAttributes.suggestedFeeRecipient = default(Address) # Test again using PayloadAttributes, should also return INVALID and no PayloadID - r = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(payloadAttributes)) + r = env.engine.forkchoiceUpdated(timeVer, fcu, Opt.some(payloadAttributes)) r.expectError() return true )) diff --git a/hive_integration/nodocker/engine/engine/invalid_ancestor.nim b/hive_integration/nodocker/engine/engine/invalid_ancestor.nim index 38af7896f..c41259c4e 100644 --- a/hive_integration/nodocker/engine/engine/invalid_ancestor.nim +++ b/hive_integration/nodocker/engine/engine/invalid_ancestor.nim @@ -117,12 +117,12 @@ method execute(cs: InvalidMissingAncestorReOrgTest, env: TestEnv): bool = blockHash=shadow.payloads[i].blockHash.short, number=shadow.payloads[i].blockNumber.uint64 - let version = env.engine.version(shadow.payloads[i].timestamp) - let r = env.engine.client.newPayload(version, shadow.payloads[i]) + let r = env.engine.newPayload(shadow.payloads[i]) let fcState = ForkchoiceStateV1( headblockHash: shadow.payloads[i].blockHash, ) - let p = env.engine.client.forkchoiceUpdated(version, fcState) + let timeVer = shadow.payloads[i].timestamp + let p = env.engine.forkchoiceUpdated(timeVer, fcState) if i == cs.invalidIndex: # If this is the first payload after the common ancestor, and this is the payload we invalidated, @@ -147,8 +147,8 @@ method execute(cs: InvalidMissingAncestorReOrgTest, env: TestEnv): bool = p.expectLatestValidHash(shadow.payloads[i].blockHash) # Resend the latest correct fcU - let version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + let timeVer = env.clMock.latestPayloadBuilt.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectNoError() # After this point, the CL Mock will send the next payload of the canonical chain return true @@ -308,14 +308,14 @@ method execute(cs: InvalidMissingAncestorReOrgSyncTest, env: TestEnv): bool = if i < cs.invalidIndex: let p = shadow.payloads[i] - let version = sec.version(p.timestamp) - let r = sec.client.newPayload(version, p) + let r = sec.newPayload(p) #r.ExpectationDescription = "Sent modified payload to secondary client, expected to be accepted" r.expectStatusEither([PayloadExecutionStatus.valid, PayloadExecutionStatus.accepted]) let fcu = ForkchoiceStateV1( headblockHash: p.blockHash, ) - let s = sec.client.forkchoiceUpdated(version, fcu) + let timeVer = sec.version(p.timestamp) + let s = sec.forkchoiceUpdated(timeVer, fcu) #s.ExpectationDescription = "Sent modified payload forkchoice updated to secondary client, expected to be accepted" s.expectStatusEither([PayloadExecutionStatus.valid, PayloadExecutionStatus.syncing]) @@ -362,14 +362,14 @@ method execute(cs: InvalidMissingAncestorReOrgSyncTest, env: TestEnv): bool = # If we are syncing through p2p, we need to keep polling until the client syncs the missing payloads let period = chronos.milliseconds(500) while true: - let version = env.engine.version(shadow.payloads[shadow.n].timestamp) - let r = env.engine.client.newPayload(version, shadow.payloads[shadow.n]) + let r = env.engine.newPayload(shadow.payloads[shadow.n]) info "Response from main client", status=r.get.status let fcu = ForkchoiceStateV1( headblockHash: shadow.payloads[shadow.n].blockHash, ) - let s = env.engine.client.forkchoiceUpdated(version, fcu) + let timeVer = shadow.payloads[shadow.n].timestamp + let s = env.engine.forkchoiceUpdated(timeVer, fcu) info "Response from main client fcu", status=s.get.payloadStatus.status if r.get.status == PayloadExecutionStatus.invalid: @@ -413,12 +413,12 @@ method execute(cs: InvalidMissingAncestorReOrgSyncTest, env: TestEnv): bool = for i in start..stop: if env.clMock.executedPayloadHistory.hasKey(i): let payload = env.clMock.executedPayloadHistory[i] - let r = env.engine.client.newPayload(payload) + let r = env.engine.newPayload(payload) r.expectStatus(PayloadExecutionStatus.valid) # Resend the latest correct fcU - let version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + let timeVer = env.clMock.latestPayloadBuilt.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectNoError() # After this point, the CL Mock will send the next payload of the canonical chain return true diff --git a/hive_integration/nodocker/engine/engine/invalid_payload.nim b/hive_integration/nodocker/engine/engine/invalid_payload.nim index 5f9933b23..ffa8fab8c 100644 --- a/hive_integration/nodocker/engine/engine/invalid_payload.nim +++ b/hive_integration/nodocker/engine/engine/invalid_payload.nim @@ -98,8 +98,8 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = )) ## This block is now unknown to the main client, sending an fcU will set it to cs.syncing mode - let version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + let timeVer = env.clMock.latestPayloadBuilt.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectPayloadStatus(PayloadExecutionStatus.syncing) let shadow = InvalidPayloadShadow( @@ -132,8 +132,7 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = shadow.nilLatestValidHash = true # Depending on the field we modified, we expect a different status - var version = env.engine.version(shadow.alteredPayload.timestamp) - let r = env.engine.client.newPayload(version, shadow.alteredPayload) + let r = env.engine.newPayload(shadow.alteredPayload) if cs.syncing or cs.invalidField == InvalidParentHash: # Execution specification:: # (status: ACCEPTED, latestValidHash: null, validationError: null) if the following conditions are met: @@ -172,8 +171,8 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = # Execution specification: # (payloadStatus: (status: INVALID, latestValidHash: null, validationError: errorMessage | null), payloadId: null) # obtained from the Payload validation process if the payload is deemed INVALID - version = env.engine.version(shadow.alteredPayload.timestamp) - let s = env.engine.client.forkchoiceUpdated(version, fcState, Opt.some(attr)) + var timeVer = shadow.alteredPayload.timestamp + let s = env.engine.forkchoiceUpdated(timeVer, fcState, Opt.some(attr)) if not cs.syncing: # Execution specification: # (payloadStatus: (status: INVALID, latestValidHash: null, validationError: errorMessage | null), payloadId: null) @@ -185,22 +184,21 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = s.expectPayloadStatus(PayloadExecutionStatus.syncing) # When we send the previous payload, the client must now be capable of determining that the invalid payload is actually invalid - let version = env.engine.version(env.clMock.latestExecutedPayload.timestamp) - let p = env.engine.client.newPayload(version, env.clMock.latestExecutedPayload) + let p = env.engine.newPayload(env.clMock.latestExecutedPayload) p.expectStatus(PayloadExecutionStatus.valid) p.expectLatestValidHash(env.clMock.latestExecutedPayload.blockHash) # Another option here could be to send an fcU to the previous payload, # but this does not seem like something the CL would do. - #s = env.engine.client.forkchoiceUpdated(ForkchoiceStateV1( + #s = env.engine.forkchoiceUpdated(ForkchoiceStateV1( # headblockHash: previousPayload.blockHash, # safeblockHash: previousPayload.blockHash, # finalizedblockHash: previousPayload.blockHash, #), nil) #s.expectPayloadStatus(Valid) - let q = env.engine.client.newPayload(version, shadow.alteredPayload) + let q = env.engine.newPayload(shadow.alteredPayload) if cs.invalidField == InvalidParentHash: # There is no invalid parentHash, if this value is incorrect, # it is assumed that the block is missing and we need to sync. @@ -224,8 +222,8 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = # Try sending the fcU again, this time we should get the proper invalid response. # At this moment the response should be INVALID if cs.invalidField != InvalidParentHash: - let version = env.engine.version(shadow.alteredPayload.timestamp) - let s = env.engine.client.forkchoiceUpdated(version, fcState) + let timeVer = shadow.alteredPayload.timestamp + let s = env.engine.forkchoiceUpdated(timeVer, fcState) # Note: syncing is acceptable here as long as the block produced after this test is produced successfully s.expectStatusEither([PayloadExecutionStatus.syncing, PayloadExecutionStatus.invalid]) @@ -238,12 +236,12 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = if cs.syncing: # Send the valid payload and its corresponding forkchoiceUpdated - let version = env.engine.version(env.clMock.latestExecutedPayload.timestamp) - let r = env.engine.client.newPayload(version, env.clMock.latestExecutedPayload) + let r = env.engine.newPayload(env.clMock.latestExecutedPayload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(env.clMock.latestExecutedPayload.blockHash) - let s = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + let timeVer = env.clMock.latestExecutedPayload.timestamp + let s = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) s.expectPayloadStatus(PayloadExecutionStatus.valid) s.expectLatestValidHash(env.clMock.latestExecutedPayload.blockHash) @@ -273,8 +271,7 @@ method execute(cs: InvalidPayloadTestCase, env: TestEnv): bool = # or syncing (parent payload is thrown out and also client assumes that the parent is part of canonical chain) # or INVALID (client still has the payload and can verify that this payload is incorrectly building on top of it), # but a VALID response is incorrect. - let version = env.engine.version(followUpAlteredPayload.timestamp) - let r = env.engine.client.newPayload(version, followUpAlteredPayload) + let r = env.engine.newPayload(followUpAlteredPayload) r.expectStatusEither([PayloadExecutionStatus.accepted, PayloadExecutionStatus.invalid, PayloadExecutionStatus.syncing]) if r.get.status in [PayloadExecutionStatus.accepted, PayloadExecutionStatus.syncing]: r.expectLatestValidHash() @@ -336,8 +333,8 @@ method execute(cs: PayloadBuildAfterInvalidPayloadTest, env: TestEnv): bool = suggestedFeerecipient: Opt.some(ZeroAddr), ) payloadAttributes = customizer.getPayloadAttributes(env.clMock.latestPayloadAttributes) - version = env.engine.version(env.clMock.latestHeader.timestamp) - r = invalidPayloadProducer.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(payloadAttributes)) + timeVer = env.clMock.latestHeader.timestamp + r = invalidPayloadProducer.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice, payloadAttributes) r.expectPayloadStatus(PayloadExecutionStatus.valid) # Wait for the payload to be produced by the EL @@ -346,7 +343,7 @@ method execute(cs: PayloadBuildAfterInvalidPayloadTest, env: TestEnv): bool = let versione = env.engine.version(payloadAttributes.timestamp) - s = invalidPayloadProducer.client.getPayload(r.get.payloadId.get, versione) + s = invalidPayloadProducer.client.getPayload(versione, r.get.payloadId.get) s.expectNoError() let basePayload = s.get.executionPayload @@ -359,13 +356,12 @@ method execute(cs: PayloadBuildAfterInvalidPayloadTest, env: TestEnv): bool = # Broadcast the invalid payload let - version = env.engine.version(inv_p.timestamp) - r = env.engine.client.newPayload(version, inv_p) + r = env.engine.newPayload(inv_p) r.expectStatus(PayloadExecutionStatus.invalid) r.expectLatestValidHash(env.clMock.latestForkchoice.headBlockHash) - let s = sec.client.newPayload(version, inv_p) + let s = sec.newPayload(inv_p) s.expectStatus(PayloadExecutionStatus.invalid) s.expectLatestValidHash(env.clMock.latestForkchoice.headBlockHash) diff --git a/hive_integration/nodocker/engine/engine/payload_attributes.nim b/hive_integration/nodocker/engine/engine/payload_attributes.nim index f9b8f014e..14dce4b0b 100644 --- a/hive_integration/nodocker/engine/engine/payload_attributes.nim +++ b/hive_integration/nodocker/engine/engine/payload_attributes.nim @@ -63,14 +63,14 @@ method execute(cs: InvalidPayloadAttributesTest, env: TestEnv): bool = # 2) Apply forkchoiceState # 3) Check payloadAttributes, if invalid respond with error: code: Invalid payload attributes # 4) Start payload build process and respond with VALID - let version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) + let timeVer = env.clMock.latestPayloadBuilt.timestamp if cs.syncing: # If we are SYNCING, the outcome should be SYNCING regardless of the validity of the payload atttributes - let r = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(attr)) + let r = env.engine.forkchoiceUpdated(timeVer, fcu, attr) r.expectPayloadStatus(PayloadExecutionStatus.syncing) r.expectPayloadID(Opt.none(Bytes8)) else: - let r = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(attr)) + let r = env.engine.forkchoiceUpdated(timeVer, fcu, attr) r.expectErrorCode(engineApiInvalidPayloadAttributes) # Check that the forkchoice was applied, regardless of the error diff --git a/hive_integration/nodocker/engine/engine/payload_execution.nim b/hive_integration/nodocker/engine/engine/payload_execution.nim index 3a5c1a4bb..e8e39985e 100644 --- a/hive_integration/nodocker/engine/engine/payload_execution.nim +++ b/hive_integration/nodocker/engine/engine/payload_execution.nim @@ -69,7 +69,7 @@ method execute(cs: ReExecutePayloadTest, env: TestEnv): bool = for i in start..lastBlock: doAssert env.clMock.executedPayloadHistory.hasKey(i) let payload = env.clMock.executedPayloadHistory[i] - let r = env.engine.client.newPayload(payload) + let r = env.engine.newPayload(payload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(payload.blockHash) @@ -152,8 +152,8 @@ method execute(cs: InOrderPayloadExecutionTest, env: TestEnv): bool = finalizedblockHash: env.clMock.latestExecutedPayload.blockHash, ) - var version = sec.version(env.clMock.latestExecutedPayload.timestamp) - var s = sec.client.forkchoiceUpdated(version, fcU) + var timeVer = env.clMock.latestExecutedPayload.timestamp + var s = sec.forkchoiceUpdated(timeVer, fcU) s.expectPayloadStatus(PayloadExecutionStatus.syncing) s.expectLatestValidHash() s.expectNoValidationError() @@ -162,12 +162,12 @@ method execute(cs: InOrderPayloadExecutionTest, env: TestEnv): bool = let start = env.clMock.firstPoSBlockNumber.get for k in start..env.clMock.latestExecutedPayload.blockNumber.uint64: let payload = env.clMock.executedPayloadHistory[k] - let s = sec.client.newPayload(payload) + let s = sec.newPayload(payload) s.expectStatus(PayloadExecutionStatus.valid) s.expectLatestValidHash(payload.blockHash) - version = sec.version(env.clMock.latestExecutedPayload.timestamp) - s = sec.client.forkchoiceUpdated(version, fcU) + timeVer = env.clMock.latestExecutedPayload.timestamp + s = sec.forkchoiceUpdated(timeVer, fcU) s.expectPayloadStatus(PayloadExecutionStatus.valid) s.expectLatestValidHash(fcU.headBlockHash) s.expectNoValidationError() @@ -248,8 +248,7 @@ method execute(cs: MultiplePayloadsExtendingCanonicalChainTest, env: TestEnv): b prevRandao: Opt.some(newPrevRandao), ) let newPayload = customizer.customizePayload(basePayload) - let version = env.engine.version(newPayload.timestamp) - let r = env.engine.client.newPayload(version, newPayload) + let r = env.engine.newPayload(newPayload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(newPayload.blockHash) return true @@ -272,7 +271,7 @@ type Shadow2 = ref object recipient: Address - previousPayload: ExecutionPayload + previousPayload: ExecutableData method withMainFork(cs: NewPayloadOnSyncingClientTest, fork: EngineFork): BaseSpec = var res = cs.clone() @@ -320,11 +319,11 @@ method execute(cs: NewPayloadOnSyncingClientTest, env: TestEnv): bool = return true )) testCond true - shadow.previousPayload = env.clMock.latestPayloadBuilt + shadow.previousPayload = env.clMock.latestExecutedPayload # Send the fcU to set it to syncing mode - let version = env.engine.version(env.clMock.latestHeader.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + let timeVer = env.clMock.latestHeader.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectPayloadStatus(PayloadExecutionStatus.syncing) pbRes = env.clMock.produceSingleBlock(BlockProcessCallbacks( @@ -343,7 +342,7 @@ method execute(cs: NewPayloadOnSyncingClientTest, env: TestEnv): bool = # Run test after the new payload has been obtained onGetPayload: proc(): bool = # Send the new payload from the second client to the first, it won't be able to validate it - let r = env.engine.client.newPayload(env.clMock.latestPayloadBuilt) + let r = env.engine.newPayload(env.clMock.latestExecutedPayload) r.expectStatusEither([PayloadExecutionStatus.accepted, PayloadExecutionStatus.syncing]) r.expectLatestValidHash() @@ -364,18 +363,18 @@ method execute(cs: NewPayloadOnSyncingClientTest, env: TestEnv): bool = finalizedblockHash: env.clMock.latestPayloadBuilt.blockHash, ) - var version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - var s = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(newAttr)) + var timeVer = env.clMock.latestPayloadBuilt.timestamp + var s = env.engine.forkchoiceUpdated(timeVer, fcu, newAttr) s.expectPayloadStatus(PayloadExecutionStatus.syncing) # Send the previous payload to be able to continue - var p = env.engine.client.newPayload(shadow.previousPayload) + var p = env.engine.newPayload(shadow.previousPayload) p.expectStatus(PayloadExecutionStatus.valid) p.expectLatestValidHash(shadow.previousPayload.blockHash) # Send the new payload again - p = env.engine.client.newPayload(env.clMock.latestPayloadBuilt) + p = env.engine.newPayload(env.clMock.latestExecutedPayload) p.expectStatus(PayloadExecutionStatus.valid) p.expectLatestValidHash(env.clMock.latestPayloadBuilt.blockHash) @@ -384,8 +383,8 @@ method execute(cs: NewPayloadOnSyncingClientTest, env: TestEnv): bool = safeblockHash: env.clMock.latestPayloadBuilt.blockHash, finalizedblockHash: env.clMock.latestPayloadBuilt.blockHash, ) - version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - s = env.engine.client.forkchoiceUpdated(version, fcu) + timeVer = env.clMock.latestPayloadBuilt.timestamp + s = env.engine.forkchoiceUpdated(timeVer, fcu) s.expectPayloadStatus(PayloadExecutionStatus.valid) return true @@ -443,7 +442,7 @@ method execute(cs: NewPayloadWithMissingFcUTest, env: TestEnv): bool = # Send each payload in the correct order but skip the ForkchoiceUpdated for each for i in start..env.clMock.latestHeadNumber.uint64: let payload = env.clMock.executedPayloadHistory[i] - let p = sec.client.newPayload(payload) + let p = sec.newPayload(payload) p.expectStatus(PayloadExecutionStatus.valid) p.expectLatestValidHash(payload.blockHash) @@ -457,8 +456,8 @@ method execute(cs: NewPayloadWithMissingFcUTest, env: TestEnv): bool = safeblockHash: env.clMock.executedPayloadHistory[env.clMock.latestHeadNumber.uint64-1].blockHash, finalizedblockHash: env.clMock.executedPayloadHistory[env.clMock.latestHeadNumber.uint64-2].blockHash, ) - let version = sec.version(env.clMock.latestHeader.timestamp) - let p = sec.client.forkchoiceUpdated(version, fcU) + let timeVer = env.clMock.latestHeader.timestamp + let p = sec.forkchoiceUpdated(timeVer, fcU) p.expectPayloadStatus(PayloadExecutionStatus.valid) p.expectLatestValidHash(fcU.headBlockHash) diff --git a/hive_integration/nodocker/engine/engine/payload_id.nim b/hive_integration/nodocker/engine/engine/payload_id.nim index a740202e5..46d6c022d 100644 --- a/hive_integration/nodocker/engine/engine/payload_id.nim +++ b/hive_integration/nodocker/engine/engine/payload_id.nim @@ -111,8 +111,8 @@ method execute(cs: UniquePayloadIDTest, env: TestEnv): bool = attr.parentBeaconBlockRoot = Opt.some(newBeaconRoot) # Request the payload with the modified attributes and add the payload ID to the list of known IDs - let version = env.engine.version(env.clMock.latestHeader.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(attr)) + let timeVer = env.clMock.latestHeader.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice, attr) r.expectNoError() testCond env.clMock.addPayloadID(env.engine, r.get.payloadId.get) return true diff --git a/hive_integration/nodocker/engine/engine/reorg.nim b/hive_integration/nodocker/engine/engine/reorg.nim index 85465332f..f0ce3fe9c 100644 --- a/hive_integration/nodocker/engine/engine/reorg.nim +++ b/hive_integration/nodocker/engine/engine/reorg.nim @@ -63,22 +63,21 @@ method execute(cs: SidechainReOrgTest, env: TestEnv): bool = let attr = customizer.getPayloadAttributes(env.clMock.latestPayloadAttributes) - var version = env.engine.version(env.clMock.latestPayloadBuilt.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(attr)) + var timeVer = env.clMock.latestPayloadBuilt.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice, Opt.some(attr)) r.expectNoError() let period = chronos.seconds(env.clMock.payloadProductionClientDelay) waitFor sleepAsync(period) - version = env.engine.version(attr.timestamp) - let g = env.engine.client.getPayload(r.get.payloadId.get, version) + let g = env.engine.getPayload(attr.timestamp, r.get.payloadId.get) g.expectNoError() - let alternativePayload = g.get.executionPayload - testCond len(alternativePayload.transactions) > 0: + let alternativePayload = g.get.toExecutableData(attr) + testCond len(alternativePayload.basePayload.transactions) > 0: fatal "alternative payload does not contain the prevRandao opcode tx" - let s = env.engine.client.newPayload(alternativePayload) + let s = env.engine.newPayload(alternativePayload) s.expectStatus(PayloadExecutionStatus.valid) s.expectLatestValidHash(alternativePayload.blockHash) @@ -88,8 +87,8 @@ method execute(cs: SidechainReOrgTest, env: TestEnv): bool = safeBlockHash: env.clMock.latestForkchoice.safeBlockHash, finalizedBlockHash: env.clMock.latestForkchoice.finalizedBlockHash, ) - version = env.engine.version(alternativePayload.timestamp) - let p = env.engine.client.forkchoiceUpdated(version, fcu) + timeVer = alternativePayload.timestamp + let p = env.engine.forkchoiceUpdated(timeVer, fcu) p.expectPayloadStatus(PayloadExecutionStatus.valid) # PrevRandao should be the alternative prevRandao we sent @@ -118,7 +117,7 @@ type scenario*: TransactionReOrgScenario ShadowTx = ref object - payload: ExecutionPayload + payload: ExecutableData nextTx: PooledTransaction tx: Opt[PooledTransaction] sendTransaction: proc(i: int): PooledTransaction {.gcsafe.} @@ -184,18 +183,17 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = var attr = env.clMock.latestPayloadAttributes attr.prevRandao = Bytes32.randomBytes() - var version = env.engine.version(env.clMock.latestHeader.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(attr)) + var timeVer = env.clMock.latestHeader.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice, attr) r.expectNoError() testCond r.get.payloadId.isSome: fatal "No payload ID returned by forkchoiceUpdated" - version = env.engine.version(attr.timestamp) - let g = env.engine.client.getPayload(r.get.payloadId.get, version) + let g = env.engine.getPayload(attr.timestamp, r.get.payloadId.get) g.expectNoError() - shadow.payload = g.get.executionPayload + shadow.payload = g.get.toExecutableData(attr) - testCond len(shadow.payload.transactions) == 0: + testCond len(shadow.payload.basePayload.transactions) == 0: fatal "Empty payload contains transactions" if cs.scenario != TransactionReOrgScenarioReOrgBackIn: @@ -221,7 +219,7 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = let customizer = CustomPayloadData( extraData: Opt.some(@[0x01.byte]) ) - shadow.payload = customizer.customizePayload(env.clMock.latestExecutableData).basePayload + shadow.payload = customizer.customizePayload(env.clMock.latestExecutableData) testCond shadow.payload.parentHash == env.clMock.latestPayloadBuilt.parentHash: fatal "Incorrect parent hash for payloads" @@ -243,16 +241,16 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = var payloadAttributes = env.clMock.latestPayloadAttributes payloadAttributes.suggestedFeeRecipient = Address.randomBytes() - var version = env.engine.version(env.clMock.latestHeader.timestamp) - let f = env.engine.client.forkchoiceUpdated(version, forkchoiceUpdated, Opt.some(payloadAttributes)) + var timeVer = Quantity env.clMock.latestHeader.timestamp + let f = env.engine.forkchoiceUpdated(timeVer, forkchoiceUpdated, payloadAttributes) f.expectPayloadStatus(PayloadExecutionStatus.valid) # Wait a second for the client to prepare the payload with the included transaction let period = chronos.seconds(env.clMock.payloadProductionClientDelay) waitFor sleepAsync(period) - version = env.engine.version(env.clMock.latestPayloadAttributes.timestamp) - let g = env.engine.client.getPayload(f.get.payloadId.get, version) + timeVer = env.clMock.latestPayloadAttributes.timestamp + let g = env.engine.getPayload(timeVer, f.get.payloadId.get) g.expectNoError() let payload = g.get.executionPayload @@ -260,13 +258,13 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = fatal "Payload built does not contain the transaction" # Send the new payload and forkchoiceUpdated to it - let n = env.engine.client.newPayload(payload) + let n = env.engine.newPayload(g.get.toExecutableData(payloadAttributes)) n.expectStatus(PayloadExecutionStatus.valid) forkchoiceUpdated.headBlockHash = payload.blockHash - version = env.engine.version(payload.timestamp) - let s = env.engine.client.forkchoiceUpdated(version, forkchoiceUpdated) + timeVer = payload.timestamp + let s = env.engine.forkchoiceUpdated(timeVer, forkchoiceUpdated) s.expectPayloadStatus(PayloadExecutionStatus.valid) return true , @@ -294,7 +292,7 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = #if shadow.payload == nil ( # fatal "No payload to re-org to", t.TestName) - let r = env.engine.client.newPayload(shadow.payload) + let r = env.engine.newPayload(shadow.payload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(shadow.payload.blockHash) @@ -304,8 +302,8 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = finalizedBlockHash: env.clMock.latestForkchoice.finalizedBlockHash, ) - var version = env.engine.version(shadow.payload.timestamp) - let s = env.engine.client.forkchoiceUpdated(version, fcu) + var timeVer = shadow.payload.timestamp + let s = env.engine.forkchoiceUpdated(timeVer, fcu) s.expectPayloadStatus(PayloadExecutionStatus.valid) let p = env.engine.client.namedHeader(Head) @@ -320,11 +318,11 @@ method execute(cs: TransactionReOrgTest, env: TestEnv): bool = # Re-org back if cs.scenario == TransactionReOrgScenarioNewPayloadOnRevert: - let r = env.engine.client.newPayload(env.clMock.latestPayloadBuilt) + let r = env.engine.newPayload(env.clMock.latestExecutedPayload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(env.clMock.latestPayloadBuilt.blockHash) - testCond env.clMock.broadcastForkchoiceUpdated(Version.V1, env.clMock.latestForkchoice) + testCond env.clMock.broadcastLatestForkchoice() if shadow.tx.isSome: # Now it should be back with main payload @@ -375,7 +373,7 @@ type ShadowCanon = ref object previousHash: Hash32 previousTimestamp: Web3Quantity - payload: ExecutionPayload + payload: ExecutableData parentForkchoice: ForkchoiceStateV1 parentTimestamp: uint64 @@ -425,17 +423,16 @@ method execute(cs: ReOrgBackToCanonicalTest, env: TestEnv): bool = var attr = env.clMock.latestPayloadAttributes attr.prevRandao = Bytes32.randomBytes() - var version = env.engine.version(env.clMock.latestHeader.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(attr)) + var timeVer = Quantity env.clMock.latestHeader.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice, attr) r.expectNoError() testCond r.get.payloadId.isSome: fatal "No payload ID returned by forkchoiceUpdated" - version = env.engine.version(attr.timestamp) - let g = env.engine.client.getPayload(r.get.payloadId.get, version) + let g = env.engine.getPayload(attr.timestamp, r.get.payloadId.get) g.expectNoError() - shadow.payload = g.get.executionPayload + shadow.payload = g.get.toExecutableData(attr) shadow.parentForkchoice = env.clMock.latestForkchoice shadow.parentTimestamp = env.clMock.latestHeader.timestamp.uint64 return true @@ -465,13 +462,13 @@ method execute(cs: ReOrgBackToCanonicalTest, env: TestEnv): bool = onGetpayload: proc(): bool = # We are about to execute the new payload of the canonical chain, re-org back to # the side payload - var version = env.engine.version(shadow.parentTimestamp) - let f = env.engine.client.forkchoiceUpdated(version, shadow.parentForkchoice) + var timeVer = shadow.parentTimestamp + let f = env.engine.forkchoiceUpdated(timeVer, shadow.parentForkchoice) f.expectPayloadStatus(PayloadExecutionStatus.valid) f.expectLatestValidHash(shadow.parentForkchoice.headBlockHash) # Execute the side payload - let n = env.engine.client.newPayload(shadow.payload) + let n = env.engine.newPayload(shadow.payload) n.expectStatus(PayloadExecutionStatus.valid) n.expectLatestValidHash(shadow.payload.blockHash) # At this point the next canonical payload will be executed by the CL mock, so we can @@ -490,13 +487,13 @@ method execute(cs: ReOrgBackToCanonicalTest, env: TestEnv): bool = ) # It is only expected that the client does not produce an error and the CL Mocker is able to progress after the re-org - var version = env.engine.version(shadow.previousTimestamp) - var r = env.engine.client.forkchoiceUpdated(version, fcu) + var timeVer = shadow.previousTimestamp + var r = env.engine.forkchoiceUpdated(timeVer, fcu) r.expectNoError() # Re-send the ForkchoiceUpdated that the CLMock had sent - version = env.engine.version(env.clMock.latestExecutedPayload.timestamp) - r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice) + timeVer = env.clMock.latestExecutedPayload.timestamp + r = env.engine.forkchoiceUpdated(timeVer, env.clMock.latestForkchoice) r.expectNoError() return true )) @@ -569,8 +566,7 @@ method execute(cs: ReOrgBackFromSyncingTest, env: TestEnv): bool = onGetpayload: proc(): bool = # Re-org to the unavailable sidechain in the middle of block production # to be able to re-org back to the canonical chain - var version = env.engine.version(shadow.payloads[^1].timestamp) - let r = env.engine.client.newPayload(version, shadow.payloads[^1]) + let r = env.engine.newPayload(shadow.payloads[^1]) r.expectStatusEither([PayloadExecutionStatus.syncing, PayloadExecutionStatus.accepted]) r.expectLatestValidHash() @@ -582,8 +578,8 @@ method execute(cs: ReOrgBackFromSyncingTest, env: TestEnv): bool = ) # It is only expected that the client does not produce an error and the CL Mocker is able to progress after the re-org - version = env.engine.version(shadow.payloads[^1].timestamp) - let s = env.engine.client.forkchoiceUpdated(version, fcu) + let timeVer = shadow.payloads[^1].timestamp + let s = env.engine.forkchoiceUpdated(timeVer, fcu) s.expectLatestValidHash() s.expectPayloadStatus(PayloadExecutionStatus.syncing) @@ -655,8 +651,7 @@ method execute(cs: ReOrgPrevValidatedPayloadOnSideChainTest, env: TestEnv): bool let payload = customData.customizePayload(env.clMock.latestExecutableData) shadow.payloads.add payload - let version = env.engine.version(payload.timestamp) - let r = env.engine.client.newPayload(version, payload) + let r = env.engine.newPayload(payload) r.expectStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(payload.blockHash) return true @@ -686,17 +681,17 @@ method execute(cs: ReOrgPrevValidatedPayloadOnSideChainTest, env: TestEnv): bool finalizedBlockHash: env.clMock.latestForkchoice.finalizedBlockHash, ) - var version = env.engine.version(reOrgPayload.timestamp) - let r = env.engine.client.forkchoiceUpdated(version, fcu, Opt.some(newPayloadAttributes)) + var timeVer = reOrgPayload.timestamp + let r = env.engine.forkchoiceUpdated(timeVer, fcu, newPayloadAttributes) r.expectPayloadStatus(PayloadExecutionStatus.valid) r.expectLatestValidHash(reOrgPayload.blockHash) - version = env.engine.version(newPayloadAttributes.timestamp) - let p = env.engine.client.getPayload(r.get.payloadId.get, version) + timeVer = newPayloadAttributes.timestamp + let p = env.engine.getPayload(timeVer, r.get.payloadId.get) p.expectPayloadParentHash(reOrgPayload.blockHash) - let payload = p.get.executionPayload - let s = env.engine.client.newPayload(payload) + let payload = p.get.toExecutableData(newPayloadAttributes) + let s = env.engine.newPayload(payload) s.expectStatus(PayloadExecutionStatus.valid) s.expectLatestValidHash(payload.blockHash) @@ -768,8 +763,7 @@ method execute(cs: SafeReOrgToSideChainTest, env: TestEnv): bool = let pbRes = env.clMock.produceSingleBlock(BlockProcessCallbacks( onGetpayload: proc(): bool = for p in shadow.payloads: - let version = env.engine.version(p.timestamp) - let r = env.engine.client.newPayload(version, p) + let r = env.engine.newPayload(p) r.expectStatusEither([PayloadExecutionStatus.valid, PayloadExecutionStatus.accepted]) let fcu = ForkchoiceStateV1( @@ -778,8 +772,8 @@ method execute(cs: SafeReOrgToSideChainTest, env: TestEnv): bool = finalizedBlockHash: env.clMock.executedPayloadHistory[1].blockHash, ) - let version = env.engine.version(shadow.payloads[1].timestamp) - let r = env.engine.client.forkchoiceUpdated(version, fcu) + let timeVer = shadow.payloads[1].timestamp + let r = env.engine.forkchoiceUpdated(timeVer, fcu) r.expectPayloadStatus(PayloadExecutionStatus.valid) let head = env.engine.client.namedHeader(Head) diff --git a/hive_integration/nodocker/engine/engine/versioning.nim b/hive_integration/nodocker/engine/engine/versioning.nim index 65036fbc1..0450ffc06 100644 --- a/hive_integration/nodocker/engine/engine/versioning.nim +++ b/hive_integration/nodocker/engine/engine/versioning.nim @@ -59,7 +59,7 @@ method execute(cs: ForkchoiceUpdatedOnPayloadRequestTest, env: TestEnv): bool = cs.forkchoiceUpdatedCustomizer.setEngineAPIVersionResolver(env.engine.com) let version = cs.forkchoiceUpdatedCustomizer.forkchoiceUpdatedVersion(env.clMock.latestHeader.timestamp.uint64) - let r = env.engine.client.forkchoiceUpdated(version, env.clMock.latestForkchoice, Opt.some(attr)) + let r = env.engine.forkchoiceUpdated(version, env.clMock.latestForkchoice, attr) #r.ExpectationDescription = cs.Expectation if expectedError != 0: r.expectErrorCode(expectedError) diff --git a/hive_integration/nodocker/engine/engine_client.nim b/hive_integration/nodocker/engine/engine_client.nim index 05479c549..45c3c1288 100644 --- a/hive_integration/nodocker/engine/engine_client.nim +++ b/hive_integration/nodocker/engine/engine_client.nim @@ -8,6 +8,8 @@ # at your option. This file may not be copied, modified, or distributed except # according to those terms. +{.push raises:[].} + import std/[times, json, strutils], stew/byteutils, @@ -38,6 +40,8 @@ template wrapTry(body: untyped) = return err(e.msg) except JsonRpcError as ex: return err(ex.msg) + except CatchableError as ex: + return err(ex.msg) template wrapTrySimpleRes(body: untyped) = wrapTry: @@ -65,6 +69,17 @@ proc forkchoiceUpdatedV3*(client: RpcClient, wrapTrySimpleRes: client.engine_forkchoiceUpdatedV3(update, payloadAttributes) +proc forkchoiceUpdated*(client: RpcClient, + version: Version, + update: ForkchoiceStateV1, + attr = Opt.none(PayloadAttributes)): + Result[ForkchoiceUpdatedResponse, string] = + case version + of Version.V1: return client.forkchoiceUpdatedV1(update, attr.V1) + of Version.V2: return client.forkchoiceUpdatedV2(update, attr) + of Version.V3: return client.forkchoiceUpdatedV3(update, attr) + of Version.V4: discard + proc getPayloadV1*(client: RpcClient, payloadId: Bytes8): Result[ExecutionPayloadV1, string] = wrapTrySimpleRes: client.engine_getPayloadV1(payloadId) @@ -82,8 +97,8 @@ proc getPayloadV4*(client: RpcClient, payloadId: Bytes8): Result[GetPayloadV4Res client.engine_getPayloadV4(payloadId) proc getPayload*(client: RpcClient, - payloadId: Bytes8, - version: Version): Result[GetPayloadResponse, string] = + version: Version, + payloadId: Bytes8): Result[GetPayloadResponse, string] = if version == Version.V4: let x = client.getPayloadV4(payloadId).valueOr: return err(error) @@ -117,27 +132,6 @@ proc getPayload*(client: RpcClient, executionPayload: executionPayload(x), )) -proc forkchoiceUpdated*(client: RpcClient, - update: ForkchoiceStateV1, - attr: PayloadAttributes): - Result[ForkchoiceUpdatedResponse, string] = - case attr.version - of Version.V1: return client.forkchoiceUpdatedV1(update, Opt.some attr.V1) - of Version.V2: return client.forkchoiceUpdatedV2(update, Opt.some attr) - of Version.V3: return client.forkchoiceUpdatedV3(update, Opt.some attr) - of Version.V4: discard - -proc forkchoiceUpdated*(client: RpcClient, - version: Version, - update: ForkchoiceStateV1, - attr = Opt.none(PayloadAttributes)): - Result[ForkchoiceUpdatedResponse, string] = - case version - of Version.V1: return client.forkchoiceUpdatedV1(update, attr.V1) - of Version.V2: return client.forkchoiceUpdatedV2(update, attr) - of Version.V3: return client.forkchoiceUpdatedV3(update, attr) - of Version.V4: discard - proc newPayloadV1*(client: RpcClient, payload: ExecutionPayloadV1): Result[PayloadStatusV1, string] = @@ -200,62 +194,12 @@ proc newPayloadV4*(client: RpcClient, payload: ExecutionPayload, versionedHashes: Opt[seq[VersionedHash]], parentBeaconBlockRoot: Opt[Hash32], - executionRequests: Opt[array[3, seq[byte]]] - ): + executionRequests: Opt[array[3, seq[byte]]]): Result[PayloadStatusV1, string] = wrapTrySimpleRes: client.engine_newPayloadV4(payload, versionedHashes, parentBeaconBlockRoot, executionRequests) -proc collectBlobHashes(list: openArray[Web3Tx]): seq[Hash32] = - for w3tx in list: - let tx = ethTx(w3tx) - for h in tx.versionedHashes: - result.add h - -proc newPayload*(client: RpcClient, - payload: ExecutionPayload, - beaconRoot = Opt.none(Hash32), - executionRequests = Opt.none(array[3, seq[byte]]) - ): Result[PayloadStatusV1, string] = - case payload.version - of Version.V1: return client.newPayloadV1(payload.V1) - of Version.V2: return client.newPayloadV2(payload.V2) - of Version.V3: - if beaconRoot.isNone: - # fallback - return client.newPayloadV2(payload.V2) - let versionedHashes = collectBlobHashes(payload.transactions) - return client.newPayloadV3(payload.V3, - versionedHashes, - beaconRoot.get) - of Version.V4: - let versionedHashes = collectBlobHashes(payload.transactions) - return client.newPayloadV4(payload.V3, - versionedHashes, - beaconRoot.get, - executionRequests.get) - -proc newPayload*(client: RpcClient, - version: Version, - payload: ExecutionPayload, - beaconRoot = Opt.none(Hash32), - executionRequests = Opt.none(array[3, seq[byte]])): Result[PayloadStatusV1, string] = - case version - of Version.V1: return client.newPayloadV1(payload) - of Version.V2: return client.newPayloadV2(payload) - of Version.V3: - let versionedHashes = collectBlobHashes(payload.transactions) - return client.newPayloadV3(payload, - Opt.some(versionedHashes), - beaconRoot) - of Version.V4: - let versionedHashes = collectBlobHashes(payload.transactions) - return client.newPayloadV4(payload, - Opt.some(versionedHashes), - beaconRoot, - executionRequests) - proc newPayload*(client: RpcClient, version: Version, payload: ExecutableData): Result[PayloadStatusV1, string] = @@ -495,16 +439,6 @@ proc headerByNumber*(client: RpcClient, number: uint64): Result[Header, string] return err("failed to get blockHeader: " & $number) return ok(res.toBlockHeader) -#proc blockByNumber*(client: RpcClient, number: uint64, output: var Block): Result[void, string] = -# wrapTry: -# let res = waitFor client.eth_getBlockByNumber(blockId(number), true) -# if res.isNil: -# return err("failed to get block: " & $number) -# output.header = toBlockHeader(res) -# output.txs = toTransactions(res.transactions) -# output.withdrawals = toWithdrawals(res.withdrawals) -# return ok() - proc headerByHash*(client: RpcClient, hash: Hash32): Result[Header, string] = wrapTry: let res = waitFor client.eth_getBlockByHash(hash, false) diff --git a/hive_integration/nodocker/engine/engine_env.nim b/hive_integration/nodocker/engine/engine_env.nim index e3a95cc66..2621b41a1 100644 --- a/hive_integration/nodocker/engine/engine_env.nim +++ b/hive_integration/nodocker/engine/engine_env.nim @@ -29,7 +29,9 @@ import common ], ../../../tests/test_helpers, - web3/execution_types + web3/execution_types, + ./engine_client, + ./types from ./node import setBlock @@ -186,7 +188,9 @@ proc numTxsInPool*(env: EngineEnv): int = env.txPool.numTxs func version*(env: EngineEnv, time: EthTime): Version = - if env.com.isCancunOrLater(time): + if env.com.isPragueOrLater(time): + Version.V4 + elif env.com.isCancunOrLater(time): Version.V3 elif env.com.isShanghaiOrLater(time): Version.V2 @@ -203,3 +207,54 @@ proc setBlock*(env: EngineEnv, blk: common.EthBlock): bool = # env.chain.setBlock(blk).isOk() debugEcho "TODO: fix setBlock" false + +proc newPayload*(env: EngineEnv, + payload: ExecutableData): Result[PayloadStatusV1, string] = + let version = env.version(payload.basePayload.timestamp) + env.client.newPayload(version, payload) + +proc newPayload*(env: EngineEnv, + version: Version, + payload: ExecutableData): Result[PayloadStatusV1, string] = + env.client.newPayload(version, payload) + +proc getPayload*(env: EngineEnv, + timestamp: uint64 | Web3Quantity | EthTime, + payloadId: Bytes8): Result[GetPayloadResponse, string] = + let version = env.version(timestamp) + env.client.getPayload(version, payloadId) + +proc getPayload*(env: EngineEnv, + version: Version, + payloadId: Bytes8): Result[GetPayloadResponse, string] = + env.client.getPayload(version, payloadId) + +proc forkchoiceUpdated*(env: EngineEnv, + timestamp: uint64 | Web3Quantity | EthTime, + update: ForkchoiceStateV1, + attr = Opt.none(PayloadAttributes)): + Result[ForkchoiceUpdatedResponse, string] = + let version = env.version(timestamp) + env.client.forkchoiceUpdated(version, update, attr) + +proc forkchoiceUpdated*(env: EngineEnv, + timestamp: uint64 | Web3Quantity | EthTime, + update: ForkchoiceStateV1, + attr: PayloadAttributes): + Result[ForkchoiceUpdatedResponse, string] = + let version = env.version(timestamp) + env.client.forkchoiceUpdated(version, update, Opt.some(attr)) + +proc forkchoiceUpdated*(env: EngineEnv, + version: Version, + update: ForkchoiceStateV1, + attr = Opt.none(PayloadAttributes)): + Result[ForkchoiceUpdatedResponse, string] = + env.client.forkchoiceUpdated(version, update, attr) + +proc forkchoiceUpdated*(env: EngineEnv, + version: Version, + update: ForkchoiceStateV1, + attr: PayloadAttributes): + Result[ForkchoiceUpdatedResponse, string] = + env.client.forkchoiceUpdated(version, update, Opt.some(attr)) diff --git a/hive_integration/nodocker/engine/types.nim b/hive_integration/nodocker/engine/types.nim index 23372b8d7..37820f7ae 100644 --- a/hive_integration/nodocker/engine/types.nim +++ b/hive_integration/nodocker/engine/types.nim @@ -57,10 +57,10 @@ type ExecutableData* = object basePayload* : ExecutionPayload - beaconRoot* : Opt[Hash32] - executionRequests*: Opt[array[3, seq[byte]]] attr* : PayloadAttributes + beaconRoot* : Opt[Hash32] versionedHashes*: Opt[seq[Hash32]] + executionRequests*: Opt[array[3, seq[byte]]] const DefaultTimeout* = 60 # seconds @@ -87,7 +87,7 @@ func timestampToBeaconRoot*(timestamp: Quantity): Hash32 = proc randomBytes*(_: type Bytes32): Bytes32 = doAssert randomBytes(result.data) == 32 - + proc randomBytes*(_: type Hash32): Hash32 = doAssert randomBytes(result.data) == 32 @@ -324,3 +324,27 @@ proc `parentHash=`*(x: var ExecutableData, val: auto) = proc `blockHash=`*(x: var ExecutableData, val: auto) = x.basePayload.blockHash = val + +proc collectBlobHashes*(list: openArray[Web3Tx]): seq[Hash32] = + for w3tx in list: + let tx = ethTx(w3tx) + for h in tx.versionedHashes: + result.add h + +func toExecutableData*(res: GetPayloadResponse, attr: PayloadAttributes): ExecutableData = + ExecutableData( + basePayload: res.executionPayload, + attr: attr, + beaconRoot: attr.parentBeaconBlockRoot, + versionedHashes: Opt.some(collectBlobHashes(res.executionPayload.transactions)), + executionRequests: res.executionRequests, + ) + +func toExecutableData*(payload: ExecutionPayload, attr: PayloadAttributes): ExecutableData = + ExecutableData( + basePayload: payload, + attr: attr, + beaconRoot: attr.parentBeaconBlockRoot, + versionedHashes: Opt.some(collectBlobHashes(payload.transactions)), + ) + \ No newline at end of file diff --git a/hive_integration/nodocker/engine/withdrawals/wd_reorg_spec.nim b/hive_integration/nodocker/engine/withdrawals/wd_reorg_spec.nim index ba96f93b3..1c719c7f4 100644 --- a/hive_integration/nodocker/engine/withdrawals/wd_reorg_spec.nim +++ b/hive_integration/nodocker/engine/withdrawals/wd_reorg_spec.nim @@ -39,7 +39,7 @@ type startAccount: UInt256 nextIndex : int wdHistory : WDHistory - sidechain : Table[uint64, ExecutionPayload] + sidechain : Table[uint64, ExecutableData] payloadId : Bytes8 height : uint64 attr : Opt[PayloadAttributes] @@ -92,7 +92,7 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = startAccount: 1.u256 shl 160, nextIndex : 0, wdHistory : WDHistory(), - sidechain : Table[uint64, ExecutionPayload]() + sidechain : Table[uint64, ExecutableData]() ) # Sidechain withdraws on the max account value range 0xffffffffffffffffffffffffffffffffffffffff @@ -177,7 +177,7 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = number=env.clMock.currentPayloadNumber sidechain.attr = Opt.some(attr) - let r = sec.client.forkchoiceUpdated(fcState, attr) + let r = sec.forkchoiceUpdated(attr.timestamp, fcState, attr) r.expectNoError() r.expectPayloadStatus(PayloadExecutionStatus.valid) testCond r.get().payloadId.isSome: @@ -188,27 +188,28 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = , onGetPayload: proc(): bool = var - payload: ExecutionPayload + payload: ExecutableData if env.clMock.latestPayloadBuilt.blockNumber.uint64 >= ws.getSidechainSplitHeight().uint64: # This payload is built by the secondary client, hence need to manually fetch it here doAssert(sidechain.attr.isSome) - let version = sidechain.attr.get().version - let r = sec.client.getPayload(sidechain.payloadId, version) + let attr = sidechain.attr.get() + let timeVer = attr.timestamp + let r = sec.getPayload(timeVer, sidechain.payloadId) r.expectNoError() - payload = r.get().executionPayload + payload = r.get().toExecutableData(attr) sidechain.sidechain[payload.blockNumber.uint64] = payload else: # This block is part of both chains, simply forward it to the secondary client - payload = env.clMock.latestPayloadBuilt + payload = env.clMock.latestExecutedPayload - let r = sec.client.newPayload(payload) + let r = sec.newPayload(payload) r.expectStatus(PayloadExecutionStatus.valid) let fcState = ForkchoiceStateV1( headBlockHash: payload.blockHash, ) - let p = sec.client.forkchoiceUpdated(payload.version, fcState) + let p = sec.forkchoiceUpdated(payload.timestamp, fcState) p.expectPayloadStatus(PayloadExecutionStatus.valid) return true )) @@ -260,7 +261,8 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = q.expectPayloadStatus(PayloadExecutionStatus.valid) inc sidechain.height - sidechain.sidechain[sidechain.height] = executionPayload(z.executionPayload) + let tmp = executionPayload(z.executionPayload) + sidechain.sidechain[sidechain.height] = tmp.toExecutableData(attr) # Check the withdrawals on the latest let res = ws.wdHistory.verifyWithdrawals(sidechain.height, Opt.none(uint64), env.client) @@ -279,7 +281,7 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = ws.timeoutSeconds = DefaultTimeout while loop < ws.timeoutSeconds: - let r = env.client.newPayloadV2(payload.V2) + let r = env.client.newPayloadV2(payload.basePayload.V2) r.expectNoError() let fcState = ForkchoiceStateV1(headBlockHash: sideHash) let p = env.client.forkchoiceUpdatedV2(fcState) @@ -313,11 +315,11 @@ proc execute*(ws: ReorgSpec, env: TestEnv): bool = hash=payload.blockHash.short, parentHash=payload.parentHash.short - let r = env.client.newPayload(payload) + let r = env.engine.newPayload(version, payload) r.expectStatusEither([PayloadExecutionStatus.valid, PayloadExecutionStatus.accepted]) let fcState = ForkchoiceStateV1(headBlockHash: payload.blockHash) - let p = env.client.forkchoiceUpdated(version, fcState) + let p = env.engine.forkchoiceUpdated(version, fcState) p.expectPayloadStatus(PayloadExecutionStatus.valid) inc payloadNumber diff --git a/hive_integration/nodocker/pyspec/pyspec_sim.nim b/hive_integration/nodocker/pyspec/pyspec_sim.nim index 575d3ff7b..f0e0a4189 100644 --- a/hive_integration/nodocker/pyspec/pyspec_sim.nim +++ b/hive_integration/nodocker/pyspec/pyspec_sim.nim @@ -20,6 +20,7 @@ import ../../../nimbus/beacon/payload_conv, ../../../nimbus/core/eip4844, ../engine/engine_client, + ../engine/types, ./test_env const @@ -35,8 +36,7 @@ const type Payload = object badBlock: bool - payload: ExecutionPayload - beaconRoot: Opt[Hash32] + payload: ExecutableData proc getPayload(node: JsonNode): Payload = try: @@ -45,8 +45,10 @@ proc getPayload(node: JsonNode): Payload = blk = rlp.decode(rlpBytes, EthBlock) Payload( badBlock: false, - payload: executionPayload(blk), - beaconRoot: blk.header.parentBeaconBlockRoot, + payload: ExecutableData( + basePayload: executionPayload(blk), + beaconRoot: blk.header.parentBeaconBlockRoot, + ) ) except RlpError: Payload( @@ -141,7 +143,7 @@ proc runTest(node: JsonNode, network: string): TestStatus = latestVersion = payload.payload.version - let res = env.rpcClient.newPayload(payload.payload, payload.beaconRoot) + let res = env.rpcClient.newPayload(latestVersion, payload.payload) if res.isErr: result = TestStatus.Failed echo "unable to send block ", diff --git a/tests/test_engine_api.nim b/tests/test_engine_api.nim index a2db2133c..b1a103a4b 100644 --- a/tests/test_engine_api.nim +++ b/tests/test_engine_api.nim @@ -121,8 +121,8 @@ proc runBasicCycleTest(env: TestEnv): Result[void, string] = withdrawals: Opt.some(newSeq[WithdrawalV1]()), ) fcuRes = ? client.forkchoiceUpdated(Version.V1, update, Opt.some(attr)) - payload = ? client.getPayload(fcuRes.payloadId.get, Version.V1) - npRes = ? client.newPayload(Version.V1, payload.executionPayload) + payload = ? client.getPayload(Version.V1, fcuRes.payloadId.get) + npRes = ? client.newPayloadV1(payload.executionPayload) discard ? client.forkchoiceUpdated(Version.V1, ForkchoiceStateV1( headBlockHash: npRes.latestValidHash.get @@ -150,10 +150,10 @@ proc runNewPayloadV4Test(env: TestEnv): Result[void, string] = parentBeaconBlockRoot: Opt.some(default(Hash32)) ) fcuRes = ? client.forkchoiceUpdated(Version.V3, update, Opt.some(attr)) - payload = ? client.getPayload(fcuRes.payloadId.get, Version.V4) - res = ? client.newPayload(Version.V4, - payload.executionPayload, - Opt.some(default(Hash32)), + payload = ? client.getPayload(Version.V4, fcuRes.payloadId.get) + res = ? client.newPayloadV4(payload.executionPayload, + Opt.some(default(seq[Hash32])), + attr.parentBeaconBlockRoot, payload.executionRequests) if res.status != PayloadExecutionStatus.valid: @@ -209,7 +209,7 @@ proc engineApiMain*() = debugEcho "FAILED TO EXECUTE TEST: ", res.error check res.isOk env.close() - + test "newPayloadV4": let env = setupEnv(Prague) let res = env.runNewPayloadV4Test()