diff --git a/AllTests-mainnet.md b/AllTests-mainnet.md index 08d211b64f..3ebaaa93c6 100644 --- a/AllTests-mainnet.md +++ b/AllTests-mainnet.md @@ -57,6 +57,7 @@ AllTests-mainnet + sanity check electra blocks [Preset: mainnet] OK + sanity check electra states [Preset: mainnet] OK + sanity check electra states, reusing buffers [Preset: mainnet] OK ++ sanity check execution payload envelopes [Preset: mainnet] OK + sanity check fulu and cross-fork getState rollback [Preset: mainnet] OK + sanity check fulu blocks [Preset: mainnet] OK + sanity check fulu states [Preset: mainnet] OK @@ -64,6 +65,7 @@ AllTests-mainnet + sanity check genesis roundtrip [Preset: mainnet] OK sanity check gloas and cross-fork getState rollback [Preset: mainnet] Skip sanity check gloas blocks [Preset: mainnet] Skip ++ sanity check gloas data columns [Preset: mainnet] OK sanity check gloas states [Preset: mainnet] Skip sanity check gloas states, reusing buffers [Preset: mainnet] Skip + sanity check phase0 blocks [Preset: mainnet] OK @@ -846,7 +848,7 @@ AllTests-mainnet + Signing aggregate and proof (getAggregateAndProofSignature(phase0)) OK + Signing aggregation slot (getSlotSignature()) OK + Signing attestation (getAttestationSignature()) OK -+ Signing payload attestation message (getPayloadAttestationSignature()) OK ++ Signing payload attestation (getPayloadAttestationSignature()) OK + Signing randao reveal (getEpochSignature()) OK + Signing validator registration (getBuilderSignature()) OK + Signing voluntary exit (getValidatorExitSignature()) OK diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 17e95ed6d9..90c0099ca7 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -1087,9 +1087,11 @@ proc getDataColumnSidecarSZ*(db: BeaconChainDB, root: Eth2Digest, assign(dataPtr[], data) db.columns.get(columnkey(root, index), decode).expectDb() -proc getDataColumnSidecar*(db: BeaconChainDB, root: Eth2Digest, index: ColumnIndex, - value: var fulu.DataColumnSidecar): bool = - if db.columns == nil: # Fulu has not been scheduled; DB table does not exist +proc getDataColumnSidecar*[ + T: fulu.DataColumnSidecar | gloas.DataColumnSidecar]( + db: BeaconChainDB, root: Eth2Digest, + index: ColumnIndex, value: var T): bool = + if db.columns == nil: # Gloas has not been scheduled; DB table does not exist return false db.columns.getSZSSZ(columnkey(root, index), value) == GetResult.found @@ -1322,6 +1324,18 @@ proc containsState*(db: BeaconChainDB, key: Eth2Digest, legacy: bool = true): bo (legacy and db.v0.containsState(key)) +proc containsExecutionPayloadEnvelope*( + db: BeaconChainDB, root: Eth2Digest): bool = + if db.envelopes == nil: + return false + db.envelopes.contains(root.data).expectDb() + +proc containsDataColumnSidecar*( + db: BeaconChainDB, root: Eth2Digest, index: ColumnIndex): bool = + if db.columns == nil: + return false + db.columns.contains(columnkey(root, index)).expectDb() + proc getBeaconBlockSummary*(db: BeaconChainDB, root: Eth2Digest): Opt[BeaconBlockSummary] = var summary: BeaconBlockSummary diff --git a/beacon_chain/spec/signatures.nim b/beacon_chain/spec/signatures.nim index 4aaf75f828..21d5d17f30 100644 --- a/beacon_chain/spec/signatures.nim +++ b/beacon_chain/spec/signatures.nim @@ -480,28 +480,28 @@ proc verify_execution_payload_envelope_signature*( fork, genesis_validators_root, epoch, msg) blsVerify(pubkey, signing_root.data, signature) -# https://github.com/ethereum/consensus-specs/blob/v1.6.0-beta.0/specs/gloas/validator.md#constructing-a-payload-attestation +# https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/gloas/validator.md#constructing-a-payload-attestation func compute_payload_attestation_message_signing_root*( fork: Fork, genesis_validators_root: Eth2Digest, - msg: PayloadAttestationMessage): Eth2Digest = + data: PayloadAttestationData): Eth2Digest = let - epoch = msg.data.slot.epoch + epoch = data.slot.epoch domain = get_domain( fork, DOMAIN_PTC_ATTESTER, epoch, genesis_validators_root) - compute_signing_root(msg, domain) + compute_signing_root(data, domain) func get_payload_attestation_message_signature*( fork: Fork, genesis_validators_root: Eth2Digest, - msg: PayloadAttestationMessage, + data: PayloadAttestationData, privkey: ValidatorPrivKey): CookedSig = let signing_root = compute_payload_attestation_message_signing_root( - fork, genesis_validators_root, msg) + fork, genesis_validators_root, data) blsSign(privkey, signing_root.data) proc verify_payload_attestation_message_signature*( fork: Fork, genesis_validators_root: Eth2Digest, - msg: PayloadAttestationMessage, + data: PayloadAttestationData, pubkey: ValidatorPubKey | CookedPubKey, signature: SomeSig): bool = let signing_root = compute_payload_attestation_message_signing_root( - fork, genesis_validators_root, msg) + fork, genesis_validators_root, data) blsVerify(pubkey, signing_root.data, signature) diff --git a/beacon_chain/spec/signatures_batch.nim b/beacon_chain/spec/signatures_batch.nim index 9ac739d235..9b4fada320 100644 --- a/beacon_chain/spec/signatures_batch.nim +++ b/beacon_chain/spec/signatures_batch.nim @@ -184,7 +184,7 @@ func payload_attestation_signature_set*( payload_attestation_message: PayloadAttestationMessage, pubkey: CookedPubKey, signature: CookedSig): SignatureSet = let signing_root = compute_payload_attestation_message_signing_root( - fork, genesis_validators_root, payload_attestation_message) + fork, genesis_validators_root, payload_attestation_message.data) SignatureSet.init(pubkey, signing_root, signature) diff --git a/beacon_chain/validators/beacon_validators.nim b/beacon_chain/validators/beacon_validators.nim index 47814619c4..35fdfc6042 100644 --- a/beacon_chain/validators/beacon_validators.nim +++ b/beacon_chain/validators/beacon_validators.nim @@ -838,6 +838,102 @@ proc sendSyncCommitteeContributions( asyncSpawn signAndSendContribution( node, validator, subcommitteeIdx, head, slot) +proc checkPayloadPresent( + node: BeaconNode, beacon_block_root: Eth2Digest): bool = + let blokData = node.dag.getForkedBlock(beacon_block_root).valueOr: + return false + + withBlck(blokData): + when consensusFork >= ConsensusFork.Gloas: + node.dag.db.containsExecutionPayloadEnvelope(beacon_block_root) + else: + true + +proc checkBlobDataAvailable( + node: BeaconNode, beacon_block_root: Eth2Digest): bool = + let blckData = node.dag.getForkedBlock(beacon_block_root).valueOr: + return false + + withBlck(blckData): + when consensusFork >= ConsensusFork.Gloas: + # check that our custody columns are available + for columnIdx in node.dataColumnQuarantine.custodyColumns: + if not node.dag.db.containsDataColumnSidecar( + beacon_block_root, columnIdx): + return false + true + else: + true + +proc createAndSendPayloadAttestation(node: BeaconNode, + fork: Fork, + genesis_validators_root: Eth2Digest, + validator: AttachedValidator, + validator_index: ValidatorIndex, + slot: Slot, + beacon_block_root: Eth2Digest) + {.async: (raises: [CancelledError]).} = + let + payload_present = node.checkPayloadPresent(beacon_block_root) + blob_data_available = node.checkBlobDataAvailable(beacon_block_root) + + let data = PayloadAttestationData( + beacon_block_root: beacon_block_root, + slot: slot, + payload_present: payload_present, + blob_data_available: blob_data_available + ) + + let signature = block: + let res = await validator.getPayloadAttestationSignature( + fork, genesis_validators_root, data) + if res.isErr(): + warn "Unble to sign payload attestation", + validator = shortLog(validator), + data = shortLog(data), + error_msg = res.error() + return + res.get() + + let message = PayloadAttestationMessage( + validator_index: validator_index.uint64, + data: data, + signature: signature + ) + + discard await node.router.routePayloadAttestationMessage( + message, checkSignature = false, checkValidator = false) + +proc sendPayloadAttestations( + node: BeaconNode, head: BlockRef, slot: Slot) = + ## Perform payload attestation duties for PTC members + + let consensusFork = node.dag.cfg.consensusForkAtEpoch(slot.epoch) + if consensusFork < ConsensusFork.Gloas: + return + + # Get the beacon block root for the slot we are attesting to + let target = head.atSlot(slot) + if head != target.blck: + notice "Payload attestation to a state in the past", + attestationTarget = shortLog(target), + head = shortLog(head) + + let + fork = node.dag.forkAtEpoch(slot.epoch) + genesis_validators_root = node.dag.genesis_validators_root + + withState(node.dag.headState): + when consensusFork >= ConsensusFork.Gloas: + var cache: StateCache + for vidx in get_ptc(forkyState.data, slot, cache): + let validator = node.getValidatorForDuties(vidx, slot).valueOr: + continue + + asyncSpawn createAndSendPayloadAttestation( + node, fork, genesis_validators_root, validator, vidx, slot, + target.blck.root ) + proc handleProposal(node: BeaconNode, head: BlockRef, slot: Slot): Future[BlockRef] {.async: (raises: [CancelledError]).} = ## Perform the proposal for the given slot, iff we have a validator attached @@ -1263,6 +1359,15 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async: (ra sendAttestations(node, head, slot) sendSyncCommitteeMessages(node, head, slot) + let payloadAttestationCutOff = node.beaconClock.fromNow( + slot.payload_attestation_deadline(node.dag.timeParams)) + if payloadAttestationCutOff.inFuture: + debug "Waiting to send payload attestations", + payloadAttestationCutOff = shortLog(payloadAttestationCutOff.offset) + await sleepAsync(payloadAttestationCutOff.offset) + + sendPayloadAttestations(node, head, slot) + updateValidatorMetrics(node) # the important stuff is done, update the vanity numbers # https://github.com/ethereum/consensus-specs/blob/v1.5.0-beta.2/specs/phase0/validator.md#broadcast-aggregate diff --git a/beacon_chain/validators/validator_pool.nim b/beacon_chain/validators/validator_pool.nim index 2567726b97..1e946c4f65 100644 --- a/beacon_chain/validators/validator_pool.nim +++ b/beacon_chain/validators/validator_pool.nim @@ -803,14 +803,14 @@ proc getBuilderSignature*(v: AttachedValidator, genesis_fork_version: Version, # https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/gloas/validator.md#constructing-payload_attestations proc getPayloadAttestationSignature*(v: AttachedValidator, fork: Fork, genesis_validators_root: Eth2Digest, - message: PayloadAttestationMessage, + data: PayloadAttestationData, ): Future[SignatureResult] {.async: (raises: [CancelledError]).} = case v.kind of ValidatorKind.Local: SignatureResult.ok( get_payload_attestation_message_signature( - fork, genesis_validators_root, message, + fork, genesis_validators_root, data, v.data.privateKey).toValidatorSig()) of ValidatorKind.Remote: return SignatureResult.err("Remote signer lacks payload attestation support") diff --git a/tests/test_beacon_chain_db.nim b/tests/test_beacon_chain_db.nim index 877a9adcb1..68c007b19b 100644 --- a/tests/test_beacon_chain_db.nim +++ b/tests/test_beacon_chain_db.nim @@ -561,6 +561,186 @@ suite "Beacon chain DB" & preset(): db.close() + test "sanity check execution payload envelopes" & preset(): + const + blockHeader0 = SignedBeaconBlockHeader( + message: BeaconBlockHeader(slot: Slot(0))) + blockHeader1 = SignedBeaconBlockHeader( + message: BeaconBlockHeader(slot: Slot(1))) + + let + blockRoot0 = hash_tree_root(blockHeader0.message) + blockRoot1 = hash_tree_root(blockHeader1.message) + + envelope0 = SignedExecutionPayloadEnvelope( + message: ExecutionPayloadEnvelope(beacon_block_root: blockRoot0)) + envelope1 = SignedExecutionPayloadEnvelope( + message: ExecutionPayloadEnvelope(beacon_block_root: blockRoot1)) + + db = cfg.makeTestDB(SLOTS_PER_EPOCH) + + var retreivedEnvelope: TrustedSignedExecutionPayloadEnvelope + + check: + not db.containsExecutionPayloadEnvelope(blockRoot0) + not db.containsExecutionPayloadEnvelope(blockRoot1) + not db.getExecutionPayloadEnvelope(blockRoot0, retreivedEnvelope) + not db.getExecutionPayloadEnvelope(blockRoot1, retreivedEnvelope) + + db.putExecutionPayloadEnvelope(envelope0) + + check: + db.containsExecutionPayloadEnvelope(blockRoot0) + not db.containsExecutionPayloadEnvelope(blockRoot1) + db.getExecutionPayloadEnvelope(blockRoot0, retreivedEnvelope) + retreivedEnvelope.message.beacon_block_root == blockRoot0 + not db.getExecutionPayloadEnvelope(blockRoot1, retreivedEnvelope) + + db.putExecutionPayloadEnvelope(envelope1) + + check: + db.containsExecutionPayloadEnvelope(blockRoot0) + db.containsExecutionPayloadEnvelope(blockRoot1) + db.getExecutionPayloadEnvelope(blockRoot0, retreivedEnvelope) + db.getExecutionPayloadEnvelope(blockRoot1, retreivedEnvelope) + + check db.delExecutionPayloadEnvelope(blockRoot0) + + check: + not db.containsExecutionPayloadEnvelope(blockRoot0) + db.containsExecutionPayloadEnvelope(blockRoot1) + not db.getExecutionPayloadEnvelope(blockRoot0, retreivedEnvelope) + db.getExecutionPayloadEnvelope(blockRoot1, retreivedEnvelope) + + check db.delExecutionPayloadEnvelope(blockRoot1) + + check: + not db.containsExecutionPayloadEnvelope(blockRoot0) + not db.containsExecutionPayloadEnvelope(blockRoot1) + not db.getExecutionPayloadEnvelope(blockRoot0, retreivedEnvelope) + not db.getExecutionPayloadEnvelope(blockRoot1, retreivedEnvelope) + + db.close() + + test "sanity check gloas data columns" & preset(): + const + blockHeader0 = SignedBeaconBlockHeader( + message: BeaconBlockHeader(slot: Slot(0))) + blockHeader1 = SignedBeaconBlockHeader( + message: BeaconBlockHeader(slot: Slot(1))) + + let + blockRoot0 = hash_tree_root(blockHeader0.message) + blockRoot1 = hash_tree_root(blockHeader1.message) + + dataColumnSidecar0 = gloas.DataColumnSidecar(index: 3, beacon_block_root: blockRoot0) + dataColumnSidecar1 = gloas.DataColumnSidecar(index: 2, beacon_block_root: blockRoot0) + dataColumnSidecar2 = gloas.DataColumnSidecar(index: 2, beacon_block_root: blockRoot1) + + db = cfg.makeTestDB(SLOTS_PER_EPOCH) + + var + buf: seq[byte] + dataColumnSidecar: gloas.DataColumnSidecar + + check: + not db.containsDataColumnSidecar(blockRoot0, 3) + not db.containsDataColumnSidecar(blockRoot0, 2) + not db.containsDataColumnSidecar(blockRoot1, 2) + not db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + not db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + not db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + not db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + db.putDataColumnSidecar(dataColumnSidecar0) + + check: + db.containsDataColumnSidecar(blockRoot0, 3) + not db.containsDataColumnSidecar(blockRoot0, 2) + not db.containsDataColumnSidecar(blockRoot1, 2) + db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar0 + not db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + not db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + not db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + db.putDataColumnSidecar(dataColumnSidecar1) + + check: + db.containsDataColumnSidecar(blockRoot0, 3) + db.containsDataColumnSidecar(blockRoot0, 2) + not db.containsDataColumnSidecar(blockRoot1, 2) + db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar0 + db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar1 + not db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + not db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + check db.delDataColumnSidecar(blockRoot0, 3) + + check: + not db.containsDataColumnSidecar(blockRoot0, 3) + db.containsDataColumnSidecar(blockRoot0, 2) + not db.containsDataColumnSidecar(blockRoot1, 2) + not db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar1 + not db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + not db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + not db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + db.putDataColumnSidecar(dataColumnSidecar2) + + check: + not db.containsDataColumnSidecar(blockRoot0, 3) + db.containsDataColumnSidecar(blockRoot0, 2) + db.containsDataColumnSidecar(blockRoot1, 2) + not db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar1 + db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar2 + not db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + check db.delDataColumnSidecar(blockRoot0, 2) + + check: + not db.containsDataColumnSidecar(blockRoot0, 3) + not db.containsDataColumnSidecar(blockRoot0, 2) + db.containsDataColumnSidecar(blockRoot1, 2) + not db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + dataColumnSidecar == dataColumnSidecar2 + not db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + not db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + check db.delDataColumnSidecar(blockRoot1, 2) + + check: + not db.containsDataColumnSidecar(blockRoot0, 3) + not db.containsDataColumnSidecar(blockRoot0, 2) + not db.containsDataColumnSidecar(blockRoot1, 2) + not db.getDataColumnSidecar(blockRoot0, 3, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot0, 2, dataColumnSidecar) + not db.getDataColumnSidecar(blockRoot1, 2, dataColumnSidecar) + not db.getDataColumnSidecarSZ(blockRoot0, 3, buf) + not db.getDataColumnSidecarSZ(blockRoot0, 2, buf) + not db.getDataColumnSidecarSZ(blockRoot1, 2, buf) + + db.close() + suite "Quarantine" & preset(): setup: let diff --git a/tests/test_signing_node.nim b/tests/test_signing_node.nim index 5ce88cbeca..2698a7c77c 100644 --- a/tests/test_signing_node.nim +++ b/tests/test_signing_node.nim @@ -837,25 +837,21 @@ block: sres2.get() == rres2.get() sres3.get() == rres3.get() - asyncTest "Signing payload attestation message (getPayloadAttestationSignature())": + asyncTest "Signing payload attestation (getPayloadAttestationSignature())": let - payloadMessage = PayloadAttestationMessage( - validator_index: 100, - data: PayloadAttestationData( - beacon_block_root: SomeOtherRoot, - slot: Slot(10), - payload_present: true, - blob_data_available: true - ), - signature: ValidatorSig.fromHex(SomeSignature).get() + payloadData = PayloadAttestationData( + beacon_block_root: SomeOtherRoot, + slot: Slot(10), + payload_present: true, + blob_data_available: true ) + sres1 = await validator1.getPayloadAttestationSignature(SigningFork, - GenesisValidatorsRoot, payloadMessage) + GenesisValidatorsRoot, payloadData) sres2 = await validator2.getPayloadAttestationSignature(SigningFork, - GenesisValidatorsRoot, payloadMessage) + GenesisValidatorsRoot, payloadData) sres3 = await validator3.getPayloadAttestationSignature(SigningFork, - GenesisValidatorsRoot, payloadMessage) - + GenesisValidatorsRoot, payloadData) check: sres1.isOk() sres2.isOk() diff --git a/tests/test_spec_signatures.nim b/tests/test_spec_signatures.nim index 27d6d94c44..e7c96b7a22 100644 --- a/tests/test_spec_signatures.nim +++ b/tests/test_spec_signatures.nim @@ -244,17 +244,17 @@ suite "Message signatures": test "payload attestation message signatures": let - msg0 = default(PayloadAttestationMessage) - msg1 = (var m = msg0; m.data.slot = m.data.slot + 1; m) - sig = get_payload_attestation_message_signature(fork0, gvr0, msg0, privkey0).toValidatorSig + data0 = default(PayloadAttestationData) + data1 = (var d = data0; d.slot = d.slot + 1; d) + sig = get_payload_attestation_message_signature(fork0, gvr0, data0, privkey0).toValidatorSig check: - verify_payload_attestation_message_signature(fork0, gvr0, msg0, pubkey0, sig) + verify_payload_attestation_message_signature(fork0, gvr0, data0, pubkey0, sig) - not verify_payload_attestation_message_signature(fork1, gvr0, msg0, pubkey0, sig) - not verify_payload_attestation_message_signature(fork0, gvr1, msg0, pubkey0, sig) - not verify_payload_attestation_message_signature(fork0, gvr0, msg1, pubkey0, sig) - not verify_payload_attestation_message_signature(fork0, gvr0, msg0, pubkey1, sig) + not verify_payload_attestation_message_signature(fork1, gvr0, data0, pubkey0, sig) + not verify_payload_attestation_message_signature(fork0, gvr1, data0, pubkey0, sig) + not verify_payload_attestation_message_signature(fork0, gvr0, data1, pubkey0, sig) + not verify_payload_attestation_message_signature(fork0, gvr0, data0, pubkey1, sig) test "BLS to execution change signatures": let diff --git a/tests/testdbutil.nim b/tests/testdbutil.nim index 2cdccdb352..42b9381aac 100644 --- a/tests/testdbutil.nim +++ b/tests/testdbutil.nim @@ -23,6 +23,7 @@ proc makeTestDB*( eth1Data = Opt.none(Eth1Data)): BeaconChainDB = # Blob support requires DENEB_FORK_EPOCH != FAR_FUTURE_EPOCH # Data column support requires FULU_FORK_EPOCH != FAR_FUTURE_EPOCH + # Execution Payload Envelope support requires GLOAS_FORK_EPOCH != FAR_FUTURE_EPOCH var cfg = cfg if cfg.CAPELLA_FORK_EPOCH == FAR_FUTURE_EPOCH: cfg.CAPELLA_FORK_EPOCH = 90000.Epoch @@ -32,6 +33,8 @@ proc makeTestDB*( cfg.ELECTRA_FORK_EPOCH = 110000.Epoch if cfg.FULU_FORK_EPOCH == FAR_FUTURE_EPOCH: cfg.FULU_FORK_EPOCH = 120000.Epoch + if cfg.GLOAS_FORK_EPOCH == FAR_FUTURE_EPOCH: + cfg.GLOAS_FORK_EPOCH = 130000.Epoch let genState = initGenesisState(cfg, validators.uint64)