tigerbeetle-node 0.11.11 → 0.11.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -196
- package/dist/.client.node.sha256 +1 -1
- package/package.json +6 -8
- package/scripts/build_lib.sh +22 -2
- package/src/node.zig +1 -0
- package/src/tigerbeetle/scripts/benchmark.bat +9 -5
- package/src/tigerbeetle/scripts/benchmark.sh +1 -4
- package/src/tigerbeetle/scripts/fail_on_diff.sh +9 -0
- package/src/tigerbeetle/scripts/fuzz_loop_hash_log.sh +12 -0
- package/src/tigerbeetle/scripts/scripts/benchmark.bat +55 -0
- package/src/tigerbeetle/scripts/scripts/benchmark.sh +66 -0
- package/src/tigerbeetle/scripts/scripts/confirm_image.sh +44 -0
- package/src/tigerbeetle/scripts/scripts/fail_on_diff.sh +9 -0
- package/src/tigerbeetle/scripts/scripts/fuzz_loop.sh +15 -0
- package/src/tigerbeetle/scripts/scripts/fuzz_loop_hash_log.sh +12 -0
- package/src/tigerbeetle/scripts/scripts/fuzz_unique_errors.sh +7 -0
- package/src/tigerbeetle/scripts/scripts/install.bat +7 -0
- package/src/tigerbeetle/scripts/scripts/install.sh +21 -0
- package/src/tigerbeetle/scripts/scripts/install_zig.bat +113 -0
- package/src/tigerbeetle/scripts/scripts/install_zig.sh +90 -0
- package/src/tigerbeetle/scripts/scripts/lint.zig +199 -0
- package/src/tigerbeetle/scripts/scripts/pre-commit.sh +9 -0
- package/src/tigerbeetle/scripts/scripts/shellcheck.sh +5 -0
- package/src/tigerbeetle/scripts/scripts/tests_on_alpine.sh +10 -0
- package/src/tigerbeetle/scripts/scripts/tests_on_ubuntu.sh +14 -0
- package/src/tigerbeetle/scripts/scripts/upgrade_ubuntu_kernel.sh +48 -0
- package/src/tigerbeetle/scripts/scripts/validate_docs.sh +23 -0
- package/src/tigerbeetle/scripts/scripts/vr_state_enumerate +46 -0
- package/src/tigerbeetle/src/benchmark.zig +253 -231
- package/src/tigerbeetle/src/config.zig +2 -3
- package/src/tigerbeetle/src/constants.zig +2 -10
- package/src/tigerbeetle/src/io/linux.zig +15 -6
- package/src/tigerbeetle/src/lsm/forest.zig +1 -0
- package/src/tigerbeetle/src/lsm/forest_fuzz.zig +63 -14
- package/src/tigerbeetle/src/lsm/groove.zig +134 -70
- package/src/tigerbeetle/src/lsm/level_iterator.zig +2 -2
- package/src/tigerbeetle/src/lsm/manifest_level.zig +1 -0
- package/src/tigerbeetle/src/lsm/posted_groove.zig +7 -4
- package/src/tigerbeetle/src/lsm/segmented_array.zig +1 -0
- package/src/tigerbeetle/src/lsm/table.zig +29 -51
- package/src/tigerbeetle/src/lsm/table_immutable.zig +6 -17
- package/src/tigerbeetle/src/lsm/table_iterator.zig +2 -2
- package/src/tigerbeetle/src/lsm/table_mutable.zig +9 -26
- package/src/tigerbeetle/src/lsm/test.zig +1 -0
- package/src/tigerbeetle/src/lsm/tree.zig +2 -26
- package/src/tigerbeetle/src/lsm/tree_fuzz.zig +7 -2
- package/src/tigerbeetle/src/message_bus.zig +2 -1
- package/src/tigerbeetle/src/simulator.zig +14 -3
- package/src/tigerbeetle/src/state_machine/auditor.zig +1 -0
- package/src/tigerbeetle/src/state_machine.zig +402 -184
- package/src/tigerbeetle/src/stdx.zig +32 -0
- package/src/tigerbeetle/src/testing/cluster/network.zig +6 -7
- package/src/tigerbeetle/src/testing/cluster.zig +6 -5
- package/src/tigerbeetle/src/testing/packet_simulator.zig +19 -10
- package/src/tigerbeetle/src/testing/state_machine.zig +1 -0
- package/src/tigerbeetle/src/unit_tests.zig +20 -22
- package/src/tigerbeetle/src/vsr/README.md +209 -0
- package/src/tigerbeetle/src/vsr/client.zig +4 -4
- package/src/tigerbeetle/src/vsr/clock.zig +2 -0
- package/src/tigerbeetle/src/vsr/journal.zig +2 -0
- package/src/tigerbeetle/src/vsr/replica.zig +646 -578
- package/src/tigerbeetle/src/vsr/superblock.zig +14 -17
- package/src/tigerbeetle/src/vsr/superblock_fuzz.zig +5 -5
- package/src/tigerbeetle/src/vsr.zig +370 -37
|
@@ -24,6 +24,7 @@ const CreateTransferResult = tb.CreateTransferResult;
|
|
|
24
24
|
|
|
25
25
|
pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
26
26
|
message_body_size_max: usize,
|
|
27
|
+
lsm_batch_multiple: usize,
|
|
27
28
|
}) type {
|
|
28
29
|
return struct {
|
|
29
30
|
const StateMachine = @This();
|
|
@@ -31,28 +32,190 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
31
32
|
const GrooveType = @import("lsm/groove.zig").GrooveType;
|
|
32
33
|
const ForestType = @import("lsm/forest.zig").ForestType;
|
|
33
34
|
|
|
34
|
-
const
|
|
35
|
+
pub const constants = struct {
|
|
36
|
+
pub const message_body_size_max = constants_.message_body_size_max;
|
|
37
|
+
|
|
38
|
+
/// The maximum number of objects within a batch, by operation.
|
|
39
|
+
pub const batch_max = struct {
|
|
40
|
+
pub const create_accounts = operation_batch_max(.create_accounts);
|
|
41
|
+
pub const create_transfers = operation_batch_max(.create_transfers);
|
|
42
|
+
pub const lookup_accounts = operation_batch_max(.lookup_accounts);
|
|
43
|
+
pub const lookup_transfers = operation_batch_max(.lookup_transfers);
|
|
44
|
+
|
|
45
|
+
comptime {
|
|
46
|
+
assert(create_accounts > 0);
|
|
47
|
+
assert(create_transfers > 0);
|
|
48
|
+
assert(lookup_accounts > 0);
|
|
49
|
+
assert(lookup_transfers > 0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn operation_batch_max(comptime operation: Operation) usize {
|
|
53
|
+
return @divFloor(message_body_size_max, std.math.max(
|
|
54
|
+
@sizeOf(Event(operation)),
|
|
55
|
+
@sizeOf(Result(operation)),
|
|
56
|
+
));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
pub const AccountImmutable = extern struct {
|
|
62
|
+
id: u128,
|
|
63
|
+
user_data: u128,
|
|
64
|
+
timestamp: u64,
|
|
65
|
+
ledger: u32,
|
|
66
|
+
code: u16,
|
|
67
|
+
flags: AccountFlags,
|
|
68
|
+
padding: [16]u8,
|
|
69
|
+
|
|
70
|
+
comptime {
|
|
71
|
+
assert(@sizeOf(AccountImmutable) == 64);
|
|
72
|
+
assert(@bitSizeOf(AccountImmutable) == @sizeOf(AccountImmutable) * 8);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
pub fn from_account(a: *const Account) AccountImmutable {
|
|
76
|
+
return .{
|
|
77
|
+
.id = a.id,
|
|
78
|
+
.user_data = a.user_data,
|
|
79
|
+
.timestamp = a.timestamp,
|
|
80
|
+
.ledger = a.ledger,
|
|
81
|
+
.code = a.code,
|
|
82
|
+
.flags = a.flags,
|
|
83
|
+
.padding = mem.zeroes([16]u8),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
pub const AccountMutable = extern struct {
|
|
89
|
+
debits_pending: u64,
|
|
90
|
+
debits_posted: u64,
|
|
91
|
+
credits_pending: u64,
|
|
92
|
+
credits_posted: u64,
|
|
93
|
+
timestamp: u64,
|
|
94
|
+
padding: [24]u8,
|
|
95
|
+
|
|
96
|
+
comptime {
|
|
97
|
+
assert(@sizeOf(AccountMutable) == 64);
|
|
98
|
+
assert(@bitSizeOf(AccountMutable) == @sizeOf(AccountMutable) * 8);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
pub fn from_account(a: *const Account) AccountMutable {
|
|
102
|
+
return .{
|
|
103
|
+
.debits_pending = a.debits_pending,
|
|
104
|
+
.debits_posted = a.debits_posted,
|
|
105
|
+
.credits_pending = a.credits_pending,
|
|
106
|
+
.credits_posted = a.credits_posted,
|
|
107
|
+
.timestamp = a.timestamp,
|
|
108
|
+
.padding = mem.zeroes([24]u8),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
pub fn into_account(immut: *const AccountImmutable, mut: *const AccountMutable) Account {
|
|
114
|
+
assert(immut.timestamp == mut.timestamp);
|
|
115
|
+
return Account{
|
|
116
|
+
.id = immut.id,
|
|
117
|
+
.user_data = immut.user_data,
|
|
118
|
+
.reserved = mem.zeroes([48]u8),
|
|
119
|
+
.ledger = immut.ledger,
|
|
120
|
+
.code = immut.code,
|
|
121
|
+
.flags = immut.flags,
|
|
122
|
+
.debits_pending = mut.debits_pending,
|
|
123
|
+
.debits_posted = mut.debits_posted,
|
|
124
|
+
.credits_pending = mut.credits_pending,
|
|
125
|
+
.credits_posted = mut.credits_posted,
|
|
126
|
+
.timestamp = mut.timestamp,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const AccountsImmutableGroove = GrooveType(
|
|
35
131
|
Storage,
|
|
36
|
-
|
|
132
|
+
AccountImmutable,
|
|
37
133
|
.{
|
|
38
|
-
.
|
|
134
|
+
.value_count_max = .{
|
|
135
|
+
.timestamp = constants_.lsm_batch_multiple * math.max(
|
|
136
|
+
constants.batch_max.create_accounts,
|
|
137
|
+
// ×2 because creating a transfer will update 2 accounts.
|
|
138
|
+
2 * constants.batch_max.create_transfers,
|
|
139
|
+
),
|
|
140
|
+
.id = constants_.lsm_batch_multiple * constants.batch_max.create_accounts,
|
|
141
|
+
.user_data = constants_.lsm_batch_multiple * constants.batch_max.create_accounts,
|
|
142
|
+
.ledger = constants_.lsm_batch_multiple * constants.batch_max.create_accounts,
|
|
143
|
+
.code = constants_.lsm_batch_multiple * constants.batch_max.create_accounts,
|
|
144
|
+
},
|
|
145
|
+
.ignored = &[_][]const u8{ "flags", "padding" },
|
|
39
146
|
.derived = .{},
|
|
40
147
|
},
|
|
41
148
|
);
|
|
149
|
+
|
|
150
|
+
const AccountsMutableGroove = GrooveType(
|
|
151
|
+
Storage,
|
|
152
|
+
AccountMutable,
|
|
153
|
+
.{
|
|
154
|
+
.value_count_max = .{
|
|
155
|
+
.timestamp = constants_.lsm_batch_multiple * math.max(
|
|
156
|
+
constants.batch_max.create_accounts,
|
|
157
|
+
// ×2 because creating a transfer will update 2 accounts.
|
|
158
|
+
2 * constants.batch_max.create_transfers,
|
|
159
|
+
),
|
|
160
|
+
// Transfers mutate the secondary indices for debits/credits pending/posted.
|
|
161
|
+
//
|
|
162
|
+
// * Each mutation results in a remove and an insert: the ×2 multiplier.
|
|
163
|
+
// * Each transfer modifies two accounts. However, this does not
|
|
164
|
+
// necessitate an additional ×2 multiplier — the credits of the debit
|
|
165
|
+
// account and the debits of the credit account are not modified.
|
|
166
|
+
.debits_pending = constants_.lsm_batch_multiple * math.max(
|
|
167
|
+
constants.batch_max.create_accounts,
|
|
168
|
+
2 * constants.batch_max.create_transfers,
|
|
169
|
+
),
|
|
170
|
+
.debits_posted = constants_.lsm_batch_multiple * math.max(
|
|
171
|
+
constants.batch_max.create_accounts,
|
|
172
|
+
2 * constants.batch_max.create_transfers,
|
|
173
|
+
),
|
|
174
|
+
.credits_pending = constants_.lsm_batch_multiple * math.max(
|
|
175
|
+
constants.batch_max.create_accounts,
|
|
176
|
+
2 * constants.batch_max.create_transfers,
|
|
177
|
+
),
|
|
178
|
+
.credits_posted = constants_.lsm_batch_multiple * math.max(
|
|
179
|
+
constants.batch_max.create_accounts,
|
|
180
|
+
2 * constants.batch_max.create_transfers,
|
|
181
|
+
),
|
|
182
|
+
},
|
|
183
|
+
.ignored = &[_][]const u8{"padding"},
|
|
184
|
+
.derived = .{},
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
|
|
42
188
|
const TransfersGroove = GrooveType(
|
|
43
189
|
Storage,
|
|
44
190
|
Transfer,
|
|
45
191
|
.{
|
|
192
|
+
.value_count_max = .{
|
|
193
|
+
.timestamp = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
194
|
+
.id = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
195
|
+
.debit_account_id = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
196
|
+
.credit_account_id = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
197
|
+
.user_data = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
198
|
+
.pending_id = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
199
|
+
.timeout = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
200
|
+
.ledger = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
201
|
+
.code = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
202
|
+
.amount = constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
203
|
+
},
|
|
46
204
|
.ignored = &[_][]const u8{ "reserved", "flags" },
|
|
47
205
|
.derived = .{},
|
|
48
206
|
},
|
|
49
207
|
);
|
|
50
|
-
|
|
208
|
+
|
|
209
|
+
const PostedGroove = @import("lsm/posted_groove.zig").PostedGrooveType(
|
|
210
|
+
Storage,
|
|
211
|
+
constants_.lsm_batch_multiple * constants.batch_max.create_transfers,
|
|
212
|
+
);
|
|
51
213
|
|
|
52
214
|
pub const Workload = WorkloadType(StateMachine);
|
|
53
215
|
|
|
54
216
|
pub const Forest = ForestType(Storage, .{
|
|
55
|
-
.
|
|
217
|
+
.accounts_immutable = AccountsImmutableGroove,
|
|
218
|
+
.accounts_mutable = AccountsMutableGroove,
|
|
56
219
|
.transfers = TransfersGroove,
|
|
57
220
|
.posted = PostedGroove,
|
|
58
221
|
});
|
|
@@ -70,32 +233,6 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
70
233
|
lookup_transfers,
|
|
71
234
|
};
|
|
72
235
|
|
|
73
|
-
pub const constants = struct {
|
|
74
|
-
pub const message_body_size_max = constants_.message_body_size_max;
|
|
75
|
-
|
|
76
|
-
/// The maximum number of objects within a batch, by operation.
|
|
77
|
-
pub const batch_max = struct {
|
|
78
|
-
pub const create_accounts = operation_batch_max(.create_accounts);
|
|
79
|
-
pub const create_transfers = operation_batch_max(.create_transfers);
|
|
80
|
-
pub const lookup_accounts = operation_batch_max(.lookup_accounts);
|
|
81
|
-
pub const lookup_transfers = operation_batch_max(.lookup_transfers);
|
|
82
|
-
|
|
83
|
-
comptime {
|
|
84
|
-
assert(create_accounts > 0);
|
|
85
|
-
assert(create_transfers > 0);
|
|
86
|
-
assert(lookup_accounts > 0);
|
|
87
|
-
assert(lookup_transfers > 0);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
fn operation_batch_max(comptime operation: Operation) usize {
|
|
91
|
-
return @divFloor(message_body_size_max, std.math.max(
|
|
92
|
-
@sizeOf(Event(operation)),
|
|
93
|
-
@sizeOf(Result(operation)),
|
|
94
|
-
));
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
|
|
99
236
|
pub const Options = struct {
|
|
100
237
|
lsm_forest_node_count: u32,
|
|
101
238
|
cache_entries_accounts: u32,
|
|
@@ -112,7 +249,8 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
112
249
|
// TODO(ifreund): use a union for these to save memory, likely an extern union
|
|
113
250
|
// so that we can safetly @ptrCast() until @fieldParentPtr() is implemented
|
|
114
251
|
// for unions. See: https://github.com/ziglang/zig/issues/6611
|
|
115
|
-
|
|
252
|
+
prefetch_accounts_immutable_context: AccountsImmutableGroove.PrefetchContext = undefined,
|
|
253
|
+
prefetch_accounts_mutable_context: AccountsMutableGroove.PrefetchContext = undefined,
|
|
116
254
|
prefetch_transfers_context: TransfersGroove.PrefetchContext = undefined,
|
|
117
255
|
prefetch_posted_context: PostedGroove.PrefetchContext = undefined,
|
|
118
256
|
|
|
@@ -225,7 +363,8 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
225
363
|
self.prefetch_callback = callback;
|
|
226
364
|
|
|
227
365
|
// TODO(Snapshots) Pass in the target snapshot.
|
|
228
|
-
self.forest.grooves.
|
|
366
|
+
self.forest.grooves.accounts_immutable.prefetch_setup(null);
|
|
367
|
+
self.forest.grooves.accounts_mutable.prefetch_setup(null);
|
|
229
368
|
self.forest.grooves.transfers.prefetch_setup(null);
|
|
230
369
|
self.forest.grooves.posted.prefetch_setup(null);
|
|
231
370
|
|
|
@@ -263,16 +402,41 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
263
402
|
|
|
264
403
|
fn prefetch_create_accounts(self: *StateMachine, accounts: []const Account) void {
|
|
265
404
|
for (accounts) |*a| {
|
|
266
|
-
self.forest.grooves.
|
|
405
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(a.id);
|
|
267
406
|
}
|
|
268
|
-
self.forest.grooves.
|
|
269
|
-
|
|
270
|
-
&self.
|
|
407
|
+
self.forest.grooves.accounts_immutable.prefetch(
|
|
408
|
+
prefetch_create_accounts_immutable_callback,
|
|
409
|
+
&self.prefetch_accounts_immutable_context,
|
|
271
410
|
);
|
|
272
411
|
}
|
|
273
412
|
|
|
274
|
-
fn
|
|
275
|
-
|
|
413
|
+
fn prefetch_create_accounts_immutable_callback(
|
|
414
|
+
completion: *AccountsImmutableGroove.PrefetchContext,
|
|
415
|
+
) void {
|
|
416
|
+
const self = @fieldParentPtr(
|
|
417
|
+
StateMachine,
|
|
418
|
+
"prefetch_accounts_immutable_context",
|
|
419
|
+
completion,
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
// Nothing to prefetch_enqueue() from accounts_mutable as accounts_immutable
|
|
423
|
+
// is all that is needed to check for pre-existing accounts before creating one.
|
|
424
|
+
// We still call prefetch() anyway to keep a valid/expected Groove state for commit().
|
|
425
|
+
|
|
426
|
+
self.forest.grooves.accounts_mutable.prefetch(
|
|
427
|
+
prefetch_create_accounts_mutable_callback,
|
|
428
|
+
&self.prefetch_accounts_mutable_context,
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
fn prefetch_create_accounts_mutable_callback(
|
|
433
|
+
completion: *AccountsMutableGroove.PrefetchContext,
|
|
434
|
+
) void {
|
|
435
|
+
const self = @fieldParentPtr(
|
|
436
|
+
StateMachine,
|
|
437
|
+
"prefetch_accounts_mutable_context",
|
|
438
|
+
completion,
|
|
439
|
+
);
|
|
276
440
|
|
|
277
441
|
self.prefetch_finish();
|
|
278
442
|
}
|
|
@@ -302,23 +466,53 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
302
466
|
for (transfers) |*t| {
|
|
303
467
|
if (t.flags.post_pending_transfer or t.flags.void_pending_transfer) {
|
|
304
468
|
if (self.forest.grooves.transfers.get(t.pending_id)) |p| {
|
|
305
|
-
self.forest.grooves.
|
|
306
|
-
self.forest.grooves.
|
|
469
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(p.debit_account_id);
|
|
470
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(p.credit_account_id);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(t.debit_account_id);
|
|
474
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(t.credit_account_id);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
self.forest.grooves.accounts_immutable.prefetch(
|
|
479
|
+
prefetch_create_transfers_callback_accounts_immutable,
|
|
480
|
+
&self.prefetch_accounts_immutable_context,
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
fn prefetch_create_transfers_callback_accounts_immutable(completion: *AccountsImmutableGroove.PrefetchContext) void {
|
|
485
|
+
const self = @fieldParentPtr(StateMachine, "prefetch_accounts_immutable_context", completion);
|
|
486
|
+
|
|
487
|
+
const transfers = mem.bytesAsSlice(Event(.create_transfers), self.prefetch_input.?);
|
|
488
|
+
for (transfers) |*t| {
|
|
489
|
+
if (t.flags.post_pending_transfer or t.flags.void_pending_transfer) {
|
|
490
|
+
if (self.forest.grooves.transfers.get(t.pending_id)) |p| {
|
|
491
|
+
if (self.forest.grooves.accounts_immutable.get(p.debit_account_id)) |dr_immut| {
|
|
492
|
+
self.forest.grooves.accounts_mutable.prefetch_enqueue(dr_immut.timestamp);
|
|
493
|
+
}
|
|
494
|
+
if (self.forest.grooves.accounts_immutable.get(p.credit_account_id)) |cr_immut| {
|
|
495
|
+
self.forest.grooves.accounts_mutable.prefetch_enqueue(cr_immut.timestamp);
|
|
496
|
+
}
|
|
307
497
|
}
|
|
308
498
|
} else {
|
|
309
|
-
self.forest.grooves.
|
|
310
|
-
|
|
499
|
+
if (self.forest.grooves.accounts_immutable.get(t.debit_account_id)) |dr_immut| {
|
|
500
|
+
self.forest.grooves.accounts_mutable.prefetch_enqueue(dr_immut.timestamp);
|
|
501
|
+
}
|
|
502
|
+
if (self.forest.grooves.accounts_immutable.get(t.credit_account_id)) |cr_immut| {
|
|
503
|
+
self.forest.grooves.accounts_mutable.prefetch_enqueue(cr_immut.timestamp);
|
|
504
|
+
}
|
|
311
505
|
}
|
|
312
506
|
}
|
|
313
507
|
|
|
314
|
-
self.forest.grooves.
|
|
315
|
-
|
|
316
|
-
&self.
|
|
508
|
+
self.forest.grooves.accounts_mutable.prefetch(
|
|
509
|
+
prefetch_create_transfers_callback_accounts_mutable,
|
|
510
|
+
&self.prefetch_accounts_mutable_context,
|
|
317
511
|
);
|
|
318
512
|
}
|
|
319
513
|
|
|
320
|
-
fn
|
|
321
|
-
const self = @fieldParentPtr(StateMachine, "
|
|
514
|
+
fn prefetch_create_transfers_callback_accounts_mutable(completion: *AccountsMutableGroove.PrefetchContext) void {
|
|
515
|
+
const self = @fieldParentPtr(StateMachine, "prefetch_accounts_mutable_context", completion);
|
|
322
516
|
|
|
323
517
|
self.forest.grooves.posted.prefetch(
|
|
324
518
|
prefetch_create_transfers_callback_posted,
|
|
@@ -334,17 +528,33 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
334
528
|
|
|
335
529
|
fn prefetch_lookup_accounts(self: *StateMachine, ids: []const u128) void {
|
|
336
530
|
for (ids) |id| {
|
|
337
|
-
self.forest.grooves.
|
|
531
|
+
self.forest.grooves.accounts_immutable.prefetch_enqueue(id);
|
|
338
532
|
}
|
|
339
533
|
|
|
340
|
-
self.forest.grooves.
|
|
341
|
-
|
|
342
|
-
&self.
|
|
534
|
+
self.forest.grooves.accounts_immutable.prefetch(
|
|
535
|
+
prefetch_lookup_accounts_immutable_callback,
|
|
536
|
+
&self.prefetch_accounts_immutable_context,
|
|
343
537
|
);
|
|
344
538
|
}
|
|
345
539
|
|
|
346
|
-
fn
|
|
347
|
-
const self = @fieldParentPtr(StateMachine, "
|
|
540
|
+
fn prefetch_lookup_accounts_immutable_callback(completion: *AccountsImmutableGroove.PrefetchContext) void {
|
|
541
|
+
const self = @fieldParentPtr(StateMachine, "prefetch_accounts_immutable_context", completion);
|
|
542
|
+
|
|
543
|
+
const ids = mem.bytesAsSlice(Event(.lookup_accounts), self.prefetch_input.?);
|
|
544
|
+
for (ids) |id| {
|
|
545
|
+
if (self.forest.grooves.accounts_immutable.get(id)) |immut| {
|
|
546
|
+
self.forest.grooves.accounts_mutable.prefetch_enqueue(immut.timestamp);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
self.forest.grooves.accounts_mutable.prefetch(
|
|
551
|
+
prefetch_lookup_accounts_mutable_callback,
|
|
552
|
+
&self.prefetch_accounts_mutable_context,
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
fn prefetch_lookup_accounts_mutable_callback(completion: *AccountsMutableGroove.PrefetchContext) void {
|
|
557
|
+
const self = @fieldParentPtr(StateMachine, "prefetch_accounts_mutable_context", completion);
|
|
348
558
|
|
|
349
559
|
self.prefetch_finish();
|
|
350
560
|
}
|
|
@@ -577,8 +787,9 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
577
787
|
const results = mem.bytesAsSlice(Account, output[0..output_len]);
|
|
578
788
|
var results_count: usize = 0;
|
|
579
789
|
for (batch) |id| {
|
|
580
|
-
if (self.
|
|
581
|
-
|
|
790
|
+
if (self.forest.grooves.accounts_immutable.get(id)) |immut| {
|
|
791
|
+
const mut = self.forest.grooves.accounts_mutable.get(immut.timestamp).?;
|
|
792
|
+
results[results_count] = into_account(immut, mut);
|
|
582
793
|
results_count += 1;
|
|
583
794
|
}
|
|
584
795
|
}
|
|
@@ -624,23 +835,30 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
624
835
|
if (a.credits_pending != 0) return .credits_pending_must_be_zero;
|
|
625
836
|
if (a.credits_posted != 0) return .credits_posted_must_be_zero;
|
|
626
837
|
|
|
627
|
-
if (self.
|
|
838
|
+
if (self.forest.grooves.accounts_immutable.get(a.id)) |e| {
|
|
839
|
+
return create_account_exists(a, e);
|
|
840
|
+
}
|
|
628
841
|
|
|
629
|
-
self.forest.grooves.
|
|
842
|
+
self.forest.grooves.accounts_immutable.put_no_clobber(&AccountImmutable.from_account(a));
|
|
843
|
+
self.forest.grooves.accounts_mutable.put_no_clobber(&AccountMutable.from_account(a));
|
|
630
844
|
|
|
631
845
|
self.commit_timestamp = a.timestamp;
|
|
632
846
|
return .ok;
|
|
633
847
|
}
|
|
634
848
|
|
|
635
849
|
fn create_account_rollback(self: *StateMachine, a: *const Account) void {
|
|
636
|
-
|
|
850
|
+
// Need to get the timestamp from the inserted account rather than the one passed in.
|
|
851
|
+
const timestamp = self.forest.grooves.accounts_immutable.get(a.id).?.timestamp;
|
|
852
|
+
|
|
853
|
+
self.forest.grooves.accounts_immutable.remove(a.id);
|
|
854
|
+
self.forest.grooves.accounts_mutable.remove(timestamp);
|
|
637
855
|
}
|
|
638
856
|
|
|
639
|
-
fn create_account_exists(a: *const Account, e: *const
|
|
857
|
+
fn create_account_exists(a: *const Account, e: *const AccountImmutable) CreateAccountResult {
|
|
640
858
|
assert(a.id == e.id);
|
|
641
859
|
if (@bitCast(u16, a.flags) != @bitCast(u16, e.flags)) return .exists_with_different_flags;
|
|
642
860
|
if (a.user_data != e.user_data) return .exists_with_different_user_data;
|
|
643
|
-
assert(zeroed_48_bytes(a.reserved) and
|
|
861
|
+
assert(zeroed_48_bytes(a.reserved) and zeroed_16_bytes(e.padding));
|
|
644
862
|
if (a.ledger != e.ledger) return .exists_with_different_ledger;
|
|
645
863
|
if (a.code != e.code) return .exists_with_different_code;
|
|
646
864
|
return .exists;
|
|
@@ -679,50 +897,55 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
679
897
|
// 2. standing for debit record and credit record, or
|
|
680
898
|
// 3. relating to debtor and creditor.
|
|
681
899
|
// We use them to distinguish between `cr` (credit account), and `c` (commit).
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
assert(
|
|
685
|
-
assert(
|
|
686
|
-
assert(t.timestamp >
|
|
687
|
-
assert(t.timestamp >
|
|
900
|
+
const dr_immut = self.forest.grooves.accounts_immutable.get(t.debit_account_id) orelse return .debit_account_not_found;
|
|
901
|
+
const cr_immut = self.forest.grooves.accounts_immutable.get(t.credit_account_id) orelse return .credit_account_not_found;
|
|
902
|
+
assert(dr_immut.id == t.debit_account_id);
|
|
903
|
+
assert(cr_immut.id == t.credit_account_id);
|
|
904
|
+
assert(t.timestamp > dr_immut.timestamp);
|
|
905
|
+
assert(t.timestamp > cr_immut.timestamp);
|
|
688
906
|
|
|
689
|
-
if (
|
|
690
|
-
if (t.ledger !=
|
|
907
|
+
if (dr_immut.ledger != cr_immut.ledger) return .accounts_must_have_the_same_ledger;
|
|
908
|
+
if (t.ledger != dr_immut.ledger) return .transfer_must_have_the_same_ledger_as_accounts;
|
|
691
909
|
|
|
692
910
|
// If the transfer already exists, then it must not influence the overflow or limit checks.
|
|
693
911
|
if (self.get_transfer(t.id)) |e| return create_transfer_exists(t, e);
|
|
694
912
|
|
|
913
|
+
const dr_mut = self.forest.grooves.accounts_mutable.get(dr_immut.timestamp).?;
|
|
914
|
+
const cr_mut = self.forest.grooves.accounts_mutable.get(cr_immut.timestamp).?;
|
|
915
|
+
assert(dr_mut.timestamp == dr_immut.timestamp);
|
|
916
|
+
assert(cr_mut.timestamp == cr_immut.timestamp);
|
|
917
|
+
|
|
695
918
|
if (t.flags.pending) {
|
|
696
|
-
if (sum_overflows(t.amount,
|
|
697
|
-
if (sum_overflows(t.amount,
|
|
919
|
+
if (sum_overflows(t.amount, dr_mut.debits_pending)) return .overflows_debits_pending;
|
|
920
|
+
if (sum_overflows(t.amount, cr_mut.credits_pending)) return .overflows_credits_pending;
|
|
698
921
|
}
|
|
699
|
-
if (sum_overflows(t.amount,
|
|
700
|
-
if (sum_overflows(t.amount,
|
|
922
|
+
if (sum_overflows(t.amount, dr_mut.debits_posted)) return .overflows_debits_posted;
|
|
923
|
+
if (sum_overflows(t.amount, cr_mut.credits_posted)) return .overflows_credits_posted;
|
|
701
924
|
// We assert that the sum of the pending and posted balances can never overflow:
|
|
702
|
-
if (sum_overflows(t.amount,
|
|
925
|
+
if (sum_overflows(t.amount, dr_mut.debits_pending + dr_mut.debits_posted)) {
|
|
703
926
|
return .overflows_debits;
|
|
704
927
|
}
|
|
705
|
-
if (sum_overflows(t.amount,
|
|
928
|
+
if (sum_overflows(t.amount, cr_mut.credits_pending + cr_mut.credits_posted)) {
|
|
706
929
|
return .overflows_credits;
|
|
707
930
|
}
|
|
708
931
|
if (sum_overflows(t.timestamp, t.timeout)) return .overflows_timeout;
|
|
709
932
|
|
|
710
|
-
if (
|
|
711
|
-
if (
|
|
933
|
+
if (into_account(dr_immut, dr_mut).debits_exceed_credits(t.amount)) return .exceeds_credits;
|
|
934
|
+
if (into_account(cr_immut, cr_mut).credits_exceed_debits(t.amount)) return .exceeds_debits;
|
|
712
935
|
|
|
713
936
|
self.forest.grooves.transfers.put_no_clobber(t);
|
|
714
937
|
|
|
715
|
-
var
|
|
716
|
-
var
|
|
938
|
+
var dr_mut_new = dr_mut.*;
|
|
939
|
+
var cr_mut_new = cr_mut.*;
|
|
717
940
|
if (t.flags.pending) {
|
|
718
|
-
|
|
719
|
-
|
|
941
|
+
dr_mut_new.debits_pending += t.amount;
|
|
942
|
+
cr_mut_new.credits_pending += t.amount;
|
|
720
943
|
} else {
|
|
721
|
-
|
|
722
|
-
|
|
944
|
+
dr_mut_new.debits_posted += t.amount;
|
|
945
|
+
cr_mut_new.credits_posted += t.amount;
|
|
723
946
|
}
|
|
724
|
-
self.forest.grooves.
|
|
725
|
-
self.forest.grooves.
|
|
947
|
+
self.forest.grooves.accounts_mutable.put(&dr_mut_new);
|
|
948
|
+
self.forest.grooves.accounts_mutable.put(&cr_mut_new);
|
|
726
949
|
|
|
727
950
|
self.commit_timestamp = t.timestamp;
|
|
728
951
|
return .ok;
|
|
@@ -733,20 +956,25 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
733
956
|
return self.post_or_void_pending_transfer_rollback(t);
|
|
734
957
|
}
|
|
735
958
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
assert(
|
|
739
|
-
assert(
|
|
959
|
+
const dr_immut = self.forest.grooves.accounts_immutable.get(t.debit_account_id).?;
|
|
960
|
+
const cr_immut = self.forest.grooves.accounts_immutable.get(t.credit_account_id).?;
|
|
961
|
+
assert(dr_immut.id == t.debit_account_id);
|
|
962
|
+
assert(cr_immut.id == t.credit_account_id);
|
|
963
|
+
|
|
964
|
+
var dr_mut = self.forest.grooves.accounts_mutable.get(dr_immut.timestamp).?.*;
|
|
965
|
+
var cr_mut = self.forest.grooves.accounts_mutable.get(cr_immut.timestamp).?.*;
|
|
966
|
+
assert(dr_mut.timestamp == dr_immut.timestamp);
|
|
967
|
+
assert(cr_mut.timestamp == cr_immut.timestamp);
|
|
740
968
|
|
|
741
969
|
if (t.flags.pending) {
|
|
742
|
-
|
|
743
|
-
|
|
970
|
+
dr_mut.debits_pending -= t.amount;
|
|
971
|
+
cr_mut.credits_pending -= t.amount;
|
|
744
972
|
} else {
|
|
745
|
-
|
|
746
|
-
|
|
973
|
+
dr_mut.debits_posted -= t.amount;
|
|
974
|
+
cr_mut.credits_posted -= t.amount;
|
|
747
975
|
}
|
|
748
|
-
self.forest.grooves.
|
|
749
|
-
self.forest.grooves.
|
|
976
|
+
self.forest.grooves.accounts_mutable.put(&dr_mut);
|
|
977
|
+
self.forest.grooves.accounts_mutable.put(&cr_mut);
|
|
750
978
|
|
|
751
979
|
self.forest.grooves.transfers.remove(t.id);
|
|
752
980
|
}
|
|
@@ -792,12 +1020,12 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
792
1020
|
assert(p.id == t.pending_id);
|
|
793
1021
|
if (!p.flags.pending) return .pending_transfer_not_pending;
|
|
794
1022
|
|
|
795
|
-
const
|
|
796
|
-
const
|
|
797
|
-
assert(
|
|
798
|
-
assert(
|
|
799
|
-
assert(p.timestamp >
|
|
800
|
-
assert(p.timestamp >
|
|
1023
|
+
const dr_immut = self.forest.grooves.accounts_immutable.get(p.debit_account_id).?;
|
|
1024
|
+
const cr_immut = self.forest.grooves.accounts_immutable.get(p.credit_account_id).?;
|
|
1025
|
+
assert(dr_immut.id == p.debit_account_id);
|
|
1026
|
+
assert(cr_immut.id == p.credit_account_id);
|
|
1027
|
+
assert(p.timestamp > dr_immut.timestamp);
|
|
1028
|
+
assert(p.timestamp > cr_immut.timestamp);
|
|
801
1029
|
assert(p.amount > 0);
|
|
802
1030
|
|
|
803
1031
|
if (t.debit_account_id > 0 and t.debit_account_id != p.debit_account_id) {
|
|
@@ -846,21 +1074,23 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
846
1074
|
|
|
847
1075
|
self.forest.grooves.posted.put_no_clobber(t.pending_id, t.flags.post_pending_transfer);
|
|
848
1076
|
|
|
849
|
-
var
|
|
850
|
-
var
|
|
1077
|
+
var dr_mut_new = self.forest.grooves.accounts_mutable.get(dr_immut.timestamp).?.*;
|
|
1078
|
+
var cr_mut_new = self.forest.grooves.accounts_mutable.get(cr_immut.timestamp).?.*;
|
|
1079
|
+
assert(dr_mut_new.timestamp == dr_immut.timestamp);
|
|
1080
|
+
assert(cr_mut_new.timestamp == cr_immut.timestamp);
|
|
851
1081
|
|
|
852
|
-
|
|
853
|
-
|
|
1082
|
+
dr_mut_new.debits_pending -= p.amount;
|
|
1083
|
+
cr_mut_new.credits_pending -= p.amount;
|
|
854
1084
|
|
|
855
1085
|
if (t.flags.post_pending_transfer) {
|
|
856
1086
|
assert(amount > 0);
|
|
857
1087
|
assert(amount <= p.amount);
|
|
858
|
-
|
|
859
|
-
|
|
1088
|
+
dr_mut_new.debits_posted += amount;
|
|
1089
|
+
cr_mut_new.credits_posted += amount;
|
|
860
1090
|
}
|
|
861
1091
|
|
|
862
|
-
self.forest.grooves.
|
|
863
|
-
self.forest.grooves.
|
|
1092
|
+
self.forest.grooves.accounts_mutable.put(&dr_mut_new);
|
|
1093
|
+
self.forest.grooves.accounts_mutable.put(&cr_mut_new);
|
|
864
1094
|
|
|
865
1095
|
self.commit_timestamp = t.timestamp;
|
|
866
1096
|
return .ok;
|
|
@@ -876,23 +1106,28 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
876
1106
|
assert(p.debit_account_id > 0);
|
|
877
1107
|
assert(p.credit_account_id > 0);
|
|
878
1108
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
assert(
|
|
882
|
-
assert(
|
|
1109
|
+
const dr_immut = self.forest.grooves.accounts_immutable.get(p.debit_account_id).?;
|
|
1110
|
+
const cr_immut = self.forest.grooves.accounts_immutable.get(p.credit_account_id).?;
|
|
1111
|
+
assert(dr_immut.id == p.debit_account_id);
|
|
1112
|
+
assert(cr_immut.id == p.credit_account_id);
|
|
1113
|
+
|
|
1114
|
+
var dr_mut = self.forest.grooves.accounts_mutable.get(dr_immut.timestamp).?.*;
|
|
1115
|
+
var cr_mut = self.forest.grooves.accounts_mutable.get(cr_immut.timestamp).?.*;
|
|
1116
|
+
assert(dr_mut.timestamp == dr_immut.timestamp);
|
|
1117
|
+
assert(cr_mut.timestamp == cr_immut.timestamp);
|
|
883
1118
|
|
|
884
1119
|
if (t.flags.post_pending_transfer) {
|
|
885
1120
|
const amount = if (t.amount > 0) t.amount else p.amount;
|
|
886
1121
|
assert(amount > 0);
|
|
887
1122
|
assert(amount <= p.amount);
|
|
888
|
-
|
|
889
|
-
|
|
1123
|
+
dr_mut.debits_posted -= amount;
|
|
1124
|
+
cr_mut.credits_posted -= amount;
|
|
890
1125
|
}
|
|
891
|
-
|
|
892
|
-
|
|
1126
|
+
dr_mut.debits_pending += p.amount;
|
|
1127
|
+
cr_mut.credits_pending += p.amount;
|
|
893
1128
|
|
|
894
|
-
self.forest.grooves.
|
|
895
|
-
self.forest.grooves.
|
|
1129
|
+
self.forest.grooves.accounts_mutable.put(&dr_mut);
|
|
1130
|
+
self.forest.grooves.accounts_mutable.put(&cr_mut);
|
|
896
1131
|
|
|
897
1132
|
self.forest.grooves.posted.remove(t.pending_id);
|
|
898
1133
|
self.forest.grooves.transfers.remove(t.id);
|
|
@@ -951,10 +1186,6 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
951
1186
|
return .exists;
|
|
952
1187
|
}
|
|
953
1188
|
|
|
954
|
-
fn get_account(self: *const StateMachine, id: u128) ?*const Account {
|
|
955
|
-
return self.forest.grooves.accounts.get(id);
|
|
956
|
-
}
|
|
957
|
-
|
|
958
1189
|
fn get_transfer(self: *const StateMachine, id: u128) ?*const Transfer {
|
|
959
1190
|
return self.forest.grooves.transfers.get(id);
|
|
960
1191
|
}
|
|
@@ -971,60 +1202,43 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
971
1202
|
assert(batch_transfers_max == constants.batch_max.lookup_transfers);
|
|
972
1203
|
|
|
973
1204
|
return .{
|
|
974
|
-
.
|
|
1205
|
+
.accounts_immutable = .{
|
|
975
1206
|
.prefetch_entries_max = std.math.max(
|
|
976
|
-
// create_account()/lookup_account() looks up 1
|
|
1207
|
+
// create_account()/lookup_account() looks up 1 AccountImmutable per item.
|
|
977
1208
|
batch_accounts_max,
|
|
978
1209
|
// create_transfer()/post_or_void_pending_transfer() looks up 2
|
|
979
|
-
//
|
|
1210
|
+
// AccountImmutables for every transfer.
|
|
980
1211
|
2 * batch_transfers_max,
|
|
981
1212
|
),
|
|
982
1213
|
.tree_options_object = .{
|
|
983
1214
|
.cache_entries_max = options.cache_entries_accounts,
|
|
984
|
-
.commit_entries_max = math.max(
|
|
985
|
-
batch_accounts_max,
|
|
986
|
-
// ×2 because creating a transfer will update 2 accounts.
|
|
987
|
-
2 * batch_transfers_max,
|
|
988
|
-
),
|
|
989
1215
|
},
|
|
990
1216
|
.tree_options_id = .{
|
|
991
1217
|
.cache_entries_max = options.cache_entries_accounts,
|
|
992
|
-
.commit_entries_max = batch_accounts_max,
|
|
993
1218
|
},
|
|
994
1219
|
.tree_options_index = .{
|
|
995
|
-
.user_data = .{
|
|
996
|
-
.ledger = .{
|
|
997
|
-
.code = .{
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
//
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
},
|
|
1016
|
-
.
|
|
1017
|
-
.commit_entries_max = math.max(
|
|
1018
|
-
batch_accounts_max,
|
|
1019
|
-
2 * batch_transfers_max,
|
|
1020
|
-
),
|
|
1021
|
-
},
|
|
1022
|
-
.credits_posted = .{
|
|
1023
|
-
.commit_entries_max = math.max(
|
|
1024
|
-
batch_accounts_max,
|
|
1025
|
-
2 * batch_transfers_max,
|
|
1026
|
-
),
|
|
1027
|
-
},
|
|
1220
|
+
.user_data = .{},
|
|
1221
|
+
.ledger = .{},
|
|
1222
|
+
.code = .{},
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
.accounts_mutable = .{
|
|
1226
|
+
.prefetch_entries_max = std.math.max(
|
|
1227
|
+
// create_account()/lookup_account() looks up 1 AccountMutable per item.
|
|
1228
|
+
batch_accounts_max,
|
|
1229
|
+
// create_transfer()/post_or_void_pending_transfer() looks up 2
|
|
1230
|
+
// AccountMutables for every transfer.
|
|
1231
|
+
2 * batch_transfers_max,
|
|
1232
|
+
),
|
|
1233
|
+
.tree_options_object = .{
|
|
1234
|
+
.cache_entries_max = options.cache_entries_accounts,
|
|
1235
|
+
},
|
|
1236
|
+
.tree_options_id = {}, // No ID tree at there's one already for AccountsMutable.
|
|
1237
|
+
.tree_options_index = .{
|
|
1238
|
+
.debits_pending = .{},
|
|
1239
|
+
.debits_posted = .{},
|
|
1240
|
+
.credits_pending = .{},
|
|
1241
|
+
.credits_posted = .{},
|
|
1028
1242
|
},
|
|
1029
1243
|
},
|
|
1030
1244
|
.transfers = .{
|
|
@@ -1032,27 +1246,24 @@ pub fn StateMachineType(comptime Storage: type, comptime constants_: struct {
|
|
|
1032
1246
|
.prefetch_entries_max = 2 * batch_transfers_max,
|
|
1033
1247
|
.tree_options_object = .{
|
|
1034
1248
|
.cache_entries_max = options.cache_entries_transfers,
|
|
1035
|
-
.commit_entries_max = batch_transfers_max,
|
|
1036
1249
|
},
|
|
1037
1250
|
.tree_options_id = .{
|
|
1038
1251
|
.cache_entries_max = options.cache_entries_transfers,
|
|
1039
|
-
.commit_entries_max = batch_transfers_max,
|
|
1040
1252
|
},
|
|
1041
1253
|
.tree_options_index = .{
|
|
1042
|
-
.debit_account_id = .{
|
|
1043
|
-
.credit_account_id = .{
|
|
1044
|
-
.user_data = .{
|
|
1045
|
-
.pending_id = .{
|
|
1046
|
-
.timeout = .{
|
|
1047
|
-
.ledger = .{
|
|
1048
|
-
.code = .{
|
|
1049
|
-
.amount = .{
|
|
1254
|
+
.debit_account_id = .{},
|
|
1255
|
+
.credit_account_id = .{},
|
|
1256
|
+
.user_data = .{},
|
|
1257
|
+
.pending_id = .{},
|
|
1258
|
+
.timeout = .{},
|
|
1259
|
+
.ledger = .{},
|
|
1260
|
+
.code = .{},
|
|
1261
|
+
.amount = .{},
|
|
1050
1262
|
},
|
|
1051
1263
|
},
|
|
1052
1264
|
.posted = .{
|
|
1053
1265
|
.cache_entries_max = options.cache_entries_posted,
|
|
1054
1266
|
.prefetch_entries_max = batch_transfers_max,
|
|
1055
|
-
.commit_entries_max = batch_transfers_max,
|
|
1056
1267
|
},
|
|
1057
1268
|
};
|
|
1058
1269
|
}
|
|
@@ -1065,6 +1276,11 @@ fn sum_overflows(a: u64, b: u64) bool {
|
|
|
1065
1276
|
}
|
|
1066
1277
|
|
|
1067
1278
|
/// Optimizes for the common case, where the array is zeroed. Completely branchless.
|
|
1279
|
+
fn zeroed_16_bytes(a: [16]u8) bool {
|
|
1280
|
+
const x = @bitCast([2]u64, a);
|
|
1281
|
+
return (x[0] | x[1]) == 0;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1068
1284
|
fn zeroed_32_bytes(a: [32]u8) bool {
|
|
1069
1285
|
const x = @bitCast([4]u64, a);
|
|
1070
1286
|
return (x[0] | x[1] | x[2] | x[3]) == 0;
|
|
@@ -1121,9 +1337,9 @@ const TestContext = struct {
|
|
|
1121
1337
|
const SuperBlock = @import("vsr/superblock.zig").SuperBlockType(Storage);
|
|
1122
1338
|
const Grid = @import("lsm/grid.zig").GridType(Storage);
|
|
1123
1339
|
const StateMachine = StateMachineType(Storage, .{
|
|
1124
|
-
// Overestimate the batch size
|
|
1125
|
-
// because the test never compacts.
|
|
1340
|
+
// Overestimate the batch size because the test never compacts.
|
|
1126
1341
|
.message_body_size_max = message_body_size_max,
|
|
1342
|
+
.lsm_batch_multiple = 1,
|
|
1127
1343
|
});
|
|
1128
1344
|
const message_body_size_max = 32 * @sizeOf(Account);
|
|
1129
1345
|
|
|
@@ -1328,12 +1544,13 @@ fn check(comptime test_table: []const u8) !void {
|
|
|
1328
1544
|
.setup => |b| {
|
|
1329
1545
|
assert(operation == null);
|
|
1330
1546
|
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1547
|
+
const immut = context.state_machine.forest.grooves.accounts_immutable.get(b.account).?;
|
|
1548
|
+
var mut = context.state_machine.forest.grooves.accounts_mutable.get(immut.timestamp).?.*;
|
|
1549
|
+
mut.debits_pending = b.debits_pending;
|
|
1550
|
+
mut.debits_posted = b.debits_posted;
|
|
1551
|
+
mut.credits_pending = b.credits_pending;
|
|
1552
|
+
mut.credits_posted = b.credits_posted;
|
|
1553
|
+
context.state_machine.forest.grooves.accounts_mutable.put(&mut);
|
|
1337
1554
|
},
|
|
1338
1555
|
|
|
1339
1556
|
.account => |a| {
|
|
@@ -1875,6 +2092,7 @@ test "StateMachine: ref all decls" {
|
|
|
1875
2092
|
const Storage = @import("storage.zig").Storage;
|
|
1876
2093
|
const StateMachine = StateMachineType(Storage, .{
|
|
1877
2094
|
.message_body_size_max = 1000 * @sizeOf(Account),
|
|
2095
|
+
.lsm_batch_multiple = 1,
|
|
1878
2096
|
});
|
|
1879
2097
|
|
|
1880
2098
|
std.testing.refAllDecls(StateMachine);
|