-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathprocess_block_header.zig
More file actions
101 lines (84 loc) · 3.99 KB
/
process_block_header.zig
File metadata and controls
101 lines (84 loc) · 3.99 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
const std = @import("std");
const Allocator = std.mem.Allocator;
const types = @import("consensus_types");
const CachedBeaconState = @import("../cache/state_cache.zig").CachedBeaconState;
const BeaconBlock = @import("../types/beacon_block.zig").BeaconBlock;
const config = @import("config");
const BeaconConfig = config.BeaconConfig;
const BeaconBlockHeader = types.phase0.BeaconBlockHeader.Type;
const Root = types.primitive.Root;
const SignedBlock = @import("../types/block.zig").SignedBlock;
const ZERO_HASH = @import("constants").ZERO_HASH;
const Block = @import("../types/block.zig").Block;
pub fn processBlockHeader(allocator: Allocator, cached_state: *CachedBeaconState, block: Block) !void {
const state = cached_state.state;
const slot = try state.slot();
// verify that the slots match
if (block.slot() != slot) {
return error.BlockSlotMismatch;
}
// Verify that the block is newer than latest block header
var latest_header_view = try state.latestBlockHeader();
const latest_header_slot = try latest_header_view.get("slot");
if (!(block.slot() > latest_header_slot)) {
return error.BlockNotNewerThanLatestHeader;
}
// verify that proposer index is the correct index
const proposer_index = try cached_state.getBeaconProposer(slot);
if (block.proposerIndex() != proposer_index) {
return error.BlockProposerIndexMismatch;
}
// verify that the parent matches
const header_parent_root = try latest_header_view.hashTreeRoot();
if (!std.mem.eql(u8, &block.parentRoot(), header_parent_root)) {
return error.BlockParentRootMismatch;
}
var body_root: [32]u8 = undefined;
try block.beaconBlockBody().hashTreeRoot(allocator, &body_root);
// cache current block as the new latest block
const latest_block_header: BeaconBlockHeader = .{
.slot = slot,
.proposer_index = proposer_index,
.parent_root = block.parentRoot(),
.state_root = ZERO_HASH,
.body_root = body_root,
};
try state.setLatestBlockHeader(&latest_block_header);
// verify proposer is not slashed. Only once per block, may use the slower read from tree
var validators_view = try state.validators();
var proposer_validator_view = try validators_view.get(proposer_index);
const proposer_slashed = try proposer_validator_view.get("slashed");
if (proposer_slashed) {
return error.BlockProposerSlashed;
}
}
pub fn blockToHeader(allocator: Allocator, signed_block: SignedBlock, out: *BeaconBlockHeader) !void {
const block = signed_block.message();
out.slot = block.slot();
out.proposer_index = block.proposerIndex();
out.parent_root = block.parentRoot();
out.state_root = block.stateRoot();
try block.hashTreeRoot(allocator, &out.body_root);
}
const TestCachedBeaconState = @import("../test_utils/root.zig").TestCachedBeaconState;
const preset = @import("preset").preset;
const Node = @import("persistent_merkle_tree").Node;
test "process block header - sanity" {
const allocator = std.testing.allocator;
var pool = try Node.Pool.init(allocator, 1024);
defer pool.deinit();
var test_state = try TestCachedBeaconState.init(allocator, &pool, 256);
const slot = config.mainnet.chain_config.ELECTRA_FORK_EPOCH * preset.SLOTS_PER_EPOCH + 2025 * preset.SLOTS_PER_EPOCH - 1;
defer test_state.deinit();
const proposers = test_state.cached_state.getEpochCache().proposers;
var message: types.electra.BeaconBlock.Type = types.electra.BeaconBlock.default_value;
const proposer_index = proposers[slot % preset.SLOTS_PER_EPOCH];
var header = try test_state.cached_state.state.latestBlockHeader();
const header_parent_root = try header.hashTreeRoot();
message.slot = slot;
message.proposer_index = proposer_index;
message.parent_root = header_parent_root.*;
const beacon_block = BeaconBlock{ .electra = &message };
const block = Block{ .regular = beacon_block };
try processBlockHeader(allocator, test_state.cached_state, block);
}