Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ pub fn build(b: *std.Build) void {

const exe = b.addExecutable(.{
.name = "abyssbook",
.root_source_file = .{ .cwd_relative = "src/main.zig" },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});

b.installArtifact(exe);
Expand All @@ -25,9 +27,11 @@ pub fn build(b: *std.Build) void {
// Add benchmark executable
const bench_exe = b.addExecutable(.{
.name = "bench",
.root_source_file = .{ .cwd_relative = "src/bench.zig" },
.target = target,
.optimize = .ReleaseFast,
.root_module = b.createModule(.{
.root_source_file = b.path("src/bench.zig"),
.target = target,
.optimize = .ReleaseFast,
}),
});

const bench_cmd = b.addRunArtifact(bench_exe);
Expand All @@ -36,9 +40,11 @@ pub fn build(b: *std.Build) void {

// Unit tests
const unit_tests = b.addTest(.{
.root_source_file = .{ .cwd_relative = "src/main.zig" },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
}),
});

const run_unit_tests = b.addRunArtifact(unit_tests);
Expand All @@ -47,9 +53,11 @@ pub fn build(b: *std.Build) void {

// E2E tests
const e2e_tests = b.addTest(.{
.root_source_file = .{ .cwd_relative = "src/e2e_tests.zig" },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("src/e2e_tests.zig"),
.target = target,
.optimize = optimize,
}),
});

const run_e2e_tests = b.addRunArtifact(e2e_tests);
Expand All @@ -58,22 +66,26 @@ pub fn build(b: *std.Build) void {

// Security tests
const security_tests = b.addTest(.{
.root_source_file = .{ .cwd_relative = "src/tests/security_tests.zig" },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("src/tests/security_tests.zig"),
.target = target,
.optimize = optimize,
}),
});

// Add the src directory to the import path for security tests
security_tests.root_module.addAnonymousImport("cli", .{ .root_source_file = .{ .cwd_relative = "src/cli.zig" } });
security_tests.root_module.addAnonymousImport("cli", .{ .root_source_file = b.path("src/cli.zig") });

const blockchain_security_tests = b.addTest(.{
.root_source_file = .{ .cwd_relative = "src/tests/blockchain_security_tests.zig" },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("src/tests/blockchain_security_tests.zig"),
.target = target,
.optimize = optimize,
}),
});

// Add the src directory to the import path for blockchain security tests
blockchain_security_tests.root_module.addAnonymousImport("blockchain_client", .{ .root_source_file = .{ .cwd_relative = "src/blockchain/client.zig" } });
blockchain_security_tests.root_module.addAnonymousImport("blockchain_client", .{ .root_source_file = b.path("src/blockchain/client.zig") });

