Fix engine_forkchoiceUpdated bug (#2274)

* fCU Ignore update to old head

* Only enable terminal PoW block conditions for fCUV1

* Typo fix: TDD -> TTD

* Add link to Shanghai fCUV2 specification

* Add link to Paris fCUV1 specification
This commit is contained in:
andri lim 2024-06-01 20:26:12 +07:00 committed by GitHub
parent 0f0ac0bc14
commit 1565c57ae6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 31 additions and 24 deletions

View File

@ -102,38 +102,45 @@ proc forkchoiceUpdated*(ben: BeaconEngineRef,
# Block is known locally, just sanity check that the beacon client does not # Block is known locally, just sanity check that the beacon client does not
# attempt to push us back to before the merge. # attempt to push us back to before the merge.
let blockNumber = header.blockNumber.truncate(uint64) #
if header.difficulty > 0.u256 or blockNumber == 0'u64: # Disable terminal PoW block conditions validation for fCUV2 and later.
var # https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.4/src/engine/shanghai.md#specification-1
td, ptd: DifficultyInt if apiVersion == Version.V1:
ttd = com.ttd.get(high(common.BlockNumber)) let blockNumber = header.blockNumber.truncate(uint64)
if header.difficulty > 0.u256 or blockNumber == 0'u64:
var
td, ptd: DifficultyInt
ttd = com.ttd.get(high(common.BlockNumber))
if not db.getTd(blockHash, td) or (blockNumber > 0'u64 and not db.getTd(header.parentHash, ptd)): if not db.getTd(blockHash, td) or (blockNumber > 0'u64 and not db.getTd(header.parentHash, ptd)):
error "TDs unavailable for TTD check", error "TDs unavailable for TTD check",
number = blockNumber, number = blockNumber,
hash = blockHash.short, hash = blockHash.short,
td = td, td = td,
parent = header.parentHash.short, parent = header.parentHash.short,
ptd = ptd ptd = ptd
return simpleFCU(PayloadExecutionStatus.invalid, "TDs unavailable for TDD check") return simpleFCU(PayloadExecutionStatus.invalid, "TDs unavailable for TTD check")
if td < ttd or (blockNumber > 0'u64 and ptd > ttd): if td < ttd or (blockNumber > 0'u64 and ptd > ttd):
notice "Refusing beacon update to pre-merge", notice "Refusing beacon update to pre-merge",
number = blockNumber, number = blockNumber,
hash = blockHash.short, hash = blockHash.short,
diff = header.difficulty, diff = header.difficulty,
ptd = ptd, ptd = ptd,
ttd = ttd ttd = ttd
return invalidFCU("Refusing beacon update to pre-merge") return invalidFCU("Refusing beacon update to pre-merge")
# If the head block is already in our canonical chain, the beacon client is # If the head block is already in our canonical chain, the beacon client is
# probably resyncing. Ignore the update. # probably resyncing. Ignore the update.
# See point 2 of fCUV1 specification
# https://github.com/ethereum/execution-apis/blob/v1.0.0-beta.4/src/engine/paris.md#specification-1
var canonHash: common.Hash256 var canonHash: common.Hash256
if db.getBlockHash(header.blockNumber, canonHash) and canonHash == blockHash: if db.getBlockHash(header.blockNumber, canonHash) and canonHash == blockHash:
# TODO should this be possible? notice "Ignoring beacon update to old head",
# If we allow these types of reorgs, we will do lots and lots of reorgs during sync blockHash=blockHash.short,
notice "Reorg to previous block", blockHash blockNumber=header.blockNumber
return validFCU(none(PayloadID), blockHash)
chain.setCanonical(header).isOkOr: chain.setCanonical(header).isOkOr:
return invalidFCU(error, com, header) return invalidFCU(error, com, header)