From 3b092d05261ce832e635eb8fcfc0cbcf13f8e00e Mon Sep 17 00:00:00 2001 From: oxlime Date: Sat, 21 Sep 2024 20:07:26 -0500 Subject: [PATCH 01/18] ochecksum error and leak --- src/network/protocol/messages/addr.zig | 189 +++++++++++++++++++++++++ src/network/protocol/messages/lib.zig | 26 ++++ src/network/wire/lib.zig | 64 ++++++++- 3 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 src/network/protocol/messages/addr.zig diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig new file mode 100644 index 0000000..88ce2fb --- /dev/null +++ b/src/network/protocol/messages/addr.zig @@ -0,0 +1,189 @@ +const std = @import("std"); +const native_endian = @import("builtin").target.cpu.arch.endian(); +const protocol = @import("../lib.zig"); + +const ServiceFlags = protocol.ServiceFlags; + +const Endian = std.builtin.Endian; +const Sha256 = std.crypto.hash.sha2.Sha256; + +const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; + +/// AddrMessage represents the "addr" message +/// +/// https://developer.bitcoin.org/reference/p2p_networking.html#addr +pub const NetworkIPAddr = struct { + time: u32, // Unix epoch time + services: u64, // Services offered by the node + ip: [16]u8, // IPv6 address (including IPv4-mapped) + port: u16, // Port number + // + // + +// NetworkIPAddr eql +pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { + return self.time == other.time + and self.services == other.services + and std.mem.eql(u8, &self.ip, &other.ip) + and self.port == other.port; +} +}; + +pub const AddrMessage = struct { + ip_address_count: CompactSizeUint, + ip_addresses: []NetworkIPAddr, + + + pub inline fn name() *const [12]u8 { + return protocol.CommandNames.ADDR ++ [_]u8{0} ** 8; + } + + /// Returns the message checksum + /// + /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` + pub fn checksum(self: AddrMessage) [4]u8 { + var digest: [32]u8 = undefined; + var hasher = Sha256.init(.{}); + const writer = hasher.writer(); + self.serializeToWriter(writer) catch unreachable; // Sha256.write is infaible + hasher.final(&digest); + + Sha256.hash(&digest, &digest, .{}); + + return digest[0..4].*; + } + + /// Free the `user_agent` if there is one + pub fn deinit(self: AddrMessage, allocator: std.mem.Allocator) void { + if (self.ip_addresses.len > 0) { + allocator.free(self.ip_addresses); + } + } + + /// Serialize the message as bytes and write them to the Writer. + /// + /// `w` should be a valid `Writer`. + pub fn serializeToWriter(self: *const AddrMessage, w: anytype) !void { + comptime { + if (!std.meta.hasFn(@TypeOf(w), "writeInt")) @compileError("Expects r to have fn 'writeInt'."); + if (!std.meta.hasFn(@TypeOf(w), "writeAll")) @compileError("Expects r to have fn 'writeAll'."); + } +// Serialize number of IP addresses + // + try self.ip_address_count.encodeToWriter(w); + + // Serialize each IP address + for (self.ip_addresses) |ip_address| { + try w.writeInt(u32, ip_address.time, .little); + try w.writeInt(u64, ip_address.services, .little); + try w.writeAll(std.mem.asBytes(&ip_address.ip)); + try w.writeInt(u16, ip_address.port, .big); + } + } + + /// Serialize a message as bytes and write them to the buffer. + /// + /// buffer.len must be >= than self.hintSerializedLen() + pub fn serializeToSlice(self: *const AddrMessage, buffer: []u8) !void { + var fbs = std.io.fixedBufferStream(buffer); + const writer = fbs.writer(); + try self.serializeToWriter(writer); + } + + /// Serialize a message as bytes and return them. + pub fn serialize(self: *const AddrMessage, allocator: std.mem.Allocator) ![]u8 { + const serialized_len = self.hintSerializedLen(); + + const ret = try allocator.alloc(u8, serialized_len); + errdefer allocator.free(ret); + + try self.serializeToSlice(ret); + + return ret; + } + + /// Deserialize a Reader bytes as a `AddrMessage` + pub fn deserializeReader(allocator: std.mem.Allocator, r: anytype) !AddrMessage { + comptime { + if (!std.meta.hasFn(@TypeOf(r), "readInt")) @compileError("Expects r to have fn 'readInt'."); + if (!std.meta.hasFn(@TypeOf(r), "readNoEof")) @compileError("Expects r to have fn 'readNoEof'."); + if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); + } + + var vm: AddrMessage = undefined; + const ip_address_count = try CompactSizeUint.decodeReader(r); + + // Allocate space for IP addresses + const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); + errdefer allocator.free(ip_addresses); + + vm.ip_addresses = ip_addresses; + + for (vm.ip_addresses) |*ip_address| { + ip_address.time = try r.readInt(u32, .little); + ip_address.services = try r.readInt(u64, .little); + try r.readNoEof(&ip_address.ip); + ip_address.port = try r.readInt(u16, .big); + } + + return vm; + } + + /// Deserialize bytes into a `AddrMessage` + pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !AddrMessage { + var fbs = std.io.fixedBufferStream(bytes); + const reader = fbs.reader(); + return try AddrMessage.deserializeReader(allocator, reader); + } + + pub fn hintSerializedLen(self: AddrMessage) usize { + // 4 + 8 + 16 + 2 + const fixed_length_per_ip = 30; + return 1 + self.ip_address_count.value() * fixed_length_per_ip;// 1 for CompactSizeUint + + } + + pub fn eql(self: *const AddrMessage, other: *const AddrMessage) bool { + if (self.ip_address_count.value() != other.ip_address_count.value()) return false; + + const count = @as(usize, self.ip_address_count.value()); // Convert to usize + for (0..count) |i| { + if (!self.ip_addresses[i].eql(&other.ip_addresses[i])) return false; + } + + return true; + } +}; + +// TESTS + +test "ok_full_flow_AddrMessage" { + const allocator = std.testing.allocator; + + { + const ips = [_]NetworkIPAddr{ + NetworkIPAddr{ + .time = 1414012889, + .services = ServiceFlags.NODE_NETWORK, + .ip = [_]u8{13} ** 16, + .port = 33, + + }, + }; + const am = AddrMessage{ + .ip_address_count = CompactSizeUint.new(1), + .ip_addresses = try allocator.alloc(NetworkIPAddr, 1), + }; + defer allocator.free(am.ip_addresses); // Ensure to free the allocated memory + + am.ip_addresses[0] = ips[0]; + + const payload = try am.serialize(allocator); + defer allocator.free(payload); + const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); + defer deserialized_am.deinit(allocator); + + try std.testing.expect(am.eql(&deserialized_am)); + } + +} diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index 83f9a3e..76f750b 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -47,6 +47,30 @@ pub const Message = union(MessageTypes) { .getblocks => |m| m.deinit(allocator), .ping => {}, .pong => {}, +pub const AddrMessage = @import("addr.zig").AddrMessage; + +pub const MessageTypes = enum { + Version, + Verack, + Mempool, + Getaddr, + Addr +}; + +pub const Message = union(MessageTypes) { + Version: VersionMessage, + Verack: VerackMessage, + Mempool: MempoolMessage, + Getaddr: GetaddrMessage, + Addr: AddrMessage, + + pub fn deinit(self: Message, allocator: std.mem.Allocator) void { + switch (self) { + .Version => |m| m.deinit(allocator), + .Verack => {}, + .Mempool => {}, + .Getaddr => {}, + .Addr => {}, } } pub fn checksum(self: Message) [4]u8 { @@ -58,6 +82,7 @@ pub const Message = union(MessageTypes) { .getblocks => |m| m.checksum(), .ping => |m| m.checksum(), .pong => |m| m.checksum(), + .addr => |m| m.checksum(), }; } @@ -70,6 +95,7 @@ pub const Message = union(MessageTypes) { .getblocks => |m| m.hintSerializedLen(), .ping => |m| m.hintSerializedLen(), .pong => |m| m.hintSerializedLen(), + .addr => |m| m.hintSerializedLen(), }; } }; diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index 3149e5b..abbd49f 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -19,6 +19,9 @@ pub const Error = error{ MessageTooLarge, }; +pub const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; +const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; + /// Return the checksum of a slice /// /// Use it on serialized messages to compute the header's value @@ -121,6 +124,11 @@ pub fn receiveMessage( try r.skipBytes(payload_len, .{}); // Purge the wire return error.UnknownMessage; }; + protocol.messages.Message{ .Getaddr = try protocol.messages.GetaddrMessage.deserializeReader(allocator, r) } + else if (std.mem.eql(u8, &command, protocol.messages.AddrMessage.name())) + protocol.messages.Message{ .Addr = try protocol.messages.AddrMessage.deserializeReader(allocator, r) } + else + return error.InvalidCommand; errdefer message.deinit(allocator); if (!std.mem.eql(u8, &message.checksum(), &checksum)) { @@ -180,8 +188,11 @@ test "ok_send_version_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .version => |rm| try std.testing.expect(message.eql(&rm)), - else => unreachable, + .Version => |rm| try std.testing.expect(message.eql(&rm)), + .Verack => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, } } @@ -206,8 +217,11 @@ test "ok_send_verack_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .verack => {}, - else => unreachable, + .Verack => {}, + .Version => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, } } @@ -243,6 +257,20 @@ test "ok_send_getblocks_message" { const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; const GetblocksMessage = protocol.messages.GetblocksMessage; + .Mempool => {}, + .Verack => unreachable, + .Version => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, + } +} + +test "ok_send_addr_message" { + const ArrayList = std.ArrayList; + const test_allocator = std.testing.allocator; + const AddrMessage = protocol.messages.AddrMessage; +// const NetworkIPAddr = protocol.messages.NetworkIPAddr; + const ServiceFlags = protocol.ServiceFlags; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -326,6 +354,34 @@ test "ok_send_pong_message" { switch (received_message) { .pong => |pong_message| try std.testing.expectEqual(message.nonce, pong_message.nonce), else => unreachable, + var ips = [_]NetworkIPAddr{ + NetworkIPAddr{ + .time = 42, + .services = ServiceFlags.NODE_NETWORK, + .ip = [_]u8{13} ** 16, + .port = 33, + + }, + }; + const message = AddrMessage{ + .ip_address_count = CompactSizeUint.new(1), + .ip_addresses = ips[0..], + }; + + const writer = list.writer(); + try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); + var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); + const reader = fbs.reader(); + + const received_message = try receiveMessage(test_allocator, reader); + defer received_message.deinit(test_allocator); + + switch (received_message) { + .Addr => |rm| try std.testing.expect(message.eql(&rm)), + .Version => unreachable, + .Verack => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, } } From d69d73662ad8380df1ce0109ed0aaff1491544de Mon Sep 17 00:00:00 2001 From: oxlime Date: Sun, 22 Sep 2024 13:43:11 -0500 Subject: [PATCH 02/18] seg fault --- src/network/protocol/messages/addr.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 88ce2fb..4a0457a 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -72,6 +72,9 @@ pub const AddrMessage = struct { // try self.ip_address_count.encodeToWriter(w); + // Ensure the slice is valid before iterating + if (self.ip_addresses.len == 0) return; + // Serialize each IP address for (self.ip_addresses) |ip_address| { try w.writeInt(u32, ip_address.time, .little); @@ -115,8 +118,9 @@ pub const AddrMessage = struct { // Allocate space for IP addresses const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); - errdefer allocator.free(ip_addresses); - + // errdefer allocator.free(ip_addresses); + defer allocator.free(ip_addresses); // Ensure memory is freed on exit + // vm.ip_addresses = ip_addresses; for (vm.ip_addresses) |*ip_address| { From 3325f1ecfc36135520679dd21e4110ccb7d5613a Mon Sep 17 00:00:00 2001 From: oxlime Date: Wed, 25 Sep 2024 08:05:23 -0500 Subject: [PATCH 03/18] checksum error --- src/network/protocol/messages/addr.zig | 128 +++++++++++++++++-------- src/network/wire/lib.zig | 64 +------------ 2 files changed, 92 insertions(+), 100 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 4a0457a..24ef6ad 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -17,8 +17,6 @@ pub const NetworkIPAddr = struct { services: u64, // Services offered by the node ip: [16]u8, // IPv6 address (including IPv4-mapped) port: u16, // Port number - // - // // NetworkIPAddr eql pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { @@ -30,7 +28,6 @@ pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { }; pub const AddrMessage = struct { - ip_address_count: CompactSizeUint, ip_addresses: []NetworkIPAddr, @@ -55,9 +52,7 @@ pub const AddrMessage = struct { /// Free the `user_agent` if there is one pub fn deinit(self: AddrMessage, allocator: std.mem.Allocator) void { - if (self.ip_addresses.len > 0) { allocator.free(self.ip_addresses); - } } /// Serialize the message as bytes and write them to the Writer. @@ -82,6 +77,22 @@ pub const AddrMessage = struct { try w.writeAll(std.mem.asBytes(&ip_address.ip)); try w.writeInt(u16, ip_address.port, .big); } + try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); + +std.debug.print("Serailize ip addresses: {any}\n", .{self.ip_addresses}); + + // Serialize each IP address + for (self.ip_addresses) |*ip_address| { + try w.writeInt(u32, ip_address.time, .little); + try w.writeInt(u64, ip_address.services, .little); + try w.writeAll(std.mem.asBytes(&ip_address.ip)); + try w.writeInt(u16, ip_address.port, .big); +std.debug.print("Serailze Read time: {}\n", .{ip_address.time}); +std.debug.print("Serailze Read services: {}\n", .{ip_address.services}); +std.debug.print("Serailze Read IP: {any}\n", .{ip_address.ip}); +std.debug.print("Serailze Read port: {}\n", .{ip_address.port}); + } + std.debug.print("seerialize to writer: {any}\n", .{w}); } /// Serialize a message as bytes and write them to the buffer. @@ -112,7 +123,6 @@ pub const AddrMessage = struct { if (!std.meta.hasFn(@TypeOf(r), "readNoEof")) @compileError("Expects r to have fn 'readNoEof'."); if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); } - var vm: AddrMessage = undefined; const ip_address_count = try CompactSizeUint.decodeReader(r); @@ -120,7 +130,7 @@ pub const AddrMessage = struct { const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); // errdefer allocator.free(ip_addresses); defer allocator.free(ip_addresses); // Ensure memory is freed on exit - // + vm.ip_addresses = ip_addresses; for (vm.ip_addresses) |*ip_address| { @@ -130,6 +140,13 @@ pub const AddrMessage = struct { ip_address.port = try r.readInt(u16, .big); } + +std.debug.print("Read time: {}\n", .{ip_address.time}); +std.debug.print("Read services: {}\n", .{ip_address.services}); +std.debug.print("Read IP: {any}\n", .{ip_address.ip}); +std.debug.print("Read port: {}\n", .{ip_address.port}); + } + return vm; } @@ -143,14 +160,14 @@ pub const AddrMessage = struct { pub fn hintSerializedLen(self: AddrMessage) usize { // 4 + 8 + 16 + 2 const fixed_length_per_ip = 30; - return 1 + self.ip_address_count.value() * fixed_length_per_ip;// 1 for CompactSizeUint + return 1 + self.ip_addresses.len * fixed_length_per_ip;// 1 for CompactSizeUint } pub fn eql(self: *const AddrMessage, other: *const AddrMessage) bool { - if (self.ip_address_count.value() != other.ip_address_count.value()) return false; + if (self.ip_addresses.len != other.ip_addresses.len) return false; - const count = @as(usize, self.ip_address_count.value()); // Convert to usize + const count = @as(usize, self.ip_addresses.len); for (0..count) |i| { if (!self.ip_addresses[i].eql(&other.ip_addresses[i])) return false; } @@ -161,33 +178,64 @@ pub const AddrMessage = struct { // TESTS -test "ok_full_flow_AddrMessage" { - const allocator = std.testing.allocator; - - { - const ips = [_]NetworkIPAddr{ - NetworkIPAddr{ - .time = 1414012889, - .services = ServiceFlags.NODE_NETWORK, - .ip = [_]u8{13} ** 16, - .port = 33, - - }, - }; - const am = AddrMessage{ - .ip_address_count = CompactSizeUint.new(1), - .ip_addresses = try allocator.alloc(NetworkIPAddr, 1), - }; - defer allocator.free(am.ip_addresses); // Ensure to free the allocated memory - - am.ip_addresses[0] = ips[0]; - - const payload = try am.serialize(allocator); - defer allocator.free(payload); - const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); - defer deserialized_am.deinit(allocator); - - try std.testing.expect(am.eql(&deserialized_am)); - } - -} +//reworked +//test "ok_full_flow_AddrMessage" { +// const test_allocator = std.testing.allocator; +// const AddrMessage = protocol.messages.AddrMessage; +// { +// const ips = [_]NetworkIPAddr{ +// .time = 1414012889, +// .services = 1, +// .ip = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 51 }, +// .port = 8333, +// }; +// +// const am = AddrMessage{ +// .ip_addresses = ips[0..], +// }; +// +// // Serialize +// const payload = try am.serialize(allocator); +// defer allocator.free(payload); +// +// // Deserialize +// const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); +// +// // Test equality +// try std.testing.expect(am.eql(&deserialized_am)); +// +// // Free allocated memory for deserialized inventory +// defer allocator.free(deserialized_am.inventory); +// } +//} + +//test "ok_full_flow_AddrMessage" { +// const allocator = std.testing.allocator; +// +// { +// const ips = [_]NetworkIPAddr{ +// NetworkIPAddr{ +// .time = 1414012889, +// .services = ServiceFlags.NODE_NETWORK, +// .ip = [_]u8{13} ** 16, +// .port = 33, +// +// }, +// }; +// const am = AddrMessage{ +// .ip_address_count = CompactSizeUint.new(1), +// .ip_addresses = try allocator.alloc(NetworkIPAddr, 1), +// }; +// defer allocator.free(am.ip_addresses); // Ensure to free the allocated memory +// +// am.ip_addresses[0] = ips[0]; +// +// const payload = try am.serialize(allocator); +// defer allocator.free(payload); +// const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); +// defer deserialized_am.deinit(allocator); +// +// try std.testing.expect(am.eql(&deserialized_am)); +// } +// +//} diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index abbd49f..3149e5b 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -19,9 +19,6 @@ pub const Error = error{ MessageTooLarge, }; -pub const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; -const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; - /// Return the checksum of a slice /// /// Use it on serialized messages to compute the header's value @@ -124,11 +121,6 @@ pub fn receiveMessage( try r.skipBytes(payload_len, .{}); // Purge the wire return error.UnknownMessage; }; - protocol.messages.Message{ .Getaddr = try protocol.messages.GetaddrMessage.deserializeReader(allocator, r) } - else if (std.mem.eql(u8, &command, protocol.messages.AddrMessage.name())) - protocol.messages.Message{ .Addr = try protocol.messages.AddrMessage.deserializeReader(allocator, r) } - else - return error.InvalidCommand; errdefer message.deinit(allocator); if (!std.mem.eql(u8, &message.checksum(), &checksum)) { @@ -188,11 +180,8 @@ test "ok_send_version_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .Version => |rm| try std.testing.expect(message.eql(&rm)), - .Verack => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, + .version => |rm| try std.testing.expect(message.eql(&rm)), + else => unreachable, } } @@ -217,11 +206,8 @@ test "ok_send_verack_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .Verack => {}, - .Version => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, + .verack => {}, + else => unreachable, } } @@ -257,20 +243,6 @@ test "ok_send_getblocks_message" { const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; const GetblocksMessage = protocol.messages.GetblocksMessage; - .Mempool => {}, - .Verack => unreachable, - .Version => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, - } -} - -test "ok_send_addr_message" { - const ArrayList = std.ArrayList; - const test_allocator = std.testing.allocator; - const AddrMessage = protocol.messages.AddrMessage; -// const NetworkIPAddr = protocol.messages.NetworkIPAddr; - const ServiceFlags = protocol.ServiceFlags; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -354,34 +326,6 @@ test "ok_send_pong_message" { switch (received_message) { .pong => |pong_message| try std.testing.expectEqual(message.nonce, pong_message.nonce), else => unreachable, - var ips = [_]NetworkIPAddr{ - NetworkIPAddr{ - .time = 42, - .services = ServiceFlags.NODE_NETWORK, - .ip = [_]u8{13} ** 16, - .port = 33, - - }, - }; - const message = AddrMessage{ - .ip_address_count = CompactSizeUint.new(1), - .ip_addresses = ips[0..], - }; - - const writer = list.writer(); - try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); - var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); - const reader = fbs.reader(); - - const received_message = try receiveMessage(test_allocator, reader); - defer received_message.deinit(test_allocator); - - switch (received_message) { - .Addr => |rm| try std.testing.expect(message.eql(&rm)), - .Version => unreachable, - .Verack => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, } } From 042c76c6837fe540ad9df547bfbe40cf2c7e2710 Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 26 Sep 2024 22:20:25 -0500 Subject: [PATCH 04/18] asdf --- src/network/protocol/messages/addr.zig | 24 ++--- src/network/wire/lib.zig | 143 ++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 21 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 24ef6ad..1f4a0a9 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -63,20 +63,7 @@ pub const AddrMessage = struct { if (!std.meta.hasFn(@TypeOf(w), "writeInt")) @compileError("Expects r to have fn 'writeInt'."); if (!std.meta.hasFn(@TypeOf(w), "writeAll")) @compileError("Expects r to have fn 'writeAll'."); } -// Serialize number of IP addresses - // - try self.ip_address_count.encodeToWriter(w); - - // Ensure the slice is valid before iterating - if (self.ip_addresses.len == 0) return; - - // Serialize each IP address - for (self.ip_addresses) |ip_address| { - try w.writeInt(u32, ip_address.time, .little); - try w.writeInt(u64, ip_address.services, .little); - try w.writeAll(std.mem.asBytes(&ip_address.ip)); - try w.writeInt(u16, ip_address.port, .big); - } + //try CompactSizeUint.new(@intCast(self.ip_addresses.len)).encodeToWriter(w); try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); std.debug.print("Serailize ip addresses: {any}\n", .{self.ip_addresses}); @@ -123,6 +110,9 @@ std.debug.print("Serailze Read port: {}\n", .{ip_address.port}); if (!std.meta.hasFn(@TypeOf(r), "readNoEof")) @compileError("Expects r to have fn 'readNoEof'."); if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); } + + std.debug.print("deserailize reader: {any}\n", .{r}); + var vm: AddrMessage = undefined; const ip_address_count = try CompactSizeUint.decodeReader(r); @@ -130,16 +120,15 @@ std.debug.print("Serailze Read port: {}\n", .{ip_address.port}); const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); // errdefer allocator.free(ip_addresses); defer allocator.free(ip_addresses); // Ensure memory is freed on exit - + vm.ip_addresses = ip_addresses; + std.debug.print("ip_addresses: {any}\n", .{ip_addresses}); for (vm.ip_addresses) |*ip_address| { ip_address.time = try r.readInt(u32, .little); ip_address.services = try r.readInt(u64, .little); try r.readNoEof(&ip_address.ip); ip_address.port = try r.readInt(u16, .big); - } - std.debug.print("Read time: {}\n", .{ip_address.time}); std.debug.print("Read services: {}\n", .{ip_address.services}); @@ -147,6 +136,7 @@ std.debug.print("Read IP: {any}\n", .{ip_address.ip}); std.debug.print("Read port: {}\n", .{ip_address.port}); } +std.debug.print("Deserialized AddrMessage: {any}\n", .{vm}); return vm; } diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index 3149e5b..e2640a7 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -19,6 +19,9 @@ pub const Error = error{ MessageTooLarge, }; +pub const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; +const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; + /// Return the checksum of a slice /// /// Use it on serialized messages to compute the header's value @@ -121,6 +124,11 @@ pub fn receiveMessage( try r.skipBytes(payload_len, .{}); // Purge the wire return error.UnknownMessage; }; + protocol.messages.Message{ .Getaddr = try protocol.messages.GetaddrMessage.deserializeReader(allocator, r) } + else if (std.mem.eql(u8, &command, protocol.messages.AddrMessage.name())) + protocol.messages.Message{ .Addr = try protocol.messages.AddrMessage.deserializeReader(allocator, r) } + else + return error.InvalidCommand; errdefer message.deinit(allocator); if (!std.mem.eql(u8, &message.checksum(), &checksum)) { @@ -180,8 +188,11 @@ test "ok_send_version_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .version => |rm| try std.testing.expect(message.eql(&rm)), - else => unreachable, + .Version => |rm| try std.testing.expect(message.eql(&rm)), + .Verack => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, } } @@ -206,8 +217,11 @@ test "ok_send_verack_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .verack => {}, - else => unreachable, + .Verack => {}, + .Version => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, } } @@ -243,10 +257,86 @@ test "ok_send_getblocks_message" { const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; const GetblocksMessage = protocol.messages.GetblocksMessage; + .Mempool => {}, + .Verack => unreachable, + .Version => unreachable, + .Getaddr => unreachable, + .Addr => unreachable, + } +} + +//test "ok_send_addr_message" { +// const ArrayList = std.ArrayList; +// const test_allocator = std.testing.allocator; +// const AddrMessage = protocol.messages.AddrMessage; +// //const ServiceFlags = protocol.ServiceFlags; +// +// var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); +// defer list.deinit(); +// +// // Create an ArrayList for NetworkIPAddr +// //var ips = ArrayList(NetworkIPAddr).init(test_allocator); +// //defer ips.deinit(); +// +// //try ips.append( +// // NetworkIPAddr{ +// // .time = 42, +// // .services = ServiceFlags.NODE_NETWORK, +// // .ip = [_]u8{13} ** 16, +// // .port = 33, +// // +// // }); +// //const message = AddrMessage{ +// // //.ip_address_count = CompactSizeUint.new(1), +// // .ip_addresses = ips, +// //}; +// var message = AddrMessage.init(test_allocator); +// defer message.deinit(); +// +// try message.ip_addresses.append(NetworkIPAddr{ +// .time = 1414012889, +// .services = 1, +// .ip = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 51 }, +// .port = 8333, +// // .time = 42, +// // .services = ServiceFlags.NODE_NETWORK, +// // .ip = [_]u8{13} ** 16, +// // .port = 33, +// }); +// +// +// const writer = list.writer(); +// try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); +// var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); +// const reader = fbs.reader(); +// +// const received_message = try receiveMessage(test_allocator, reader); +// defer received_message.deinit(test_allocator); +// +// switch (received_message) { +// .Addr => |rm| try std.testing.expect(message.eql(&rm)), +// .Version => unreachable, +// .Verack => unreachable, +// .Mempool => unreachable, +// .Getaddr => unreachable, +// } +//} + +test "ok_send_addr_message" { + const ArrayList = std.ArrayList; + const test_allocator = std.testing.allocator; + const AddrMessage = protocol.messages.AddrMessage; +<<<<<<< HEAD +// const NetworkIPAddr = protocol.messages.NetworkIPAddr; + const ServiceFlags = protocol.ServiceFlags; +======= + //const ServiceFlags = protocol.ServiceFlags; +>>>>>>> 352f310 (checksum error) var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); +<<<<<<< HEAD const message = GetblocksMessage{ .version = 42, .header_hashes = try test_allocator.alloc([32]u8, 2), @@ -326,6 +416,51 @@ test "ok_send_pong_message" { switch (received_message) { .pong => |pong_message| try std.testing.expectEqual(message.nonce, pong_message.nonce), else => unreachable, + var ips = [_]NetworkIPAddr{ + NetworkIPAddr{ + .time = 42, + .services = ServiceFlags.NODE_NETWORK, + .ip = [_]u8{13} ** 16, + .port = 33, + + }, + }; + const message = AddrMessage{ + .ip_address_count = CompactSizeUint.new(1), + .ip_addresses = ips[0..], +======= + //var message = AddrMessage{ + // .ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1), + //}; + const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); + defer test_allocator.free(ip_addresses); + + ip_addresses[0] = NetworkIPAddr{ + .time = 1414012889, + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + }; + + var message = AddrMessage{ + .ip_addresses = ip_addresses, +>>>>>>> 352f310 (checksum error) + }; + + const writer = list.writer(); + try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); + var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); + const reader = fbs.reader(); + + const received_message = try receiveMessage(test_allocator, reader); + defer received_message.deinit(test_allocator); + + switch (received_message) { + .Addr => |rm| try std.testing.expect(message.eql(&rm)), + .Version => unreachable, + .Verack => unreachable, + .Mempool => unreachable, + .Getaddr => unreachable, } } From daa4f99ea1ac68ebd52de793a2e5d56931c60114 Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 26 Sep 2024 23:16:07 -0500 Subject: [PATCH 05/18] rebased --- src/network/protocol/messages/addr.zig | 18 --- src/network/protocol/messages/lib.zig | 29 +---- src/network/wire/lib.zig | 161 +++++++------------------ 3 files changed, 50 insertions(+), 158 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 1f4a0a9..7429a66 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -66,20 +66,13 @@ pub const AddrMessage = struct { //try CompactSizeUint.new(@intCast(self.ip_addresses.len)).encodeToWriter(w); try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); -std.debug.print("Serailize ip addresses: {any}\n", .{self.ip_addresses}); - // Serialize each IP address for (self.ip_addresses) |*ip_address| { try w.writeInt(u32, ip_address.time, .little); try w.writeInt(u64, ip_address.services, .little); try w.writeAll(std.mem.asBytes(&ip_address.ip)); try w.writeInt(u16, ip_address.port, .big); -std.debug.print("Serailze Read time: {}\n", .{ip_address.time}); -std.debug.print("Serailze Read services: {}\n", .{ip_address.services}); -std.debug.print("Serailze Read IP: {any}\n", .{ip_address.ip}); -std.debug.print("Serailze Read port: {}\n", .{ip_address.port}); } - std.debug.print("seerialize to writer: {any}\n", .{w}); } /// Serialize a message as bytes and write them to the buffer. @@ -111,32 +104,21 @@ std.debug.print("Serailze Read port: {}\n", .{ip_address.port}); if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); } - std.debug.print("deserailize reader: {any}\n", .{r}); - var vm: AddrMessage = undefined; const ip_address_count = try CompactSizeUint.decodeReader(r); // Allocate space for IP addresses const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); - // errdefer allocator.free(ip_addresses); - defer allocator.free(ip_addresses); // Ensure memory is freed on exit vm.ip_addresses = ip_addresses; - std.debug.print("ip_addresses: {any}\n", .{ip_addresses}); for (vm.ip_addresses) |*ip_address| { ip_address.time = try r.readInt(u32, .little); ip_address.services = try r.readInt(u64, .little); try r.readNoEof(&ip_address.ip); ip_address.port = try r.readInt(u16, .big); - -std.debug.print("Read time: {}\n", .{ip_address.time}); -std.debug.print("Read services: {}\n", .{ip_address.services}); -std.debug.print("Read IP: {any}\n", .{ip_address.ip}); -std.debug.print("Read port: {}\n", .{ip_address.port}); } -std.debug.print("Deserialized AddrMessage: {any}\n", .{vm}); return vm; } diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index 76f750b..803dd16 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -6,6 +6,7 @@ pub const GetaddrMessage = @import("getaddr.zig").GetaddrMessage; pub const GetblocksMessage = @import("getblocks.zig").GetblocksMessage; pub const PingMessage = @import("ping.zig").PingMessage; pub const PongMessage = @import("pong.zig").PongMessage; +pub const AddrMessage = @import("addr.zig").AddrMessage; pub const MessageTypes = enum { version, @@ -15,6 +16,7 @@ pub const MessageTypes = enum { getblocks, ping, pong, + addr, }; pub const Message = union(MessageTypes) { @@ -25,6 +27,7 @@ pub const Message = union(MessageTypes) { getblocks: GetblocksMessage, ping: PingMessage, pong: PongMessage, + addr: AddrMessage, pub fn name(self: Message) *const [12]u8 { return switch (self) { @@ -35,6 +38,7 @@ pub const Message = union(MessageTypes) { .getblocks => |m| @TypeOf(m).name(), .ping => |m| @TypeOf(m).name(), .pong => |m| @TypeOf(m).name(), + .addr => |m| @TypeOf(m).name(), }; } @@ -47,30 +51,7 @@ pub const Message = union(MessageTypes) { .getblocks => |m| m.deinit(allocator), .ping => {}, .pong => {}, -pub const AddrMessage = @import("addr.zig").AddrMessage; - -pub const MessageTypes = enum { - Version, - Verack, - Mempool, - Getaddr, - Addr -}; - -pub const Message = union(MessageTypes) { - Version: VersionMessage, - Verack: VerackMessage, - Mempool: MempoolMessage, - Getaddr: GetaddrMessage, - Addr: AddrMessage, - - pub fn deinit(self: Message, allocator: std.mem.Allocator) void { - switch (self) { - .Version => |m| m.deinit(allocator), - .Verack => {}, - .Mempool => {}, - .Getaddr => {}, - .Addr => {}, + .addr => |m| m.deinit(allocator), } } pub fn checksum(self: Message) [4]u8 { diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index e2640a7..d9ea79b 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -120,15 +120,12 @@ pub fn receiveMessage( protocol.messages.Message{ .ping = try protocol.messages.PingMessage.deserializeReader(allocator, r) } else if (std.mem.eql(u8, &command, protocol.messages.PongMessage.name())) protocol.messages.Message{ .pong = try protocol.messages.PongMessage.deserializeReader(allocator, r) } + else if (std.mem.eql(u8, &command, protocol.messages.AddrMessage.name())) + protocol.messages.Message{ .addr = try protocol.messages.AddrMessage.deserializeReader(allocator, r) } else { try r.skipBytes(payload_len, .{}); // Purge the wire return error.UnknownMessage; }; - protocol.messages.Message{ .Getaddr = try protocol.messages.GetaddrMessage.deserializeReader(allocator, r) } - else if (std.mem.eql(u8, &command, protocol.messages.AddrMessage.name())) - protocol.messages.Message{ .Addr = try protocol.messages.AddrMessage.deserializeReader(allocator, r) } - else - return error.InvalidCommand; errdefer message.deinit(allocator); if (!std.mem.eql(u8, &message.checksum(), &checksum)) { @@ -188,11 +185,8 @@ test "ok_send_version_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .Version => |rm| try std.testing.expect(message.eql(&rm)), - .Verack => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, + .version => |rm| try std.testing.expect(message.eql(&rm)), + else => unreachable, } } @@ -217,11 +211,8 @@ test "ok_send_verack_message" { defer received_message.deinit(test_allocator); switch (received_message) { - .Verack => {}, - .Version => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, + .verack => {}, + else => unreachable, } } @@ -257,86 +248,10 @@ test "ok_send_getblocks_message" { const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; const GetblocksMessage = protocol.messages.GetblocksMessage; - .Mempool => {}, - .Verack => unreachable, - .Version => unreachable, - .Getaddr => unreachable, - .Addr => unreachable, - } -} - -//test "ok_send_addr_message" { -// const ArrayList = std.ArrayList; -// const test_allocator = std.testing.allocator; -// const AddrMessage = protocol.messages.AddrMessage; -// //const ServiceFlags = protocol.ServiceFlags; -// -// var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); -// defer list.deinit(); -// -// // Create an ArrayList for NetworkIPAddr -// //var ips = ArrayList(NetworkIPAddr).init(test_allocator); -// //defer ips.deinit(); -// -// //try ips.append( -// // NetworkIPAddr{ -// // .time = 42, -// // .services = ServiceFlags.NODE_NETWORK, -// // .ip = [_]u8{13} ** 16, -// // .port = 33, -// // -// // }); -// //const message = AddrMessage{ -// // //.ip_address_count = CompactSizeUint.new(1), -// // .ip_addresses = ips, -// //}; -// var message = AddrMessage.init(test_allocator); -// defer message.deinit(); -// -// try message.ip_addresses.append(NetworkIPAddr{ -// .time = 1414012889, -// .services = 1, -// .ip = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 51 }, -// .port = 8333, -// // .time = 42, -// // .services = ServiceFlags.NODE_NETWORK, -// // .ip = [_]u8{13} ** 16, -// // .port = 33, -// }); -// -// -// const writer = list.writer(); -// try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); -// var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); -// const reader = fbs.reader(); -// -// const received_message = try receiveMessage(test_allocator, reader); -// defer received_message.deinit(test_allocator); -// -// switch (received_message) { -// .Addr => |rm| try std.testing.expect(message.eql(&rm)), -// .Version => unreachable, -// .Verack => unreachable, -// .Mempool => unreachable, -// .Getaddr => unreachable, -// } -//} - -test "ok_send_addr_message" { - const ArrayList = std.ArrayList; - const test_allocator = std.testing.allocator; - const AddrMessage = protocol.messages.AddrMessage; -<<<<<<< HEAD -// const NetworkIPAddr = protocol.messages.NetworkIPAddr; - const ServiceFlags = protocol.ServiceFlags; -======= - //const ServiceFlags = protocol.ServiceFlags; ->>>>>>> 352f310 (checksum error) var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); -<<<<<<< HEAD const message = GetblocksMessage{ .version = 42, .header_hashes = try test_allocator.alloc([32]u8, 2), @@ -416,19 +331,20 @@ test "ok_send_pong_message" { switch (received_message) { .pong => |pong_message| try std.testing.expectEqual(message.nonce, pong_message.nonce), else => unreachable, - var ips = [_]NetworkIPAddr{ - NetworkIPAddr{ - .time = 42, - .services = ServiceFlags.NODE_NETWORK, - .ip = [_]u8{13} ** 16, - .port = 33, - - }, - }; - const message = AddrMessage{ - .ip_address_count = CompactSizeUint.new(1), - .ip_addresses = ips[0..], -======= + } +} + +test "ok_send_addr_message" { + const Config = @import("../../config/config.zig").Config; + + const ArrayList = std.ArrayList; + const test_allocator = std.testing.allocator; + const AddrMessage = protocol.messages.AddrMessage; + //const ServiceFlags = protocol.ServiceFlags; + + var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); + defer list.deinit(); + //var message = AddrMessage{ // .ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1), //}; @@ -444,24 +360,37 @@ test "ok_send_pong_message" { var message = AddrMessage{ .ip_addresses = ip_addresses, ->>>>>>> 352f310 (checksum error) }; - const writer = list.writer(); - try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); - var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); - const reader = fbs.reader(); - - const received_message = try receiveMessage(test_allocator, reader); + const received_message = try write_and_read_message( + test_allocator, + &list, + Config.BitcoinNetworkId.MAINNET, + Config.PROTOCOL_VERSION, + message, + ) orelse unreachable; defer received_message.deinit(test_allocator); switch (received_message) { - .Addr => |rm| try std.testing.expect(message.eql(&rm)), - .Version => unreachable, - .Verack => unreachable, - .Mempool => unreachable, - .Getaddr => unreachable, + .addr => |rm| try std.testing.expect(message.eql(&rm)), + else => unreachable, } + +// const writer = list.writer(); +// try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); +// var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); +// const reader = fbs.reader(); +// +// const received_message = try receiveMessage(test_allocator, reader); +// defer received_message.deinit(test_allocator); +// +// switch (received_message) { +// .Addr => |rm| try std.testing.expect(message.eql(&rm)), +// .Version => unreachable, +// .Verack => unreachable, +// .Mempool => unreachable, +// .Getaddr => unreachable, +// } } test "ko_receive_invalid_payload_length" { From 818e8c0b314f2d9d7e49f0db65fa0df445cc6fcd Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 26 Sep 2024 23:34:50 -0500 Subject: [PATCH 06/18] unit test --- src/network/protocol/messages/addr.zig | 91 ++++++++------------------ src/network/wire/lib.zig | 3 - 2 files changed, 29 insertions(+), 65 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 7429a66..48deaf7 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -149,65 +149,32 @@ pub const AddrMessage = struct { }; // TESTS - -//reworked -//test "ok_full_flow_AddrMessage" { -// const test_allocator = std.testing.allocator; -// const AddrMessage = protocol.messages.AddrMessage; -// { -// const ips = [_]NetworkIPAddr{ -// .time = 1414012889, -// .services = 1, -// .ip = [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 0, 2, 51 }, -// .port = 8333, -// }; -// -// const am = AddrMessage{ -// .ip_addresses = ips[0..], -// }; -// -// // Serialize -// const payload = try am.serialize(allocator); -// defer allocator.free(payload); -// -// // Deserialize -// const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); -// -// // Test equality -// try std.testing.expect(am.eql(&deserialized_am)); -// -// // Free allocated memory for deserialized inventory -// defer allocator.free(deserialized_am.inventory); -// } -//} - -//test "ok_full_flow_AddrMessage" { -// const allocator = std.testing.allocator; -// -// { -// const ips = [_]NetworkIPAddr{ -// NetworkIPAddr{ -// .time = 1414012889, -// .services = ServiceFlags.NODE_NETWORK, -// .ip = [_]u8{13} ** 16, -// .port = 33, -// -// }, -// }; -// const am = AddrMessage{ -// .ip_address_count = CompactSizeUint.new(1), -// .ip_addresses = try allocator.alloc(NetworkIPAddr, 1), -// }; -// defer allocator.free(am.ip_addresses); // Ensure to free the allocated memory -// -// am.ip_addresses[0] = ips[0]; -// -// const payload = try am.serialize(allocator); -// defer allocator.free(payload); -// const deserialized_am = try AddrMessage.deserializeSlice(allocator, payload); -// defer deserialized_am.deinit(allocator); -// -// try std.testing.expect(am.eql(&deserialized_am)); -// } -// -//} +test "ok_full_flow_AddrMessage" { + const test_allocator = std.testing.allocator; + { + const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); + defer test_allocator.free(ip_addresses); + + ip_addresses[0] = NetworkIPAddr{ + .time = 1414012889, + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + }; + const am = AddrMessage{ + .ip_addresses = ip_addresses[0..], + }; + + // Serialize + const payload = try am.serialize(test_allocator); + defer test_allocator.free(payload); + + // Deserialize + const deserialized_am = try AddrMessage.deserializeSlice(test_allocator, payload); + + // Test equality + try std.testing.expect(am.eql(&deserialized_am)); + + defer test_allocator.free(deserialized_am.ip_addresses); + } +} diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index d9ea79b..16eb92b 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -345,9 +345,6 @@ test "ok_send_addr_message" { var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); - //var message = AddrMessage{ - // .ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1), - //}; const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); defer test_allocator.free(ip_addresses); From 81280a8db7ac72670088fe8f9063018b7f1aab2a Mon Sep 17 00:00:00 2001 From: oxlime Date: Fri, 27 Sep 2024 11:18:41 -0500 Subject: [PATCH 07/18] review changes --- src/network/protocol/messages/addr.zig | 57 +++++++++++--------------- src/network/wire/lib.zig | 21 +--------- 2 files changed, 26 insertions(+), 52 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 48deaf7..f5511e5 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -1,36 +1,29 @@ const std = @import("std"); -const native_endian = @import("builtin").target.cpu.arch.endian(); const protocol = @import("../lib.zig"); -const ServiceFlags = protocol.ServiceFlags; - const Endian = std.builtin.Endian; const Sha256 = std.crypto.hash.sha2.Sha256; const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; -/// AddrMessage represents the "addr" message -/// -/// https://developer.bitcoin.org/reference/p2p_networking.html#addr pub const NetworkIPAddr = struct { time: u32, // Unix epoch time services: u64, // Services offered by the node ip: [16]u8, // IPv6 address (including IPv4-mapped) port: u16, // Port number -// NetworkIPAddr eql -pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { - return self.time == other.time - and self.services == other.services - and std.mem.eql(u8, &self.ip, &other.ip) - and self.port == other.port; -} + // NetworkIPAddr eql + pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { + return self.time == other.time and self.services == other.services and std.mem.eql(u8, &self.ip, &other.ip) and self.port == other.port; + } }; +/// AddrMessage represents the "addr" message +/// +/// https://developer.bitcoin.org/reference/p2p_networking.html#addr pub const AddrMessage = struct { ip_addresses: []NetworkIPAddr, - pub inline fn name() *const [12]u8 { return protocol.CommandNames.ADDR ++ [_]u8{0} ** 8; } @@ -52,7 +45,7 @@ pub const AddrMessage = struct { /// Free the `user_agent` if there is one pub fn deinit(self: AddrMessage, allocator: std.mem.Allocator) void { - allocator.free(self.ip_addresses); + allocator.free(self.ip_addresses); } /// Serialize the message as bytes and write them to the Writer. @@ -70,7 +63,7 @@ pub const AddrMessage = struct { for (self.ip_addresses) |*ip_address| { try w.writeInt(u32, ip_address.time, .little); try w.writeInt(u64, ip_address.services, .little); - try w.writeAll(std.mem.asBytes(&ip_address.ip)); + try w.writeAll(std.mem.asBytes(&ip_address.ip)); try w.writeInt(u16, ip_address.port, .big); } } @@ -132,19 +125,19 @@ pub const AddrMessage = struct { pub fn hintSerializedLen(self: AddrMessage) usize { // 4 + 8 + 16 + 2 const fixed_length_per_ip = 30; - return 1 + self.ip_addresses.len * fixed_length_per_ip;// 1 for CompactSizeUint - + const count = CompactSizeUint.new(self.ip_addresses.len).hint_encoded_len(); + return count + self.ip_addresses.len * fixed_length_per_ip; } pub fn eql(self: *const AddrMessage, other: *const AddrMessage) bool { if (self.ip_addresses.len != other.ip_addresses.len) return false; - const count = @as(usize, self.ip_addresses.len); - for (0..count) |i| { - if (!self.ip_addresses[i].eql(&other.ip_addresses[i])) return false; - } + const count = @as(usize, self.ip_addresses.len); + for (0..count) |i| { + if (!self.ip_addresses[i].eql(&other.ip_addresses[i])) return false; + } - return true; + return true; } }; @@ -152,15 +145,15 @@ pub const AddrMessage = struct { test "ok_full_flow_AddrMessage" { const test_allocator = std.testing.allocator; { - const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); - defer test_allocator.free(ip_addresses); - - ip_addresses[0] = NetworkIPAddr{ - .time = 1414012889, - .services = 1, - .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, - .port = 8080, - }; + const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); + defer test_allocator.free(ip_addresses); + + ip_addresses[0] = NetworkIPAddr{ + .time = 1414012889, + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + }; const am = AddrMessage{ .ip_addresses = ip_addresses[0..], }; diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index 16eb92b..22b184c 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -19,9 +19,6 @@ pub const Error = error{ MessageTooLarge, }; -pub const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; -const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; - /// Return the checksum of a slice /// /// Use it on serialized messages to compute the header's value @@ -336,11 +333,11 @@ test "ok_send_pong_message" { test "ok_send_addr_message" { const Config = @import("../../config/config.zig").Config; + const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; const AddrMessage = protocol.messages.AddrMessage; - //const ServiceFlags = protocol.ServiceFlags; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -372,22 +369,6 @@ test "ok_send_addr_message" { .addr => |rm| try std.testing.expect(message.eql(&rm)), else => unreachable, } - -// const writer = list.writer(); -// try sendMessage(test_allocator, writer, protocol.PROTOCOL_VERSION, protocol.BitcoinNetworkId.MAINNET, message); -// var fbs: std.io.FixedBufferStream([]u8) = std.io.fixedBufferStream(list.items); -// const reader = fbs.reader(); -// -// const received_message = try receiveMessage(test_allocator, reader); -// defer received_message.deinit(test_allocator); -// -// switch (received_message) { -// .Addr => |rm| try std.testing.expect(message.eql(&rm)), -// .Version => unreachable, -// .Verack => unreachable, -// .Mempool => unreachable, -// .Getaddr => unreachable, -// } } test "ko_receive_invalid_payload_length" { From 77b5cd6a19940c64a4ef0ccee8b20295aa9b3e9a Mon Sep 17 00:00:00 2001 From: oxlime Date: Wed, 2 Oct 2024 08:27:47 -0500 Subject: [PATCH 08/18] NetworkIpAddress.deserializeReader --- src/network/protocol/messages/addr.zig | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index f5511e5..f198a1b 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -16,6 +16,15 @@ pub const NetworkIPAddr = struct { pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { return self.time == other.time and self.services == other.services and std.mem.eql(u8, &self.ip, &other.ip) and self.port == other.port; } + + pub fn deserializeReader(reader: anytype) !NetworkIPAddr { + return NetworkIPAddr{ + .time = try reader.readInt(u32, .little), + .services = try reader.readInt(u64, .little), + .ip = try reader.readBytesNoEof(16), + .port = try reader.readInt(u16, .big), + }; + } }; /// AddrMessage represents the "addr" message @@ -97,22 +106,19 @@ pub const AddrMessage = struct { if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); } - var vm: AddrMessage = undefined; const ip_address_count = try CompactSizeUint.decodeReader(r); // Allocate space for IP addresses const ip_addresses = try allocator.alloc(NetworkIPAddr, ip_address_count.value()); + errdefer allocator.free(ip_addresses); - vm.ip_addresses = ip_addresses; - - for (vm.ip_addresses) |*ip_address| { - ip_address.time = try r.readInt(u32, .little); - ip_address.services = try r.readInt(u64, .little); - try r.readNoEof(&ip_address.ip); - ip_address.port = try r.readInt(u16, .big); + for (ip_addresses) |*ip_address| { + ip_address.* = try NetworkIPAddr.deserializeReader(r); } - return vm; + return AddrMessage{ + .ip_addresses = ip_addresses, + }; } /// Deserialize bytes into a `AddrMessage` From 9ab87794b0b78a9f53401831a87f6f41301c3e57 Mon Sep 17 00:00:00 2001 From: oxlime Date: Wed, 2 Oct 2024 08:35:48 -0500 Subject: [PATCH 09/18] NetworkIpAddress.serializeWriter --- src/network/protocol/messages/addr.zig | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index f198a1b..4417d8b 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -17,6 +17,13 @@ pub const NetworkIPAddr = struct { return self.time == other.time and self.services == other.services and std.mem.eql(u8, &self.ip, &other.ip) and self.port == other.port; } + pub fn serializeWriter(self: *const NetworkIPAddr, writer: anytype) !void { + try writer.writeInt(u32, self.time, .little); + try writer.writeInt(u64, self.services, .little); + try writer.writeAll(&self.ip); + try writer.writeInt(u16, self.port, .big); + } + pub fn deserializeReader(reader: anytype) !NetworkIPAddr { return NetworkIPAddr{ .time = try reader.readInt(u32, .little), @@ -65,15 +72,9 @@ pub const AddrMessage = struct { if (!std.meta.hasFn(@TypeOf(w), "writeInt")) @compileError("Expects r to have fn 'writeInt'."); if (!std.meta.hasFn(@TypeOf(w), "writeAll")) @compileError("Expects r to have fn 'writeAll'."); } - //try CompactSizeUint.new(@intCast(self.ip_addresses.len)).encodeToWriter(w); try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); - - // Serialize each IP address - for (self.ip_addresses) |*ip_address| { - try w.writeInt(u32, ip_address.time, .little); - try w.writeInt(u64, ip_address.services, .little); - try w.writeAll(std.mem.asBytes(&ip_address.ip)); - try w.writeInt(u16, ip_address.port, .big); + for (self.ip_addresses) |*addr| { + try addr.serializeWriter(w); } } From f6006d0e9f9526036fd3d7016a621cd987846535 Mon Sep 17 00:00:00 2001 From: oxlime Date: Wed, 2 Oct 2024 08:49:41 -0500 Subject: [PATCH 10/18] zig fmt --- src/network/protocol/messages/addr.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 4417d8b..2f2bd8a 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -133,7 +133,7 @@ pub const AddrMessage = struct { // 4 + 8 + 16 + 2 const fixed_length_per_ip = 30; const count = CompactSizeUint.new(self.ip_addresses.len).hint_encoded_len(); - return count + self.ip_addresses.len * fixed_length_per_ip; + return count + self.ip_addresses.len * fixed_length_per_ip; } pub fn eql(self: *const AddrMessage, other: *const AddrMessage) bool { From a7db9a749b8c142797f89e39bfc2452b46d6052d Mon Sep 17 00:00:00 2001 From: oxlime Date: Wed, 2 Oct 2024 09:00:17 -0500 Subject: [PATCH 11/18] fix error --- src/network/protocol/messages/lib.zig | 3 --- src/network/wire/lib.zig | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index 4a4520d..b69c6b2 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -7,11 +7,8 @@ pub const BlockMessage = @import("block.zig").BlockMessage; pub const GetblocksMessage = @import("getblocks.zig").GetblocksMessage; pub const PingMessage = @import("ping.zig").PingMessage; pub const PongMessage = @import("pong.zig").PongMessage; -<<<<<<< HEAD pub const AddrMessage = @import("addr.zig").AddrMessage; -======= pub const MerkleBlockMessage = @import("merkleblock.zig").MerkleBlockMessage; ->>>>>>> main pub const FeeFilterMessage = @import("feefilter.zig").FeeFilterMessage; pub const SendCmpctMessage = @import("sendcmpct.zig").SendCmpctMessage; pub const FilterClearMessage = @import("filterclear.zig").FilterClearMessage; diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index 09a5b3a..e185dc3 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -407,7 +407,6 @@ test "ok_send_pong_message" { } } -<<<<<<< HEAD test "ok_send_addr_message" { const Config = @import("../../config/config.zig").Config; const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; @@ -433,7 +432,7 @@ test "ok_send_addr_message" { .ip_addresses = ip_addresses, }; - const received_message = try write_and_read_message( + var received_message = try write_and_read_message( test_allocator, &list, Config.BitcoinNetworkId.MAINNET, From 409fc1035b9ad89507ee2e248538a40fdc2b1d90 Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 3 Oct 2024 00:14:46 -0500 Subject: [PATCH 12/18] networkAddress changes --- src/network/peer.zig | 15 +++- src/network/protocol/NetworkAddress.zig | 30 ++++++- src/network/protocol/messages/addr.zig | 50 ++++-------- src/network/protocol/messages/lib.zig | 4 +- src/network/protocol/messages/version.zig | 98 +++++++++++------------ src/network/wire/lib.zig | 77 +++++++++++------- 6 files changed, 155 insertions(+), 119 deletions(-) diff --git a/src/network/peer.zig b/src/network/peer.zig index 4a2b8a8..643ad58 100644 --- a/src/network/peer.zig +++ b/src/network/peer.zig @@ -4,6 +4,7 @@ const protocol = @import("./protocol/lib.zig"); const wire = @import("./wire/lib.zig"); const Config = @import("../config/config.zig").Config; const MessageUtils = @import("./message/utils.zig"); +const NetworkAddress = @import("./protocol/NetworkAddress.zig").NetworkAddress; pub const Boundness = enum { inbound, @@ -80,7 +81,7 @@ pub const Peer = struct { switch (received_message) { .version => |vm| { self.protocol_version = @min(self.config.protocol_version, vm.version); - self.services = vm.trans_services; + self.services = vm.addr_from.services; }, .verack => return, @@ -95,8 +96,16 @@ pub const Peer = struct { const message = protocol.messages.VersionMessage.new( self.config.protocol_version, - .{ .ip = std.mem.zeroes([16]u8), .port = 0, .services = self.config.services }, - .{ .ip = address.in6.sa.addr, .port = address.in6.getPort(), .services = 0 }, + NetworkAddress{ + .services = self.config.services, + .ip = std.mem.zeroes([16]u8), + .port = 0, + }, + NetworkAddress{ + .services = 0, + .ip = address.in6.sa.addr, + .port = address.in6.getPort(), + }, std.crypto.random.int(u64), self.config.bestBlock(), ); diff --git a/src/network/protocol/NetworkAddress.zig b/src/network/protocol/NetworkAddress.zig index e496c25..d9eb5cc 100644 --- a/src/network/protocol/NetworkAddress.zig +++ b/src/network/protocol/NetworkAddress.zig @@ -1,3 +1,27 @@ -ip: [16]u8, -port: u16, -services: u64, +const std = @import("std"); + +pub const NetworkAddress = struct { + ip: [16]u8, + port: u16, + services: u64, + + pub fn eql(self: *const NetworkAddress, other: *const NetworkAddress) bool { + return std.mem.eql(u8, &self.ip, &other.ip) and + self.port == other.port and + self.services == other.services; + } + + pub fn serializeToWriter(self: *const NetworkAddress, writer: anytype) !void { + try writer.writeInt(u64, self.services, .little); + try writer.writeAll(&self.ip); + try writer.writeInt(u16, self.port, .big); + } + + pub fn deserializeReader(reader: anytype) !NetworkAddress { + return NetworkAddress{ + .services = try reader.readInt(u64, .little), + .ip = try reader.readBytesNoEof(16), + .port = try reader.readInt(u16, .big), + }; + } +}; diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 2f2bd8a..1978d7e 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -1,5 +1,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const genericChecksum = @import("lib.zig").genericChecksum; +const NetworkAddress = @import("../NetworkAddress.zig").NetworkAddress; const Endian = std.builtin.Endian; const Sha256 = std.crypto.hash.sha2.Sha256; @@ -8,28 +10,22 @@ const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; pub const NetworkIPAddr = struct { time: u32, // Unix epoch time - services: u64, // Services offered by the node - ip: [16]u8, // IPv6 address (including IPv4-mapped) - port: u16, // Port number + address: NetworkAddress, // NetworkIPAddr eql pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { - return self.time == other.time and self.services == other.services and std.mem.eql(u8, &self.ip, &other.ip) and self.port == other.port; + return self.time == other.time and self.address.eql(&other.address); } - pub fn serializeWriter(self: *const NetworkIPAddr, writer: anytype) !void { + pub fn serializeToWriter(self: *const NetworkIPAddr, writer: anytype) !void { try writer.writeInt(u32, self.time, .little); - try writer.writeInt(u64, self.services, .little); - try writer.writeAll(&self.ip); - try writer.writeInt(u16, self.port, .big); + try self.address.serializeToWriter(writer); } pub fn deserializeReader(reader: anytype) !NetworkIPAddr { return NetworkIPAddr{ .time = try reader.readInt(u32, .little), - .services = try reader.readInt(u64, .little), - .ip = try reader.readBytesNoEof(16), - .port = try reader.readInt(u16, .big), + .address = try NetworkAddress.deserializeReader(reader), }; } }; @@ -47,16 +43,8 @@ pub const AddrMessage = struct { /// Returns the message checksum /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` - pub fn checksum(self: AddrMessage) [4]u8 { - var digest: [32]u8 = undefined; - var hasher = Sha256.init(.{}); - const writer = hasher.writer(); - self.serializeToWriter(writer) catch unreachable; // Sha256.write is infaible - hasher.final(&digest); - - Sha256.hash(&digest, &digest, .{}); - - return digest[0..4].*; + pub fn checksum(self: *const AddrMessage) [4]u8 { + return genericChecksum(self); } /// Free the `user_agent` if there is one @@ -68,13 +56,9 @@ pub const AddrMessage = struct { /// /// `w` should be a valid `Writer`. pub fn serializeToWriter(self: *const AddrMessage, w: anytype) !void { - comptime { - if (!std.meta.hasFn(@TypeOf(w), "writeInt")) @compileError("Expects r to have fn 'writeInt'."); - if (!std.meta.hasFn(@TypeOf(w), "writeAll")) @compileError("Expects r to have fn 'writeAll'."); - } try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); for (self.ip_addresses) |*addr| { - try addr.serializeWriter(w); + try addr.serializeToWriter(w); } } @@ -101,12 +85,6 @@ pub const AddrMessage = struct { /// Deserialize a Reader bytes as a `AddrMessage` pub fn deserializeReader(allocator: std.mem.Allocator, r: anytype) !AddrMessage { - comptime { - if (!std.meta.hasFn(@TypeOf(r), "readInt")) @compileError("Expects r to have fn 'readInt'."); - if (!std.meta.hasFn(@TypeOf(r), "readNoEof")) @compileError("Expects r to have fn 'readNoEof'."); - if (!std.meta.hasFn(@TypeOf(r), "readAll")) @compileError("Expects r to have fn 'readAll'."); - } - const ip_address_count = try CompactSizeUint.decodeReader(r); // Allocate space for IP addresses @@ -157,9 +135,11 @@ test "ok_full_flow_AddrMessage" { ip_addresses[0] = NetworkIPAddr{ .time = 1414012889, - .services = 1, - .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, - .port = 8080, + .address = NetworkAddress{ + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + } }; const am = AddrMessage{ .ip_addresses = ip_addresses[0..], diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index b69c6b2..77cfd9e 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -150,7 +150,7 @@ pub const Message = union(MessageTypes) { .notfound => |*m| m.checksum(), .sendheaders => |*m| m.checksum(), .filterload => |*m| m.checksum(), - .addr => |m| m.checksum(), + .addr => |*m| m.checksum(), }; } @@ -172,7 +172,7 @@ pub const Message = union(MessageTypes) { .notfound => |m| m.hintSerializedLen(), .sendheaders => |m| m.hintSerializedLen(), .filterload => |*m| m.hintSerializedLen(), - .addr => |m| m.hintSerializedLen(), + .addr => |*m| m.hintSerializedLen(), }; } }; diff --git a/src/network/protocol/messages/version.zig b/src/network/protocol/messages/version.zig index 0f4b3ef..a2080cc 100644 --- a/src/network/protocol/messages/version.zig +++ b/src/network/protocol/messages/version.zig @@ -7,22 +7,19 @@ const Sha256 = std.crypto.hash.sha2.Sha256; const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; const genericChecksum = @import("lib.zig").genericChecksum; +const NetworkAddress = @import("../NetworkAddress.zig").NetworkAddress; /// VersionMessage represents the "version" message /// /// https://developer.bitcoin.org/reference/p2p_networking.html#version pub const VersionMessage = struct { - recv_ip: [16]u8, - trans_ip: [16]u8, timestamp: i64, services: u64 = 0, nonce: u64, - recv_services: u64, - trans_services: u64, + addr_recv: NetworkAddress, + addr_from: NetworkAddress, version: i32, start_height: i32, - recv_port: u16, - trans_port: u16, user_agent: ?[]const u8 = null, relay: ?bool = null, @@ -64,13 +61,9 @@ pub const VersionMessage = struct { try w.writeInt(i32, self.version, .little); try w.writeInt(u64, self.services, .little); try w.writeInt(i64, self.timestamp, .little); - try w.writeInt(u64, self.recv_services, .little); - try w.writeAll(std.mem.asBytes(&self.recv_ip)); - try w.writeInt(u16, self.recv_port, .big); - try w.writeInt(u64, self.trans_services, .little); - try w.writeAll(std.mem.asBytes(&self.trans_ip)); - try w.writeInt(u16, self.trans_port, .big); try w.writeInt(u64, self.nonce, .little); + try self.addr_recv.serializeToWriter(w); + try self.addr_from.serializeToWriter(w); try compact_user_agent_len.encodeToWriter(w); if (user_agent_len != 0) { try w.writeAll(self.user_agent.?); @@ -115,14 +108,11 @@ pub const VersionMessage = struct { vm.version = try r.readInt(i32, .little); vm.services = try r.readInt(u64, .little); vm.timestamp = try r.readInt(i64, .little); - vm.recv_services = try r.readInt(u64, .little); - try r.readNoEof(&vm.recv_ip); - vm.recv_port = try r.readInt(u16, .big); - vm.trans_services = try r.readInt(u64, .little); - try r.readNoEof(&vm.trans_ip); - vm.trans_port = try r.readInt(u16, .big); vm.nonce = try r.readInt(u64, .little); + vm.addr_recv = try NetworkAddress.deserializeReader(r); + vm.addr_from = try NetworkAddress.deserializeReader(r); + const user_agent_len = (try CompactSizeUint.decodeReader(r)).value(); if (user_agent_len != 0) { @@ -161,15 +151,17 @@ pub const VersionMessage = struct { if (self.version != other.version // or self.services != other.services // or self.timestamp != other.timestamp // - or self.recv_services != other.recv_services // - or !std.mem.eql(u8, &self.recv_ip, &other.recv_ip) // - or self.recv_port != other.recv_port // - or self.trans_services != other.trans_services // - or !std.mem.eql(u8, &self.trans_ip, &other.trans_ip) // - or self.trans_port != other.trans_port // + // or self.nonce != other.nonce) { return false; } + + // Compare NetworkAddress fields + if (!self.addr_recv.eql(&other.addr_recv) or + !self.addr_from.eql(&other.addr_from)) + { + return false; + } // user_agent if (self.user_agent) |lua| { @@ -194,16 +186,12 @@ pub const VersionMessage = struct { return true; } - pub fn new(protocol_version: i32, me: protocol.NetworkAddress, you: protocol.NetworkAddress, nonce: u64, last_block: i32) Self { + pub fn new(protocol_version: i32, me: NetworkAddress, you: NetworkAddress, nonce: u64, last_block: i32) Self { return .{ .version = protocol_version, .timestamp = std.time.timestamp(), - .recv_services = you.services, - .trans_services = me.services, - .recv_ip = you.ip, - .trans_ip = me.ip, - .recv_port = you.port, - .trans_port = me.port, + .addr_recv = you, + .addr_from = me, .nonce = nonce, .start_height = last_block, }; @@ -221,12 +209,16 @@ test "ok_full_flow_VersionMessage" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress{ + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress{ + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = null, .start_height = 1000, @@ -247,12 +239,16 @@ test "ok_full_flow_VersionMessage" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = null, .start_height = 1000, @@ -274,12 +270,16 @@ test "ok_full_flow_VersionMessage" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = &user_agent, .start_height = 1000, diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index e185dc3..a57407c 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -176,6 +176,7 @@ test "ok_send_version_message" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; + const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -185,12 +186,16 @@ test "ok_send_version_message" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = &user_agent, .start_height = 1000, @@ -410,6 +415,7 @@ test "ok_send_pong_message" { test "ok_send_addr_message" { const Config = @import("../../config/config.zig").Config; const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; + const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; @@ -423,9 +429,11 @@ test "ok_send_addr_message" { ip_addresses[0] = NetworkIPAddr{ .time = 1414012889, - .services = 1, - .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, - .port = 8080, + .address = NetworkAddress{ + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + } }; var message = AddrMessage{ @@ -479,6 +487,7 @@ test "ko_receive_invalid_payload_length" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; + const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -488,12 +497,16 @@ test "ko_receive_invalid_payload_length" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = &user_agent, .start_height = 1000, @@ -519,6 +532,7 @@ test "ko_receive_invalid_checksum" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; + const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -528,12 +542,16 @@ test "ko_receive_invalid_checksum" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = &user_agent, .start_height = 1000, @@ -559,6 +577,7 @@ test "ko_receive_invalid_command" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; + const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -568,12 +587,16 @@ test "ko_receive_invalid_command" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .recv_services = ServiceFlags.NODE_WITNESS, - .trans_services = ServiceFlags.NODE_BLOOM, - .recv_ip = [_]u8{13} ** 16, - .trans_ip = [_]u8{12} ** 16, - .recv_port = 33, - .trans_port = 22, + .addr_recv = NetworkAddress { + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress { + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, + }, .nonce = 31, .user_agent = &user_agent, .start_height = 1000, From 6e9a831e8a7ee65fde55e514f9a6a068effc659f Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 3 Oct 2024 00:16:46 -0500 Subject: [PATCH 13/18] zig fmt --- src/network/peer.zig | 20 ++++---- src/network/protocol/messages/addr.zig | 13 ++--- src/network/protocol/messages/filterload.zig | 4 +- src/network/protocol/messages/version.zig | 54 ++++++++++---------- src/network/wire/lib.zig | 29 +++++------ 5 files changed, 57 insertions(+), 63 deletions(-) diff --git a/src/network/peer.zig b/src/network/peer.zig index 643ad58..297bf22 100644 --- a/src/network/peer.zig +++ b/src/network/peer.zig @@ -96,16 +96,16 @@ pub const Peer = struct { const message = protocol.messages.VersionMessage.new( self.config.protocol_version, - NetworkAddress{ - .services = self.config.services, - .ip = std.mem.zeroes([16]u8), - .port = 0, - }, - NetworkAddress{ - .services = 0, - .ip = address.in6.sa.addr, - .port = address.in6.getPort(), - }, + NetworkAddress{ + .services = self.config.services, + .ip = std.mem.zeroes([16]u8), + .port = 0, + }, + NetworkAddress{ + .services = 0, + .ip = address.in6.sa.addr, + .port = address.in6.getPort(), + }, std.crypto.random.int(u64), self.config.bestBlock(), ); diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 1978d7e..81429b8 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -133,14 +133,11 @@ test "ok_full_flow_AddrMessage" { const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); defer test_allocator.free(ip_addresses); - ip_addresses[0] = NetworkIPAddr{ - .time = 1414012889, - .address = NetworkAddress{ - .services = 1, - .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, - .port = 8080, - } - }; + ip_addresses[0] = NetworkIPAddr{ .time = 1414012889, .address = NetworkAddress{ + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + } }; const am = AddrMessage{ .ip_addresses = ip_addresses[0..], }; diff --git a/src/network/protocol/messages/filterload.zig b/src/network/protocol/messages/filterload.zig index afa51db..6ec1116 100644 --- a/src/network/protocol/messages/filterload.zig +++ b/src/network/protocol/messages/filterload.zig @@ -69,7 +69,7 @@ pub const FilterLoadMessage = struct { const filter = try allocator.alloc(u8, filter_len); errdefer allocator.free(filter); try r.readNoEof(filter); - + const hash_func = try r.readInt(u32, .little); const tweak = try r.readInt(u32, .little); const flags = try r.readInt(u8, .little); @@ -90,7 +90,7 @@ pub const FilterLoadMessage = struct { pub fn hintSerializedLen(self: *const Self) usize { const fixed_length = 4 + 4 + 1; // hash_func (4 bytes) + tweak (4 bytes) + flags (1 byte) const compact_filter_len = CompactSizeUint.new(self.filter.len).hint_encoded_len(); - return compact_filter_len + self.filter.len + fixed_length; + return compact_filter_len + self.filter.len + fixed_length; } pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { diff --git a/src/network/protocol/messages/version.zig b/src/network/protocol/messages/version.zig index a2080cc..1c39a0a 100644 --- a/src/network/protocol/messages/version.zig +++ b/src/network/protocol/messages/version.zig @@ -151,11 +151,11 @@ pub const VersionMessage = struct { if (self.version != other.version // or self.services != other.services // or self.timestamp != other.timestamp // - // + // or self.nonce != other.nonce) { return false; } - + // Compare NetworkAddress fields if (!self.addr_recv.eql(&other.addr_recv) or !self.addr_from.eql(&other.addr_from)) @@ -210,15 +210,15 @@ test "ok_full_flow_VersionMessage" { .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, .addr_recv = NetworkAddress{ - .services = ServiceFlags.NODE_WITNESS, - .ip = [_]u8{13} ** 16, - .port = 33, + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress{ + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, }, - .addr_from = NetworkAddress{ - .services = ServiceFlags.NODE_BLOOM, - .ip = [_]u8{12} ** 16, - .port = 22, - }, .nonce = 31, .user_agent = null, .start_height = 1000, @@ -239,16 +239,16 @@ test "ok_full_flow_VersionMessage" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { - .services = ServiceFlags.NODE_WITNESS, - .ip = [_]u8{13} ** 16, - .port = 33, + .addr_recv = NetworkAddress{ + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, + }, + .addr_from = NetworkAddress{ + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, }, - .addr_from = NetworkAddress { - .services = ServiceFlags.NODE_BLOOM, - .ip = [_]u8{12} ** 16, - .port = 22, - }, .nonce = 31, .user_agent = null, .start_height = 1000, @@ -270,15 +270,15 @@ test "ok_full_flow_VersionMessage" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { - .services = ServiceFlags.NODE_WITNESS, - .ip = [_]u8{13} ** 16, - .port = 33, + .addr_recv = NetworkAddress{ + .services = ServiceFlags.NODE_WITNESS, + .ip = [_]u8{13} ** 16, + .port = 33, }, - .addr_from = NetworkAddress { - .services = ServiceFlags.NODE_BLOOM, - .ip = [_]u8{12} ** 16, - .port = 22, + .addr_from = NetworkAddress{ + .services = ServiceFlags.NODE_BLOOM, + .ip = [_]u8{12} ** 16, + .port = 22, }, .nonce = 31, .user_agent = &user_agent, diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index a57407c..4dc680e 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -186,12 +186,12 @@ test "ok_send_version_message" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { + .addr_recv = NetworkAddress{ .services = ServiceFlags.NODE_WITNESS, .ip = [_]u8{13} ** 16, .port = 33, }, - .addr_from = NetworkAddress { + .addr_from = NetworkAddress{ .services = ServiceFlags.NODE_BLOOM, .ip = [_]u8{12} ** 16, .port = 22, @@ -427,14 +427,11 @@ test "ok_send_addr_message" { const ip_addresses = try test_allocator.alloc(NetworkIPAddr, 1); defer test_allocator.free(ip_addresses); - ip_addresses[0] = NetworkIPAddr{ - .time = 1414012889, - .address = NetworkAddress{ - .services = 1, - .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, - .port = 8080, - } - }; + ip_addresses[0] = NetworkIPAddr{ .time = 1414012889, .address = NetworkAddress{ + .services = 1, + .ip = [16]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 2, 51 }, + .port = 8080, + } }; var message = AddrMessage{ .ip_addresses = ip_addresses, @@ -497,12 +494,12 @@ test "ko_receive_invalid_payload_length" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { + .addr_recv = NetworkAddress{ .services = ServiceFlags.NODE_WITNESS, .ip = [_]u8{13} ** 16, .port = 33, }, - .addr_from = NetworkAddress { + .addr_from = NetworkAddress{ .services = ServiceFlags.NODE_BLOOM, .ip = [_]u8{12} ** 16, .port = 22, @@ -542,12 +539,12 @@ test "ko_receive_invalid_checksum" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { + .addr_recv = NetworkAddress{ .services = ServiceFlags.NODE_WITNESS, .ip = [_]u8{13} ** 16, .port = 33, }, - .addr_from = NetworkAddress { + .addr_from = NetworkAddress{ .services = ServiceFlags.NODE_BLOOM, .ip = [_]u8{12} ** 16, .port = 22, @@ -587,12 +584,12 @@ test "ko_receive_invalid_command" { .version = 42, .services = ServiceFlags.NODE_NETWORK, .timestamp = 43, - .addr_recv = NetworkAddress { + .addr_recv = NetworkAddress{ .services = ServiceFlags.NODE_WITNESS, .ip = [_]u8{13} ** 16, .port = 33, }, - .addr_from = NetworkAddress { + .addr_from = NetworkAddress{ .services = ServiceFlags.NODE_BLOOM, .ip = [_]u8{12} ** 16, .port = 22, From bb2a8a74e16201d612866c70f10f35ab7b7bcf5f Mon Sep 17 00:00:00 2001 From: oxlime Date: Thu, 3 Oct 2024 10:49:30 -0500 Subject: [PATCH 14/18] fix --- src/network/protocol/messages/lib.zig | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index 68e3f9c..2bed402 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -160,12 +160,9 @@ pub const Message = union(MessageTypes) { .notfound => |*m| m.checksum(), .sendheaders => |*m| m.checksum(), .filterload => |*m| m.checksum(), -<<<<<<< HEAD .addr => |*m| m.checksum(), -======= .headers => |*m| m.checksum(), .cmpctblock => |*m| m.checksum(), ->>>>>>> origin/main }; } @@ -187,12 +184,9 @@ pub const Message = union(MessageTypes) { .notfound => |m| m.hintSerializedLen(), .sendheaders => |m| m.hintSerializedLen(), .filterload => |*m| m.hintSerializedLen(), -<<<<<<< HEAD .addr => |*m| m.hintSerializedLen(), -======= .headers => |*m| m.hintSerializedLen(), .cmpctblock => |*m| m.hintSerializedLen(), ->>>>>>> origin/main }; } }; From 0af9c4d1a2d264e123f439a38af2751e86618b3f Mon Sep 17 00:00:00 2001 From: oxlime Date: Fri, 4 Oct 2024 10:51:34 -0500 Subject: [PATCH 15/18] remove << --- src/network/protocol/messages/lib.zig | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index 079b513..d8ee65b 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -97,12 +97,9 @@ pub const Message = union(MessageTypes) { switch (self.*) { .version => |*m| m.deinit(allocator), .getblocks => |*m| m.deinit(allocator), -<<<<<<< HEAD .ping => {}, .pong => {}, .addr => |m| m.deinit(allocator), -======= ->>>>>>> bf535489e34dac03fabc9ab2dd605d0c5b17af69 .merkleblock => |*m| m.deinit(allocator), .block => |*m| m.deinit(allocator), .filteradd => |*m| m.deinit(allocator), From cdbfa862ccb3c2edc233e6f3bc8c64193641f752 Mon Sep 17 00:00:00 2001 From: oxlime Date: Fri, 4 Oct 2024 10:57:49 -0500 Subject: [PATCH 16/18] fix location --- src/network/peer.zig | 2 +- src/network/protocol/messages/addr.zig | 2 +- src/network/protocol/messages/version.zig | 2 +- src/network/wire/lib.zig | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/network/peer.zig b/src/network/peer.zig index 297bf22..c861b7e 100644 --- a/src/network/peer.zig +++ b/src/network/peer.zig @@ -4,7 +4,7 @@ const protocol = @import("./protocol/lib.zig"); const wire = @import("./wire/lib.zig"); const Config = @import("../config/config.zig").Config; const MessageUtils = @import("./message/utils.zig"); -const NetworkAddress = @import("./protocol/NetworkAddress.zig").NetworkAddress; +const NetworkAddress = @import("./protocol/types/NetworkAddress.zig").NetworkAddress; pub const Boundness = enum { inbound, diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 81429b8..5b579c5 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -1,7 +1,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); const genericChecksum = @import("lib.zig").genericChecksum; -const NetworkAddress = @import("../NetworkAddress.zig").NetworkAddress; +const NetworkAddress = @import("../types/NetworkAddress.zig").NetworkAddress; const Endian = std.builtin.Endian; const Sha256 = std.crypto.hash.sha2.Sha256; diff --git a/src/network/protocol/messages/version.zig b/src/network/protocol/messages/version.zig index 1eb23ac..2a232b5 100644 --- a/src/network/protocol/messages/version.zig +++ b/src/network/protocol/messages/version.zig @@ -7,7 +7,7 @@ const Sha256 = std.crypto.hash.sha2.Sha256; const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; const genericChecksum = @import("lib.zig").genericChecksum; -const NetworkAddress = @import("../NetworkAddress.zig").NetworkAddress; +const NetworkAddress = @import("../types/NetworkAddress.zig").NetworkAddress; const genericSerialize = @import("lib.zig").genericSerialize; const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice; diff --git a/src/network/wire/lib.zig b/src/network/wire/lib.zig index 16f4363..a7d1174 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -179,7 +179,7 @@ test "ok_send_version_message" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; - const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; + const NetworkAddress = @import("../protocol/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -456,7 +456,7 @@ test "ok_send_pong_message" { test "ok_send_addr_message" { const Config = @import("../../config/config.zig").Config; const NetworkIPAddr = @import("../protocol/messages/addr.zig").NetworkIPAddr; - const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; + const NetworkAddress = @import("../protocol/types/NetworkAddress.zig").NetworkAddress; const ArrayList = std.ArrayList; const test_allocator = std.testing.allocator; @@ -525,7 +525,7 @@ test "ko_receive_invalid_payload_length" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; - const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; + const NetworkAddress = @import("../protocol/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -570,7 +570,7 @@ test "ko_receive_invalid_checksum" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; - const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; + const NetworkAddress = @import("../protocol/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -615,7 +615,7 @@ test "ko_receive_invalid_command" { const test_allocator = std.testing.allocator; const VersionMessage = protocol.messages.VersionMessage; const ServiceFlags = protocol.ServiceFlags; - const NetworkAddress = @import("../protocol/NetworkAddress.zig").NetworkAddress; + const NetworkAddress = @import("../protocol/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); From 2e27ca95004ffa97b0d1483788ed29d6d8aef638 Mon Sep 17 00:00:00 2001 From: oxlime Date: Fri, 4 Oct 2024 11:03:22 -0500 Subject: [PATCH 17/18] generic deserializeSlice --- src/network/protocol/messages/addr.zig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index 5b579c5..ab37328 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -2,6 +2,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); const genericChecksum = @import("lib.zig").genericChecksum; const NetworkAddress = @import("../types/NetworkAddress.zig").NetworkAddress; +const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice; const Endian = std.builtin.Endian; const Sha256 = std.crypto.hash.sha2.Sha256; @@ -36,6 +37,8 @@ pub const NetworkIPAddr = struct { pub const AddrMessage = struct { ip_addresses: []NetworkIPAddr, + const Self = @This(); + pub inline fn name() *const [12]u8 { return protocol.CommandNames.ADDR ++ [_]u8{0} ** 8; } @@ -102,9 +105,7 @@ pub const AddrMessage = struct { /// Deserialize bytes into a `AddrMessage` pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !AddrMessage { - var fbs = std.io.fixedBufferStream(bytes); - const reader = fbs.reader(); - return try AddrMessage.deserializeReader(allocator, reader); + return genericDeserializeSlice(Self, allocator, bytes); } pub fn hintSerializedLen(self: AddrMessage) usize { From 6ac71f07d00c2d7ed1e9051f02e29b2398839219 Mon Sep 17 00:00:00 2001 From: oxlime Date: Fri, 4 Oct 2024 11:06:28 -0500 Subject: [PATCH 18/18] generic serialize added --- src/network/protocol/messages/addr.zig | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/network/protocol/messages/addr.zig b/src/network/protocol/messages/addr.zig index ab37328..e096d05 100644 --- a/src/network/protocol/messages/addr.zig +++ b/src/network/protocol/messages/addr.zig @@ -3,6 +3,7 @@ const protocol = @import("../lib.zig"); const genericChecksum = @import("lib.zig").genericChecksum; const NetworkAddress = @import("../types/NetworkAddress.zig").NetworkAddress; const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice; +const genericSerialize = @import("lib.zig").genericSerialize; const Endian = std.builtin.Endian; const Sha256 = std.crypto.hash.sha2.Sha256; @@ -65,25 +66,9 @@ pub const AddrMessage = struct { } } - /// Serialize a message as bytes and write them to the buffer. - /// - /// buffer.len must be >= than self.hintSerializedLen() - pub fn serializeToSlice(self: *const AddrMessage, buffer: []u8) !void { - var fbs = std.io.fixedBufferStream(buffer); - const writer = fbs.writer(); - try self.serializeToWriter(writer); - } - /// Serialize a message as bytes and return them. pub fn serialize(self: *const AddrMessage, allocator: std.mem.Allocator) ![]u8 { - const serialized_len = self.hintSerializedLen(); - - const ret = try allocator.alloc(u8, serialized_len); - errdefer allocator.free(ret); - - try self.serializeToSlice(ret); - - return ret; + return genericSerialize(self, allocator); } /// Deserialize a Reader bytes as a `AddrMessage`