Skip to content

Conversation

@twoeths
Copy link
Collaborator

@twoeths twoeths commented Oct 24, 2025

Motivation

  • fix operation and sanity spec tests

Description

  • merge chain config for spec test
  • ReusedEpochTransitionCache is (implicitly) inited and deinited once
  • fix various memory leak issues
  • track spec tests in a new CI job

2 remaining skipped tests are:

part of #21

@twoeths twoeths changed the title fix: operation spec tests v1.5.0 fix: operation and sanity spec tests v1.5.0 Oct 28, 2025
@twoeths twoeths mentioned this pull request Oct 30, 2025
@twoeths twoeths marked this pull request as ready for review October 31, 2025 07:12
Copy link
Contributor

@spiral-ladder spiral-ladder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks amazing! Gave a preliminary look

Comment on lines +26 to +33
var cloned_aggregation_bits: s.BitListType(preset.MAX_VALIDATORS_PER_COMMITTEE).Type = undefined;
try s.BitListType(preset.MAX_VALIDATORS_PER_COMMITTEE).clone(allocator, &attestation.aggregation_bits, &cloned_aggregation_bits);
var appended: bool = false;
errdefer {
if (!appended) {
cloned_aggregation_bits.deinit(allocator);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively we can couple the deinit logic with the next 3 try's (which is up to where we're interested in deinit-ing), relying on a random appended bool seems prone to mistakes


pub fn isValidDepositSignature(config: *const BeaconConfig, pubkey: BLSPubkey, withdrawal_credential: WithdrawalCredentials, amount: u64, deposit_signature: BLSSignature) !bool {
/// refer to https://github.com/ethereum/consensus-specs/blob/v1.5.0/specs/electra/beacon-chain.md#new-is_valid_deposit_signature
/// no need to return error union since consumer does not care about the reason of failure
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it might be useful to know, even from a testing pov and even if the spec returns a bool, which portions of validation failed since we're uncompressing, validating the pubkey/sig and verifying against the message too. It seems like we're omitting useful error messages just to comply with the spec. Do we necessarily need it to return bool?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think this is a similar thought to ChainSafe/lodestar#6330

Essentially, we may return an Error!void and only if absolutely necessary, wrap to convert to bool for purposes of spec compliance.

},
.electra => |attestations_electra| {
try processAttestationsAltair(allocator, cached_state, ssz.electra.Attestation.Type, attestations_electra.items, verify_signatures);
try processAttestationsAltair(allocator, cached_state, attestations_electra.items, verify_signatures);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's clearer and less prone to error if the reader of this code explicitly knows that we're passing in an attestation type of electra fork, rather than leaving it to zig to read the type internally within the process fn

for (attestations) |*attestation| {
const data = attestation.data;
try validateAttestation(AT, cached_state, attestation);
try validateAttestation(cached_state, attestation);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as the processAttestationAltair

const CachedBeaconStateAllForks = @import("../cache/state_cache.zig").CachedBeaconStateAllForks;
const BeaconStateAllForks = @import("../types/beacon_state.zig").BeaconStateAllForks;
const ssz = @import("consensus_types");
const s = @import("ssz");
Copy link
Contributor

@spiral-ladder spiral-ladder Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in near future we should consider what we want to do with namespaces, right now we're using ssz for consensus types but then we run into situations like this where we can't use ssz the library.

Should we just use ct for consensus_types and ssz to mean ssz the library?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to reserve ssz for ssz library, and something else for consensus_types

Copy link
Contributor

@ensi321 ensi321 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good. minor comments


pub fn getDomainForVoluntaryExit(self: *const BeaconConfig, state_slot: Slot, message_slot: ?Slot) ![32]u8 {
const domain = if (state_slot < self.chain.DENEB_FORK_EPOCH * preset.SLOTS_PER_EPOCH) {
const domain = if (state_slot / preset.SLOTS_PER_EPOCH < self.chain.DENEB_FORK_EPOCH) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: probably better do @divFloor here

const CachedBeaconStateAllForks = @import("../cache/state_cache.zig").CachedBeaconStateAllForks;
const BeaconStateAllForks = @import("../types/beacon_state.zig").BeaconStateAllForks;
const ssz = @import("consensus_types");
const s = @import("ssz");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer to reserve ssz for ssz library, and something else for consensus_types

const payload_withdrawals_root = switch (body) {
.regular => |b| blk: {
const actual_withdrawals = b.executionPayload().getWithdrawals();
std.debug.assert(withdrawals_result.withdrawals.items.len == actual_withdrawals.items.len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this assertion? We can potentially save one hashTreeRoot call

}

// Update the nextWithdrawalValidatorIndex
const nextWithdrawalValidatorIndex = state.nextWithdrawalValidatorIndex();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const nextWithdrawalValidatorIndex = state.nextWithdrawalValidatorIndex();
const new_withdrawal_validator_index = state.nextWithdrawalValidatorIndex();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants