fix engine api and angine api test
This commit is contained in:
parent
9e8d2d0550
commit
d07ef2ee56
|
@ -327,3 +327,6 @@ proc isBlockPoS*(cl: CLMocker, bn: common.BlockNumber): bool =
|
|||
return false
|
||||
|
||||
return true
|
||||
|
||||
proc posBlockNumber*(cl: CLMocker): uint64 =
|
||||
cl.firstPoSBlockNumber.get(0'u64)
|
||||
|
|
|
@ -9,7 +9,7 @@ proc main() =
|
|||
let start = getTime()
|
||||
|
||||
for x in engineTestList:
|
||||
var t = setupELClient()
|
||||
var t = setupELClient(x.chainFile)
|
||||
t.setRealTTD(x.ttd)
|
||||
let status = x.run(t)
|
||||
t.stopELClient()
|
||||
|
@ -17,5 +17,6 @@ proc main() =
|
|||
|
||||
let elpd = getTime() - start
|
||||
print(stat, elpd, "engine")
|
||||
echo stat
|
||||
|
||||
main()
|
||||
|
|
|
@ -16,18 +16,91 @@ type
|
|||
name*: string
|
||||
run*: proc(t: TestEnv): TestStatus
|
||||
ttd*: int64
|
||||
chainFile*: string
|
||||
|
||||
const
|
||||
prevRandaoContractAddr = hexToByteArray[20]("0000000000000000000000000000000000000316")
|
||||
|
||||
template testCond(expr: untyped) =
|
||||
if not (expr):
|
||||
return TestStatus.Failed
|
||||
when result is bool:
|
||||
return false
|
||||
else:
|
||||
return TestStatus.Failed
|
||||
|
||||
template testCond(expr, body: untyped) =
|
||||
if not (expr):
|
||||
body
|
||||
return TestStatus.Failed
|
||||
when result is bool:
|
||||
return false
|
||||
else:
|
||||
return TestStatus.Failed
|
||||
|
||||
proc `$`(x: Option[Hash256]): string =
|
||||
if x.isNone:
|
||||
"none"
|
||||
else:
|
||||
x.get().data.toHex
|
||||
|
||||
proc `$`(x: Option[BlockHash]): string =
|
||||
if x.isNone:
|
||||
"none"
|
||||
else:
|
||||
x.get().toHex
|
||||
|
||||
proc `$`(x: Option[PayloadID]): string =
|
||||
if x.isNone:
|
||||
"none"
|
||||
else:
|
||||
x.get().toHex
|
||||
|
||||
proc `==`(a: Option[BlockHash], b: Option[Hash256]): bool =
|
||||
if a.isNone or b.isNone:
|
||||
return false
|
||||
a.get() == b.get().data.BlockHash
|
||||
|
||||
template testFCU(res, cond: untyped, validHash: Option[Hash256], id = none(PayloadID)) =
|
||||
testCond res.isOk
|
||||
let s = res.get()
|
||||
testCond s.payloadStatus.status == PayloadExecutionStatus.cond:
|
||||
error "Unexpected FCU status", expect=PayloadExecutionStatus.cond, get=s.payloadStatus.status
|
||||
testCond s.payloadStatus.latestValidHash == validHash:
|
||||
error "Unexpected FCU latestValidHash", expect=validHash, get=s.payloadStatus.latestValidHash
|
||||
testCond s.payloadId == id:
|
||||
error "Unexpected FCU payloadID", expect=id, get=s.payloadId
|
||||
|
||||
template testFCU(res, cond: untyped) =
|
||||
testCond res.isOk
|
||||
let s = res.get()
|
||||
testCond s.payloadStatus.status == PayloadExecutionStatus.cond:
|
||||
error "Unexpected FCU status", expect=PayloadExecutionStatus.cond, get=s.payloadStatus.status
|
||||
|
||||
template testNP(res, cond: untyped, validHash = none(Hash256)) =
|
||||
testCond res.isOk
|
||||
let s = res.get()
|
||||
testCond s.status == PayloadExecutionStatus.cond:
|
||||
error "Unexpected NewPayload status", expect=PayloadExecutionStatus.cond, get=s.status
|
||||
testCond s.latestValidHash == validHash:
|
||||
error "Unexpected NewPayload latestValidHash", expect=validHash, get=s.latestValidHash
|
||||
|
||||
template testNPEither(res, cond: untyped, validHash = none(Hash256)) =
|
||||
testCond res.isOk
|
||||
let s = res.get()
|
||||
testCond s.status in cond:
|
||||
error "Unexpected NewPayload status", expect=cond, get=s.status
|
||||
testCond s.latestValidHash == validHash:
|
||||
error "Unexpected NewPayload latestValidHash", expect=validHash, get=s.latestValidHash
|
||||
|
||||
proc sendTx(t: TestEnv, recipient: EthAddress, val: UInt256, data: openArray[byte] = []): bool =
|
||||
t.tx = t.makeNextTransaction(recipient, val, data)
|
||||
let rr = t.rpcClient.sendTransaction(t.tx)
|
||||
if rr.isErr:
|
||||
error "Unable to send transaction", msg=rr.error
|
||||
return false
|
||||
return true
|
||||
|
||||
proc sendTx(t: TestEnv, val: UInt256): bool =
|
||||
t.sendTx(prevRandaoContractAddr, val)
|
||||
|
||||
# Invalid Terminal Block in ForkchoiceUpdated:
|
||||
# Client must reject ForkchoiceUpdated directives if the referenced HeadBlockHash does not meet the TTD requirement.
|
||||
|
@ -43,17 +116,11 @@ proc invalidTerminalBlockForkchoiceUpdated(t: TestEnv): TestStatus =
|
|||
)
|
||||
|
||||
let res = t.rpcClient.forkchoiceUpdatedV1(forkchoiceState)
|
||||
|
||||
# Execution specification:
|
||||
# {payloadStatus: {status: INVALID, latestValidHash=0x00..00}, payloadId: null}
|
||||
# either obtained from the Payload validation process or as a result of validating a PoW block referenced by forkchoiceState.headBlockHash
|
||||
testCond res.isOk
|
||||
|
||||
let s = res.get()
|
||||
testCond s.payloadStatus.status == PayloadExecutionStatus.invalid
|
||||
testCond s.payloadStatus.latestValidHash.isNone
|
||||
testCond s.payloadId.isNone
|
||||
|
||||
testFCU(res, invalid, some(Hash256()))
|
||||
# ValidationError is not validated since it can be either null or a string message
|
||||
|
||||
# Check that PoW chain progresses
|
||||
|
@ -91,13 +158,9 @@ proc invalidTerminalBlockNewPayload(t: TestEnv): TestStatus =
|
|||
let res = t.rpcClient.newPayloadV1(hashedPayload)
|
||||
|
||||
# Execution specification:
|
||||
# {status: INVALID_TERMINAL_BLOCK, latestValidHash: null, validationError: errorMessage | null}
|
||||
# {status: INVALID, latestValidHash=0x00..00}
|
||||
# if terminal block conditions are not satisfied
|
||||
testCond res.isOk
|
||||
|
||||
let s = res.get()
|
||||
testCond s.status == PayloadExecutionStatus.invalid
|
||||
testCond s.latestValidHash.isNone
|
||||
testNP(res, invalid, some(Hash256()))
|
||||
|
||||
# Check that PoW chain progresses
|
||||
testCond t.verifyPoWProgress(t.gHeader.blockHash)
|
||||
|
@ -346,7 +409,6 @@ template invalidPayloadAttributesGen(procname: untyped, syncingCond: bool) =
|
|||
else:
|
||||
let r = client.forkchoiceUpdatedV1(fcu, some(attr))
|
||||
if r.isOk:
|
||||
debugEcho "EEEE"
|
||||
return false
|
||||
|
||||
# Check that the forkchoice was applied, regardless of the error
|
||||
|
@ -385,13 +447,10 @@ proc preTTDFinalizedBlockHash(t: TestEnv): TestStatus =
|
|||
clMock = t.clMock
|
||||
|
||||
var res = client.forkchoiceUpdatedV1(forkchoiceState)
|
||||
# TBD: Behavior on this edge-case is undecided, as behavior of the Execution client
|
||||
# if not defined on re-orgs to a point before the latest finalized block.
|
||||
testFCU(res, invalid, some(Hash256()))
|
||||
|
||||
res = client.forkchoiceUpdatedV1(clMock.latestForkchoice)
|
||||
testCond res.isOk
|
||||
let s = res.get()
|
||||
testCond s.payloadStatus.status == PayloadExecutionStatus.valid
|
||||
testFCU(res, valid)
|
||||
|
||||
# Corrupt the hash of a valid payload, client should reject the payload.
|
||||
# All possible scenarios:
|
||||
|
@ -548,6 +607,55 @@ proc parentHashOnExecPayload(t: TestEnv): TestStatus =
|
|||
))
|
||||
testCond produceSingleBlockRes
|
||||
|
||||
# Attempt to re-org to a chain containing an invalid transition payload
|
||||
proc invalidTransitionPayload(t: TestEnv): TestStatus =
|
||||
result = TestStatus.OK
|
||||
|
||||
# Wait until TTD is reached by main client
|
||||
let ok = waitFor t.clMock.waitForTTD()
|
||||
testCond ok
|
||||
|
||||
let clMock = t.clMock
|
||||
let client = t.rpcClient
|
||||
|
||||
# Produce two blocks before trying to re-org
|
||||
t.nonce = 2 # Initial PoW chain already contains 2 transactions
|
||||
var pbRes = clMock.produceBlocks(2, BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
t.sendTx(1.u256)
|
||||
))
|
||||
|
||||
testCond pbRes
|
||||
|
||||
# Introduce the invalid transition payload
|
||||
pbRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
# This is being done in the middle of the block building
|
||||
# process simply to be able to re-org back.
|
||||
onGetPayload: proc(): bool =
|
||||
let basePayload = clMock.executedPayloadHistory[clMock.posBlockNumber]
|
||||
let alteredPayload = generateInvalidPayload(basePayload, InvalidStateRoot)
|
||||
|
||||
let res = client.newPayloadV1(alteredPayload)
|
||||
let cond = {PayloadExecutionStatus.invalid, PayloadExecutionStatus.accepted}
|
||||
testNPEither(res, cond, some(Hash256()))
|
||||
|
||||
let rr = client.forkchoiceUpdatedV1(
|
||||
ForkchoiceStateV1(headBlockHash: alteredPayload.blockHash)
|
||||
)
|
||||
testFCU(rr, invalid, some(Hash256()))
|
||||
|
||||
var header: EthBlockHeader
|
||||
let rz = client.latestHeader(header)
|
||||
if rz.isErr:
|
||||
error "unable to get header", msg=rz.error
|
||||
return false
|
||||
|
||||
let blockHash = BlockHash header.blockHash.data
|
||||
blockHash == clMock.latestExecutedPayload.blockHash
|
||||
))
|
||||
|
||||
testCond pbRes
|
||||
|
||||
template invalidPayloadTestCaseGen(procName: untyped, payloadField: InvalidPayloadField, emptyTxs: bool = false) =
|
||||
proc procName(t: TestEnv): TestStatus =
|
||||
result = TestStatus.OK
|
||||
|
@ -559,22 +667,17 @@ template invalidPayloadTestCaseGen(procName: untyped, payloadField: InvalidPaylo
|
|||
let clMock = t.clMock
|
||||
let client = t.rpcClient
|
||||
|
||||
template txProc() =
|
||||
template txProc(): bool =
|
||||
when not emptyTxs:
|
||||
let
|
||||
tx = t.makeNextTransaction(prevRandaoContractAddr, 0.u256)
|
||||
rr = client.sendTransaction(tx)
|
||||
|
||||
if rr.isErr:
|
||||
error "Unable to send transaction", msg=rr.error
|
||||
return false
|
||||
t.sendTx(0.u256)
|
||||
else:
|
||||
true
|
||||
|
||||
# Produce blocks before starting the test
|
||||
var pbRes = clMock.produceBlocks(5, BlockProcessCallbacks(
|
||||
# Make sure at least one transaction is included in each block
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
txProc()
|
||||
return true
|
||||
))
|
||||
|
||||
testCond pbRes
|
||||
|
@ -585,7 +688,6 @@ template invalidPayloadTestCaseGen(procName: untyped, payloadField: InvalidPaylo
|
|||
# Make sure at least one transaction is included in the payload
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
txProc()
|
||||
return true
|
||||
,
|
||||
# Run test after the new payload has been obtained
|
||||
onGetPayload: proc(): bool =
|
||||
|
@ -598,8 +700,7 @@ template invalidPayloadTestCaseGen(procName: untyped, payloadField: InvalidPaylo
|
|||
error "No transactions in the base payload"
|
||||
return false
|
||||
|
||||
let execData = clMock.latestPayloadBuilt.toExecutableData
|
||||
let alteredPayload = generateInvalidPayload(execData, payloadField, t.vaultKey)
|
||||
let alteredPayload = generateInvalidPayload(clMock.latestPayloadBuilt, payloadField, t.vaultKey)
|
||||
invalidPayload.hash = hash256(alteredPayload.blockHash)
|
||||
|
||||
# Depending on the field we modified, we expect a different status
|
||||
|
@ -735,13 +836,8 @@ template blockStatusExecPayloadGen(procname: untyped, transitionBlock: bool) =
|
|||
var produceSingleBlockRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
var address: EthAddress
|
||||
let tx = t.makeNextTransaction(address, 1.u256)
|
||||
let res = client.sendTransaction(tx)
|
||||
if res.isErr:
|
||||
error "Unable to send transaction"
|
||||
return false
|
||||
|
||||
shadow.hash = rlpHash(tx)
|
||||
testCond t.sendTx(address, 1.u256)
|
||||
shadow.hash = rlpHash(t.tx)
|
||||
return true
|
||||
,
|
||||
onNewPayloadBroadcast: proc(): bool =
|
||||
|
@ -804,13 +900,8 @@ template blockStatusHeadBlockGen(procname: untyped, transitionBlock: bool) =
|
|||
var produceSingleBlockRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
var address: EthAddress
|
||||
let tx = t.makeNextTransaction(address, 1.u256)
|
||||
let res = client.sendTransaction(tx)
|
||||
if res.isErr:
|
||||
error "Unable to send transaction"
|
||||
return false
|
||||
|
||||
shadow.hash = rlpHash(tx)
|
||||
testCond t.sendTx(address, 1.u256)
|
||||
shadow.hash = rlpHash(t.tx)
|
||||
return true
|
||||
,
|
||||
# Run test after a forkchoice with new HeadBlockHash has been broadcasted
|
||||
|
@ -858,13 +949,8 @@ template blockStatusSafeBlockGen(procname: untyped, transitionBlock: bool) =
|
|||
var produceSingleBlockRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
var address: EthAddress
|
||||
let tx = t.makeNextTransaction(address, 1.u256)
|
||||
let res = client.sendTransaction(tx)
|
||||
if res.isErr:
|
||||
error "Unable to send transaction"
|
||||
return false
|
||||
|
||||
shadow.hash = rlpHash(tx)
|
||||
testCond t.sendTx(address, 1.u256)
|
||||
shadow.hash = rlpHash(t.tx)
|
||||
return true
|
||||
,
|
||||
# Run test after a forkchoice with new HeadBlockHash has been broadcasted
|
||||
|
@ -911,13 +997,8 @@ template blockStatusFinalizedBlockGen(procname: untyped, transitionBlock: bool)
|
|||
var produceSingleBlockRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
var address: EthAddress
|
||||
let tx = t.makeNextTransaction(address, 1.u256)
|
||||
let res = client.sendTransaction(tx)
|
||||
if res.isErr:
|
||||
error "Unable to send transaction"
|
||||
return false
|
||||
|
||||
shadow.hash = rlpHash(tx)
|
||||
testCond t.sendTx(address, 1.u256)
|
||||
shadow.hash = rlpHash(t.tx)
|
||||
return true
|
||||
,
|
||||
# Run test after a forkchoice with new HeadBlockHash has been broadcasted
|
||||
|
@ -1149,11 +1230,7 @@ proc outOfOrderPayloads(t: TestEnv): TestStatus =
|
|||
# We send the transactions after we got the Payload ID, before the clMocker gets the prepared Payload
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
for i in 0..<txPerPayload:
|
||||
let tx = t.makeNextTransaction(recipient, amountPerTx)
|
||||
let res = client.sendTransaction(tx)
|
||||
if res.isErr:
|
||||
error "Unable to send transaction"
|
||||
return false
|
||||
testCond t.sendTx(recipient, amountPerTx)
|
||||
return true
|
||||
))
|
||||
testCond produceBlockRes
|
||||
|
@ -1293,8 +1370,7 @@ proc transactionReorg(t: TestEnv): TestStatus =
|
|||
testCond ok
|
||||
|
||||
# Produce blocks before starting the test
|
||||
let produce5BlockRes = t.clMock.produceBlocks(5, BlockProcessCallbacks())
|
||||
testCond produce5BlockRes
|
||||
testCond t.clMock.produceBlocks(5, BlockProcessCallbacks())
|
||||
|
||||
# Create transactions that modify the state in order to testCond after the reorg.
|
||||
const
|
||||
|
@ -1312,20 +1388,14 @@ proc transactionReorg(t: TestEnv): TestStatus =
|
|||
for i in 0..<txCount:
|
||||
# Data is the key where a `1` will be stored
|
||||
let data = i.u256
|
||||
let tx = t.makeNextTransaction(contractAddr, 0.u256, data.toBytesBE)
|
||||
txs[i] = tx
|
||||
|
||||
# Send the transaction
|
||||
let res = client.sendTransaction(tx)
|
||||
testCond res.isOk:
|
||||
error "Unable to send transaction", msg=res.error
|
||||
testCond t.sendTx(contractAddr, 0.u256, data.toBytesBE)
|
||||
txs[i] = t.tx
|
||||
|
||||
# Produce the block containing the transaction
|
||||
var blockRes = clMock.produceSingleBlock(BlockProcessCallbacks())
|
||||
testCond blockRes
|
||||
testCond clMock.produceSingleBlock(BlockProcessCallbacks())
|
||||
|
||||
# Get the receipt
|
||||
let rr = client.txReceipt(rlpHash(tx))
|
||||
let rr = client.txReceipt(rlpHash(t.tx))
|
||||
testCond rr.isOk:
|
||||
error "Unable to obtain transaction receipt", msg=rr.error
|
||||
|
||||
|
@ -1416,8 +1486,7 @@ proc sidechainReorg(t: TestEnv): TestStatus =
|
|||
testCond ok
|
||||
|
||||
# Produce blocks before starting the test
|
||||
let produce5BlockRes = t.clMock.produceBlocks(5, BlockProcessCallbacks())
|
||||
testCond produce5BlockRes
|
||||
testCond t.clMock.produceBlocks(5, BlockProcessCallbacks())
|
||||
|
||||
let
|
||||
client = t.rpcClient
|
||||
|
@ -1426,10 +1495,7 @@ proc sidechainReorg(t: TestEnv): TestStatus =
|
|||
# Produce two payloads, send fcU with first payload, testCond transaction outcome, then reorg, testCond transaction outcome again
|
||||
|
||||
# This single transaction will change its outcome based on the payload
|
||||
let tx = t.makeNextTransaction(prevRandaoContractAddr, 0.u256)
|
||||
let rr = client.sendTransaction(tx)
|
||||
testCond rr.isOk:
|
||||
error "Unable to send transaction", msg=rr.error
|
||||
testCond t.sendTx(0.u256)
|
||||
|
||||
let singleBlockRes = clMock.produceSingleBlock(BlockProcessCallbacks(
|
||||
onNewPayloadBroadcast: proc(): bool =
|
||||
|
@ -1524,10 +1590,7 @@ proc suggestedFeeRecipient(t: TestEnv): TestStatus =
|
|||
# Send multiple transactions
|
||||
for i in 0..<txCount:
|
||||
# Empty self tx
|
||||
let tx = t.makeNextTransaction(vaultAccountAddr, 0.u256)
|
||||
let res = client.sendTransaction(tx)
|
||||
testCond res.isOk:
|
||||
error "unable to send transaction", msg=res.error
|
||||
discard t.sendTx(vaultAccountAddr, 0.u256)
|
||||
|
||||
# Produce the next block with the fee recipient set
|
||||
clMock.nextFeeRecipient = feeRecipient
|
||||
|
@ -1579,21 +1642,14 @@ proc suggestedFeeRecipient(t: TestEnv): TestStatus =
|
|||
error "balance does not match fees",
|
||||
feeRecipientBalance, feeRecipientFees
|
||||
|
||||
proc sendTx(t: TestEnv): Future[void] {.async.} =
|
||||
proc sendTxAsync(t: TestEnv): Future[void] {.async.} =
|
||||
let
|
||||
client = t.rpcClient
|
||||
clMock = t.clMock
|
||||
period = chronos.milliseconds(500)
|
||||
|
||||
while not clMock.ttdReached:
|
||||
await sleepAsync(period)
|
||||
|
||||
let
|
||||
tx = t.makeNextTransaction(prevRandaoContractAddr, 0.u256)
|
||||
rr = client.sendTransaction(tx)
|
||||
|
||||
if rr.isErr:
|
||||
error "Unable to send transaction", msg=rr.error
|
||||
discard t.sendTx(0.u256)
|
||||
|
||||
proc prevRandaoOpcodeTx(t: TestEnv): TestStatus =
|
||||
result = TestStatus.OK
|
||||
|
@ -1601,7 +1657,7 @@ proc prevRandaoOpcodeTx(t: TestEnv): TestStatus =
|
|||
let
|
||||
client = t.rpcClient
|
||||
clMock = t.clMock
|
||||
sendTxFuture = sendTx(t)
|
||||
sendTxFuture = sendTxAsync(t)
|
||||
|
||||
# Wait until TTD is reached by this client
|
||||
let ok = waitFor clMock.waitForTTD()
|
||||
|
@ -1646,15 +1702,8 @@ proc prevRandaoOpcodeTx(t: TestEnv): TestStatus =
|
|||
|
||||
let produceBlockRes = clMock.produceBlocks(10, BlockProcessCallbacks(
|
||||
onPayloadProducerSelected: proc(): bool =
|
||||
let
|
||||
tx = t.makeNextTransaction(prevRandaoContractAddr, 0.u256)
|
||||
rr = client.sendTransaction(tx)
|
||||
|
||||
if rr.isErr:
|
||||
error "Unable to send transaction", msg=rr.error
|
||||
return false
|
||||
|
||||
shadow.txs.add tx
|
||||
testCond t.sendTx(0.u256)
|
||||
shadow.txs.add t.tx
|
||||
inc shadow.currentTxIndex
|
||||
return true
|
||||
,
|
||||
|
@ -1764,6 +1813,12 @@ const engineTestList* = [
|
|||
name: "ParentHash==BlockHash on NewPayload",
|
||||
run: parentHashOnExecPayload,
|
||||
),
|
||||
TestSpec(
|
||||
name: "Invalid Transition Payload",
|
||||
run: invalidTransitionPayload,
|
||||
ttd: 393504,
|
||||
chainFile: "blocks_2_td_393504.rlp",
|
||||
),
|
||||
TestSpec(
|
||||
name: "Invalid ParentHash NewPayload",
|
||||
run: invalidPayload1,
|
||||
|
|
|
@ -263,7 +263,10 @@ proc modifyHash(x: Hash256): Hash256 =
|
|||
result = x
|
||||
result.data[^1] = byte(255 - x.data[^1].int)
|
||||
|
||||
proc generateInvalidPayload*(basePayload: ExecutableData, payloadField: InvalidPayloadField, vaultKey: PrivateKey): ExecutionPayloadV1 =
|
||||
proc generateInvalidPayload*(basePayload: ExecutableData,
|
||||
payloadField: InvalidPayloadField,
|
||||
vaultKey: PrivateKey): ExecutionPayloadV1 =
|
||||
|
||||
var customPayload: CustomPayload
|
||||
|
||||
case payloadField
|
||||
|
@ -324,3 +327,8 @@ proc generateInvalidPayload*(basePayload: ExecutableData, payloadField: InvalidP
|
|||
customPayload.transactions = some(@[modTx])
|
||||
|
||||
customizePayload(basePayload, customPayload)
|
||||
|
||||
proc generateInvalidPayload*(basePayload: ExecutionPayloadV1,
|
||||
payloadField: InvalidPayloadField,
|
||||
vaultKey = default(PrivateKey)): ExecutionPayloadV1 =
|
||||
generateInvalidPayload(basePayload.toExecutableData, payloadField, vaultKey)
|
||||
|
|
|
@ -8,6 +8,7 @@ import
|
|||
json_rpc/[rpcserver, rpcclient],
|
||||
../../../nimbus/[
|
||||
config,
|
||||
conf_utils,
|
||||
genesis,
|
||||
context,
|
||||
constants,
|
||||
|
@ -48,8 +49,9 @@ type
|
|||
gHeader*: EthBlockHeader
|
||||
ttd*: DifficultyInt
|
||||
clMock*: CLMocker
|
||||
nonce: uint64
|
||||
nonce*: uint64
|
||||
vaultKey*: PrivateKey
|
||||
tx*: Transaction
|
||||
|
||||
Web3BlockHash* = web3types.BlockHash
|
||||
Web3Address* = web3types.Address
|
||||
|
@ -62,12 +64,17 @@ const
|
|||
baseFolder = "hive_integration" / "nodocker" / "engine"
|
||||
genesisFile = baseFolder / "genesis.json"
|
||||
sealerKey = baseFolder / "sealer.key"
|
||||
chainFolder = baseFolder / "chains"
|
||||
|
||||
# This is the account that sends vault funding transactions.
|
||||
vaultAccountAddr* = hexToByteArray[20]("0xcf49fda3be353c69b41ed96333cd24302da4556f")
|
||||
vaultKeyHex = "63b508a03c3b5937ceb903af8b1b0c191012ef6eb7e9c3fb7afa94e5d214d376"
|
||||
|
||||
proc setupELClient*(t: TestEnv) =
|
||||
proc setupELClient*(t: TestEnv, chainFile: string) =
|
||||
if chainFile.len > 0:
|
||||
# disable clique if we are using PoW chain
|
||||
t.conf.networkParams.config.poaEngine = false
|
||||
|
||||
t.ctx = newEthContext()
|
||||
let res = t.ctx.am.importPrivateKey(sealerKey)
|
||||
if res.isErr:
|
||||
|
@ -96,7 +103,13 @@ proc setupELClient*(t: TestEnv) =
|
|||
setupEngineAPI(t.sealingEngine, t.rpcServer)
|
||||
setupDebugRpc(t.chainDB, t.rpcServer)
|
||||
|
||||
t.sealingEngine.start()
|
||||
# Do not start clique sealing engine if we are using a Proof of Work chain file
|
||||
if chainFile.len > 0:
|
||||
if not importRlpBlock(chainFolder / chainFile, t.chainDB):
|
||||
quit(QuitFailure)
|
||||
else:
|
||||
t.sealingEngine.start()
|
||||
|
||||
t.rpcServer.start()
|
||||
|
||||
t.rpcClient = newRpcSocketClient()
|
||||
|
@ -110,11 +123,11 @@ proc setupELClient*(t: TestEnv) =
|
|||
|
||||
t.vaultKey = kRes.get
|
||||
|
||||
proc setupELClient*(): TestEnv =
|
||||
proc setupELClient*(chainFile: string): TestEnv =
|
||||
result = TestEnv(
|
||||
conf: makeConfig(@["--engine-signer:658bdf435d810c91414ec09147daa6db62406379", "--custom-network:" & genesisFile])
|
||||
)
|
||||
setupELClient(result)
|
||||
setupELClient(result, chainFile)
|
||||
|
||||
proc stopELClient*(t: TestEnv) =
|
||||
waitFor t.rpcClient.close()
|
||||
|
|
|
@ -19,6 +19,7 @@ type
|
|||
ok*: int
|
||||
skipped*: int
|
||||
failed*: int
|
||||
failingCases*: seq[string]
|
||||
|
||||
proc inc*(stat: var SimStat, name: string, status: TestStatus) =
|
||||
echo name, ", ", status
|
||||
|
@ -28,9 +29,13 @@ proc inc*(stat: var SimStat, name: string, status: TestStatus) =
|
|||
inc stat.skipped
|
||||
else:
|
||||
inc stat.failed
|
||||
stat.failingCases.add name
|
||||
|
||||
proc `$`*(stat: SimStat): string =
|
||||
"ok: $1, skipped: $2, failed: $3" % [$stat.ok, $stat.skipped, $stat.failed]
|
||||
result.add "Failing Cases:\n"
|
||||
for c in stat.failingCases:
|
||||
result.add "- $1 \n" % [c]
|
||||
result.add "ok: $1, skipped: $2, failed: $3" % [$stat.ok, $stat.skipped, $stat.failed]
|
||||
|
||||
proc print*(stat: SimStat, dur: Duration, name: string) =
|
||||
var f = open(name & ".md", fmWrite)
|
||||
|
|
|
@ -75,6 +75,14 @@ proc simpleFCU*(status: PayloadExecutionStatus): ForkchoiceUpdatedResponse =
|
|||
proc simpleFCU*(status: PayloadExecutionStatus, msg: string): ForkchoiceUpdatedResponse =
|
||||
ForkchoiceUpdatedResponse(payloadStatus: PayloadStatusV1(status: status, validationError: some(msg)))
|
||||
|
||||
proc invalidFCU*(hash: Hash256 = Hash256()): ForkchoiceUpdatedResponse =
|
||||
ForkchoiceUpdatedResponse(payloadStatus:
|
||||
PayloadStatusV1(
|
||||
status: PayloadExecutionStatus.invalid,
|
||||
latestValidHash: some(BlockHash hash.data)
|
||||
)
|
||||
)
|
||||
|
||||
proc validFCU*(id: Option[PayloadID], validHash: Hash256): ForkchoiceUpdatedResponse =
|
||||
ForkchoiceUpdatedResponse(
|
||||
payloadStatus: PayloadStatusV1(
|
||||
|
@ -91,8 +99,13 @@ proc invalidStatus*(validHash: Hash256, msg: string): PayloadStatusV1 =
|
|||
validationError: some(msg)
|
||||
)
|
||||
|
||||
proc invalidStatus*(validHash: Hash256 = Hash256()): PayloadStatusV1 =
|
||||
PayloadStatusV1(
|
||||
status: PayloadExecutionStatus.invalid,
|
||||
latestValidHash: some(BlockHash validHash.data)
|
||||
)
|
||||
|
||||
proc toBlockBody*(payload: ExecutionPayloadV1): BlockBody =
|
||||
# TODO the transactions from the payload have to be converted here
|
||||
result.transactions.setLen(payload.transactions.len)
|
||||
for i, tx in payload.transactions:
|
||||
result.transactions[i] = rlp.decode(distinctBase tx, Transaction)
|
||||
|
|
|
@ -84,7 +84,7 @@ proc setupEngineAPI*(
|
|||
if td < ttd:
|
||||
warn "Ignoring pre-merge payload",
|
||||
number = header.blockNumber, hash = blockHash.data.toHex, td, ttd
|
||||
return PayloadStatusV1(status: PayloadExecutionStatus.invalid)
|
||||
return invalidStatus()
|
||||
|
||||
if header.timestamp <= parent.timestamp:
|
||||
warn "Invalid timestamp",
|
||||
|
@ -96,7 +96,14 @@ proc setupEngineAPI*(
|
|||
let body = toBlockBody(payload)
|
||||
let vres = sealingEngine.chain.insertBlockWithoutSetHead(header, body)
|
||||
if vres != ValidationResult.OK:
|
||||
return invalidStatus(db.getHeadBlockHash(), "Failed to insert block")
|
||||
let ptd = db.getScore(parent.parentHash)
|
||||
let blockHash = if ptd >= ttd:
|
||||
db.getHeadBlockHash()
|
||||
else:
|
||||
# If the most recent valid ancestor is a PoW block,
|
||||
# latestValidHash MUST be set to ZERO
|
||||
Hash256()
|
||||
return invalidStatus(blockHash, "Failed to insert block")
|
||||
|
||||
# We've accepted a valid payload from the beacon client. Mark the local
|
||||
# chain transitions to notify other subsystems (e.g. downloader) of the
|
||||
|
@ -231,7 +238,7 @@ proc setupEngineAPI*(
|
|||
ptd = ptd,
|
||||
ttd = ttd
|
||||
|
||||
return simpleFCU(PayloadExecutionStatus.invalid)
|
||||
return invalidFCU()
|
||||
|
||||
# If the head block is already in our canonical chain, the beacon client is
|
||||
# probably resyncing. Ignore the update.
|
||||
|
|
Loading…
Reference in New Issue