-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathprocess_block.zig
More file actions
123 lines (115 loc) · 6.11 KB
/
process_block.zig
File metadata and controls
123 lines (115 loc) · 6.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const std = @import("std");
const Allocator = std.mem.Allocator;
const BeaconConfig = @import("config").BeaconConfig;
const EpochCache = @import("../cache/epoch_cache.zig").EpochCache;
const SlashingsCache = @import("../cache/slashings_cache.zig").SlashingsCache;
const buildSlashingsCacheIfNeeded = @import("../cache/slashings_cache.zig").buildFromStateIfNeeded;
const BeaconState = @import("fork_types").BeaconState;
const BlockType = @import("fork_types").BlockType;
const BeaconBlock = @import("fork_types").BeaconBlock;
const ForkSeq = @import("config").ForkSeq;
const types = @import("consensus_types");
const Root = types.primitive.Root.Type;
const ValidatorIndex = types.primitive.ValidatorIndex.Type;
const preset = @import("preset").preset;
const BlockExternalData = @import("../state_transition.zig").BlockExternalData;
const Withdrawals = types.capella.Withdrawals.Type;
const WithdrawalsResult = @import("./process_withdrawals.zig").WithdrawalsResult;
const processBlobKzgCommitments = @import("./process_blob_kzg_commitments.zig").processBlobKzgCommitments;
const processBlockHeader = @import("./process_block_header.zig").processBlockHeader;
const processEth1Data = @import("./process_eth1_data.zig").processEth1Data;
const processExecutionPayload = @import("./process_execution_payload.zig").processExecutionPayload;
const processOperations = @import("./process_operations.zig").processOperations;
const processRandao = @import("./process_randao.zig").processRandao;
const processSyncAggregate = @import("./process_sync_committee.zig").processSyncAggregate;
const processWithdrawals = @import("./process_withdrawals.zig").processWithdrawals;
const getExpectedWithdrawals = @import("./process_withdrawals.zig").getExpectedWithdrawals;
const isExecutionEnabled = @import("../utils/execution.zig").isExecutionEnabled;
// TODO: proposer reward api
// const ProposerRewardType = @import("../types/proposer_reward.zig").ProposerRewardType;
pub const ProcessBlockOpts = struct {
verify_signature: bool = true,
};
/// Process a block and update the state following Ethereum Consensus specifications.
pub fn processBlock(
comptime fork: ForkSeq,
allocator: Allocator,
config: *const BeaconConfig,
epoch_cache: *EpochCache,
state: *BeaconState(fork),
slashings_cache: *SlashingsCache,
comptime block_type: BlockType,
block: *const BeaconBlock(block_type, fork),
external_data: BlockExternalData,
opts: ProcessBlockOpts,
// TODO: metrics
) !void {
// Build slashings cache against the *current* latest_block_header slot (pre-header update).
try buildSlashingsCacheIfNeeded(allocator, state, slashings_cache);
try processBlockHeader(fork, allocator, epoch_cache, state, block_type, block);
// Keep cache slot in sync with latest_block_header without forcing a rebuild.
slashings_cache.updateLatestBlockSlot(block.slot());
const body = block.body();
const current_epoch = epoch_cache.epoch;
// The call to the process_execution_payload must happen before the call to the process_randao as the former depends
// on the randao_mix computed with the reveal of the previous block.
if (comptime fork.gte(.bellatrix)) {
if (isExecutionEnabled(fork, state, block_type, block)) {
// TODO Deneb: Allow to disable withdrawals for interop testing
// https://github.com/ethereum/consensus-specs/blob/b62c9e877990242d63aa17a2a59a49bc649a2f2e/specs/eip4844/beacon-chain.md#disabling-withdrawals
if (comptime fork.gte(.capella)) {
// TODO: given max withdrawals of MAX_WITHDRAWALS_PER_PAYLOAD, can use fixed size array instead of heap alloc
var withdrawals_result = WithdrawalsResult{ .withdrawals = try Withdrawals.initCapacity(
allocator,
preset.MAX_WITHDRAWALS_PER_PAYLOAD,
) };
var withdrawal_balances = std.AutoHashMap(ValidatorIndex, usize).init(allocator);
defer withdrawal_balances.deinit();
try getExpectedWithdrawals(
fork,
allocator,
epoch_cache,
state,
&withdrawals_result,
&withdrawal_balances,
);
defer withdrawals_result.withdrawals.deinit(allocator);
const payload_withdrawals_root = switch (block_type) {
.full => blk: {
const actual_withdrawals = block.body().executionPayload().inner.withdrawals;
std.debug.assert(withdrawals_result.withdrawals.items.len == actual_withdrawals.items.len);
var root: Root = undefined;
try types.capella.Withdrawals.hashTreeRoot(allocator, &actual_withdrawals, &root);
break :blk root;
},
.blinded => block.body().executionPayloadHeader().inner.withdrawals_root,
};
try processWithdrawals(fork, allocator, state, withdrawals_result, payload_withdrawals_root);
}
try processExecutionPayload(
fork,
allocator,
config,
state,
current_epoch,
block_type,
body,
external_data,
);
}
}
try processRandao(fork, config, epoch_cache, state, block_type, body, block.proposerIndex(), opts.verify_signature);
try processEth1Data(fork, state, body.eth1Data());
try processOperations(fork, allocator, config, epoch_cache, state, slashings_cache, block_type, body, opts);
if (comptime fork.gte(.altair)) {
try processSyncAggregate(fork, allocator, config, epoch_cache, state, body.syncAggregate(), opts.verify_signature);
}
if (comptime fork.gte(.deneb)) {
try processBlobKzgCommitments(external_data);
// Only throw PreData so beacon can also sync/process blocks optimistically
// and let forkChoice handle it
if (external_data.data_availability_status == .pre_data) {
return error.DataAvailabilityPreData;
}
}
}