Skip to content

Commit 6758bc3

Browse files
authored
Fix test nitpicks: pin expected digests, reuse helpers, fix f64 precision (#7)
- eip712: Replace determinism-only checks with pinned canonical EIP-712 digest vectors for Permit and Permit2 PermitSingle tests - hd_wallet: Pin exact expected master key and chain_code bytes for BIP-32 test instead of non-zero checks - secp256k1: Replace manual half-order comparison with existing isHighS helper and HALF_ORDER_BYTES constant - units: Use 9007.0 ETH (within f64 exact integer range) instead of 10000.0 to avoid misleading f64 precision behavior
1 parent 68cc5fe commit 6758bc3

4 files changed

Lines changed: 16 additions & 53 deletions

File tree

src/eip712.zig

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,11 +1058,10 @@ test "ERC20 Permit typed data hash" {
10581058
};
10591059

10601060
const hash1 = try hashTypedData(allocator, domain, permit_msg, &type_defs);
1061-
const hash2 = try hashTypedData(allocator, domain, permit_msg, &type_defs);
10621061

1063-
// Verify deterministic 32-byte result
1064-
try testing.expectEqual(@as(usize, 32), hash1.len);
1065-
try testing.expectEqualSlices(u8, &hash1, &hash2);
1062+
// Verify against canonical expected EIP-712 digest
1063+
const expected_permit_hash = try hex.hexToBytesFixed(32, "a291091bcb960bb950bcde8c114f51268db75fc46b0bd1ed9d0b98e99b7c0b78");
1064+
try testing.expectEqualSlices(u8, &expected_permit_hash, &hash1);
10661065
}
10671066

10681067
test "hashDomain with all 5 fields" {
@@ -1198,9 +1197,8 @@ test "Permit2 PermitSingle nested struct" {
11981197
};
11991198

12001199
const hash1 = try hashTypedData(allocator, domain, permit_single, &type_defs);
1201-
const hash2 = try hashTypedData(allocator, domain, permit_single, &type_defs);
12021200

1203-
// Verify deterministic 32-byte result
1204-
try testing.expectEqual(@as(usize, 32), hash1.len);
1205-
try testing.expectEqualSlices(u8, &hash1, &hash2);
1201+
// Verify against canonical expected EIP-712 digest
1202+
const expected_permit2_hash = try hex.hexToBytesFixed(32, "deb9a47018f32b20c6e10646036eae3ad57736889291e780cd092389f05f19ad");
1203+
try testing.expectEqualSlices(u8, &expected_permit2_hash, &hash1);
12061204
}

src/hd_wallet.zig

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -235,26 +235,12 @@ test "BIP-32 master key from known seed" {
235235
@memcpy(seed[0..32], &first_half);
236236

237237
const master = try masterKeyFromSeed(seed);
238-
// Master key should be non-zero
239-
var key_nonzero = false;
240-
for (master.key) |b| if (b != 0) {
241-
key_nonzero = true;
242-
break;
243-
};
244-
try std.testing.expect(key_nonzero);
245-
246-
// Chain code should be non-zero
247-
var cc_nonzero = false;
248-
for (master.chain_code) |b| if (b != 0) {
249-
cc_nonzero = true;
250-
break;
251-
};
252-
try std.testing.expect(cc_nonzero);
253238

254-
// Deterministic
255-
const master2 = try masterKeyFromSeed(seed);
256-
try std.testing.expectEqualSlices(u8, &master.key, &master2.key);
257-
try std.testing.expectEqualSlices(u8, &master.chain_code, &master2.chain_code);
239+
// Pin exact expected BIP-32 vector outputs
240+
const expected_key = try hex_mod.hexToBytesFixed(32, "4cc2c096af45067fed8c711d57ed5c4923eb3ee761e08f5474c33754b80c9d0f");
241+
const expected_chain_code = try hex_mod.hexToBytesFixed(32, "2218ccd37b9b7c6d41122fed49d2ddcc151b2f463301b8fa9d5067bdbdb40af2");
242+
try std.testing.expectEqualSlices(u8, &expected_key, &master.key);
243+
try std.testing.expectEqualSlices(u8, &expected_chain_code, &master.chain_code);
258244
}
259245

260246
test "known mnemonic abandon...about to exact address" {

src/secp256k1.zig

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -501,36 +501,14 @@ test "sign produces low-s (EIP-2) canonical signature" {
501501
// Hardhat account #0
502502
const private_key = try hex.hexToBytesFixed(32, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80");
503503

504-
// n/2 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
505-
const half_n: [32]u8 = .{
506-
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
507-
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
508-
0x5D, 0x57, 0x6E, 0x73, 0x57, 0xA4, 0x50, 0x1D,
509-
0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0,
510-
};
511-
512504
const messages = [_][]const u8{ "canonical1", "canonical2", "canonical3", "canonical4", "canonical5" };
513505

514506
for (messages) |msg| {
515507
const message_hash = keccak.hash(msg);
516508
const sig = try sign(private_key, message_hash);
517509

518-
// Extract s as big-endian bytes and verify s <= n/2
519-
const s_bytes = sig.s;
520-
var s_is_lte = false;
521-
for (0..32) |i| {
522-
if (s_bytes[i] < half_n[i]) {
523-
s_is_lte = true;
524-
break;
525-
} else if (s_bytes[i] > half_n[i]) {
526-
break;
527-
}
528-
}
529-
// If we didn't break early, all bytes were equal (s == n/2), which is also valid
530-
if (!s_is_lte) {
531-
// Check if all bytes are equal (s == n/2)
532-
s_is_lte = std.mem.eql(u8, &s_bytes, &half_n);
533-
}
534-
try std.testing.expect(s_is_lte);
510+
// Verify s <= n/2 using the existing isHighS helper and HALF_ORDER_BYTES
511+
const s_scalar = Scalar.fromBytes(sig.s, .big) catch unreachable;
512+
try std.testing.expect(!isHighS(s_scalar));
535513
}
536514
}

src/utils/units.zig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ test "parseEther zero" {
5555
}
5656

5757
test "parseEther large value" {
58-
try std.testing.expectEqual(@as(u256, 10_000_000_000_000_000_000_000), parseEther(10000.0));
58+
// Use 9007.0 which is within f64's exact integer range (2^53)
59+
try std.testing.expectEqual(@as(u256, 9007_000_000_000_000_000_000), parseEther(9007.0));
5960
}
6061

6162
test "formatEther zero" {

0 commit comments

Comments
 (0)