add blob validation to `test_fixture_fork_choice` (#5441)
Preparation for processing new tests from: - https://github.com/ethereum/consensus-specs/pull/3463
This commit is contained in:
parent
eadd0d69ce
commit
aacb853a0b
2
Makefile
2
Makefile
|
@ -321,7 +321,7 @@ consensus_spec_tests_minimal: | build deps
|
||||||
MAKE="$(MAKE)" V="$(V)" $(ENV_SCRIPT) scripts/compile_nim_program.sh \
|
MAKE="$(MAKE)" V="$(V)" $(ENV_SCRIPT) scripts/compile_nim_program.sh \
|
||||||
$@ \
|
$@ \
|
||||||
"tests/consensus_spec/consensus_spec_tests_preset.nim" \
|
"tests/consensus_spec/consensus_spec_tests_preset.nim" \
|
||||||
$(NIM_PARAMS) -d:const_preset=minimal $(TEST_MODULES_FLAGS) && \
|
$(NIM_PARAMS) -d:const_preset=minimal -d:FIELD_ELEMENTS_PER_BLOB=4 $(TEST_MODULES_FLAGS) && \
|
||||||
echo -e $(BUILD_END_MSG) "build/$@"
|
echo -e $(BUILD_END_MSG) "build/$@"
|
||||||
|
|
||||||
# Tests we only run for the default preset
|
# Tests we only run for the default preset
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
# Status libraries
|
# Status libraries
|
||||||
stew/results, chronicles,
|
stew/[byteutils, results], chronicles,
|
||||||
taskpools,
|
taskpools,
|
||||||
# Internals
|
# Internals
|
||||||
../../beacon_chain/spec/[helpers, forks, state_transition_block],
|
../../beacon_chain/spec/[helpers, forks, state_transition_block],
|
||||||
|
@ -28,7 +28,7 @@ import
|
||||||
|
|
||||||
from std/json import
|
from std/json import
|
||||||
JsonNode, getBool, getInt, getStr, hasKey, items, len, pairs, `$`, `[]`
|
JsonNode, getBool, getInt, getStr, hasKey, items, len, pairs, `$`, `[]`
|
||||||
from std/sequtils import toSeq
|
from std/sequtils import mapIt, toSeq
|
||||||
from std/strutils import contains
|
from std/strutils import contains
|
||||||
|
|
||||||
# Test format described at https://github.com/ethereum/consensus-specs/tree/v1.3.0/tests/formats/fork_choice
|
# Test format described at https://github.com/ethereum/consensus-specs/tree/v1.3.0/tests/formats/fork_choice
|
||||||
|
@ -45,6 +45,10 @@ type
|
||||||
opInvalidateRoot
|
opInvalidateRoot
|
||||||
opChecks
|
opChecks
|
||||||
|
|
||||||
|
BlobData = object
|
||||||
|
blobs: seq[KzgBlob]
|
||||||
|
proofs: seq[KzgProof]
|
||||||
|
|
||||||
Operation = object
|
Operation = object
|
||||||
valid: bool
|
valid: bool
|
||||||
# variant specific fields
|
# variant specific fields
|
||||||
|
@ -55,6 +59,7 @@ type
|
||||||
att: Attestation
|
att: Attestation
|
||||||
of opOnBlock:
|
of opOnBlock:
|
||||||
blck: ForkedSignedBeaconBlock
|
blck: ForkedSignedBeaconBlock
|
||||||
|
blobData: Opt[BlobData]
|
||||||
of opOnMergeBlock:
|
of opOnMergeBlock:
|
||||||
powBlock: PowBlock
|
powBlock: PowBlock
|
||||||
of opOnAttesterSlashing:
|
of opOnAttesterSlashing:
|
||||||
|
@ -69,7 +74,7 @@ from ../../beacon_chain/spec/datatypes/capella import
|
||||||
BeaconBlock, BeaconState, SignedBeaconBlock
|
BeaconBlock, BeaconState, SignedBeaconBlock
|
||||||
|
|
||||||
from ../../beacon_chain/spec/datatypes/deneb import
|
from ../../beacon_chain/spec/datatypes/deneb import
|
||||||
BeaconBlock, BeaconState, SignedBeaconBlock
|
KzgBlob, KzgProof, BeaconBlock, BeaconState, SignedBeaconBlock
|
||||||
|
|
||||||
proc initialLoad(
|
proc initialLoad(
|
||||||
path: string, db: BeaconChainDB,
|
path: string, db: BeaconChainDB,
|
||||||
|
@ -134,6 +139,8 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
|
|
||||||
result = @[]
|
result = @[]
|
||||||
for step in steps[0]:
|
for step in steps[0]:
|
||||||
|
var numExtraFields = 0
|
||||||
|
|
||||||
if step.hasKey"tick":
|
if step.hasKey"tick":
|
||||||
result.add Operation(kind: opOnTick,
|
result.add Operation(kind: opOnTick,
|
||||||
tick: step["tick"].getInt())
|
tick: step["tick"].getInt())
|
||||||
|
@ -147,12 +154,14 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
att: att)
|
att: att)
|
||||||
elif step.hasKey"block":
|
elif step.hasKey"block":
|
||||||
let filename = step["block"].getStr()
|
let filename = step["block"].getStr()
|
||||||
|
doAssert step.hasKey"blobs" == step.hasKey"proofs"
|
||||||
case fork
|
case fork
|
||||||
of ConsensusFork.Phase0:
|
of ConsensusFork.Phase0:
|
||||||
let blck = parseTest(
|
let blck = parseTest(
|
||||||
path/filename & ".ssz_snappy",
|
path/filename & ".ssz_snappy",
|
||||||
SSZ, phase0.SignedBeaconBlock
|
SSZ, phase0.SignedBeaconBlock
|
||||||
)
|
)
|
||||||
|
doAssert not step.hasKey"blobs"
|
||||||
result.add Operation(kind: opOnBlock,
|
result.add Operation(kind: opOnBlock,
|
||||||
blck: ForkedSignedBeaconBlock.init(blck))
|
blck: ForkedSignedBeaconBlock.init(blck))
|
||||||
of ConsensusFork.Altair:
|
of ConsensusFork.Altair:
|
||||||
|
@ -160,6 +169,7 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
path/filename & ".ssz_snappy",
|
path/filename & ".ssz_snappy",
|
||||||
SSZ, altair.SignedBeaconBlock
|
SSZ, altair.SignedBeaconBlock
|
||||||
)
|
)
|
||||||
|
doAssert not step.hasKey"blobs"
|
||||||
result.add Operation(kind: opOnBlock,
|
result.add Operation(kind: opOnBlock,
|
||||||
blck: ForkedSignedBeaconBlock.init(blck))
|
blck: ForkedSignedBeaconBlock.init(blck))
|
||||||
of ConsensusFork.Bellatrix:
|
of ConsensusFork.Bellatrix:
|
||||||
|
@ -167,6 +177,7 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
path/filename & ".ssz_snappy",
|
path/filename & ".ssz_snappy",
|
||||||
SSZ, bellatrix.SignedBeaconBlock
|
SSZ, bellatrix.SignedBeaconBlock
|
||||||
)
|
)
|
||||||
|
doAssert not step.hasKey"blobs"
|
||||||
result.add Operation(kind: opOnBlock,
|
result.add Operation(kind: opOnBlock,
|
||||||
blck: ForkedSignedBeaconBlock.init(blck))
|
blck: ForkedSignedBeaconBlock.init(blck))
|
||||||
of ConsensusFork.Capella:
|
of ConsensusFork.Capella:
|
||||||
|
@ -174,15 +185,27 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
path/filename & ".ssz_snappy",
|
path/filename & ".ssz_snappy",
|
||||||
SSZ, capella.SignedBeaconBlock
|
SSZ, capella.SignedBeaconBlock
|
||||||
)
|
)
|
||||||
|
doAssert not step.hasKey"blobs"
|
||||||
result.add Operation(kind: opOnBlock,
|
result.add Operation(kind: opOnBlock,
|
||||||
blck: ForkedSignedBeaconBlock.init(blck))
|
blck: ForkedSignedBeaconBlock.init(blck))
|
||||||
of ConsensusFork.Deneb:
|
of ConsensusFork.Deneb:
|
||||||
let blck = parseTest(
|
let
|
||||||
|
blck = parseTest(
|
||||||
path/filename & ".ssz_snappy",
|
path/filename & ".ssz_snappy",
|
||||||
SSZ, deneb.SignedBeaconBlock
|
SSZ, deneb.SignedBeaconBlock)
|
||||||
)
|
blobData =
|
||||||
|
if step.hasKey"blobs":
|
||||||
|
numExtraFields += 2
|
||||||
|
Opt.some BlobData(
|
||||||
|
blobs: distinctBase(parseTest(
|
||||||
|
path/(step["blobs"].getStr()) & ".ssz_snappy",
|
||||||
|
SSZ, List[KzgBlob, Limit MAX_BLOBS_PER_BLOCK])),
|
||||||
|
proofs: step["proofs"].mapIt(KzgProof.fromHex(it.getStr())))
|
||||||
|
else:
|
||||||
|
Opt.none(BlobData)
|
||||||
result.add Operation(kind: opOnBlock,
|
result.add Operation(kind: opOnBlock,
|
||||||
blck: ForkedSignedBeaconBlock.init(blck))
|
blck: ForkedSignedBeaconBlock.init(blck),
|
||||||
|
blobData: blobData)
|
||||||
elif step.hasKey"attester_slashing":
|
elif step.hasKey"attester_slashing":
|
||||||
let filename = step["attester_slashing"].getStr()
|
let filename = step["attester_slashing"].getStr()
|
||||||
let attesterSlashing = parseTest(
|
let attesterSlashing = parseTest(
|
||||||
|
@ -205,10 +228,10 @@ proc loadOps(path: string, fork: ConsensusFork): seq[Operation] =
|
||||||
doAssert false, "Unknown test step: " & $step
|
doAssert false, "Unknown test step: " & $step
|
||||||
|
|
||||||
if step.hasKey"valid":
|
if step.hasKey"valid":
|
||||||
doAssert step.len == 2
|
doAssert step.len == 2 + numExtraFields
|
||||||
result[^1].valid = step["valid"].getBool()
|
result[^1].valid = step["valid"].getBool()
|
||||||
elif not step.hasKey"checks" and not step.hasKey"payload_status":
|
elif not step.hasKey"checks" and not step.hasKey"payload_status":
|
||||||
doAssert step.len == 1
|
doAssert step.len == 1 + numExtraFields
|
||||||
result[^1].valid = true
|
result[^1].valid = true
|
||||||
|
|
||||||
proc stepOnBlock(
|
proc stepOnBlock(
|
||||||
|
@ -218,10 +241,21 @@ proc stepOnBlock(
|
||||||
state: var ForkedHashedBeaconState,
|
state: var ForkedHashedBeaconState,
|
||||||
stateCache: var StateCache,
|
stateCache: var StateCache,
|
||||||
signedBlock: ForkySignedBeaconBlock,
|
signedBlock: ForkySignedBeaconBlock,
|
||||||
|
blobData: Opt[BlobData],
|
||||||
time: BeaconTime,
|
time: BeaconTime,
|
||||||
invalidatedRoots: Table[Eth2Digest, Eth2Digest]):
|
invalidatedRoots: Table[Eth2Digest, Eth2Digest]):
|
||||||
Result[BlockRef, VerifierError] =
|
Result[BlockRef, VerifierError] =
|
||||||
# 1. Move state to proper slot.
|
# 1. Validate blobs
|
||||||
|
when typeof(signedBlock).toFork() >= ConsensusFork.Deneb:
|
||||||
|
let kzgCommits = signedBlock.message.body.blob_kzg_commitments.asSeq
|
||||||
|
if kzgCommits.len > 0 or blobData.isSome:
|
||||||
|
if blobData.isNone or kzgCommits.validate_blobs(
|
||||||
|
blobData.get.blobs, blobData.get.proofs).isErr:
|
||||||
|
return err(VerifierError.Invalid)
|
||||||
|
else:
|
||||||
|
doAssert blobData.isNone, "Pre-Deneb test with specified blob data"
|
||||||
|
|
||||||
|
# 2. Move state to proper slot
|
||||||
doAssert dag.updateState(
|
doAssert dag.updateState(
|
||||||
state,
|
state,
|
||||||
dag.getBlockIdAtSlot(time.slotOrZero).expect("block exists"),
|
dag.getBlockIdAtSlot(time.slotOrZero).expect("block exists"),
|
||||||
|
@ -229,7 +263,7 @@ proc stepOnBlock(
|
||||||
stateCache
|
stateCache
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2. Add block to DAG
|
# 3. Add block to DAG
|
||||||
when signedBlock is phase0.SignedBeaconBlock:
|
when signedBlock is phase0.SignedBeaconBlock:
|
||||||
type TrustedBlock = phase0.TrustedSignedBeaconBlock
|
type TrustedBlock = phase0.TrustedSignedBeaconBlock
|
||||||
elif signedBlock is altair.SignedBeaconBlock:
|
elif signedBlock is altair.SignedBeaconBlock:
|
||||||
|
@ -272,12 +306,12 @@ proc stepOnBlock(
|
||||||
blckRef: BlockRef, signedBlock: TrustedBlock,
|
blckRef: BlockRef, signedBlock: TrustedBlock,
|
||||||
epochRef: EpochRef, unrealized: FinalityCheckpoints):
|
epochRef: EpochRef, unrealized: FinalityCheckpoints):
|
||||||
|
|
||||||
# 3. Update fork choice if valid
|
# 4. Update fork choice if valid
|
||||||
let status = fkChoice[].process_block(
|
let status = fkChoice[].process_block(
|
||||||
dag, epochRef, blckRef, unrealized, signedBlock.message, time)
|
dag, epochRef, blckRef, unrealized, signedBlock.message, time)
|
||||||
doAssert status.isOk()
|
doAssert status.isOk()
|
||||||
|
|
||||||
# 4. Update DAG with new head
|
# 5. Update DAG with new head
|
||||||
var quarantine = Quarantine.init()
|
var quarantine = Quarantine.init()
|
||||||
let newHead = fkChoice[].get_head(dag, time).get()
|
let newHead = fkChoice[].get_head(dag, time).get()
|
||||||
dag.updateHead(dag.getBlockRef(newHead).get(), quarantine, [])
|
dag.updateHead(dag.getBlockRef(newHead).get(), quarantine, [])
|
||||||
|
@ -377,7 +411,7 @@ proc doRunTest(path: string, fork: ConsensusFork) =
|
||||||
let status = stepOnBlock(
|
let status = stepOnBlock(
|
||||||
stores.dag, stores.fkChoice,
|
stores.dag, stores.fkChoice,
|
||||||
verifier, state[], stateCache,
|
verifier, state[], stateCache,
|
||||||
blck, time, invalidatedRoots)
|
blck, step.blobData, time, invalidatedRoots)
|
||||||
doAssert status.isOk == step.valid
|
doAssert status.isOk == step.valid
|
||||||
of opOnAttesterSlashing:
|
of opOnAttesterSlashing:
|
||||||
let indices =
|
let indices =
|
||||||
|
@ -436,5 +470,8 @@ template fcSuite(suiteName: static[string], testPathElem: static[string]) =
|
||||||
for kind, path in walkDir(basePath, relative = true, checkDir = true):
|
for kind, path in walkDir(basePath, relative = true, checkDir = true):
|
||||||
runTest(suiteName, basePath/path, fork)
|
runTest(suiteName, basePath/path, fork)
|
||||||
|
|
||||||
|
from ../../beacon_chain/conf import loadKzgTrustedSetup
|
||||||
|
discard loadKzgTrustedSetup() # Required for Deneb tests
|
||||||
|
|
||||||
fcSuite("ForkChoice", "fork_choice")
|
fcSuite("ForkChoice", "fork_choice")
|
||||||
fcSuite("Sync", "sync")
|
fcSuite("Sync", "sync")
|
||||||
|
|
Loading…
Reference in New Issue