From eb888a0e2326ec826f2ce16bc8eeebaf5d8f4427 Mon Sep 17 00:00:00 2001 From: oxlime <93354898+oxlime@users.noreply.github.com> Date: Mon, 7 Oct 2024 06:43:55 -0500 Subject: [PATCH] feat(p2p/messages): add addr message (#135) --- src/network/peer.zig | 15 +- src/network/protocol/messages/addr.zig | 143 ++++++++++++++++++ src/network/protocol/messages/filterload.zig | 4 +- src/network/protocol/messages/lib.zig | 11 +- src/network/protocol/messages/version.zig | 98 ++++++------ src/network/protocol/types/NetworkAddress.zig | 30 +++- src/network/wire/lib.zig | 110 +++++++++++--- 7 files changed, 329 insertions(+), 82 deletions(-) create mode 100644 src/network/protocol/messages/addr.zig diff --git a/src/network/peer.zig b/src/network/peer.zig index 4a2b8a8..c861b7e 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/types/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/messages/addr.zig b/src/network/protocol/messages/addr.zig new file mode 100644 index 0000000..e096d05 --- /dev/null +++ b/src/network/protocol/messages/addr.zig @@ -0,0 +1,143 @@ +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 genericSerialize = @import("lib.zig").genericSerialize; + +const Endian = std.builtin.Endian; +const Sha256 = std.crypto.hash.sha2.Sha256; + +const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; + +pub const NetworkIPAddr = struct { + time: u32, // Unix epoch time + address: NetworkAddress, + + // NetworkIPAddr eql + pub fn eql(self: *const NetworkIPAddr, other: *const NetworkIPAddr) bool { + return self.time == other.time and self.address.eql(&other.address); + } + + pub fn serializeToWriter(self: *const NetworkIPAddr, writer: anytype) !void { + try writer.writeInt(u32, self.time, .little); + try self.address.serializeToWriter(writer); + } + + pub fn deserializeReader(reader: anytype) !NetworkIPAddr { + return NetworkIPAddr{ + .time = try reader.readInt(u32, .little), + .address = try NetworkAddress.deserializeReader(reader), + }; + } +}; + +/// AddrMessage represents the "addr" message +/// +/// https://developer.bitcoin.org/reference/p2p_networking.html#addr +pub const AddrMessage = struct { + ip_addresses: []NetworkIPAddr, + + const Self = @This(); + + 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: *const AddrMessage) [4]u8 { + return genericChecksum(self); + } + + /// Free the `user_agent` if there is one + pub fn deinit(self: AddrMessage, allocator: std.mem.Allocator) void { + 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 { + try CompactSizeUint.new(self.ip_addresses.len).encodeToWriter(w); + for (self.ip_addresses) |*addr| { + try addr.serializeToWriter(w); + } + } + + /// Serialize a message as bytes and return them. + pub fn serialize(self: *const AddrMessage, allocator: std.mem.Allocator) ![]u8 { + return genericSerialize(self, allocator); + } + + /// Deserialize a Reader bytes as a `AddrMessage` + pub fn deserializeReader(allocator: std.mem.Allocator, r: anytype) !AddrMessage { + 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); + + for (ip_addresses) |*ip_address| { + ip_address.* = try NetworkIPAddr.deserializeReader(r); + } + + return AddrMessage{ + .ip_addresses = ip_addresses, + }; + } + + /// Deserialize bytes into a `AddrMessage` + pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !AddrMessage { + return genericDeserializeSlice(Self, allocator, bytes); + } + + pub fn hintSerializedLen(self: AddrMessage) usize { + // 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; + } + + 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; + } + + return true; + } +}; + +// TESTS +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, .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..], + }; + + // 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/protocol/messages/filterload.zig b/src/network/protocol/messages/filterload.zig index d3ffc8c..9b17311 100644 --- a/src/network/protocol/messages/filterload.zig +++ b/src/network/protocol/messages/filterload.zig @@ -58,7 +58,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); @@ -78,7 +78,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/lib.zig b/src/network/protocol/messages/lib.zig index 7395c1c..d8ee65b 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -7,6 +7,7 @@ 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; +pub const AddrMessage = @import("addr.zig").AddrMessage; pub const MerkleBlockMessage = @import("merkleblock.zig").MerkleBlockMessage; pub const FeeFilterMessage = @import("feefilter.zig").FeeFilterMessage; pub const SendCmpctMessage = @import("sendcmpct.zig").SendCmpctMessage; @@ -29,6 +30,7 @@ pub const MessageTypes = enum { getblocks, ping, pong, + addr, merkleblock, sendcmpct, feefilter, @@ -52,6 +54,7 @@ pub const Message = union(MessageTypes) { getblocks: GetblocksMessage, ping: PingMessage, pong: PongMessage, + addr: AddrMessage, merkleblock: MerkleBlockMessage, sendcmpct: SendCmpctMessage, feefilter: FeeFilterMessage, @@ -74,6 +77,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(), .merkleblock => |m| @TypeOf(m).name(), .sendcmpct => |m| @TypeOf(m).name(), .feefilter => |m| @TypeOf(m).name(), @@ -93,6 +97,9 @@ pub const Message = union(MessageTypes) { switch (self.*) { .version => |*m| m.deinit(allocator), .getblocks => |*m| m.deinit(allocator), + .ping => {}, + .pong => {}, + .addr => |m| m.deinit(allocator), .merkleblock => |*m| m.deinit(allocator), .block => |*m| m.deinit(allocator), .filteradd => |*m| m.deinit(allocator), @@ -121,6 +128,7 @@ pub const Message = union(MessageTypes) { .notfound => |*m| m.checksum(), .sendheaders => |*m| m.checksum(), .filterload => |*m| m.checksum(), + .addr => |*m| m.checksum(), .getdata => |*m| m.checksum(), .headers => |*m| m.checksum(), .cmpctblock => |*m| m.checksum(), @@ -145,6 +153,7 @@ pub const Message = union(MessageTypes) { .notfound => |m| m.hintSerializedLen(), .sendheaders => |m| m.hintSerializedLen(), .filterload => |*m| m.hintSerializedLen(), + .addr => |*m| m.hintSerializedLen(), .getdata => |m| m.hintSerializedLen(), .headers => |*m| m.hintSerializedLen(), .cmpctblock => |*m| m.hintSerializedLen(), @@ -194,4 +203,4 @@ pub fn genericDeserializeSlice(comptime T: type, allocator: std.mem.Allocator, b const reader = fbs.reader(); return try T.deserializeReader(allocator, reader); -} \ No newline at end of file +} diff --git a/src/network/protocol/messages/version.zig b/src/network/protocol/messages/version.zig index 4ffa346..2a232b5 100644 --- a/src/network/protocol/messages/version.zig +++ b/src/network/protocol/messages/version.zig @@ -7,6 +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("../types/NetworkAddress.zig").NetworkAddress; const genericSerialize = @import("lib.zig").genericSerialize; const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice; @@ -14,17 +15,13 @@ const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice; /// /// 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, @@ -66,13 +63,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.?); @@ -102,14 +95,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) { @@ -147,16 +137,18 @@ 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| { if (other.user_agent) |rua| { @@ -180,16 +172,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, }; @@ -206,12 +194,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, @@ -232,12 +224,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, @@ -259,12 +255,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/protocol/types/NetworkAddress.zig b/src/network/protocol/types/NetworkAddress.zig index e496c25..d9eb5cc 100644 --- a/src/network/protocol/types/NetworkAddress.zig +++ b/src/network/protocol/types/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/wire/lib.zig b/src/network/wire/lib.zig index 85163ff..a7d1174 100644 --- a/src/network/wire/lib.zig +++ b/src/network/wire/lib.zig @@ -125,6 +125,8 @@ 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 if (std.mem.eql(u8, &command, protocol.messages.MerkleBlockMessage.name())) protocol.messages.Message{ .merkleblock = try protocol.messages.MerkleBlockMessage.deserializeReader(allocator, r) } else if (std.mem.eql(u8, &command, protocol.messages.SendCmpctMessage.name())) @@ -177,6 +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/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -186,12 +189,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, @@ -446,6 +453,46 @@ 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/types/NetworkAddress.zig").NetworkAddress; + + const ArrayList = std.ArrayList; + const test_allocator = std.testing.allocator; + const AddrMessage = protocol.messages.AddrMessage; + + var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); + defer list.deinit(); + + 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, + } }; + + var message = AddrMessage{ + .ip_addresses = ip_addresses, + }; + + var 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)), + else => unreachable, + } +} + test "ok_send_sendheaders_message" { const Config = @import("../../config/config.zig").Config; const ArrayList = std.ArrayList; @@ -478,6 +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/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -487,12 +535,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, @@ -518,6 +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/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -527,12 +580,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, @@ -558,6 +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/types/NetworkAddress.zig").NetworkAddress; var list: std.ArrayListAligned(u8, null) = ArrayList(u8).init(test_allocator); defer list.deinit(); @@ -567,12 +625,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,