From 9ed82b22a8c4e1d4c59e1891bef7ce84a83f6469 Mon Sep 17 00:00:00 2001 From: InKryption <59504965+InKryption@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:47:50 +0200 Subject: [PATCH] refactor(core,accountsdb,bincode,net): Fixes, improvements, renames + discuss (#315) * Refactor `NestedHashTree.getValue` * Use term 'zeroes' instead of 'default' in Pubkey * fuzz: Make TrackedAccount data fixed size It was always already just 32 bytes, there was no real reason for it to be dynamically allocated. * misc: * bincode: Improved names and functionality + fix * fix `bincode.free` for various types * renames & unifies `arraylist.defaultArrayList[Unmanaged]OnEOFConfig` to `arraylist.defaultOnEofConfig`. * renames `arraylist.arrayListFieldConfig` to `arraylist.standardConfig`. * renames `shortvec.ShortVecConfig` to `shortvec.sliceConfig`. * renames `shortvec.ShortVecArrayListConfig` to `shortvec.arrayListConfig`. * Constify data which doesn't need to be mutable * Fix leaks in error path * Use init constants instead of functions * Inline test data, improve std.testing usage * Further simplify `NestedHashTree` * Upper-case init decls * `Hash.default()` -> `Hash.ZEROES` * Upper-case `CompiledKeyMeta.ALL_FALSE` * Upper-case `SocketAddr.UNSPECIFIED` * `ClientVersion.default` -> `ClientVersion.CURRENT` * `Transaction.empty` -> `Transaction.EMPTY` * Remove test It doesn't test anything very useful * comptime-assert error branch as unreachable * Inline more test data & use more inference * remove `socket_addrs_unspecified` * `isAllZeroes` -> `isZeroed` --- src/accountsdb/accounts_file.zig | 2 +- src/accountsdb/db.zig | 10 +- src/accountsdb/fuzz.zig | 29 ++-- src/accountsdb/index.zig | 2 +- src/accountsdb/snapshots.zig | 13 +- src/accountsdb/swiss_map.zig | 4 +- src/bincode/arraylist.zig | 54 +++---- src/bincode/bincode.zig | 25 +-- src/bincode/hashmap.zig | 5 +- src/bincode/shortvec.zig | 12 +- src/common/merkle_tree.zig | 25 ++- src/core/account.zig | 6 +- src/core/hash.zig | 6 +- src/core/pubkey.zig | 40 ++--- src/core/shred.zig | 8 +- src/core/transaction.zig | 249 ++++++++++++++---------------- src/gossip/data.zig | 28 ++-- src/gossip/message.zig | 4 +- src/ledger/cleanup_service.zig | 20 ++- src/ledger/reader.zig | 2 +- src/ledger/tests.zig | 2 +- src/ledger/transaction_status.zig | 2 +- src/net/net.zig | 16 +- src/version/version.zig | 4 +- 24 files changed, 252 insertions(+), 316 deletions(-) diff --git a/src/accountsdb/accounts_file.zig b/src/accountsdb/accounts_file.zig index 603c4cf5a..59c349e37 100644 --- a/src/accountsdb/accounts_file.zig +++ b/src/accountsdb/accounts_file.zig @@ -154,7 +154,7 @@ pub const AccountInFile = struct { const valid_lamports = self.account_info.lamports != 0 or ( // ie, is default account self.data.len == 0 and - self.owner().isDefault() and + self.owner().isZeroed() and self.executable().* == false and self.rent_epoch().* == 0); if (!valid_lamports) { diff --git a/src/accountsdb/db.zig b/src/accountsdb/db.zig index da58d494b..6d37e31cd 100644 --- a/src/accountsdb/db.zig +++ b/src/accountsdb/db.zig @@ -1035,7 +1035,7 @@ pub const AccountsDB = struct { } } else { // hashes arent always stored correctly in snapshots - if (account_hash.order(&Hash.default()) == .eq) { + if (account_hash.order(&Hash.ZEROES) == .eq) { const account, var lock_guard = try self.getAccountFromRefWithReadLock(max_slot_ref); defer lock_guard.unlock(); @@ -2372,7 +2372,7 @@ pub const AccountsDB = struct { }); // TODO: this is a temporary value - const delta_hash = Hash.default(); + const delta_hash = Hash.ZEROES; const archive_file = blk: { const archive_file_name_bounded = sig.accounts_db.snapshots.FullSnapshotFileInfo.snapshotNameStr(.{ @@ -2550,7 +2550,7 @@ pub const AccountsDB = struct { }); // TODO: compute the correct value during account writes - const delta_hash = Hash.default(); + const delta_hash = Hash.ZEROES; const archive_file = blk: { const archive_file_name_bounded = sig.accounts_db.snapshots.IncrementalSnapshotFileInfo.snapshotNameStr(.{ @@ -2618,7 +2618,7 @@ pub const AccountsDB = struct { .slot = params.target_slot, .bank_hash_info = .{ .accounts_delta_hash = delta_hash, - .accounts_hash = Hash.default(), + .accounts_hash = Hash.ZEROES, .stats = bank_hash_stats, }, .rooted_slots = .{}, @@ -3258,7 +3258,7 @@ test "write and read an account" { .data = &data, .executable = false, .lamports = 100, - .owner = Pubkey.default(), + .owner = Pubkey.ZEROES, .rent_epoch = 0, }; diff --git a/src/accountsdb/fuzz.zig b/src/accountsdb/fuzz.zig index 63955755e..727b89ef9 100644 --- a/src/accountsdb/fuzz.zig +++ b/src/accountsdb/fuzz.zig @@ -13,25 +13,23 @@ const BankFields = sig.accounts_db.snapshots.BankFields; pub const TrackedAccount = struct { pubkey: Pubkey, slot: u64, - data: []u8, + data: [32]u8, - pub fn initRandom(random: std.rand.Random, slot: Slot, allocator: std.mem.Allocator) !TrackedAccount { + pub fn initRandom(random: std.rand.Random, slot: Slot) !TrackedAccount { + var data: [32]u8 = undefined; + random.bytes(&data); return .{ .pubkey = Pubkey.initRandom(random), .slot = slot, - .data = try allocator.alloc(u8, 32), + .data = data, }; } - pub fn deinit(self: *TrackedAccount, allocator: std.mem.Allocator) void { - allocator.free(self.data); - } - pub fn toAccount(self: *const TrackedAccount, allocator: std.mem.Allocator) !Account { return .{ .lamports = 19, - .data = try allocator.dupe(u8, self.data), - .owner = Pubkey.default(), + .data = try allocator.dupe(u8, &self.data), + .owner = Pubkey.ZEROES, .executable = false, .rent_epoch = 0, }; @@ -123,9 +121,6 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void { var tracked_accounts = std.AutoArrayHashMap(Pubkey, TrackedAccount).init(allocator); defer tracked_accounts.deinit(); - defer for (tracked_accounts.values()) |*value| { - value.deinit(allocator); - }; try tracked_accounts.ensureTotalCapacity(10_000); var random_bank_fields = try BankFields.initRandom(allocator, random, 1 << 8); @@ -158,7 +153,7 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void { for (&accounts, &pubkeys, 0..) |*account, *pubkey, i| { errdefer for (accounts[0..i]) |prev_account| prev_account.deinit(allocator); - var tracked_account = try TrackedAccount.initRandom(random, slot, allocator); + var tracked_account = try TrackedAccount.initRandom(random, slot); const existing_pubkey = random.boolean(); if (existing_pubkey and tracked_accounts.count() > 0) { @@ -170,12 +165,8 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void { account.* = try tracked_account.toAccount(allocator); pubkey.* = tracked_account.pubkey; - const r = try tracked_accounts.getOrPut(tracked_account.pubkey); - if (r.found_existing) { - r.value_ptr.deinit(allocator); - } // always overwrite the old slot - r.value_ptr.* = tracked_account; + try tracked_accounts.put(tracked_account.pubkey, tracked_account); } defer for (accounts) |account| account.deinit(allocator); @@ -198,7 +189,7 @@ pub fn run(seed: u64, args: *std.process.ArgIterator) !void { var account = try accounts_db.getAccount(&tracked_account.pubkey); defer account.deinit(allocator); - if (!std.mem.eql(u8, tracked_account.data, account.data)) { + if (!std.mem.eql(u8, &tracked_account.data, account.data)) { @panic("found accounts with different data"); } }, diff --git a/src/accountsdb/index.zig b/src/accountsdb/index.zig index baa0da43a..0912742fc 100644 --- a/src/accountsdb/index.zig +++ b/src/accountsdb/index.zig @@ -84,7 +84,7 @@ pub const AccountRef = struct { pub fn default() AccountRef { return AccountRef{ - .pubkey = Pubkey.default(), + .pubkey = Pubkey.ZEROES, .slot = 0, .location = .{ .UnrootedMap = .{ .index = 0 } }, }; diff --git a/src/accountsdb/snapshots.zig b/src/accountsdb/snapshots.zig index b40ad51bc..59c643e49 100644 --- a/src/accountsdb/snapshots.zig +++ b/src/accountsdb/snapshots.zig @@ -23,7 +23,6 @@ const SlotHistory = sig.accounts_db.sysvars.SlotHistory; const Logger = sig.trace.Logger; -const defaultArrayListUnmanagedOnEOFConfig = bincode.arraylist.defaultArrayListUnmanagedOnEOFConfig; const parallelUntarToFileSystem = sig.utils.tar.parallelUntarToFileSystem; const readDirectory = sig.utils.directory.readDirectory; @@ -675,9 +674,9 @@ pub const BankIncrementalSnapshotPersistence = struct { pub fn default() @This() { return .{ .full_slot = 0, - .full_hash = Hash.default(), + .full_hash = Hash.ZEROES, .full_capitalization = 0, - .incremental_hash = Hash.default(), + .incremental_hash = Hash.ZEROES, .incremental_capitalization = 0, }; } @@ -1066,8 +1065,8 @@ pub const AccountsDbFields = struct { pub const @"!bincode-config:file_map" = bincode.hashmap.hashMapFieldConfig(FileMap, .{ .value = bincode.list.valueEncodedAsSlice(AccountFileInfo, .{}), }); - pub const @"!bincode-config:rooted_slots" = defaultArrayListUnmanagedOnEOFConfig(Slot); - pub const @"!bincode-config:rooted_slot_hashes" = defaultArrayListUnmanagedOnEOFConfig(SlotAndHash); + pub const @"!bincode-config:rooted_slots" = bincode.arraylist.defaultOnEofConfig(std.ArrayListUnmanaged(Slot)); + pub const @"!bincode-config:rooted_slot_hashes" = bincode.arraylist.defaultOnEofConfig(std.ArrayListUnmanaged(SlotAndHash)); pub const FileMap = std.AutoArrayHashMap(Slot, AccountFileInfo); @@ -1599,7 +1598,7 @@ pub const FullSnapshotFileInfo = struct { test snapshotNameStr { try std.testing.expectEqualStrings( "snapshot-10-11111111111111111111111111111111.tar.zst", - snapshotNameStr(.{ .slot = 10, .hash = Hash.default() }).constSlice(), + snapshotNameStr(.{ .slot = 10, .hash = Hash.ZEROES }).constSlice(), ); } }; @@ -1669,7 +1668,7 @@ pub const IncrementalSnapshotFileInfo = struct { test snapshotNameStr { try std.testing.expectEqualStrings( "incremental-snapshot-10-25-11111111111111111111111111111111.tar.zst", - snapshotNameStr(.{ .base_slot = 10, .slot = 25, .hash = Hash.default() }).constSlice(), + snapshotNameStr(.{ .base_slot = 10, .slot = 25, .hash = Hash.ZEROES }).constSlice(), ); } }; diff --git a/src/accountsdb/swiss_map.zig b/src/accountsdb/swiss_map.zig index 139b36eaf..edf52728a 100644 --- a/src/accountsdb/swiss_map.zig +++ b/src/accountsdb/swiss_map.zig @@ -504,11 +504,11 @@ test "swissmap resize" { try map.ensureTotalCapacity(100); const ref = accounts_db.index.AccountRef.default(); - map.putAssumeCapacity(sig.core.Pubkey.default(), ref); + map.putAssumeCapacity(sig.core.Pubkey.ZEROES, ref); // this will resize the map with the key still in there try map.ensureTotalCapacity(200); - const get_ref = map.get(sig.core.Pubkey.default()) orelse return error.MissingAccount; + const get_ref = map.get(sig.core.Pubkey.ZEROES) orelse return error.MissingAccount; try std.testing.expect(std.meta.eql(get_ref, ref)); } diff --git a/src/bincode/arraylist.zig b/src/bincode/arraylist.zig index 99b264f56..3b4720e2f 100644 --- a/src/bincode/arraylist.zig +++ b/src/bincode/arraylist.zig @@ -9,8 +9,8 @@ const Params = bincode.Params; const readIntAsLength = bincode.readIntAsLength; /// The standard bincode serialization for an ArrayList -pub fn arrayListFieldConfig(comptime ArrayListType: type) bincode.FieldConfig(ArrayListType) { - const list_info = arrayListInfo(ArrayListType).?; +pub fn standardConfig(comptime List: type) bincode.FieldConfig(List) { + const list_info = arrayListInfo(List).?; const S = struct { fn serialize(writer: anytype, data: anytype, params: bincode.Params) anyerror!void { @@ -24,10 +24,10 @@ pub fn arrayListFieldConfig(comptime ArrayListType: type) bincode.FieldConfig(Ar allocator: std.mem.Allocator, reader: anytype, params: Params, - ) anyerror!ArrayListType { + ) anyerror!List { const len = (try readIntAsLength(usize, reader, params)) orelse return error.ArrayListTooBig; - var data: ArrayListType = try ArrayListType.initCapacity(allocator, len); + var data: List = try List.initCapacity(allocator, len); errdefer bincode.free(allocator, data); for (0..len) |_| { data.appendAssumeCapacity(try bincode.read(allocator, list_info.Elem, reader, params)); @@ -51,41 +51,37 @@ pub fn arrayListFieldConfig(comptime ArrayListType: type) bincode.FieldConfig(Ar }; } -pub fn defaultArrayListUnmanagedOnEOFConfig(comptime T: type) bincode.FieldConfig(std.ArrayListUnmanaged(T)) { +/// Defaults the field of type `List` to an empty state on EOF. +pub fn defaultOnEofConfig(comptime List: type) bincode.FieldConfig(List) { + const al_info = arrayListInfo(List) orelse @compileError("Expected std.ArrayList[Unmanaged]Aligned(T), got " ++ @typeName(List)); const S = struct { - fn deserialize(allocator: std.mem.Allocator, reader: anytype, params: bincode.Params) anyerror!std.ArrayListUnmanaged(T) { + fn deserialize(allocator: std.mem.Allocator, reader: anytype, params: bincode.Params) anyerror!List { const len = if (bincode.readIntAsLength(usize, reader, params)) |maybe_len| (maybe_len orelse return error.ArrayListTooBig) - else |err| { - if (err == error.EndOfStream) return .{}; - return err; + else |err| switch (err) { + error.EndOfStream, + => return switch (al_info.management) { + .managed => List.init(allocator), + .unmanaged => .{}, + }, + else => |e| return e, }; - const slice = try allocator.alloc(T, len); + const slice = try allocator.alignedAlloc(al_info.Elem, al_info.alignment, len); errdefer allocator.free(slice); - return std.ArrayListUnmanaged(T).fromOwnedSlice(slice); + return switch (al_info.management) { + .managed => List.fromOwnedSlice(allocator, slice), + .unmanaged => List.fromOwnedSlice(slice), + }; } fn free(allocator: std.mem.Allocator, data: anytype) void { - data.deinit(allocator); - } - }; - - return .{ - .deserializer = S.deserialize, - .free = S.free, - }; -} -pub fn defaultArrayListOnEOFConfig(comptime T: type) bincode.FieldConfig(std.ArrayList(T)) { - const S = struct { - fn deserialize(allocator: std.mem.Allocator, reader: anytype, params: bincode.Params) anyerror!std.ArrayList(T) { - var unmanaged = try defaultArrayListUnmanagedOnEOFConfig(T).deserializer.?(allocator, reader, params); - return unmanaged.toManaged(allocator); - } - - fn free(_: std.mem.Allocator, data: anytype) void { - data.deinit(); + var copy = data; + switch (al_info.management) { + .managed => copy.deinit(), + .unmanaged => copy.deinit(allocator), + } } }; diff --git a/src/bincode/bincode.zig b/src/bincode/bincode.zig index 445f4be91..74ff77610 100644 --- a/src/bincode/bincode.zig +++ b/src/bincode/bincode.zig @@ -547,20 +547,8 @@ pub fn free(allocator: std.mem.Allocator, value: anytype) void { } } else inline for (info.fields) |field| { if (getFieldConfig(T, field)) |field_config| { - if (field_config.free) |free_fcn| { - var field_value = @field(value, field.name); - switch (@typeInfo(field.type)) { - .Pointer => |*field_info| { - // TODO: Why do we do only slice? - if (field_info.size == .Slice) { - free_fcn(allocator, field_value); - } - }, - else => { - free_fcn(allocator, &field_value); - }, - } - + if (field_config.free) |freeFn| { + freeFn(allocator, @field(value, field.name)); continue; } } @@ -631,7 +619,7 @@ pub fn getConfig(comptime T: type) ?FieldConfig(T) { return if (comptime hashMapInfo(T) != null) hashmap.hashMapFieldConfig(T, .{}) else if (comptime arrayListInfo(T) != null) - arraylist.arrayListFieldConfig(T) + arraylist.standardConfig(T) else null; } @@ -661,8 +649,8 @@ pub fn getSerializedSizeWithSlice(slice: []u8, data: anytype, params: Params) !u return ser_slice.len; } -pub fn writeToArray(alloc: std.mem.Allocator, data: anytype, params: Params) !std.ArrayList(u8) { - var array_buf = try std.ArrayList(u8).initCapacity(alloc, 2048); +pub fn writeToArray(allocator: std.mem.Allocator, data: anytype, params: Params) !std.ArrayList(u8) { + var array_buf = try std.ArrayList(u8).initCapacity(allocator, 2048); try bincode.write(array_buf.writer(), data, params); return array_buf; @@ -741,11 +729,10 @@ test "bincode: custom enum" { } test "bincode: default on eof" { - const defaultArrayListOnEOFConfig = @import("../sig.zig").bincode.arraylist.defaultArrayListOnEOFConfig; const Foo = struct { value: u8 = 0, accounts: std.ArrayList(u64), - pub const @"!bincode-config:accounts" = defaultArrayListOnEOFConfig(u64); + pub const @"!bincode-config:accounts" = arraylist.defaultOnEofConfig(std.ArrayList(u64)); pub const @"!bincode-config:value" = int.defaultOnEof(u8, 0); }; diff --git a/src/bincode/hashmap.zig b/src/bincode/hashmap.zig index 5a49e93ba..2e2c93062 100644 --- a/src/bincode/hashmap.zig +++ b/src/bincode/hashmap.zig @@ -73,10 +73,11 @@ pub fn hashMapFieldConfig( } fn free(allocator: std.mem.Allocator, data: anytype) void { + var copy = data; if (hm_info.management == .managed) { - data.deinit(); + copy.deinit(); } else { - data.deinit(allocator); + copy.deinit(allocator); } } }; diff --git a/src/bincode/shortvec.zig b/src/bincode/shortvec.zig index cfc6227fc..26b03b584 100644 --- a/src/bincode/shortvec.zig +++ b/src/bincode/shortvec.zig @@ -6,7 +6,8 @@ const bincode = sig.bincode; const serialize_short_u16 = sig.bincode.varint.serialize_short_u16; const deserialize_short_u16 = sig.bincode.varint.deserialize_short_u16; -pub fn ShortVecConfig(comptime Child: type) bincode.FieldConfig([]Child) { +pub fn sliceConfig(comptime Slice: type) bincode.FieldConfig(Slice) { + const Child = std.meta.Elem(Slice); const S = struct { pub fn serialize(writer: anytype, data: anytype, params: bincode.Params) !void { const len: u16 = std.math.cast(u16, data.len) orelse return error.DataTooLarge; @@ -16,7 +17,7 @@ pub fn ShortVecConfig(comptime Child: type) bincode.FieldConfig([]Child) { } } - pub fn deserialize(allocator: std.mem.Allocator, reader: anytype, params: bincode.Params) ![]Child { + pub fn deserialize(allocator: std.mem.Allocator, reader: anytype, params: bincode.Params) !Slice { const len = try deserialize_short_u16(reader, params); const elems = try allocator.alloc(Child, len); errdefer allocator.free(elems); @@ -28,18 +29,19 @@ pub fn ShortVecConfig(comptime Child: type) bincode.FieldConfig([]Child) { } pub fn free(allocator: std.mem.Allocator, data: anytype) void { + for (data) |elem| bincode.free(allocator, elem); allocator.free(data); } }; - return bincode.FieldConfig([]Child){ + return .{ .serializer = S.serialize, .deserializer = S.deserialize, .free = S.free, }; } -pub fn ShortVecArrayListConfig(comptime Child: type) bincode.FieldConfig(std.ArrayList(Child)) { +pub fn arrayListConfig(comptime Child: type) bincode.FieldConfig(std.ArrayList(Child)) { const S = struct { pub fn serialize(writer: anytype, data: anytype, params: bincode.Params) !void { const list: std.ArrayList(Child) = data; @@ -66,7 +68,7 @@ pub fn ShortVecArrayListConfig(comptime Child: type) bincode.FieldConfig(std.Arr } }; - return bincode.FieldConfig(std.ArrayList(Child)){ + return .{ .serializer = S.serialize, .deserializer = S.deserialize, .free = S.free, diff --git a/src/common/merkle_tree.zig b/src/common/merkle_tree.zig index 17983e3ae..4c63cf3f2 100644 --- a/src/common/merkle_tree.zig +++ b/src/common/merkle_tree.zig @@ -31,24 +31,21 @@ pub fn merkleTreeHash(hashes: []Hash, fanout: usize) !*Hash { pub const NestedHashTree = struct { hashes: []std.ArrayListUnmanaged(Hash), - pub fn getValue(self: *NestedHashTree, index: usize) !*Hash { + pub fn getValue(self: *const NestedHashTree, index: usize) *Hash { + std.debug.assert(index < self.len()); var search_index: usize = 0; - var i: usize = 0; - while (i < self.hashes.len) { - const nested_len = self.hashes[i].items.len; - if (search_index + nested_len > index) { + for (self.hashes) |hash_list| { + if (search_index + hash_list.items.len > index) { const index_in_nested = index - search_index; - return &self.hashes[i].items[index_in_nested]; + return &hash_list.items[index_in_nested]; } else { - search_index += nested_len; - i += 1; + search_index += hash_list.items.len; } } - - return error.InvalidIndex; + unreachable; } - pub fn len(self: *NestedHashTree) usize { + pub fn len(self: *const NestedHashTree) usize { var length: usize = 0; for (self.hashes) |*hashes| { length += hashes.items.len; @@ -70,16 +67,16 @@ pub const NestedHashTree = struct { var hasher = Sha256.init(.{}); for (start..end) |j| { - const h = self.getValue(j) catch unreachable; + const h = self.getValue(j); hasher.update(&h.data); } const hash = hasher.finalResult(); - (self.getValue(index) catch unreachable).data = hash; + self.getValue(index).data = hash; index += 1; } length = index; if (length == 1) { - return self.getValue(0) catch unreachable; + return self.getValue(0); } } } diff --git a/src/core/account.zig b/src/core/account.zig index e2532a16e..92c31fb42 100644 --- a/src/core/account.zig +++ b/src/core/account.zig @@ -160,14 +160,14 @@ pub fn hashAccount( test "core.account: test account hash matches rust" { var data: [3]u8 = .{ 1, 2, 3 }; - var account = Account{ + var account: Account = .{ .lamports = 10, .data = &data, - .owner = Pubkey.default(), + .owner = Pubkey.ZEROES, .executable = false, .rent_epoch = 20, }; - const pubkey = Pubkey.default(); + const pubkey = Pubkey.ZEROES; const hash = hashAccount( account.lamports, diff --git a/src/core/hash.zig b/src/core/hash.zig index b481c9007..c70105e20 100644 --- a/src/core/hash.zig +++ b/src/core/hash.zig @@ -9,6 +9,8 @@ pub const Hash = extern struct { pub const size = 32; + pub const ZEROES: Hash = .{ .data = .{0} ** size }; + const base58 = sig.crypto.base58.Base58Sized(size); pub fn fromSizedSlice(data: *const [size]u8) Hash { @@ -17,10 +19,6 @@ pub const Hash = extern struct { return hash; } - pub fn default() Hash { - return .{ .data = .{0} ** size }; - } - pub fn generateSha256Hash(bytes: []const u8) Hash { var data: [size]u8 = undefined; Sha256.hash(bytes, &data, .{}); diff --git a/src/core/pubkey.zig b/src/core/pubkey.zig index adebd8210..51717eb81 100644 --- a/src/core/pubkey.zig +++ b/src/core/pubkey.zig @@ -1,29 +1,21 @@ const std = @import("std"); const sig = @import("../sig.zig"); -const Ed25519 = std.crypto.sign.Ed25519; -const U8ArrayConfig = sig.bincode.int.U8ArrayConfig; pub const Pubkey = extern struct { data: [size]u8, + const Self = @This(); pub const size = 32; - pub const @"!bincode-config:data" = U8ArrayConfig(size); + pub const @"!bincode-config:data" = sig.bincode.int.U8ArrayConfig(size); + + pub const ZEROES: Pubkey = .{ .data = .{0} ** size }; - const Self = @This(); const base58 = sig.crypto.base58.Base58Sized(size); pub fn fromString(str: []const u8) !Self { return .{ .data = try base58.decode(str) }; } - /// ***fromBytes*** will automatically base58 decode the value. It will also cache the decoded string - /// for future calls to string() method. - /// - /// Options: - /// - `skip_encoding`: If (in the unlikely scenario) you will never call the string() method, you can - /// set this option to true and it will not decode & cache the encoded value. This can be helpful in - /// scenarios where you plan to only use the bytes and want to save on expensive base58 encoding. - /// pub fn fromBytes(bytes: []const u8) !Self { if (bytes.len != size) { return Error.InvalidBytesLength; @@ -31,30 +23,28 @@ pub const Pubkey = extern struct { return .{ .data = bytes[0..size].* }; } - pub fn string(self: Self) base58.String { - return base58.encode(self.data); + pub fn fromPublicKey(public_key: *const std.crypto.sign.Ed25519.PublicKey) Self { + return fromBytes(&public_key.bytes) catch unreachable; } - /// ***initRandom*** generates a random pubkey. Optionally set `skip_encoding` to skip expensive base58 encoding. pub fn initRandom(random: std.Random) Self { var bytes: [size]u8 = undefined; random.bytes(&bytes); return .{ .data = bytes }; } - pub fn default() Self { - return .{ .data = [_]u8{0} ** size }; - } - pub fn equals(self: *const Self, other: *const Pubkey) bool { const xx: @Vector(size, u8) = self.data; const yy: @Vector(size, u8) = other.data; - const r = @reduce(.And, xx == yy); - return r; + return @reduce(.And, xx == yy); } - pub fn fromPublicKey(public_key: *const Ed25519.PublicKey) Self { - return Self.fromBytes(&public_key.bytes) catch unreachable; + pub fn isZeroed(self: *const Self) bool { + return self.equals(&ZEROES); + } + + pub fn string(self: Self) base58.String { + return base58.encode(self.data); } pub fn format( @@ -65,10 +55,6 @@ pub const Pubkey = extern struct { ) !void { return base58.format(self.data, writer); } - - pub fn isDefault(self: *const Self) bool { - return std.mem.eql(u8, &self.data, &[_]u8{0} ** size); - } }; const Error = error{ InvalidBytesLength, InvalidEncodedLength, InvalidEncodedValue }; diff --git a/src/core/shred.zig b/src/core/shred.zig index ac5577bb5..daf642838 100644 --- a/src/core/shred.zig +++ b/src/core/shred.zig @@ -50,24 +50,24 @@ test "core.shred: test ShredVersion" { const logger = test_logger.logger(); - const shred_version_one = ShredVersion.computeShredVersion(Hash.default(), null); + const shred_version_one = ShredVersion.computeShredVersion(Hash.ZEROES, null); try std.testing.expect(shred_version_one == 1); logger.debug().logf("shred_version_one: {}", .{shred_version_one}); var hard_forks = HardForks.default(testing_alloc); defer _ = hard_forks.deinit(); - const shred_version_two = ShredVersion.computeShredVersion(Hash.default(), hard_forks); + const shred_version_two = ShredVersion.computeShredVersion(Hash.ZEROES, hard_forks); try std.testing.expect(shred_version_two == 1); logger.debug().logf("shred_version_two: {}", .{shred_version_two}); try hard_forks.register(1); - const shred_version_three = ShredVersion.computeShredVersion(Hash.default(), hard_forks); + const shred_version_three = ShredVersion.computeShredVersion(Hash.ZEROES, hard_forks); try std.testing.expect(shred_version_three == 55551); logger.debug().logf("shred_version_three: {}", .{shred_version_three}); try hard_forks.register(1); - const shred_version_four = ShredVersion.computeShredVersion(Hash.default(), hard_forks); + const shred_version_four = ShredVersion.computeShredVersion(Hash.ZEROES, hard_forks); try std.testing.expect(shred_version_four == 46353); logger.debug().logf("shred_version_three: {}", .{shred_version_four}); } diff --git a/src/core/transaction.zig b/src/core/transaction.zig index 1d93adb2f..c2384c398 100644 --- a/src/core/transaction.zig +++ b/src/core/transaction.zig @@ -9,13 +9,13 @@ const Signature = sig.core.Signature; const indexOf = sig.utils.slice.indexOf; const peekableReader = sig.utils.io.peekableReader; -const ShortVecConfig = sig.bincode.shortvec.ShortVecConfig; +const shortVecConfig = sig.bincode.shortvec.sliceConfig; pub const VersionedTransaction = struct { - signatures: []Signature, + signatures: []const Signature, message: VersionedMessage, - pub const @"!bincode-config:signatures" = ShortVecConfig(Signature); + pub const @"!bincode-config:signatures" = shortVecConfig([]const Signature); pub fn deinit(self: VersionedTransaction, allocator: std.mem.Allocator) void { allocator.free(self.signatures); @@ -100,7 +100,7 @@ pub const V0Message = struct { header: MessageHeader, /// List of accounts loaded by this transaction. - account_keys: []Pubkey, + account_keys: []const Pubkey, /// The blockhash of a recent block. recent_blockhash: Hash, @@ -118,15 +118,15 @@ pub const V0Message = struct { /// 1) message `account_keys` /// 2) ordered list of keys loaded from `writable` lookup table indexes /// 3) ordered list of keys loaded from `readable` lookup table indexes - instructions: []CompiledInstruction, + instructions: []const CompiledInstruction, /// List of address table lookups used to load additional accounts /// for this transaction. - address_table_lookups: []MessageAddressTableLookup, + address_table_lookups: []const MessageAddressTableLookup, - pub const @"!bincode-config:account_keys" = ShortVecConfig(Pubkey); - pub const @"!bincode-config:instructions" = ShortVecConfig(CompiledInstruction); - pub const @"!bincode-config:address_table_lookups" = ShortVecConfig(MessageAddressTableLookup); + pub const @"!bincode-config:account_keys" = shortVecConfig([]const Pubkey); + pub const @"!bincode-config:instructions" = shortVecConfig([]const CompiledInstruction); + pub const @"!bincode-config:address_table_lookups" = shortVecConfig([]const MessageAddressTableLookup); pub fn deinit(self: V0Message, allocator: std.mem.Allocator) void { inline for (.{ self.instructions, self.address_table_lookups }) |slice| { @@ -156,12 +156,12 @@ pub const MessageAddressTableLookup = struct { /// Address lookup table account key account_key: Pubkey, /// List of indexes used to load writable account addresses - writable_indexes: []u8, + writable_indexes: []const u8, /// List of indexes used to load readonly account addresses - readonly_indexes: []u8, + readonly_indexes: []const u8, - pub const @"!bincode-config:writable_indexes" = ShortVecConfig(u8); - pub const @"!bincode-config:readonly_indexes" = ShortVecConfig(u8); + pub const @"!bincode-config:writable_indexes" = shortVecConfig([]const u8); + pub const @"!bincode-config:readonly_indexes" = shortVecConfig([]const u8); pub fn deinit(self: MessageAddressTableLookup, allocator: std.mem.Allocator) void { allocator.free(self.writable_indexes); @@ -170,19 +170,17 @@ pub const MessageAddressTableLookup = struct { }; pub const Transaction = struct { - signatures: []Signature, + signatures: []const Signature, message: Message, - pub const @"!bincode-config:signatures" = ShortVecConfig(Signature); + pub const @"!bincode-config:signatures" = shortVecConfig([]const Signature); pub const MAX_BYTES: usize = 1232; - pub fn default() Transaction { - return Transaction{ - .signatures = &[_]Signature{}, - .message = Message.default(), - }; - } + pub const EMPTY: Transaction = .{ + .signatures = &.{}, + .message = Message.EMPTY, + }; pub fn newUnsigned(allocator: std.mem.Allocator, message: Message) error{OutOfMemory}!Transaction { return Transaction{ @@ -220,25 +218,26 @@ pub const Transaction = struct { pub const Message = struct { header: MessageHeader, - account_keys: []Pubkey, + account_keys: []const Pubkey, recent_blockhash: Hash, - instructions: []CompiledInstruction, + instructions: []const CompiledInstruction, - pub const @"!bincode-config:account_keys" = ShortVecConfig(Pubkey); - pub const @"!bincode-config:instructions" = ShortVecConfig(CompiledInstruction); + pub const @"!bincode-config:account_keys" = shortVecConfig([]const Pubkey); + pub const @"!bincode-config:instructions" = shortVecConfig([]const CompiledInstruction); - pub fn default() Message { - return Message{ - .header = MessageHeader{ - .num_required_signatures = 0, - .num_readonly_signed_accounts = 0, - .num_readonly_unsigned_accounts = 0, - }, - .account_keys = &[_]Pubkey{}, - .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &[_]CompiledInstruction{}, - }; - } + pub const EMPTY: Message = .{ + .header = .{ + .num_required_signatures = 0, + .num_readonly_signed_accounts = 0, + .num_readonly_unsigned_accounts = 0, + }, + .account_keys = &.{}, + .recent_blockhash = blk: { + @setEvalBranchQuota(1962); + break :blk Hash.generateSha256Hash(&.{0}); + }, + .instructions = &.{}, + }; pub fn init(allocator: std.mem.Allocator, instructions: []const Instruction, payer: Pubkey, recent_blockhash: Hash) !Message { var compiled_keys = try CompiledKeys.init(allocator, instructions, payer); @@ -254,11 +253,21 @@ pub const Message = struct { } pub fn clone(self: *const Message, allocator: std.mem.Allocator) error{OutOfMemory}!Message { + const account_keys = try allocator.dupe(Pubkey, self.account_keys); + errdefer allocator.free(account_keys); + const instructions = try allocator.alloc(CompiledInstruction, self.instructions.len); - for (instructions, 0..) |*ci, i| ci.* = try self.instructions[i].clone(allocator); + errdefer allocator.free(instructions); + + for (instructions, self.instructions, 0..) |*ci, original_ci, i| { + errdefer for (instructions[0..i]) |prev_ci| prev_ci.deinit(allocator); + ci.* = try original_ci.clone(allocator); + } + errdefer comptime unreachable; // otherwise we have to remember to free each instruction + return .{ .header = self.header, - .account_keys = try allocator.dupe(Pubkey, self.account_keys), + .account_keys = account_keys, .recent_blockhash = self.recent_blockhash, .instructions = instructions, }; @@ -344,12 +353,12 @@ pub const CompiledInstruction = struct { /// Index into the transaction keys array indicating the program account that executes this instruction. program_id_index: u8, /// Ordered indices into the transaction keys array indicating which accounts to pass to the program. - accounts: []u8, + accounts: []const u8, /// The program input data. - data: []u8, + data: []const u8, - pub const @"!bincode-config:accounts" = ShortVecConfig(u8); - pub const @"!bincode-config:data" = ShortVecConfig(u8); + pub const @"!bincode-config:accounts" = shortVecConfig([]const u8); + pub const @"!bincode-config:data" = shortVecConfig([]const u8); pub fn clone(self: *const CompiledInstruction, allocator: std.mem.Allocator) error{OutOfMemory}!CompiledInstruction { return .{ @@ -396,14 +405,14 @@ pub const CompiledKeys = struct { for (instructions) |instruction| { const instruction_meta_gopr = try key_meta_map.getOrPut(instruction.program_id); if (!instruction_meta_gopr.found_existing) { - instruction_meta_gopr.value_ptr.* = CompiledKeyMeta.default(); + instruction_meta_gopr.value_ptr.* = CompiledKeyMeta.ALL_FALSE; } instruction_meta_gopr.value_ptr.*.is_invoked = true; for (instruction.accounts) |account_meta| { const account_meta_gopr = try key_meta_map.getOrPut(account_meta.pubkey); if (!account_meta_gopr.found_existing) { - account_meta_gopr.value_ptr.* = CompiledKeyMeta.default(); + account_meta_gopr.value_ptr.* = CompiledKeyMeta.ALL_FALSE; } account_meta_gopr.value_ptr.*.is_signer = account_meta_gopr.value_ptr.*.is_signer or account_meta.is_signer; account_meta_gopr.value_ptr.*.is_writable = account_meta_gopr.value_ptr.*.is_writable or account_meta.is_writable; @@ -412,7 +421,7 @@ pub const CompiledKeys = struct { if (maybe_payer) |payer| { const payer_meta_gopr = try key_meta_map.getOrPut(payer); if (!payer_meta_gopr.found_existing) { - payer_meta_gopr.value_ptr.* = CompiledKeyMeta.default(); + payer_meta_gopr.value_ptr.* = CompiledKeyMeta.ALL_FALSE; } payer_meta_gopr.value_ptr.*.is_signer = true; payer_meta_gopr.value_ptr.*.is_writable = true; @@ -480,13 +489,11 @@ pub const CompiledKeyMeta = packed struct { is_writable: bool, is_invoked: bool, - pub fn default() CompiledKeyMeta { - return .{ - .is_signer = false, - .is_writable = false, - .is_invoked = false, - }; - } + pub const ALL_FALSE: CompiledKeyMeta = .{ + .is_signer = false, + .is_writable = false, + .is_invoked = false, + }; }; pub const CompileError = error{ @@ -575,134 +582,111 @@ test "create transfer transaction" { try std.testing.expectEqualSlices(u8, &expected_bytes, actual_bytes); } -test "tmp" { - const msg = Message.default(); - try std.testing.expect(msg.account_keys.len == 0); -} - test "blank Message fails to sanitize" { - try std.testing.expect(error.MissingWritableFeePayer == Message.default().sanitize()); + try std.testing.expectError(error.MissingWritableFeePayer, Message.EMPTY.sanitize()); } test "minimal valid Message sanitizes" { - var pubkeys = [_]Pubkey{Pubkey.default()}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectEqual({}, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 0, }, - .account_keys = &pubkeys, - .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &[_]CompiledInstruction{}, - }; - try message.sanitize(); + .account_keys = &.{Pubkey.ZEROES}, + .recent_blockhash = Hash.generateSha256Hash(&.{0}), + .instructions = &.{}, + })); } test "Message sanitize fails if missing signers" { - var pubkeys = [_]Pubkey{Pubkey.default()}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.NotEnoughAccounts, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 2, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 0, }, - .account_keys = &pubkeys, - .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &[_]CompiledInstruction{}, - }; - try std.testing.expect(error.NotEnoughAccounts == message.sanitize()); + .account_keys = &.{Pubkey.ZEROES}, + .recent_blockhash = Hash.generateSha256Hash(&.{0}), + .instructions = &.{}, + })); } test "Message sanitize fails if missing unsigned" { - var pubkeys = [_]Pubkey{Pubkey.default()}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.NotEnoughAccounts, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 1, }, - .account_keys = &pubkeys, - .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &[_]CompiledInstruction{}, - }; - try std.testing.expect(error.NotEnoughAccounts == message.sanitize()); + .account_keys = &.{Pubkey.ZEROES}, + .recent_blockhash = Hash.generateSha256Hash(&.{0}), + .instructions = &.{}, + })); } test "Message sanitize fails if no writable signed" { - var pubkeys = [_]Pubkey{ Pubkey.default(), Pubkey.default() }; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.MissingWritableFeePayer, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 1, .num_readonly_unsigned_accounts = 0, }, - .account_keys = &pubkeys, + .account_keys = &.{ Pubkey.ZEROES, Pubkey.ZEROES }, .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &[_]CompiledInstruction{}, - }; - try std.testing.expect(error.MissingWritableFeePayer == message.sanitize()); + .instructions = &.{}, + })); } test "Message sanitize fails if missing program id" { - var pubkeys = [_]Pubkey{Pubkey.default()}; - var instructions = [_]CompiledInstruction{.{ - .program_id_index = 1, - .accounts = &[_]u8{}, - .data = &[_]u8{}, - }}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.ProgramIdAccountMissing, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 0, }, - .account_keys = &pubkeys, + .account_keys = &.{Pubkey.ZEROES}, .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &instructions, - }; - try std.testing.expect(error.ProgramIdAccountMissing == message.sanitize()); + .instructions = &.{.{ + .program_id_index = 1, + .accounts = &.{}, + .data = &.{}, + }}, + })); } test "Message sanitize fails if program id has index 0" { - var pubkeys = [_]Pubkey{Pubkey.default()}; - var instructions = [_]CompiledInstruction{.{ - .program_id_index = 0, - .accounts = &[_]u8{}, - .data = &[_]u8{}, - }}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.ProgramIdCannotBePayer, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 0, }, - .account_keys = &pubkeys, + .account_keys = &.{Pubkey.ZEROES}, .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &instructions, - }; - try std.testing.expect(error.ProgramIdCannotBePayer == message.sanitize()); + .instructions = &.{.{ + .program_id_index = 0, + .accounts = &.{}, + .data = &.{}, + }}, + })); } test "Message sanitize fails if account index is out of bounds" { - var pubkeys = [_]Pubkey{ Pubkey.default(), Pubkey.default() }; - var accounts = [_]u8{2}; - var instructions = [_]CompiledInstruction{.{ - .program_id_index = 1, - .accounts = &accounts, - .data = &[_]u8{}, - }}; - const message = Message{ - .header = MessageHeader{ + try std.testing.expectError(error.AccountIndexOutOfBounds, Message.sanitize(&.{ + .header = .{ .num_required_signatures = 1, .num_readonly_signed_accounts = 0, .num_readonly_unsigned_accounts = 1, }, - .account_keys = &pubkeys, + .account_keys = &.{ Pubkey.ZEROES, Pubkey.ZEROES }, .recent_blockhash = Hash.generateSha256Hash(&[_]u8{0}), - .instructions = &instructions, - }; - try std.testing.expect(error.AccountIndexOutOfBounds == message.sanitize()); + .instructions = &.{.{ + .program_id_index = 1, + .accounts = &.{2}, + .data = &.{}, + }}, + })); } test "V0Message serialization and deserialization" { @@ -725,7 +709,7 @@ test "VersionedMessage v0 serialization and deserialization" { pub const test_v0_transaction = struct { pub fn asStruct(allocator: std.mem.Allocator) !VersionedTransaction { - return VersionedTransaction{ + return .{ .signatures = try allocator.dupe(Signature, &.{ try Signature.fromString("2cxn1LdtB7GcpeLEnHe5eA7LymTXKkqGF6UvmBM2EtttZEeqBREDaAD7LCagDFHyuc3xXxyDkMPiy3CpK5m6Uskw"), try Signature.fromString("4gr9L7K3bALKjPRiRSk4JDB3jYmNaauf6rewNV3XFubX5EHxBn98gqBGhbwmZAB9DJ2pv8GWE1sLoYqhhLbTZcLj"), @@ -777,8 +761,8 @@ pub const test_v0_versioned_message = struct { pub const test_v0_message = struct { pub fn asStruct(allocator: std.mem.Allocator) !V0Message { - return V0Message{ - .header = MessageHeader{ + return .{ + .header = .{ .num_required_signatures = 39, .num_readonly_signed_accounts = 12, .num_readonly_unsigned_accounts = 102, @@ -787,8 +771,7 @@ pub const test_v0_message = struct { try Pubkey.fromString("GubTBrbgk9JwkwX1FkXvsrF1UC2AP7iTgg8SGtgH14QE"), try Pubkey.fromString("5yCD7QeAk5uAduhLZGxePv21RLsVEktPqJG5pbmZx4J4"), }), - .recent_blockhash = try Hash - .parseBase58String("4xzjBNLkRqhBVmZ7JKcX2UEP8wzYKYWpXk7CPXzgrEZW"), + .recent_blockhash = try Hash.parseBase58String("4xzjBNLkRqhBVmZ7JKcX2UEP8wzYKYWpXk7CPXzgrEZW"), .instructions = try allocator.dupe(CompiledInstruction, &.{.{ .program_id_index = 100, .accounts = try allocator.dupe(u8, &.{ 1, 3 }), @@ -800,7 +783,7 @@ pub const test_v0_message = struct { .address_table_lookups = try allocator.dupe(MessageAddressTableLookup, &.{.{ .account_key = try Pubkey.fromString("ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD"), .writable_indexes = try allocator.dupe(u8, &.{ 1, 3, 5, 7, 90 }), - .readonly_indexes = try allocator.dupe(u8, &.{}), + .readonly_indexes = &.{}, }}), }; } diff --git a/src/gossip/data.zig b/src/gossip/data.zig index 8670de2cb..6f8a7adb9 100644 --- a/src/gossip/data.zig +++ b/src/gossip/data.zig @@ -21,7 +21,6 @@ const DynamicArrayBitSet = sig.bloom.bit_set.DynamicArrayBitSet; const getWallclockMs = sig.time.getWallclockMs; const BitVecConfig = sig.bloom.bit_vec.BitVecConfig; -const ShortVecArrayListConfig = sig.bincode.shortvec.ShortVecArrayListConfig; const sanitizeWallclock = sig.gossip.message.sanitizeWallclock; const PACKET_DATA_SIZE = sig.net.packet.PACKET_DATA_SIZE; @@ -631,7 +630,7 @@ pub const Vote = struct { pub fn initRandom(random: std.rand.Random) Vote { return Vote{ .from = Pubkey.initRandom(random), - .transaction = Transaction.default(), + .transaction = Transaction.EMPTY, .wallclock = getWallclockMs(), .slot = random.int(u64), }; @@ -1194,14 +1193,14 @@ pub const ContactInfo = struct { addrs: ArrayList(IpAddr), sockets: ArrayList(SocketEntry), extensions: ArrayList(Extension), - cache: [SOCKET_CACHE_SIZE]SocketAddr = socket_addrs_unspecified(), + cache: [SOCKET_CACHE_SIZE]SocketAddr = .{SocketAddr.UNSPECIFIED} ** SOCKET_CACHE_SIZE, // TODO: improve implementation of post deserialise method pub const @"!bincode-config:post-deserialize" = bincode.FieldConfig(ContactInfo){ .post_deserialize_fn = ContactInfo.buildCache }; pub const @"!bincode-config:cache" = bincode.FieldConfig([SOCKET_CACHE_SIZE]SocketAddr){ .skip = true }; - pub const @"!bincode-config:addrs" = ShortVecArrayListConfig(IpAddr); - pub const @"!bincode-config:sockets" = ShortVecArrayListConfig(SocketEntry); - pub const @"!bincode-config:extensions" = ShortVecArrayListConfig(Extension); + pub const @"!bincode-config:addrs" = bincode.shortvec.arrayListConfig(IpAddr); + pub const @"!bincode-config:sockets" = bincode.shortvec.arrayListConfig(SocketEntry); + pub const @"!bincode-config:extensions" = bincode.shortvec.arrayListConfig(Extension); pub const @"!bincode-config:wallclock" = var_int_config_u64; const Self = @This(); @@ -1248,11 +1247,10 @@ pub const ContactInfo = struct { .wallclock = wallclock, .outset = outset, .shred_version = shred_version, - .version = ClientVersion.default(), + .version = ClientVersion.CURRENT, .addrs = ArrayList(IpAddr).init(allocator), .sockets = ArrayList(SocketEntry).init(allocator), .extensions = ArrayList(void).init(allocator), - .cache = socket_addrs_unspecified(), }; } @@ -1341,7 +1339,7 @@ pub const ContactInfo = struct { next_entry.offset += removed_entry.offset; } self.removeAddrIfUnused(removed_entry.index); - self.cache[@intFromEnum(key)] = SocketAddr.unspecified(); + self.cache[@intFromEnum(key)] = SocketAddr.UNSPECIFIED; } } @@ -1479,10 +1477,6 @@ pub const SocketEntry = struct { } }; -fn socket_addrs_unspecified() [SOCKET_CACHE_SIZE]SocketAddr { - return .{SocketAddr.unspecified()} ** SOCKET_CACHE_SIZE; -} - pub const RestartHeaviestFork = struct { from: Pubkey, wallclock: u64, @@ -1863,7 +1857,7 @@ test "RestartHeaviestFork serialization matches rust" { .last_slot = 12, .observed_stake = 11, .shred_version = 20, - .last_slot_hash = Hash.default(), + .last_slot_hash = Hash.ZEROES, }; var buf = [_]u8{0} ** 1024; @@ -1887,7 +1881,7 @@ test "RestartLastVotedForkSlots serialization matches rust" { .from = try Pubkey.fromString("6ZsiX6YcwEa93yWtVwGRiK8Ceoxq2VieVh2pvEiUtpCW"), .wallclock = 0, .last_voted_slot = 0, - .last_voted_hash = Hash.default(), + .last_voted_hash = Hash.ZEROES, .shred_version = 0, .offsets = offsets, }; @@ -2030,7 +2024,7 @@ test "sanitize invalid SnapshotHashes full slot has error" { test "sanitize invalid SnapshotHashes incremental slot has error" { var prng = std.rand.DefaultPrng.init(524145234); const random = prng.random(); - var incremental: [1]SlotAndHash = .{.{ .slot = 1_000_000_000_487_283, .hash = Hash.default() }}; + var incremental: [1]SlotAndHash = .{.{ .slot = 1_000_000_000_487_283, .hash = Hash.ZEROES }}; var instance = SnapshotHashes.initRandom(random); instance.incremental = &incremental; const data = GossipData{ .SnapshotHashes = instance }; @@ -2040,7 +2034,7 @@ test "sanitize invalid SnapshotHashes incremental slot has error" { test "sanitize SnapshotHashes full > incremental has error" { var prng = std.rand.DefaultPrng.init(524145234); const random = prng.random(); - var incremental: [1]SlotAndHash = .{.{ .slot = 1, .hash = Hash.default() }}; + var incremental: [1]SlotAndHash = .{.{ .slot = 1, .hash = Hash.ZEROES }}; var instance = SnapshotHashes.initRandom(random); instance.full.slot = 2; instance.incremental = &incremental; diff --git a/src/gossip/message.zig b/src/gossip/message.zig index 07c498edd..2acbd89bc 100644 --- a/src/gossip/message.zig +++ b/src/gossip/message.zig @@ -266,7 +266,7 @@ test "gossip.message: pull request serializes and deserializes" { // pull requests only use ContactInfo data const gossip_addr = SocketAddr.initIpv4(.{ 127, 0, 0, 1 }, 1234); - const unspecified_addr = SocketAddr.unspecified(); + const unspecified_addr = SocketAddr.UNSPECIFIED; const legacy_contact_info = LegacyContactInfo{ .id = pubkey, .gossip = gossip_addr, @@ -310,7 +310,7 @@ test "gossip.message: push message serializes and deserializes correctly" { const id = Pubkey.fromPublicKey(&pk); const gossip_addr = SocketAddr.initIpv4(.{ 127, 0, 0, 1 }, 1234); - const unspecified_addr = SocketAddr.unspecified(); + const unspecified_addr = SocketAddr.UNSPECIFIED; var buf = [_]u8{0} ** 1024; diff --git a/src/ledger/cleanup_service.zig b/src/ledger/cleanup_service.zig index e07d77133..0cfd1c277 100644 --- a/src/ledger/cleanup_service.zig +++ b/src/ledger/cleanup_service.zig @@ -243,7 +243,13 @@ fn writePurgeRange(write_batch: *BlockstoreDB.WriteBatch, from_slot: Slot, to_sl try purgeRangeWithCount(write_batch, schema.transaction_status, .{ Signature.default(), from_slot }, .{ Signature.default(), to_slot }, &delete_count); // NOTE: for `address_signatures`, agave doesnt key based on slot for some reason (permalink comment seems incorrect?) // https://github.com/anza-xyz/agave/blob/da029625d180dd1d396d26b74a5c281b7786e8c9/ledger/src/blockstore_db.rs#L962 - try purgeRangeWithCount(write_batch, schema.address_signatures, .{ .slot = from_slot, .address = Pubkey.default(), .transaction_index = 0, .signature = Signature.default() }, .{ .slot = to_slot, .address = Pubkey.default(), .transaction_index = 0, .signature = Signature.default() }, &delete_count); + try purgeRangeWithCount( + write_batch, + schema.address_signatures, + .{ .slot = from_slot, .address = Pubkey.ZEROES, .transaction_index = 0, .signature = Signature.default() }, + .{ .slot = to_slot, .address = Pubkey.ZEROES, .transaction_index = 0, .signature = Signature.default() }, + &delete_count, + ); try purgeRangeWithCount(write_batch, schema.transaction_memos, .{ Signature.default(), from_slot }, .{ Signature.default(), to_slot }, &delete_count); try purgeRangeWithCount(write_batch, schema.transaction_status_index, from_slot, to_slot, &delete_count); try purgeRangeWithCount(write_batch, schema.rewards, from_slot, to_slot, &delete_count); @@ -255,7 +261,7 @@ fn writePurgeRange(write_batch: *BlockstoreDB.WriteBatch, from_slot: Slot, to_sl try purgeRangeWithCount(write_batch, schema.merkle_root_meta, .{ .slot = from_slot, .fec_set_index = 0 }, .{ .slot = to_slot, .fec_set_index = 0 }, &delete_count); // slot is not indexed in this method, so this is a full purge // NOTE: do we want to do this? why not just keep the data, since it will be updated/put-back eventually - try purgeRangeWithCount(write_batch, schema.program_costs, Pubkey.default(), Pubkey.default(), &delete_count); + try purgeRangeWithCount(write_batch, schema.program_costs, Pubkey.ZEROES, Pubkey.ZEROES, &delete_count); // make sure we covered all the column families std.debug.assert(delete_count == ledger.schema.list.len); @@ -294,7 +300,13 @@ fn purgeFilesInRange(db: *BlockstoreDB, from_slot: Slot, to_slot: Slot) !void { try purgeFileRangeWithCount(db, schema.transaction_status, .{ Signature.default(), from_slot }, .{ Signature.default(), to_slot }, &delete_count); // NOTE: for `address_signatures`, agave doesnt key based on slot for some reason (permalink comment seems incorrect?) // https://github.com/anza-xyz/agave/blob/da029625d180dd1d396d26b74a5c281b7786e8c9/ledger/src/blockstore_db.rs#L962 - try purgeFileRangeWithCount(db, schema.address_signatures, .{ .slot = from_slot, .address = Pubkey.default(), .transaction_index = 0, .signature = Signature.default() }, .{ .slot = to_slot, .address = Pubkey.default(), .transaction_index = 0, .signature = Signature.default() }, &delete_count); + try purgeFileRangeWithCount( + db, + schema.address_signatures, + .{ .slot = from_slot, .address = Pubkey.ZEROES, .transaction_index = 0, .signature = Signature.default() }, + .{ .slot = to_slot, .address = Pubkey.ZEROES, .transaction_index = 0, .signature = Signature.default() }, + &delete_count, + ); try purgeFileRangeWithCount(db, schema.transaction_memos, .{ Signature.default(), from_slot }, .{ Signature.default(), to_slot }, &delete_count); try purgeFileRangeWithCount(db, schema.transaction_status_index, from_slot, to_slot, &delete_count); try purgeFileRangeWithCount(db, schema.rewards, from_slot, to_slot, &delete_count); @@ -306,7 +318,7 @@ fn purgeFilesInRange(db: *BlockstoreDB, from_slot: Slot, to_slot: Slot) !void { try purgeFileRangeWithCount(db, schema.merkle_root_meta, .{ .slot = from_slot, .fec_set_index = 0 }, .{ .slot = to_slot, .fec_set_index = 0 }, &delete_count); // slot is not indexed in this method, so this is a full purge // NOTE: do we want to do this? why not just keep the data, since it will be updated/put-back eventually - try purgeFileRangeWithCount(db, schema.program_costs, Pubkey.default(), Pubkey.default(), &delete_count); + try purgeFileRangeWithCount(db, schema.program_costs, Pubkey.ZEROES, Pubkey.ZEROES, &delete_count); // make sure we covered all the column families std.debug.assert(delete_count == ledger.schema.list.len); diff --git a/src/ledger/reader.zig b/src/ledger/reader.zig index 01ffab8e9..5b335106c 100644 --- a/src/ledger/reader.zig +++ b/src/ledger/reader.zig @@ -547,7 +547,7 @@ pub const BlockstoreReader = struct { const previous_blockhash = if (parent_slot_entries.items.len != 0) parent_slot_entries.items[parent_slot_entries.items.len - 1].hash else - Hash.default(); + Hash.ZEROES; const rewards = try self.db.get(self.allocator, schema.rewards, slot) orelse schema.rewards.Value{ .rewards = &.{}, .num_partitions = null }; diff --git a/src/ledger/tests.zig b/src/ledger/tests.zig index ab783db90..af658022c 100644 --- a/src/ledger/tests.zig +++ b/src/ledger/tests.zig @@ -174,7 +174,7 @@ test "insert shreds and transaction statuses then get blocks" { .transactions = expected_transactions.items, .parent_slot = slot - 1, .blockhash = blockhash_string.slice(), - .previous_blockhash = sig.core.Hash.default().base58String().slice(), + .previous_blockhash = sig.core.Hash.ZEROES.base58String().slice(), .rewards = &.{}, .num_partitions = null, .block_time = null, diff --git a/src/ledger/transaction_status.zig b/src/ledger/transaction_status.zig index 9ae4b2767..1d6e6d401 100644 --- a/src/ledger/transaction_status.zig +++ b/src/ledger/transaction_status.zig @@ -135,7 +135,7 @@ pub const LoadedAddresses = struct { }; pub const TransactionReturnData = struct { - program_id: sig.core.Pubkey = sig.core.Pubkey.default(), + program_id: sig.core.Pubkey = sig.core.Pubkey.ZEROES, data: []const u8 = &.{}, pub fn deinit(self: @This(), allocator: Allocator) void { diff --git a/src/net/net.zig b/src/net/net.zig index cb1119184..b34f6b5cc 100644 --- a/src/net/net.zig +++ b/src/net/net.zig @@ -8,14 +8,10 @@ pub const SocketAddr = union(enum(u8)) { const Self = @This(); - pub const UNSPECIFIED = Self{ - .V4 = .{ - .ip = Ipv4Addr{ - .octets = [4]u8{ 0, 0, 0, 0 }, - }, - .port = 0, - }, - }; + pub const UNSPECIFIED: SocketAddr = .{ .V4 = .{ + .ip = .{ .octets = .{ 0, 0, 0, 0 } }, + .port = 0, + } }; pub fn init(addr: IpAddr, portt: u16) Self { return switch (addr) { @@ -152,10 +148,6 @@ pub const SocketAddr = union(enum(u8)) { }; } - pub fn unspecified() Self { - return UNSPECIFIED; - } - pub fn port(self: *const Self) u16 { switch (self.*) { .V4 => |v4| { diff --git a/src/version/version.zig b/src/version/version.zig index e8e78aa12..ab7e5a9ee 100644 --- a/src/version/version.zig +++ b/src/version/version.zig @@ -14,9 +14,7 @@ pub const ClientVersion = struct { const Self = @This(); - pub fn default() Self { - return CURRENT_CLIENT_VERSION; - } + pub const CURRENT = CURRENT_CLIENT_VERSION; pub fn new( major: u16,