const run_security_tests = b.addRunArtifact(security_tests);
const run_blockchain_security_tests = b.addRunArtifact(blockchain_security_tests);
Expand Down
20 changes: 10 additions & 10 deletions src/blockchain/client.zig
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub const BlockchainClient = struct {
if (now - last_request < BlockchainConstants.RATE_LIMIT_DELAY_MS) {
// Use nanosleep for more precise timing without blocking threads
const sleep_time = BlockchainConstants.RATE_LIMIT_DELAY_MS * std.time.ns_per_ms;
std.time.sleep(sleep_time);
std.Thread.sleep(sleep_time);
}

_ = self.last_request_time.swap(now, .monotonic);
Expand All @@ -119,7 +119,7 @@ pub const BlockchainClient = struct {
if (attempt < BlockchainConstants.MAX_RETRIES - 1) {
// Exponential backoff
const delay = BlockchainConstants.BASE_RETRY_DELAY_MS * (@as(u64, 1) << @intCast(attempt));
std.time.sleep(delay * std.time.ns_per_ms);
std.Thread.sleep(delay * std.time.ns_per_ms);
}
continue;
};
Expand Down Expand Up @@ -260,7 +260,7 @@ pub const BlockchainClient = struct {

// Convert to hex string
var order_id_buffer: [BlockchainConstants.ORDER_ID_HEX_LENGTH]u8 = undefined;
const order_id = std.fmt.bufPrint(&order_id_buffer, "{}", .{std.fmt.fmtSliceHexLower(&order_id_bytes)}) catch return error.OrderIdGenerationFailed;
const order_id = std.fmt.bufPrint(&order_id_buffer, "{s}", .{std.fmt.bytesToHex(&order_id_bytes, .lower)}) catch return error.OrderIdGenerationFailed;
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The std.fmt.bytesToHex function in Zig 0.15.1 returns a formatter object, not a string slice. When used inside a format string with the {s} specifier, it may not work as expected. Consider using std.fmt.fmtSliceHexLower (if available) or allocating a buffer and using std.fmt.bufPrint with a proper format specifier like {} instead of {s}.

Suggested change
const order_id = std.fmt.bufPrint(&order_id_buffer, "{s}", .{std.fmt.bytesToHex(&order_id_bytes, .lower)}) catch return error.OrderIdGenerationFailed;
const order_id = std.fmt.bufPrint(&order_id_buffer, "{}", .{std.fmt.bytesToHex(&order_id_bytes, .lower)}) catch return error.OrderIdGenerationFailed;

Copilot uses AI. Check for mistakes.

return try self.allocator.dupe(u8, order_id);
}
Expand Down Expand Up @@ -298,7 +298,7 @@ pub const BlockchainClient = struct {
self.disconnect();

// Securely clear and free owned api_key memory
std.crypto.utils.secureZero(u8, self.api_key);
@memset(self.api_key, 0);
self.allocator.free(self.api_key);
}

Expand Down Expand Up @@ -346,14 +346,14 @@ pub const Orderbook = struct {
pub fn deinit(self: *Orderbook, allocator: std.mem.Allocator) void {
// Clear and free order data securely
for (self.bids) |bid| {
std.crypto.utils.secureZero(u8, @constCast(bid.order_id));
std.crypto.utils.secureZero(u8, @constCast(bid.owner_address));
@memset(@constCast(bid.order_id), 0);
@memset(@constCast(bid.owner_address), 0);
allocator.free(bid.order_id);
allocator.free(bid.owner_address);
}
for (self.asks) |ask| {
std.crypto.utils.secureZero(u8, @constCast(ask.order_id));
std.crypto.utils.secureZero(u8, @constCast(ask.owner_address));
@memset(@constCast(ask.order_id), 0);
@memset(@constCast(ask.owner_address), 0);
allocator.free(ask.order_id);
allocator.free(ask.owner_address);
}
Expand All @@ -363,8 +363,8 @@ pub const Orderbook = struct {
allocator.free(self.asks);

// Clear and free market data
std.crypto.utils.secureZero(u8, @constCast(self.market));
std.crypto.utils.secureZero(u8, @constCast(self.market_address));
@memset(@constCast(self.market), 0);
@memset(@constCast(self.market_address), 0);
allocator.free(self.market);
allocator.free(self.market_address);
}
Expand Down
4 changes: 2 additions & 2 deletions src/blockchain/error.zig
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub const ErrorHandler = struct {
// If this isn't the first attempt, apply exponential backoff
if (retry_count > 0) {
const delay_ms = self.base_delay_ms * (@as(u32, 1) << @intCast(retry_count - 1));
std.time.sleep(delay_ms * std.time.ns_per_ms);
std.Thread.sleep(delay_ms * std.time.ns_per_ms);

// Log retry attempt
std.debug.print("Retrying operation (attempt {d}/{d})...\n", .{ retry_count, self.max_retries });
Expand Down Expand Up @@ -130,7 +130,7 @@ pub const ErrorHandler = struct {
// Rate limiting requires retry with backoff
BlockchainError.RateLimitExceeded => {
// Add extra delay for rate limit errors
std.time.sleep(BlockchainConstants.RATE_LIMIT_EXTRA_DELAY_MS * std.time.ns_per_ms);
std.Thread.sleep(BlockchainConstants.RATE_LIMIT_EXTRA_DELAY_MS * std.time.ns_per_ms);
if (retry_count < self.max_retries) {
continue;
} else {
Expand Down
16 changes: 9 additions & 7 deletions src/blockchain/signer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ pub const TransactionSigner = struct {
return error.InvalidSecretKeyLength;
}

// Create Ed25519 keypair from 32-byte seed
var seed: [32]u8 = undefined;
@memcpy(&seed, secret_key[0..32]);

const keypair = try ed25519.KeyPair.create(seed);
// Create Ed25519 keypair from 32-byte seed - need to extend to 64 bytes for SecretKey
var full_seed: [64]u8 = undefined;
@memcpy(full_seed[0..32], secret_key[0..32]);
@memset(full_seed[32..64], 0); // Zero pad the rest

const secret_key_obj = try ed25519.SecretKey.fromBytes(full_seed);
const keypair = try ed25519.KeyPair.fromSecretKey(secret_key_obj);

return TransactionSigner{
.allocator = allocator,
Expand Down Expand Up @@ -55,7 +57,7 @@ pub const TransactionSigner = struct {
size,
timestamp,
nonce,
std.fmt.fmtSliceHexLower(&self.keypair.public_key.bytes),
std.fmt.bytesToHex(&self.keypair.public_key.bytes, .lower),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The std.fmt.bytesToHex function returns a formatter object. When used inside a format string, it should use {} format specifier rather than {s}. Change the format string to use {} or consider a different approach to convert bytes to hex string.

Copilot uses AI. Check for mistakes.
}
);

Expand Down Expand Up @@ -95,7 +97,7 @@ pub const TransactionSigner = struct {
order_id,
timestamp,
nonce,
std.fmt.fmtSliceHexLower(&self.keypair.public_key.bytes),
std.fmt.bytesToHex(&self.keypair.public_key.bytes, .lower),
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The std.fmt.bytesToHex function returns a formatter object. When used inside a format string, it should use {} format specifier rather than {s}. Change the format string to use {} or consider a different approach to convert bytes to hex string.

Copilot uses AI. Check for mistakes.
}
);

Expand Down
6 changes: 3 additions & 3 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ pub fn execute(registry: *CommandRegistry, args: []const []const u8) !void {
}

// Stage 3: Sanitize command arguments
var sanitized_args = std.ArrayList([]const u8).init(std.heap.page_allocator);
var sanitized_args = std.ArrayList([]const u8){};
defer {
for (sanitized_args.items) |arg| {
std.heap.page_allocator.free(arg);
}
sanitized_args.deinit();
sanitized_args.deinit(std.heap.page_allocator);
}

for (command_args) |arg| {
Expand Down Expand Up @@ -128,7 +128,7 @@ pub fn execute(registry: *CommandRegistry, args: []const []const u8) !void {
continue;
}

try sanitized_args.append(try std.heap.page_allocator.dupe(u8, arg_result.cleaned_input));
try sanitized_args.append(std.heap.page_allocator, try std.heap.page_allocator.dupe(u8, arg_result.cleaned_input));
}

// Validate command name is not empty after sanitization
Expand Down
6 changes: 3 additions & 3 deletions src/cli/args/parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ pub const ArgParser = struct {
return .{
.args = args,
.allocator = allocator,
.definitions = std.ArrayList(ArgDef).init(allocator),
.definitions = std.ArrayList(ArgDef){},
.parsed_args = std.StringHashMap(ParsedArg).init(allocator),
.subcommand = if (args.len > 0) args[0] else null,
};
}

pub fn deinit(self: *ArgParser) void {
self.definitions.deinit();
self.definitions.deinit(self.allocator);

var it = self.parsed_args.iterator();
while (it.next()) |entry| {
Expand All @@ -59,7 +59,7 @@ pub const ArgParser = struct {
}

pub fn addArg(self: *ArgParser, name: []const u8, description: []const u8, required: bool, default_value: ?[]const u8) !void {
try self.definitions.append(.{
try self.definitions.append(self.allocator, .{
.name = name,
.description = description,
.required = required,
Expand Down
9 changes: 6 additions & 3 deletions src/cli/commands.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ pub const CommandRegistry = struct {
allocator: std.mem.Allocator,

pub fn init(allocator: std.mem.Allocator) CommandRegistry {
var registry = CommandRegistry{
const registry = CommandRegistry{
.commands = std.StringHashMap(Command).init(allocator),
.allocator = allocator,
};
// Store reference for help command access
registry_ref = &registry;
// Note: registry_ref will be set after the registry is moved to its final location
return registry;
}

pub fn setGlobalRef(self: *CommandRegistry) void {
registry_ref = self;
}

pub fn deinit(self: *CommandRegistry) void {
self.commands.deinit();
Expand Down
Loading