fix shanghai withdrawal validation
previously, the withdrawal validation is in process_block only, but the one in persist block, which is also used in synchronizer is not validated properly.
This commit is contained in:
parent
f8c1a7f0a8
commit
ff1a45e095
|
@ -226,7 +226,7 @@ jobs:
|
||||||
echo '```' >> release_notes.md
|
echo '```' >> release_notes.md
|
||||||
|
|
||||||
- name: Delete tag
|
- name: Delete tag
|
||||||
uses: dev-drprasad/delete-tag-and-release@v0.2.0
|
uses: dev-drprasad/delete-tag-and-release@v1.0.1
|
||||||
with:
|
with:
|
||||||
delete_release: true
|
delete_release: true
|
||||||
tag_name: nightly
|
tag_name: nightly
|
||||||
|
|
|
@ -162,7 +162,7 @@ jobs:
|
||||||
cat windows_amd64_stat/* >> stat_notes.md
|
cat windows_amd64_stat/* >> stat_notes.md
|
||||||
|
|
||||||
- name: Delete tag
|
- name: Delete tag
|
||||||
uses: dev-drprasad/delete-tag-and-release@v0.2.0
|
uses: dev-drprasad/delete-tag-and-release@v1.0.1
|
||||||
with:
|
with:
|
||||||
delete_release: true
|
delete_release: true
|
||||||
tag_name: sim-stat
|
tag_name: sim-stat
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[json, strutils, options],
|
std/[json],
|
||||||
stew/byteutils,
|
stew/byteutils,
|
||||||
../../../tools/common/helpers,
|
../../../tools/common/helpers,
|
||||||
../../../nimbus/common/chain_config
|
../../../nimbus/common/chain_config
|
||||||
|
|
|
@ -94,6 +94,9 @@ proc toGenesisHeader*(
|
||||||
if g.difficulty.isZero and fork <= London:
|
if g.difficulty.isZero and fork <= London:
|
||||||
result.difficulty = GENESIS_DIFFICULTY
|
result.difficulty = GENESIS_DIFFICULTY
|
||||||
|
|
||||||
|
if fork >= Shanghai:
|
||||||
|
result.withdrawalsRoot = some(EMPTY_ROOT_HASH)
|
||||||
|
|
||||||
proc toGenesisHeader*(
|
proc toGenesisHeader*(
|
||||||
genesis: Genesis;
|
genesis: Genesis;
|
||||||
fork: HardFork;
|
fork: HardFork;
|
||||||
|
|
|
@ -14,8 +14,7 @@ import
|
||||||
../../common/common,
|
../../common/common,
|
||||||
../../utils/utils,
|
../../utils/utils,
|
||||||
../pow,
|
../pow,
|
||||||
../clique,
|
../clique
|
||||||
../validate
|
|
||||||
|
|
||||||
export
|
export
|
||||||
common
|
common
|
||||||
|
|
|
@ -109,8 +109,7 @@ proc persistBlocksImpl(c: ChainRef; headers: openArray[BlockHeader];
|
||||||
let res = c.com.validateHeaderAndKinship(
|
let res = c.com.validateHeaderAndKinship(
|
||||||
header,
|
header,
|
||||||
body,
|
body,
|
||||||
checkSealOK = false, # TODO: how to checkseal from here
|
checkSealOK = false) # TODO: how to checkseal from here
|
||||||
pow = c.pow)
|
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
debug "block validation error",
|
debug "block validation error",
|
||||||
msg = res.error
|
msg = res.error
|
||||||
|
|
|
@ -85,20 +85,15 @@ proc procBlkPreamble(vmState: BaseVMState;
|
||||||
if vmState.determineFork >= FkShanghai:
|
if vmState.determineFork >= FkShanghai:
|
||||||
if header.withdrawalsRoot.isNone:
|
if header.withdrawalsRoot.isNone:
|
||||||
raise ValidationError.newException("Post-Shanghai block header must have withdrawalsRoot")
|
raise ValidationError.newException("Post-Shanghai block header must have withdrawalsRoot")
|
||||||
elif body.withdrawals.isNone:
|
if body.withdrawals.isNone:
|
||||||
raise ValidationError.newException("Post-Shanghai block body must have withdrawals")
|
raise ValidationError.newException("Post-Shanghai block body must have withdrawals")
|
||||||
else:
|
|
||||||
if body.withdrawals.get.calcWithdrawalsRoot != header.withdrawalsRoot.get:
|
|
||||||
debug "Mismatched withdrawalsRoot",
|
|
||||||
blockNumber = header.blockNumber
|
|
||||||
return false
|
|
||||||
|
|
||||||
for withdrawal in body.withdrawals.get:
|
for withdrawal in body.withdrawals.get:
|
||||||
vmState.stateDB.addBalance(withdrawal.address, withdrawal.amount.gwei)
|
vmState.stateDB.addBalance(withdrawal.address, withdrawal.amount.gwei)
|
||||||
else:
|
else:
|
||||||
if header.withdrawalsRoot.isSome:
|
if header.withdrawalsRoot.isSome:
|
||||||
raise ValidationError.newException("Pre-Shanghai block header must not have withdrawalsRoot")
|
raise ValidationError.newException("Pre-Shanghai block header must not have withdrawalsRoot")
|
||||||
elif body.withdrawals.isSome:
|
if body.withdrawals.isSome:
|
||||||
raise ValidationError.newException("Pre-Shanghai block body must not have withdrawals")
|
raise ValidationError.newException("Pre-Shanghai block body must not have withdrawals")
|
||||||
|
|
||||||
if vmState.cumulativeGasUsed != header.gasUsed:
|
if vmState.cumulativeGasUsed != header.gasUsed:
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, sets, times, strutils],
|
std/[sequtils, sets, times, strutils],
|
||||||
../common/common,
|
|
||||||
../db/accounts_cache,
|
../db/accounts_cache,
|
||||||
".."/[transaction, common/common],
|
".."/[transaction, common/common],
|
||||||
".."/[errors],
|
".."/[errors],
|
||||||
|
@ -24,8 +23,6 @@ from stew/byteutils
|
||||||
import nil
|
import nil
|
||||||
|
|
||||||
export
|
export
|
||||||
pow.PowRef,
|
|
||||||
pow.new,
|
|
||||||
results
|
results
|
||||||
|
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
@ -73,8 +70,7 @@ proc validateSeal(pow: PowRef; header: BlockHeader): Result[void,string] =
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc validateHeader(com: CommonRef; header, parentHeader: BlockHeader;
|
proc validateHeader(com: CommonRef; header, parentHeader: BlockHeader;
|
||||||
txs: openArray[Transaction]; checkSealOK: bool;
|
body: BlockBody; checkSealOK: bool): Result[void,string] =
|
||||||
pow: PowRef): Result[void,string] =
|
|
||||||
|
|
||||||
template inDAOExtraRange(blockNumber: BlockNumber): bool =
|
template inDAOExtraRange(blockNumber: BlockNumber): bool =
|
||||||
# EIP-799
|
# EIP-799
|
||||||
|
@ -88,7 +84,7 @@ proc validateHeader(com: CommonRef; header, parentHeader: BlockHeader;
|
||||||
if header.extraData.len > 32:
|
if header.extraData.len > 32:
|
||||||
return err("BlockHeader.extraData larger than 32 bytes")
|
return err("BlockHeader.extraData larger than 32 bytes")
|
||||||
|
|
||||||
if header.gasUsed == 0 and 0 < txs.len:
|
if header.gasUsed == 0 and 0 < body.transactions.len:
|
||||||
return err("zero gasUsed but transactions present");
|
return err("zero gasUsed but transactions present");
|
||||||
|
|
||||||
if header.gasUsed < 0 or header.gasUsed > header.gasLimit:
|
if header.gasUsed < 0 or header.gasUsed > header.gasLimit:
|
||||||
|
@ -123,10 +119,10 @@ proc validateHeader(com: CommonRef; header, parentHeader: BlockHeader;
|
||||||
return err("provided header difficulty is too low")
|
return err("provided header difficulty is too low")
|
||||||
|
|
||||||
if checkSealOK:
|
if checkSealOK:
|
||||||
return pow.validateSeal(header)
|
return com.pow.validateSeal(header)
|
||||||
|
|
||||||
? com.validateWithdrawals(header)
|
? com.validateWithdrawals(header, body)
|
||||||
? com.validateEip4844Header(header, parentHeader, txs)
|
? com.validateEip4844Header(header, parentHeader, body.transactions)
|
||||||
|
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
|
@ -148,8 +144,8 @@ func validateUncle(currBlock, uncle, uncleParent: BlockHeader):
|
||||||
|
|
||||||
|
|
||||||
proc validateUncles(com: CommonRef; header: BlockHeader;
|
proc validateUncles(com: CommonRef; header: BlockHeader;
|
||||||
uncles: openArray[BlockHeader]; checkSealOK: bool;
|
uncles: openArray[BlockHeader];
|
||||||
pow: PowRef): Result[void,string] =
|
checkSealOK: bool): Result[void,string] =
|
||||||
let hasUncles = uncles.len > 0
|
let hasUncles = uncles.len > 0
|
||||||
let shouldHaveUncles = header.ommersHash != EMPTY_UNCLE_HASH
|
let shouldHaveUncles = header.ommersHash != EMPTY_UNCLE_HASH
|
||||||
|
|
||||||
|
@ -213,7 +209,7 @@ proc validateUncles(com: CommonRef; header: BlockHeader;
|
||||||
|
|
||||||
# Now perform VM level validation of the uncle
|
# Now perform VM level validation of the uncle
|
||||||
if checkSealOK:
|
if checkSealOK:
|
||||||
result = pow.validateSeal(uncle)
|
result = com.pow.validateSeal(uncle)
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -380,10 +376,8 @@ proc validateTransaction*(
|
||||||
proc validateHeaderAndKinship*(
|
proc validateHeaderAndKinship*(
|
||||||
com: CommonRef;
|
com: CommonRef;
|
||||||
header: BlockHeader;
|
header: BlockHeader;
|
||||||
uncles: openArray[BlockHeader];
|
body: BlockBody;
|
||||||
txs: openArray[Transaction];
|
checkSealOK: bool): Result[void, string] =
|
||||||
checkSealOK: bool;
|
|
||||||
pow: PowRef): Result[void, string] =
|
|
||||||
if header.isGenesis:
|
if header.isGenesis:
|
||||||
if header.extraData.len > 32:
|
if header.extraData.len > 32:
|
||||||
return err("BlockHeader.extraData larger than 32 bytes")
|
return err("BlockHeader.extraData larger than 32 bytes")
|
||||||
|
@ -396,41 +390,22 @@ proc validateHeaderAndKinship*(
|
||||||
return err("Failed to load block header from DB")
|
return err("Failed to load block header from DB")
|
||||||
|
|
||||||
result = com.validateHeader(
|
result = com.validateHeader(
|
||||||
header, parent, txs, checkSealOK, pow)
|
header, parent, body, checkSealOK)
|
||||||
if result.isErr:
|
if result.isErr:
|
||||||
return
|
return
|
||||||
|
|
||||||
if uncles.len > MAX_UNCLES:
|
if body.uncles.len > MAX_UNCLES:
|
||||||
return err("Number of uncles exceed limit.")
|
return err("Number of uncles exceed limit.")
|
||||||
|
|
||||||
if not chainDB.exists(header.stateRoot):
|
if not chainDB.exists(header.stateRoot):
|
||||||
return err("`state_root` was not found in the db.")
|
return err("`state_root` was not found in the db.")
|
||||||
|
|
||||||
if com.consensus != ConsensusType.POS:
|
if com.consensus != ConsensusType.POS:
|
||||||
result = com.validateUncles(header, uncles, checkSealOK, pow)
|
result = com.validateUncles(header, body.uncles, checkSealOK)
|
||||||
|
|
||||||
if result.isOk:
|
if result.isOk:
|
||||||
result = com.validateGasLimitOrBaseFee(header, parent)
|
result = com.validateGasLimitOrBaseFee(header, parent)
|
||||||
|
|
||||||
proc validateHeaderAndKinship*(
|
|
||||||
com: CommonRef;
|
|
||||||
header: BlockHeader;
|
|
||||||
body: BlockBody;
|
|
||||||
checkSealOK: bool;
|
|
||||||
pow: PowRef): Result[void, string] =
|
|
||||||
|
|
||||||
com.validateHeaderAndKinship(
|
|
||||||
header, body.uncles, body.transactions, checkSealOK, pow)
|
|
||||||
|
|
||||||
proc validateHeaderAndKinship*(
|
|
||||||
com: CommonRef;
|
|
||||||
ethBlock: EthBlock;
|
|
||||||
checkSealOK: bool;
|
|
||||||
pow: PowRef): Result[void,string] =
|
|
||||||
com.validateHeaderAndKinship(
|
|
||||||
ethBlock.header, ethBlock.uncles, ethBlock.txs,
|
|
||||||
checkSealOK, pow)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# End
|
# End
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,9 +15,25 @@ import
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
# https://eips.ethereum.org/EIPS/eip-4895
|
# https://eips.ethereum.org/EIPS/eip-4895
|
||||||
func validateWithdrawals*(
|
proc validateWithdrawals*(
|
||||||
com: CommonRef, header: BlockHeader
|
com: CommonRef, header: BlockHeader, body: BlockBody
|
||||||
): Result[void, string] =
|
): Result[void, string] =
|
||||||
|
|
||||||
|
if com.forkGTE(Shanghai):
|
||||||
|
if header.withdrawalsRoot.isNone:
|
||||||
|
return err("Post-Shanghai block header must have withdrawalsRoot")
|
||||||
|
elif body.withdrawals.isNone:
|
||||||
|
return err("Post-Shanghai block body must have withdrawals")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
if body.withdrawals.get.calcWithdrawalsRoot != header.withdrawalsRoot.get:
|
||||||
|
return err("Mismatched withdrawalsRoot blockNumber =" & $header.blockNumber)
|
||||||
|
except RlpError as ex:
|
||||||
|
return err(ex.msg)
|
||||||
|
else:
|
||||||
if header.withdrawalsRoot.isSome:
|
if header.withdrawalsRoot.isSome:
|
||||||
return err("Withdrawals not yet implemented")
|
return err("Pre-Shanghai block header must not have withdrawalsRoot")
|
||||||
|
elif body.withdrawals.isSome:
|
||||||
|
return err("Pre-Shanghai block body must not have withdrawals")
|
||||||
|
|
||||||
return ok()
|
return ok()
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
# according to those terms.
|
# according to those terms.
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[math, macros],
|
std/[macros],
|
||||||
stew/results,
|
stew/results,
|
||||||
"."/[types, blake2b_f, blscurve],
|
"."/[types, blake2b_f, blscurve],
|
||||||
./interpreter/[gas_meter, gas_costs, utils/utils_numeric],
|
./interpreter/[gas_meter, gas_costs, utils/utils_numeric],
|
||||||
|
|
|
@ -180,7 +180,7 @@ proc validateDifficulty(ctx: LegacySyncRef,
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc validateHeader(ctx: LegacySyncRef, header: BlockHeader,
|
proc validateHeader(ctx: LegacySyncRef, header: BlockHeader,
|
||||||
txs: openArray[Transaction],
|
body: BlockBody,
|
||||||
height = none(BlockNumber)): bool
|
height = none(BlockNumber)): bool
|
||||||
{.raises: [CatchableError].} =
|
{.raises: [CatchableError].} =
|
||||||
if header.parentHash == GENESIS_PARENT_HASH:
|
if header.parentHash == GENESIS_PARENT_HASH:
|
||||||
|
@ -237,13 +237,13 @@ proc validateHeader(ctx: LegacySyncRef, header: BlockHeader,
|
||||||
parentNumber=parentHeader.blockNumber
|
parentNumber=parentHeader.blockNumber
|
||||||
return false
|
return false
|
||||||
|
|
||||||
res = com.validateWithdrawals(header)
|
res = com.validateWithdrawals(header, body)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
trace "validate withdrawals error",
|
trace "validate withdrawals error",
|
||||||
msg=res.error
|
msg=res.error
|
||||||
return false
|
return false
|
||||||
|
|
||||||
res = com.validateEip4844Header(header, parentHeader, txs)
|
res = com.validateEip4844Header(header, parentHeader, body.transactions)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
trace "validate eip4844 error",
|
trace "validate eip4844 error",
|
||||||
msg=res.error
|
msg=res.error
|
||||||
|
@ -1053,7 +1053,13 @@ proc handleNewBlock(ctx: LegacySyncRef,
|
||||||
number=blk.header.blockNumber
|
number=blk.header.blockNumber
|
||||||
return
|
return
|
||||||
|
|
||||||
if not ctx.validateHeader(blk.header, blk.txs):
|
let body = BlockBody(
|
||||||
|
transactions: blk.txs,
|
||||||
|
uncles: blk.uncles,
|
||||||
|
withdrawals: blk.withdrawals
|
||||||
|
)
|
||||||
|
|
||||||
|
if not ctx.validateHeader(blk.header, body):
|
||||||
error "invalid header from peer",
|
error "invalid header from peer",
|
||||||
peer, hash=short(blk.header.blockHash)
|
peer, hash=short(blk.header.blockHash)
|
||||||
return
|
return
|
||||||
|
|
|
@ -49,8 +49,6 @@ type
|
||||||
network : string
|
network : string
|
||||||
postStateHash: Hash256
|
postStateHash: Hash256
|
||||||
|
|
||||||
var pow = PowRef.new
|
|
||||||
|
|
||||||
proc testFixture(node: JsonNode, testStatusIMPL: var TestStatus, debugMode = false, trace = false)
|
proc testFixture(node: JsonNode, testStatusIMPL: var TestStatus, debugMode = false, trace = false)
|
||||||
|
|
||||||
func normalizeNumber(n: JsonNode): JsonNode =
|
func normalizeNumber(n: JsonNode): JsonNode =
|
||||||
|
@ -206,7 +204,7 @@ proc importBlock(tester: var Tester, com: CommonRef,
|
||||||
|
|
||||||
if validation:
|
if validation:
|
||||||
let rc = com.validateHeaderAndKinship(
|
let rc = com.validateHeaderAndKinship(
|
||||||
tb.header, tb.body, checkSeal, pow)
|
tb.header, tb.body, checkSeal)
|
||||||
if rc.isErr:
|
if rc.isErr:
|
||||||
raise newException(
|
raise newException(
|
||||||
ValidationError, "validateHeaderAndKinship: " & rc.error)
|
ValidationError, "validateHeaderAndKinship: " & rc.error)
|
||||||
|
@ -259,7 +257,7 @@ proc runTester(tester: var Tester, com: CommonRef, testStatusIMPL: var TestStatu
|
||||||
|
|
||||||
# manually validating
|
# manually validating
|
||||||
let res = com.validateHeaderAndKinship(
|
let res = com.validateHeaderAndKinship(
|
||||||
tb.header, tb.body, checkSeal, pow)
|
tb.header, tb.body, checkSeal)
|
||||||
check res.isOk
|
check res.isOk
|
||||||
when defined(noisy):
|
when defined(noisy):
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
|
|
Loading…
Reference in New Issue