FC fix: Genesis hash should canonical too (#2839)

* FC fix: Genesis hash should canonical too

* Remove debugEcho from production code
This commit is contained in:
andri lim 2024-11-06 19:38:35 +07:00 committed by GitHub
parent cff7091826
commit fcb668d23f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 1048 additions and 42 deletions

View File

@ -749,6 +749,9 @@ func blockFromBaseTo*(c: ForkedChainRef, number: BlockNumber): seq[Block] =
prevHash = item.blk.header.parentHash prevHash = item.blk.header.parentHash
func isCanonical*(c: ForkedChainRef, blockHash: Hash32): bool = func isCanonical*(c: ForkedChainRef, blockHash: Hash32): bool =
if blockHash == c.baseHash:
return true
shouldNotKeyError: shouldNotKeyError:
var prevHash = c.cursorHash var prevHash = c.cursorHash
while prevHash != c.baseHash: while prevHash != c.baseHash:

View File

@ -171,7 +171,8 @@ proc procBlkEpilogue(
expected = header.stateRoot, expected = header.stateRoot,
actual = stateRoot, actual = stateRoot,
arrivedFrom = vmState.com.db.getCanonicalHead().stateRoot arrivedFrom = vmState.com.db.getCanonicalHead().stateRoot
return err("stateRoot mismatch") return err("stateRoot mismatch, expect: " &
$header.stateRoot & ", got: " & $stateRoot)
if not skipReceipts: if not skipReceipts:
let bloom = createBloom(vmState.receipts) let bloom = createBloom(vmState.receipts)

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,23 @@
{
"payload": {
"parentHash": "0x13613aa073d32a70ebd3c9f952da2c0f956978b64c1b37c25641c6fecb024ade",
"feeRecipient": "0xf97e180c050e5ab072211ad2c213eb5aee4df134",
"stateRoot": "0xb132115a8ec822fa5316aafd8b7832017e902da9165371fbcd3697103113d50a",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0xbcbb53c61f6b8358614a7dcc9b3e00d953342e397c27280933aa9f24c7f13a65",
"blockNumber": "0x1",
"gasLimit": "0x17dd79d",
"gasUsed": "0x0",
"timestamp": "0x6724E329",
"extraData": "0xd883010e0c846765746888676f312e32332e32856c696e7578",
"baseFeePerGas": "0x342770c0",
"blockHash": "0xb1f5a0430be7376caf86a606101c2818d14f419326eec9b8ffa30e9209e148d5",
"transactions": [],
"withdrawals": [],
"blobGasUsed": "0x0",
"excessBlobGas": "0x0"
},
"expectedBlobVersionedHashes": [],
"parentBeaconBlockRoot": "0x8b21a0a0256067676ec4b20d4118ed5bde170d78b4e9a8db1f7b7640d3b8b7c0"
}

View File

@ -28,16 +28,31 @@ import
../hive_integration/nodocker/engine/engine_client ../hive_integration/nodocker/engine/engine_client
type type
TestEnv* = ref object TestEnv = ref object
com : CommonRef com : CommonRef
server : RpcHttpServer server : RpcHttpServer
client : RpcHttpClient client : RpcHttpClient
chain : ForkedChainRef chain : ForkedChainRef
const NewPayloadV4Params* = object
genesisFile = "tests/customgenesis/engine_api_genesis.json" payload*: ExecutionPayload
expectedBlobVersionedHashes*: Opt[seq[Hash32]]
parentBeaconBlockRoot*: Opt[Hash32]
executionRequests*: Opt[array[3, seq[byte]]]
proc setupConfig(): NimbusConf = TestSpec = object
name: string
fork: HardFork
genesisFile: string
testProc: proc(env: TestEnv): Result[void, string]
NewPayloadV4Params.useDefaultSerializationIn JrpcConv
const
defaultGenesisFile = "tests/customgenesis/engine_api_genesis.json"
mekongGenesisFile = "tests/customgenesis/mekong.json"
proc setupConfig(genesisFile: string): NimbusConf =
makeConfig(@[ makeConfig(@[
"--custom-network:" & genesisFile, "--custom-network:" & genesisFile,
"--listen-address: 127.0.0.1", "--listen-address: 127.0.0.1",
@ -55,11 +70,12 @@ proc setupClient(port: Port): RpcHttpClient =
waitFor client.connect("127.0.0.1", port, false) waitFor client.connect("127.0.0.1", port, false)
return client return client
proc setupEnv(envFork: HardFork = MergeFork): TestEnv = proc setupEnv(envFork: HardFork = MergeFork,
genesisFile: string = defaultGenesisFile): TestEnv =
doAssert(envFork >= MergeFork) doAssert(envFork >= MergeFork)
let let
conf = setupConfig() conf = setupConfig(genesisFile)
if envFork >= Shanghai: if envFork >= Shanghai:
conf.networkParams.config.shanghaiTime = Opt.some(0.EthTime) conf.networkParams.config.shanghaiTime = Opt.some(0.EthTime)
@ -73,7 +89,7 @@ proc setupEnv(envFork: HardFork = MergeFork): TestEnv =
let let
com = setupCom(conf) com = setupCom(conf)
head = com.db.getCanonicalHead() head = com.db.getCanonicalHead()
chain = newForkedChain(com, head) chain = ForkedChainRef.init(com)
txPool = TxPoolRef.new(com) txPool = TxPoolRef.new(com)
# txPool must be informed of active head # txPool must be informed of active head
@ -168,18 +184,10 @@ proc runNewPayloadV4Test(env: TestEnv): Result[void, string] =
ok() ok()
type
NewPayloadV4Params* = object
payload*: ExecutionPayload
expectedBlobVersionedHashes*: Opt[seq[Hash32]]
parentBeaconBlockRoot*: Opt[Hash32]
executionRequests*: Opt[array[3, seq[byte]]]
NewPayloadV4Params.useDefaultSerializationIn JrpcConv
const paramsFile = "tests/engine_api/newPayloadV4_invalid_blockhash.json"
proc newPayloadV4ParamsTest(env: TestEnv): Result[void, string] = proc newPayloadV4ParamsTest(env: TestEnv): Result[void, string] =
const
paramsFile = "tests/engine_api/newPayloadV4_invalid_blockhash.json"
let let
client = env.client client = env.client
params = JrpcConv.loadFile(paramsFile, NewPayloadV4Params) params = JrpcConv.loadFile(paramsFile, NewPayloadV4Params)
@ -200,31 +208,75 @@ proc newPayloadV4ParamsTest(env: TestEnv): Result[void, string] =
ok() ok()
proc genesisShouldCanonicalTest(env: TestEnv): Result[void, string] =
const
paramsFile = "tests/engine_api/genesis_base_canonical.json"
let
client = env.client
params = JrpcConv.loadFile(paramsFile, NewPayloadV4Params)
res = ? client.newPayloadV3(
params.payload,
params.expectedBlobVersionedHashes,
params.parentBeaconBlockRoot)
if res.status != PayloadExecutionStatus.valid:
return err("res.status should equals to PayloadExecutionStatus.valid")
if res.latestValidHash.isNone:
return err("lastestValidHash should not empty")
let
update = ForkchoiceStateV1(
headBlockHash: params.payload.blockHash,
safeBlockHash: params.payload.parentHash,
finalizedBlockHash: params.payload.parentHash,
)
fcuRes = ? client.forkchoiceUpdated(Version.V3, update)
if fcuRes.payloadStatus.status != PayloadExecutionStatus.valid:
return err("fcuRes.payloadStatus.status should equals to PayloadExecutionStatus.valid")
ok()
const testList = [
TestSpec(
name: "Basic cycle",
fork: MergeFork,
testProc: runBasicCycleTest
),
TestSpec(
name: "newPayloadV4",
fork: Prague,
testProc: runNewPayloadV4Test
),
TestSpec(
name: "newPayloadV4 params",
fork: Prague,
testProc: newPayloadV4ParamsTest
),
TestSpec(
name: "Genesis block hash should canonical",
fork: Cancun,
testProc: genesisShouldCanonicalTest,
genesisFile: mekongGenesisFile
),
]
proc engineApiMain*() = proc engineApiMain*() =
suite "Engine API": suite "Engine API":
test "Basic cycle": for z in testList:
let env = setupEnv() test z.name:
let res = env.runBasicCycleTest() let genesisFile = if z.genesisFile.len > 0:
if res.isErr: z.genesisFile
debugEcho "FAILED TO EXECUTE TEST: ", res.error else:
check res.isOk defaultGenesisFile
env.close() let env = setupEnv(z.fork, genesisFile)
let res = z.testProc(env)
test "newPayloadV4": if res.isErr:
let env = setupEnv(Prague) debugEcho "FAILED TO EXECUTE ", z.name, ": ", res.error
let res = env.runNewPayloadV4Test() check res.isOk
if res.isErr: env.close()
debugEcho "FAILED TO EXECUTE TEST: ", res.error
check res.isOk
env.close()
test "newPayloadV4 params":
let env = setupEnv(Prague)
let res = env.newPayloadV4ParamsTest()
if res.isErr:
debugEcho "FAILED TO EXECUTE TEST: ", res.error
check res.isOk
env.close()
when isMainModule: when isMainModule:
engineApiMain() engineApiMain()