diff --git a/src/consensus/helpers/genesis.zig b/src/consensus/helpers/genesis.zig index 111a154..af854d3 100644 --- a/src/consensus/helpers/genesis.zig +++ b/src/consensus/helpers/genesis.zig @@ -11,9 +11,10 @@ const capella = @import("../../consensus/capella/types.zig"); const electra = @import("../../consensus/electra/types.zig"); const deneb = @import("../../consensus/deneb/types.zig"); const validator_helper = @import("../../consensus/helpers/validator.zig"); +const balance_helper = @import("../../consensus/helpers/balance.zig"); const ssz = @import("../../ssz/ssz.zig"); -pub fn isValidGenesisState(state: *const consensus.BeaconState, allocator: std.mem.Allocator) !bool { +pub fn isValidGenesisState(state: *consensus.BeaconState, allocator: std.mem.Allocator) !bool { if (state.genesisTime() < configs.ActiveConfig.get().MIN_GENESIS_TIME) { return false; } @@ -100,9 +101,10 @@ pub fn initializeBeaconStateFromEth1( const randao_mixes_slice = try allocator.alloc(primitives.Bytes32, preset.ActivePreset.get().EPOCHS_PER_HISTORICAL_VECTOR); @memset(randao_mixes_slice, eth1_block_hash); - const state = switch (fork_type) { + + var state = switch (fork_type) { .phase0 => consensus.BeaconState{ - .phase0 = phase0.BeaconState{ + .phase0 = std.mem.zeroInit(phase0.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -110,34 +112,14 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - }, + }), }, .altair => consensus.BeaconState{ - .altair = altair.BeaconState{ + .altair = std.mem.zeroInit(altair.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -145,37 +127,16 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - .inactivity_scores = undefined, .current_sync_committee = undefined, .next_sync_committee = undefined, - }, + }), }, .bellatrix => consensus.BeaconState{ - .bellatrix = bellatrix.BeaconState{ + .bellatrix = std.mem.zeroInit(bellatrix.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -183,38 +144,17 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - .inactivity_scores = undefined, .current_sync_committee = undefined, .next_sync_committee = undefined, .latest_execution_payload_header = undefined, - }, + }), }, .capella => consensus.BeaconState{ - .capella = capella.BeaconState{ + .capella = std.mem.zeroInit(capella.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -222,39 +162,17 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - .inactivity_scores = undefined, .current_sync_committee = undefined, .next_sync_committee = undefined, .latest_execution_payload_header = undefined, - .historical_summaries = undefined, - }, + }), }, .deneb => consensus.BeaconState{ - .deneb = capella.BeaconState{ + .deneb = std.mem.zeroInit(capella.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -262,39 +180,17 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - .inactivity_scores = undefined, .current_sync_committee = undefined, .next_sync_committee = undefined, .latest_execution_payload_header = undefined, - .historical_summaries = undefined, - }, + }), }, .electra => consensus.BeaconState{ - .electra = electra.BeaconState{ + .electra = std.mem.zeroInit(electra.BeaconState, .{ .genesis_time = eth1_timestamp + configs.ActiveConfig.get().GENESIS_DELAY, .fork = fork, .eth1_data = consensus.Eth1Data{ @@ -302,79 +198,59 @@ pub fn initializeBeaconStateFromEth1( .deposit_count = @as(u64, deposits.len), .deposit_root = undefined, }, - .latest_block_header = consensus.BeaconBlockHeader{ + .latest_block_header = std.mem.zeroInit(consensus.BeaconBlockHeader, .{ .body_root = body_root, - .parent_root = undefined, - .state_root = undefined, - .proposer_index = 0, - .slot = 0, - }, + }), .randao_mixes = randao_mixes_slice, - .genesis_validators_root = undefined, - .slot = 0, - .block_roots = undefined, - .state_roots = undefined, - .historical_roots = undefined, - .eth1_data_votes = undefined, - .eth1_deposit_index = undefined, - .validators = undefined, - .balances = undefined, - .slashings = undefined, - .previous_epoch_attestations = undefined, - .current_epoch_attestations = undefined, - .justification_bits = undefined, - .previous_justified_checkpoint = undefined, - .current_justified_checkpoint = undefined, - .finalized_checkpoint = undefined, - .inactivity_scores = undefined, .current_sync_committee = undefined, .next_sync_committee = undefined, .latest_execution_payload_header = undefined, - .historical_summaries = undefined, - .pending_balance_deposits = undefined, - .pending_partial_withdrawals = undefined, - .pending_consolidations = undefined, .deposit_requests_start_index = constants.UNSET_DEPOSIT_REQUESTS_START_INDEX, - }, + }), }, }; - // - // // Process deposits - // var leaves = try std.ArrayList(DepositData).initCapacity(std.heap.page_allocator, deposits.len); - // defer leaves.deinit(); - // - // for (deposits, 0..) |deposit, index| { - // try leaves.append(deposit.data); - // var deposit_data_list = try std.ArrayList(DepositData).initCapacity(std.heap.page_allocator, DEPOSIT_CONTRACT_TREE_DEPTH); - // defer deposit_data_list.deinit(); - // try deposit_data_list.appendSlice(leaves.items[0..index + 1]); - // state.eth1_data.deposit_root = try hash_tree_root(deposit_data_list.items); - // try process_deposit(&state, deposit); - // } - // - // // Process deposit balance updates - // for (state.pending_balance_deposits) |deposit| { - // try increase_balance(&state, deposit.index, deposit.amount); - // } - // state.pending_balance_deposits.clearRetainingCapacity(); - // - // // Process activations - // for (state.validators) |*validator, index| { - // const balance = state.balances[index]; - // validator.effective_balance = @min( - // balance - balance % EFFECTIVE_BALANCE_INCREMENT, - // try get_max_effective_balance(validator), - // ); - // if (validator.effective_balance >= MIN_ACTIVATION_BALANCE) { - // validator.activation_eligibility_epoch = GENESIS_EPOCH; - // validator.activation_epoch = GENESIS_EPOCH; - // } - // } - // - // // Set genesis validators root for domain separation and chain versioning - // state.genesis_validators_root = try hash_tree_root(state.validators); - // + // Process deposits + var leaves = try std.ArrayList(consensus.DepositData).initCapacity(allocator, deposits.len); + defer leaves.deinit(); + + for (deposits, 0..) |deposit, index| { + try leaves.append(deposit.data); + var deposit_data_list = try std.ArrayList(consensus.DepositData).initCapacity(allocator, index + 1); + defer deposit_data_list.deinit(); + try deposit_data_list.appendSlice(leaves.items[0 .. index + 1]); + try ssz.hashTreeRoot(deposit_data_list.items, &state.eth1Data().deposit_root, allocator); + processDeposit(&state, &deposit); + } + + // Process deposit balance updates + if (state == .electra) { + for (state.electra.pending_balance_deposits) |deposit| { + balance_helper.increaseBalance(&state, deposit.electra.index, deposit.electra.amount); + } + state.electra.pending_balance_deposits.len = 0; + } + + // Process activations + for (state.validators(), 0..) |*validator, index| { + const balance = state.balances()[index]; + const max_balance = if (state == .electra) + preset.ActivePreset.get().MAX_EFFECTIVE_BALANCE_ELECTRA + else + preset.ActivePreset.get().MAX_EFFECTIVE_BALANCE; + validator.effective_balance = @min( + balance - @mod(balance, preset.ActivePreset.get().EFFECTIVE_BALANCE_INCREMENT), + max_balance, + ); + if (validator.effective_balance >= preset.ActivePreset.get().MIN_ACTIVATION_BALANCE) { + validator.activation_eligibility_epoch = constants.GENESIS_EPOCH; + validator.activation_epoch = constants.GENESIS_EPOCH; + } + } + + // Set genesis validators root for domain separation and chain versioning + try ssz.hashTreeRoot(state.validators(), state.genesisValidatorsRootRef(), allocator); + // // Fill in sync committees // state.current_sync_committee = try get_next_sync_committee(&state); // state.next_sync_committee = try get_next_sync_committee(&state); @@ -384,3 +260,9 @@ pub fn initializeBeaconStateFromEth1( return state; } + +fn processDeposit(state: *consensus.BeaconState, deposit: *const consensus.Deposit) void { + const a = state.eth1Data(); + std.debug.print("Deposit data: {}\n", .{deposit.data}); + std.debug.print("State data: {}\n", .{a}); +} diff --git a/src/consensus/helpers/validator.zig b/src/consensus/helpers/validator.zig index 8eb55d6..bec733c 100644 --- a/src/consensus/helpers/validator.zig +++ b/src/consensus/helpers/validator.zig @@ -389,6 +389,15 @@ pub fn slashValidator(state: *consensus.BeaconState, slashed_index: primitives.V balance_helper.increaseBalance(state, whistleblower, whistleblower_reward - proposer_reward); } +pub fn isCompoundingWithdrawalCredential(withdrawal_credentials: primitives.Bytes32) bool { + return withdrawal_credentials[0] == constants.COMPOUNDING_WITHDRAWAL_PREFIX; +} + +pub fn hasCompoundingWithdrawalCredential(validator: *consensus.Validator) bool { + // Check if validator has an 0x02 prefixed "compounding" withdrawal credential + return isCompoundingWithdrawalCredential(validator.withdrawal_credentials); +} + test "test getBalanceChurnLimit" { preset.ActivePreset.set(preset.Presets.minimal); defer preset.ActivePreset.reset(); diff --git a/src/consensus/types.zig b/src/consensus/types.zig index 4ebbfb2..2a4af99 100644 --- a/src/consensus/types.zig +++ b/src/consensus/types.zig @@ -527,6 +527,16 @@ pub const BeaconState = union(primitives.ForkType) { deneb: capella.BeaconState, electra: electra.BeaconState, + pub fn forkedBeaconState(self: *BeaconState) *BeaconState { + return self; + } + + pub fn eth1Data(self: *BeaconState) *Eth1Data { + return switch (self.*) { + inline else => |*state| &state.eth1_data, + }; + } + pub fn genesisTime(self: *const BeaconState) u64 { return switch (self.*) { inline else => |state| state.genesis_time, @@ -551,6 +561,12 @@ pub const BeaconState = union(primitives.ForkType) { }; } + pub fn genesisValidatorsRootRef(self: *BeaconState) *primitives.Root { + return switch (self.*) { + inline else => |*state| &state.genesis_validators_root, + }; + } + pub fn fork(self: *const BeaconState) Fork { return switch (self.*) { inline else => |state| state.fork, diff --git a/src/primitives/constants.zig b/src/primitives/constants.zig index 1a00900..d44f021 100644 --- a/src/primitives/constants.zig +++ b/src/primitives/constants.zig @@ -11,8 +11,8 @@ pub const DEPOSIT_CONTRACT_TREE_DEPTH: u64 = 32; pub const SYNC_COMMITTEE_SUBNET_COUNT: usize = 4; pub const JUSTIFICATION_BITS_LENGTH: u64 = 4; pub const ENDIANNESS = .little; -pub const BLS_WITHDRAWAL_PREFIX: types.Bytes1 = .{0x00}; -pub const ETH1_ADDRESS_WITHDRAWAL_PREFIX: types.Bytes1 = .{0x01}; +pub const BLS_WITHDRAWAL_PREFIX: types.Bytes1 = 0x00; +pub const ETH1_ADDRESS_WITHDRAWAL_PREFIX: types.Bytes1 = 0x01; pub const DOMAIN_BEACON_PROPOSER: types.DomainType = .{ 0x00, 0x00, 0x00, 0x00 }; pub const DOMAIN_BEACON_ATTESTER: types.DomainType = .{ 0x01, 0x00, 0x00, 0x00 }; pub const DOMAIN_RANDAO: types.DomainType = .{ 0x02, 0x00, 0x00, 0x00 }; @@ -42,3 +42,5 @@ pub const MAX_BLOBS_PER_BLOCK: usize = 6; pub const PROPOSER_WEIGHT: u64 = 8; pub const WEIGHT_DENOMINATOR: u64 = 64; pub const UNSET_DEPOSIT_REQUESTS_START_INDEX: u64 = std.math.maxInt(u64); + +pub const COMPOUNDING_WITHDRAWAL_PREFIX: types.Bytes1 = 0x02; diff --git a/src/primitives/types.zig b/src/primitives/types.zig index 7f74c61..df44e95 100644 --- a/src/primitives/types.zig +++ b/src/primitives/types.zig @@ -3,7 +3,7 @@ const constants = @import("constants.zig"); const utils = @import("utils.zig"); const preset = @import("../presets/preset.zig"); -pub const Bytes1 = [1]u8; +pub const Bytes1 = u8; pub const Bytes4 = [4]u8; pub const Bytes20 = [20]u8; pub const Bytes32 = [32]u8;