Skip to content

Commit

Permalink
Resolve conflicting files
Browse files Browse the repository at this point in the history
  • Loading branch information
KhairallahA committed Oct 9, 2024
2 parents a2e5613 + 0c66e2c commit 4149341
Show file tree
Hide file tree
Showing 34 changed files with 1,720 additions and 666 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ pie showData
| opSha1 | 0xa7 || The input is hashed using SHA-1. |
| opSha256 | 0xa8 || The input is hashed using SHA-256. |
| opHash160 | 0xa9 || The input is hashed twice: first with SHA-256 and then with RIPEMD-160. |
| opHash256 | 0xaa | | The input is hashed two times with SHA-256. |
| opHash256 | 0xaa | | The input is hashed two times with SHA-256. |
| opCodeSeparator | 0xab || All of the signature checking words will only match signatures to the data after the most recently-executed opCODESEPARATOR. |
| opCheckSig | 0xac || The entire transaction's outputs, inputs, and script are hashed. The signature used by opCHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. |
| opCheckSigVerify | 0xad || Same as opCHECKSIG, but opVERIFY is executed afterward. |
Expand Down
29 changes: 26 additions & 3 deletions src/network/peer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -80,7 +81,9 @@ 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;
// send verack message
try self.sendVerackMessage();
},

.verack => return,
Expand All @@ -95,8 +98,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(),
);
Expand All @@ -110,6 +121,18 @@ pub const Peer = struct {
);
}

/// Send verack message to peer
fn sendVerackMessage(self: *const Peer) !void {
const verack_message = protocol.messages.VerackMessage{}; // Empty message, as verack doesn't carry data
try wire.sendMessage(
self.allocator,
self.stream.writer(),
self.config.protocol_version,
self.config.network_id,
verack_message,
);
}

pub fn listen(self: *Peer) void {
std.log.info("Listening for messages from {any}", .{self.address});
while (self.should_listen) {
Expand Down
3 changes: 0 additions & 3 deletions src/network/protocol/NetworkAddress.zig

This file was deleted.

4 changes: 3 additions & 1 deletion src/network/protocol/lib.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub const messages = @import("./messages/lib.zig");
pub const NetworkAddress = @import("NetworkAddress.zig");
pub const NetworkAddress = @import("types/NetworkAddress.zig");
pub const InventoryItem = @import("types/InventoryItem.zig");

/// Network services
pub const ServiceFlags = struct {
pub const NODE_NETWORK: u64 = 0x1;
Expand Down
143 changes: 143 additions & 0 deletions src/network/protocol/messages/addr.zig
Original file line number Diff line number Diff line change
@@ -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);
}
}
34 changes: 6 additions & 28 deletions src/network/protocol/messages/block.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
const std = @import("std");
const native_endian = @import("builtin").target.cpu.arch.endian();
const protocol = @import("../lib.zig");
const genericChecksum = @import("lib.zig").genericChecksum;
const genericSerialize = @import("lib.zig").genericSerialize;
const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice;

const ServiceFlags = protocol.ServiceFlags;

Expand Down Expand Up @@ -28,15 +31,7 @@ pub const BlockMessage = struct {
}

pub fn checksum(self: BlockMessage) [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);
}

pub fn deinit(self: *BlockMessage, allocator: std.mem.Allocator) void {
Expand Down Expand Up @@ -64,24 +59,9 @@ pub const BlockMessage = struct {
}
}

/// Serialize a message as bytes and write them to the buffer.
///
/// buffer.len must be >= than self.hintSerializedLen()
pub fn serializeToSlice(self: *const Self, buffer: []u8) !void {
var fbs = std.io.fixedBufferStream(buffer);
try self.serializeToWriter(fbs.writer());
}

/// Serialize a message as bytes and return them.
pub fn serialize(self: *const BlockMessage, 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);
}

pub fn deserializeReader(allocator: std.mem.Allocator, r: anytype) !BlockMessage {
Expand Down Expand Up @@ -112,8 +92,7 @@ pub const BlockMessage = struct {

/// Deserialize bytes into a `VersionMessage`
pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !Self {
var fbs = std.io.fixedBufferStream(bytes);
return try Self.deserializeReader(allocator, fbs.reader());
return genericDeserializeSlice(Self, allocator, bytes);
}

pub fn hintSerializedLen(self: BlockMessage) usize {
Expand All @@ -128,7 +107,6 @@ pub const BlockMessage = struct {
};

// TESTS

test "ok_full_flow_BlockMessage" {
const OpCode = @import("../../../script/opcodes/constant.zig").Opcode;
const allocator = std.testing.allocator;
Expand Down
4 changes: 2 additions & 2 deletions src/network/protocol/messages/cmpctblock.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const Sha256 = std.crypto.hash.sha2.Sha256;
const BlockHeader = @import("../../../types/block_header.zig");
const CompactSizeUint = @import("bitcoin-primitives").types.CompatSizeUint;
const genericChecksum = @import("lib.zig").genericChecksum;
const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice;

pub const CmpctBlockMessage = struct {
header: BlockHeader,
Expand Down Expand Up @@ -118,8 +119,7 @@ pub const CmpctBlockMessage = struct {
}

pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !Self {
var fbs = std.io.fixedBufferStream(bytes);
return try Self.deserializeReader(allocator, fbs.reader());
return genericDeserializeSlice(Self, allocator, bytes);
}

pub fn hintSerializedLen(self: *const Self) usize {
Expand Down
23 changes: 4 additions & 19 deletions src/network/protocol/messages/feefilter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const std = @import("std");
const protocol = @import("../lib.zig");
const Sha256 = std.crypto.hash.sha2.Sha256;
const genericChecksum = @import("lib.zig").genericChecksum;
const genericSerialize = @import("lib.zig").genericSerialize;
const genericDeserializeSlice = @import("lib.zig").genericDeserializeSlice;

/// FeeFilterMessage represents the "feefilter" message
///
Expand All @@ -22,13 +24,6 @@ pub const FeeFilterMessage = struct {
return genericChecksum(self);
}

/// Serialize a message as bytes and write them to the buffer.
///
/// buffer.len must be >= than self.hintSerializedLen()
pub fn serializeToSlice(self: *const Self, buffer: []u8) !void {
var fbs = std.io.fixedBufferStream(buffer);
try self.serializeToWriter(fbs.writer());
}

/// Serialize the message as bytes and write them to the Writer.
pub fn serializeToWriter(self: *const Self, w: anytype) !void {
Expand All @@ -37,14 +32,7 @@ pub const FeeFilterMessage = struct {

/// Serialize a message as bytes and return them.
pub fn serialize(self: *const Self, 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 `FeeFilterMessage`
Expand All @@ -60,10 +48,7 @@ pub const FeeFilterMessage = struct {

/// Deserialize bytes into a `FeeFilterMessage`
pub fn deserializeSlice(allocator: std.mem.Allocator, bytes: []const u8) !Self {
var fbs = std.io.fixedBufferStream(bytes);
const reader = fbs.reader();

return try Self.deserializeReader(allocator, reader);
return genericDeserializeSlice(Self, allocator, bytes);
}

pub fn hintSerializedLen(_: *const Self) usize {
Expand Down
Loading

0 comments on commit 4149341

Please sign in to comment.