From 0e87d6b9aebba8fc016a5b2e8e856ec92d17526d Mon Sep 17 00:00:00 2001 From: Tuan Tran Date: Tue, 1 Oct 2024 18:32:06 +0700 Subject: [PATCH] chore: generic checksum impl (#145) --- src/network/protocol/messages/feefilter.zig | 11 ++--------- src/network/protocol/messages/filteradd.zig | 6 ++---- src/network/protocol/messages/filterclear.zig | 4 ++-- src/network/protocol/messages/getaddr.zig | 4 ++-- src/network/protocol/messages/getblocks.zig | 11 ++--------- src/network/protocol/messages/lib.zig | 18 ++++++++++++++++++ src/network/protocol/messages/mempool.zig | 4 ++-- src/network/protocol/messages/merkleblock.zig | 11 ++--------- src/network/protocol/messages/ping.zig | 11 ++--------- src/network/protocol/messages/pong.zig | 11 ++--------- src/network/protocol/messages/sendcmpct.zig | 11 ++--------- src/network/protocol/messages/verack.zig | 4 ++-- src/network/protocol/messages/version.zig | 11 ++--------- 13 files changed, 42 insertions(+), 75 deletions(-) diff --git a/src/network/protocol/messages/feefilter.zig b/src/network/protocol/messages/feefilter.zig index 73f4d25..3e70761 100644 --- a/src/network/protocol/messages/feefilter.zig +++ b/src/network/protocol/messages/feefilter.zig @@ -1,6 +1,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; +const genericChecksum = @import("lib.zig").genericChecksum; /// FeeFilterMessage represents the "feefilter" message /// @@ -18,15 +19,7 @@ pub const FeeFilterMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const Self) [4]u8 { - var digest: [32]u8 = undefined; - var hasher = Sha256.init(.{}); - const writer = hasher.writer(); - self.serializeToWriter(writer) catch unreachable; // Sha256.write is infallible - hasher.final(&digest); - - Sha256.hash(&digest, &digest, .{}); - - return digest[0..4].*; + return genericChecksum(self); } /// Serialize a message as bytes and write them to the buffer. diff --git a/src/network/protocol/messages/filteradd.zig b/src/network/protocol/messages/filteradd.zig index a683a21..1a4fd66 100644 --- a/src/network/protocol/messages/filteradd.zig +++ b/src/network/protocol/messages/filteradd.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const genericChecksum = @import("lib.zig").genericChecksum; /// FilterAddMessage represents the "filteradd" message /// @@ -15,10 +16,7 @@ pub const FilterAddMessage = struct { /// Returns the message checksum pub fn checksum(self: *const Self) [4]u8 { - var digest: [32]u8 = undefined; - std.crypto.hash.sha2.Sha256.hash(self.element, &digest, .{}); - std.crypto.hash.sha2.Sha256.hash(&digest, &digest, .{}); - return digest[0..4].*; + return genericChecksum(self); } /// Serialize the message as bytes and write them to the Writer. diff --git a/src/network/protocol/messages/filterclear.zig b/src/network/protocol/messages/filterclear.zig index c537a32..08e5b71 100644 --- a/src/network/protocol/messages/filterclear.zig +++ b/src/network/protocol/messages/filterclear.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const default_checksum = @import("lib.zig").default_checksum; /// FilterClear represents the "filterclear" message /// @@ -13,8 +14,7 @@ pub const FilterClearMessage = struct { pub fn checksum(self: FilterClearMessage) [4]u8 { _ = self; - // If payload is empty, the checksum is always 0x5df6e0e2 (SHA256(SHA256(""))) - return [4]u8{ 0x5d, 0xf6, 0xe0, 0xe2 }; + return default_checksum; } /// Serialize a message as bytes and return them. diff --git a/src/network/protocol/messages/getaddr.zig b/src/network/protocol/messages/getaddr.zig index 6fca13f..095f78a 100644 --- a/src/network/protocol/messages/getaddr.zig +++ b/src/network/protocol/messages/getaddr.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const default_checksum = @import("lib.zig").default_checksum; /// GetaddrMessage represents the "getaddr" message /// @@ -13,8 +14,7 @@ pub const GetaddrMessage = struct { pub fn checksum(self: GetaddrMessage) [4]u8 { _ = self; - // If payload is empty, the checksum is always 0x5df6e0e2 (SHA256(SHA256(""))) - return [4]u8{ 0x5d, 0xf6, 0xe0, 0xe2 }; + return default_checksum; } /// Serialize a message as bytes and return them. diff --git a/src/network/protocol/messages/getblocks.zig b/src/network/protocol/messages/getblocks.zig index 9e85ad2..d2fe032 100644 --- a/src/network/protocol/messages/getblocks.zig +++ b/src/network/protocol/messages/getblocks.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const genericChecksum = @import("lib.zig").genericChecksum; const Sha256 = std.crypto.hash.sha2.Sha256; @@ -21,15 +22,7 @@ pub const GetblocksMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const GetblocksMessage) [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].*; + return genericChecksum(self); } /// Free the `header_hashes` diff --git a/src/network/protocol/messages/lib.zig b/src/network/protocol/messages/lib.zig index a3ea704..adcdd47 100644 --- a/src/network/protocol/messages/lib.zig +++ b/src/network/protocol/messages/lib.zig @@ -11,6 +11,7 @@ pub const FeeFilterMessage = @import("feefilter.zig").FeeFilterMessage; pub const SendCmpctMessage = @import("sendcmpct.zig").SendCmpctMessage; pub const FilterClearMessage = @import("filterclear.zig").FilterClearMessage; pub const FilterAddMessage = @import("filteradd.zig").FilterAddMessage; +const Sha256 = std.crypto.hash.sha2.Sha256; pub const NotFoundMessage = @import("notfound.zig").NotFoundMessage; pub const SendHeadersMessage = @import("sendheaders.zig").SendHeadersMessage; @@ -153,3 +154,20 @@ pub const Message = union(MessageTypes) { }; } }; + +pub const default_checksum: [4]u8 = [_]u8{ 0x5d, 0xf6, 0xe0, 0xe2 }; + +pub fn genericChecksum(m: anytype) [4]u8 { + comptime { + if (!std.meta.hasMethod(@TypeOf(m), "serializeToWriter")) @compileError("Expects m to have fn 'serializeToWriter'."); + } + + var digest: [32]u8 = undefined; + var hasher = Sha256.init(.{}); + m.serializeToWriter(hasher.writer()) catch unreachable; + hasher.final(&digest); + + Sha256.hash(&digest, &digest, .{}); + + return digest[0..4].*; +} diff --git a/src/network/protocol/messages/mempool.zig b/src/network/protocol/messages/mempool.zig index d47d593..186ff23 100644 --- a/src/network/protocol/messages/mempool.zig +++ b/src/network/protocol/messages/mempool.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const default_checksum = @import("lib.zig").default_checksum; /// MempoolMessage represents the "mempool" message /// @@ -13,8 +14,7 @@ pub const MempoolMessage = struct { pub fn checksum(self: MempoolMessage) [4]u8 { _ = self; - // If payload is empty, the checksum is always 0x5df6e0e2 (SHA256(SHA256(""))) - return [4]u8{ 0x5d, 0xf6, 0xe0, 0xe2 }; + return default_checksum; } /// Serialize a message as bytes and return them. diff --git a/src/network/protocol/messages/merkleblock.zig b/src/network/protocol/messages/merkleblock.zig index cb452c8..1027d39 100644 --- a/src/network/protocol/messages/merkleblock.zig +++ b/src/network/protocol/messages/merkleblock.zig @@ -4,7 +4,7 @@ const protocol = @import("../lib.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; const BlockHeader = @import("../../../types/BlockHeader.zig"); const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; - +const genericChecksum = @import("lib.zig").genericChecksum; /// MerkleBlockMessage represents the "MerkleBlock" message /// /// https://developer.bitcoin.org/reference/p2p_networking.html#merkleblock @@ -22,14 +22,7 @@ pub const MerkleBlockMessage = struct { /// Returns the message checksum pub fn checksum(self: *const Self) [4]u8 { - var digest: [32]u8 = undefined; - var hasher = Sha256.init(.{}); - self.serializeToWriter(hasher.writer()) catch unreachable; - hasher.final(&digest); - - Sha256.hash(&digest, &digest, .{}); - - return digest[0..4].*; + return genericChecksum(self); } /// Free the allocated memory diff --git a/src/network/protocol/messages/ping.zig b/src/network/protocol/messages/ping.zig index fc925b3..40e5de9 100644 --- a/src/network/protocol/messages/ping.zig +++ b/src/network/protocol/messages/ping.zig @@ -1,6 +1,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; +const genericChecksum = @import("lib.zig").genericChecksum; /// PingMessage represents the "Ping" message /// @@ -18,15 +19,7 @@ pub const PingMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const Self) [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].*; + return genericChecksum(self); } /// Serialize a message as bytes and write them to the buffer. diff --git a/src/network/protocol/messages/pong.zig b/src/network/protocol/messages/pong.zig index f14121f..f739cbb 100644 --- a/src/network/protocol/messages/pong.zig +++ b/src/network/protocol/messages/pong.zig @@ -1,6 +1,7 @@ const std = @import("std"); const protocol = @import("../lib.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; +const genericChecksum = @import("lib.zig").genericChecksum; /// PongMessage represents the "Pong" message /// @@ -18,15 +19,7 @@ pub const PongMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const Self) [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].*; + return genericChecksum(self); } /// Serialize a message as bytes and write them to the buffer. diff --git a/src/network/protocol/messages/sendcmpct.zig b/src/network/protocol/messages/sendcmpct.zig index 0f94f04..0105f35 100644 --- a/src/network/protocol/messages/sendcmpct.zig +++ b/src/network/protocol/messages/sendcmpct.zig @@ -4,6 +4,7 @@ const protocol = @import("../lib.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; +const genericChecksum = @import("lib.zig").genericChecksum; /// SendCmpctMessage represents the "sendcmpct" message /// @@ -20,15 +21,7 @@ pub const SendCmpctMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const SendCmpctMessage) [4]u8 { - var digest: [32]u8 = undefined; - var hasher = Sha256.init(.{}); - const writer = hasher.writer(); - self.serializeToWriter(writer) catch unreachable; // Sha256.write is infallible - hasher.final(&digest); - - Sha256.hash(&digest, &digest, .{}); - - return digest[0..4].*; + return genericChecksum(self); } /// Serialize the message as bytes and write them to the Writer. pub fn serializeToWriter(self: *const SendCmpctMessage, w: anytype) !void { diff --git a/src/network/protocol/messages/verack.zig b/src/network/protocol/messages/verack.zig index 95be448..936234c 100644 --- a/src/network/protocol/messages/verack.zig +++ b/src/network/protocol/messages/verack.zig @@ -1,5 +1,6 @@ const std = @import("std"); const protocol = @import("../lib.zig"); +const default_checksum = @import("lib.zig").default_checksum; /// VerackMessage represents the "verack" message /// @@ -13,8 +14,7 @@ pub const VerackMessage = struct { pub fn checksum(self: VerackMessage) [4]u8 { _ = self; - // If payload is empty, the checksum is always 0x5df6e0e2 (SHA256(SHA256(""))) - return [4]u8{ 0x5d, 0xf6, 0xe0, 0xe2 }; + return default_checksum; } /// Serialize a message as bytes and return them. diff --git a/src/network/protocol/messages/version.zig b/src/network/protocol/messages/version.zig index 4c4b2b8..0a59fe9 100644 --- a/src/network/protocol/messages/version.zig +++ b/src/network/protocol/messages/version.zig @@ -6,6 +6,7 @@ const ServiceFlags = protocol.ServiceFlags; const Sha256 = std.crypto.hash.sha2.Sha256; const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint; +const genericChecksum = @import("lib.zig").genericChecksum; /// VersionMessage represents the "version" message /// @@ -35,15 +36,7 @@ pub const VersionMessage = struct { /// /// Computed as `Sha256(Sha256(self.serialize()))[0..4]` pub fn checksum(self: *const Self) [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].*; + return genericChecksum(self); } /// Free the `user_agent` if there is one