Engine API simulator: simplify versioned method call (#2821)

* Engine API simulator: simplify versioned method call

* More cleanup
This commit is contained in:
andri lim 2024-11-02 16:58:18 +07:00 committed by GitHub
parent a45ac7e327
commit 4ffe056a25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 284 additions and 305 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -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
))

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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)),
)

View File

@ -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

View File

@ -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 ",

View File

@ -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()