-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathconfig.zig
More file actions
157 lines (139 loc) · 5.78 KB
/
config.zig
File metadata and controls
157 lines (139 loc) · 5.78 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
const std = @import("std");
const napi = @import("zapi:zapi");
const active_preset = @import("preset").active_preset;
const c = @import("config");
const BeaconConfig = @import("config").BeaconConfig;
const ChainConfig = @import("config").ChainConfig;
/// Allocator for internal allocations.
/// Creating ChainConfigs allocate memory for certain fields.
const allocator = std.heap.page_allocator;
pub const State = struct {
config: BeaconConfig = undefined,
initialized: bool = false,
pub fn init(self: *State) void {
if (self.initialized) return;
switch (active_preset) {
.mainnet => self.config = c.mainnet.config,
.minimal => self.config = c.minimal.config,
.gnosis => self.config = c.chiado.config,
}
}
pub fn deinit(self: *State) void {
if (!self.initialized) return;
// Free any allocated fields in config here
inline for (std.meta.fields(ChainConfig)) |field| {
switch (field.type) {
[]const u8 => allocator.free(@field(self.config.chain, field.name)),
[]ChainConfig.BlobScheduleEntry => allocator.free(@field(self.config.chain, field.name)),
else => {},
}
}
self.initialized = false;
}
};
pub var state: State = .{};
pub fn Config_set(env: napi.Env, cb: napi.CallbackInfo(2)) !napi.Value {
if (!state.initialized) {
return error.ConfigNotInitialized;
}
const obj = try cb.arg(0).coerceToObject();
const chain_config = try chainConfigFromObject(env, obj);
const genesis_validators_root_info = try cb.arg(1).getTypedarrayInfo();
if (genesis_validators_root_info.data.len != 32) {
return error.InvalidGenesisValidatorsRootLength;
}
state.config = BeaconConfig.init(
chain_config,
genesis_validators_root_info.data[0..32].*,
);
state.initialized = true;
return env.getUndefined();
}
pub fn chainConfigFromObject(env: napi.Env, obj: napi.Value) !ChainConfig {
var chain_config: ChainConfig = undefined;
inline for (std.meta.fields(ChainConfig)) |field| {
const field_value = obj.getNamedProperty(field.name) catch |err| {
try env.throwError(@errorName(err), "Missing field " ++ field.name);
return error.PendingException;
};
switch (field.type) {
u64 => {
const num = try field_value.getValueInt64();
// TODO check for infinity
@field(chain_config, field.name) = num;
},
u256 => {
var sign_bit: u1 = 0;
var words_buf: [4]u64 = undefined;
const words = try field_value.getValueBigintWords(&sign_bit, &words_buf);
if (sign_bit != 0) {
return error.InvalidChainConfigFieldValue;
}
var num_u256: u256 = 0;
for (0..4) |i| {
num_u256 |= u256(words[i]) << (@as(u256, i) * 64);
}
@field(chain_config, field.name) = num_u256;
},
[4]u8 => {
const typedarray_info = try field_value.getTypedarrayInfo();
if (typedarray_info.data.len != 4) {
return error.InvalidVersionLength;
}
var version: [4]u8 = undefined;
@memcpy(&version, typedarray_info.data);
@field(chain_config, field.name) = version;
},
[20]u8 => {
const typedarray_info = try field_value.getTypedarrayInfo();
if (typedarray_info.data.len != 20) {
return error.InvalidAddressLength;
}
var address: [20]u8 = undefined;
@memcpy(&address, typedarray_info.data);
@field(chain_config, field.name) = address;
},
[32]u8 => {
const typedarray_info = try field_value.getTypedarrayInfo();
if (typedarray_info.data.len != 32) {
return error.InvalidRootLength;
}
var root: [32]u8 = undefined;
@memcpy(&root, typedarray_info.data);
@field(chain_config, field.name) = root;
},
[]const u8 => {
var str_buf: [64]u8 = undefined;
const str = try field_value.getValueStringUtf8(&str_buf);
@field(chain_config, field.name) = try allocator.dupe(u8, str);
},
[]ChainConfig.BlobScheduleEntry => {
const array_length = try field_value.getArrayLength();
const blob_schedule = try allocator.alloc(c.BlobScheduleEntry, array_length);
errdefer allocator.free(blob_schedule);
for (0..array_length) |i| {
const entry_value = try field_value.getElement(i);
const epoch_value = try entry_value.getNamedProperty("EPOCH");
const max_blobs_value = try entry_value.getNamedProperty("MAX_BLOBS_PER_BLOCK");
blob_schedule[i] = c.BlobScheduleEntry{
.EPOCH = try epoch_value.getValueUint64(),
.MAX_BLOBS_PER_BLOCK = try max_blobs_value.getValueUint64(),
};
}
@field(chain_config, field.name) = blob_schedule;
},
else => return error.UnsupportedChainConfigFieldType,
}
}
return chain_config;
}
pub fn register(env: napi.Env, exports: napi.Value) !void {
const config_obj = try env.createObject();
try config_obj.setNamedProperty("set", try env.createFunction(
"set",
2,
Config_set,
null,
));
try exports.setNamedProperty("config", config_obj);
}