Skip to content

Commit f1a31cb

Browse files
committed
add test for blake3 + simple function
1 parent af2ccc1 commit f1a31cb

File tree

2 files changed

+198
-18
lines changed

2 files changed

+198
-18
lines changed

packages/blake3-wasm/assembly/blake3.ts

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Constants from the reference implementation
2-
const OUT_LEN: usize = 32;
2+
const OUT_LEN: i32 = 32;
33
// const KEY_LEN: usize = 32;
4-
const BLOCK_LEN: usize = 64;
5-
const CHUNK_LEN: usize = 1024;
4+
const BLOCK_LEN: i32 = 64;
5+
const CHUNK_LEN: i32 = 1024;
66

77
const CHUNK_START: u32 = 1 << 0;
88
const CHUNK_END: u32 = 1 << 1;
@@ -16,10 +16,10 @@ const IV: StaticArray<u32> = [
1616
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
1717
];
1818

19-
const MSG_PERMUTATION: StaticArray<usize> = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
19+
const MSG_PERMUTATION: StaticArray<i32> = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
2020

2121
// The mixing function, G, which mixes either a column or a diagonal.
22-
function g(state: StaticArray<u32>, a: usize, b: usize, c: usize, d: usize, mx: u32, my: u32): void {
22+
function g(state: StaticArray<u32>, a: i32, b: i32, c: i32, d: i32, mx: u32, my: u32): void {
2323
state[a] = state[a] + state[b] + mx;
2424
state[d] = rotl32(state[d] ^ state[a], 16);
2525
state[c] = state[c] + state[d];
@@ -115,25 +115,27 @@ function words_from_little_endian_bytes(bytes: Uint8Array, words: StaticArray<u3
115115
}
116116
}
117117

118-
export class Blake3Hasher {
118+
class Blake3Hasher {
119119
private chunk_state: ChunkState;
120120
private key_words: StaticArray<u32>;
121121
private cv_stack: StaticArray<StaticArray<u32>>;
122122
private cv_stack_len: u8;
123123
private flags: u32;
124124

125125
constructor() {
126-
this.key_words = new StaticArray<u32>(8);
126+
const key_words = new StaticArray<u32>(8);
127127
for (let i = 0; i < 8; i++) {
128-
this.key_words[i] = IV[i];
128+
key_words[i] = IV[i];
129129
}
130-
this.chunk_state = new ChunkState(this.key_words, 0, 0);
130+
this.key_words = key_words;
131+
this.chunk_state = new ChunkState(key_words, 0, 0);
131132
this.cv_stack = new StaticArray<StaticArray<u32>>(54);
133+
this.cv_stack_len = 0;
134+
this.flags = 0;
135+
132136
for (let i = 0; i < 54; i++) {
133137
this.cv_stack[i] = new StaticArray<u32>(8);
134138
}
135-
this.cv_stack_len = 0;
136-
this.flags = 0;
137139
}
138140

139141
update(input: Uint8Array): void {
@@ -205,17 +207,18 @@ class ChunkState {
205207

206208
constructor(key_words: StaticArray<u32>, chunk_counter: u64, flags: u32) {
207209
this.chaining_value = new StaticArray<u32>(8);
208-
for (let i = 0; i < 8; i++) {
209-
this.chaining_value[i] = key_words[i];
210-
}
211210
this.chunk_counter = chunk_counter;
212211
this.block = new Uint8Array(BLOCK_LEN);
213212
this.block_len = 0;
214213
this.blocks_compressed = 0;
215214
this.flags = flags;
215+
216+
for (let i = 0; i < 8; i++) {
217+
this.chaining_value[i] = key_words[i];
218+
}
216219
}
217220

218-
len(): usize {
221+
len(): i32 {
219222
return BLOCK_LEN * this.blocks_compressed + this.block_len;
220223
}
221224

@@ -249,7 +252,7 @@ class ChunkState {
249252
for (let i = 0; i < take; i++) {
250253
this.block[this.block_len + i] = input[inputPos + i];
251254
}
252-
this.block_len += take;
255+
this.block_len += take as u8;
253256
inputPos += take;
254257
}
255258
}
@@ -352,6 +355,20 @@ function parent_cv(
352355
return parent_output(left_child_cv, right_child_cv, key_words, flags).chaining_value();
353356
}
354357

355-
export function createBlake3Hasher(): Blake3Hasher {
356-
return new Blake3Hasher();
358+
export function blake3(input: Uint8Array): Uint8Array {
359+
const hasher = new Blake3Hasher();
360+
hasher.update(input);
361+
const output = new Uint8Array(32);
362+
hasher.finalize(output);
363+
return output;
364+
}
365+
366+
export function blake3Hex(input: Uint8Array): string {
367+
const hash = blake3(input);
368+
const hex = new Array<string>(64);
369+
for (let i = 0; i < 32; i++) {
370+
hex[i * 2] = (hash[i] >> 4).toString(16);
371+
hex[i * 2 + 1] = (hash[i] & 0x0f).toString(16);
372+
}
373+
return hex.join("");
357374
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// Adapted from https://github.com/mcmilk/BLAKE3-tests/blob/11a8abeceac93b5eba664eae3679efb4ffa5bc0a/blake3_test.c
2+
3+
import { blake3Hex } from "../build/debug.js";
4+
5+
const buffer = new Uint8Array(102400);
6+
let i = 0;
7+
let j = 0;
8+
9+
for (i = 0, j = 0; i < buffer.length; i++, j++) {
10+
if (j === 251) {
11+
j = 0;
12+
}
13+
buffer[i] = j;
14+
}
15+
16+
const testCases = [
17+
{
18+
buf: buffer.slice(0, 0),
19+
expected: "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262",
20+
},
21+
{
22+
buf: buffer.slice(0, 1),
23+
expected: "2d3adedff11b61f14c886e35afa036736dcd87a74d27b5c1510225d0f592e213",
24+
},
25+
{
26+
buf: buffer.slice(0, 2),
27+
expected: "7b7015bb92cf0b318037702a6cdd81dee41224f734684c2c122cd6359cb1ee63",
28+
},
29+
{
30+
buf: buffer.slice(0, 3),
31+
expected: "e1be4d7a8ab5560aa4199eea339849ba8e293d55ca0a81006726d184519e647f",
32+
},
33+
{
34+
buf: buffer.slice(0, 4),
35+
expected: "f30f5ab28fe047904037f77b6da4fea1e27241c5d132638d8bedce9d40494f32",
36+
},
37+
{
38+
buf: buffer.slice(0, 5),
39+
expected: "b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2",
40+
},
41+
{
42+
buf: buffer.slice(0, 6),
43+
expected: "06c4e8ffb6872fad96f9aaca5eee1553eb62aed0ad7198cef42e87f6a616c844",
44+
},
45+
{
46+
buf: buffer.slice(0, 7),
47+
expected: "3f8770f387faad08faa9d8414e9f449ac68e6ff0417f673f602a646a891419fe",
48+
},
49+
{
50+
buf: buffer.slice(0, 8),
51+
expected: "2351207d04fc16ade43ccab08600939c7c1fa70a5c0aaca76063d04c3228eaeb",
52+
},
53+
{
54+
buf: buffer.slice(0, 63),
55+
expected: "e9bc37a594daad83be9470df7f7b3798297c3d834ce80ba85d6e207627b7db7b",
56+
},
57+
{
58+
buf: buffer.slice(0, 64),
59+
expected: "4eed7141ea4a5cd4b788606bd23f46e212af9cacebacdc7d1f4c6dc7f2511b98",
60+
},
61+
{
62+
buf: buffer.slice(0, 65),
63+
expected: "de1e5fa0be70df6d2be8fffd0e99ceaa8eb6e8c93a63f2d8d1c30ecb6b263dee",
64+
},
65+
{
66+
buf: buffer.slice(0, 127),
67+
expected: "d81293fda863f008c09e92fc382a81f5a0b4a1251cba1634016a0f86a6bd640d",
68+
},
69+
{
70+
buf: buffer.slice(0, 128),
71+
expected: "f17e570564b26578c33bb7f44643f539624b05df1a76c81f30acd548c44b45ef",
72+
},
73+
{
74+
buf: buffer.slice(0, 129),
75+
expected: "683aaae9f3c5ba37eaaf072aed0f9e30bac0865137bae68b1fde4ca2aebdcb12",
76+
},
77+
{
78+
buf: buffer.slice(0, 1023),
79+
expected: "10108970eeda3eb932baac1428c7a2163b0e924c9a9e25b35bba72b28f70bd1",
80+
},
81+
{
82+
buf: buffer.slice(0, 1024),
83+
expected: "42214739f095a406f3fc83deb889744ac00df831c10daa55189b5d121c855af",
84+
},
85+
{
86+
buf: buffer.slice(0, 1025),
87+
expected: "d00278ae47eb27b34faecf67b4fe263f82d5412916c1ffd97c8cb7fb814b844",
88+
},
89+
{
90+
buf: buffer.slice(0, 2048),
91+
expected: "e776b6028c7cd22a4d0ba182a8bf62205d2ef576467e838ed6f2529b85fba24a",
92+
},
93+
{
94+
buf: buffer.slice(0, 2049),
95+
expected: "5f4d72f40d7a5f82b15ca2b2e44b1de3c2ef86c426c95c1af0b6879522563030",
96+
},
97+
{
98+
buf: buffer.slice(0, 3072),
99+
expected: "b98cb0ff3623be03326b373de6b9095218513e64f1ee2edd2525c7ad1e5cffd2",
100+
},
101+
{
102+
buf: buffer.slice(0, 3073),
103+
expected: "7124b49501012f81cc7f11ca069ec9226cecb8a2c850cfe644e327d22d3e1cd3",
104+
},
105+
{
106+
buf: buffer.slice(0, 4096),
107+
expected: "015094013f57a5277b59d8475c0501042c0b642e531b0a1c8f58d2163229e969",
108+
},
109+
{
110+
buf: buffer.slice(0, 4097),
111+
expected: "9b4052b38f1c5fc8b1f9ff7ac7b27cd242487b3d890d15c96a1c25b8aa0fb995",
112+
},
113+
{
114+
buf: buffer.slice(0, 5120),
115+
expected: "9cadc15fed8b5d854562b26a9536d9707cadeda9b143978f319ab34230535833a",
116+
},
117+
{
118+
buf: buffer.slice(0, 5121),
119+
expected: "628bd2cb2004694adaab7bbd778a25df25c47b9d4155a55f8fbd79f2fe154cff9",
120+
},
121+
{
122+
buf: buffer.slice(0, 6144),
123+
expected: "3e2e5b74e048f3add6d21faab3f83aa44d3b2278afb83b80b3c35164ebeca205",
124+
},
125+
{
126+
buf: buffer.slice(0, 6145),
127+
expected: "f1323a8631446cc50536a9f705ee5cb619424d46887f3c376c695b70e0f0507f",
128+
},
129+
{
130+
buf: buffer.slice(0, 7168),
131+
expected: "61da957ec2499a95d6b8023e2b0e604ec7f6b50e80a9678b89d2628e99ada77a",
132+
},
133+
{
134+
buf: buffer.slice(0, 7169),
135+
expected: "a003fc7a51754a9b3c7fae0367ab3d782dccf28855a03d435f8cfe74605e7817",
136+
},
137+
{
138+
buf: buffer.slice(0, 8192),
139+
expected: "aae792484c8efe4f19e2ca7d371d8c467ffb10748d8a5a1ae579948f718a2a63",
140+
},
141+
{
142+
buf: buffer.slice(0, 8193),
143+
expected: "bab6c09cb8ce8cf459261398d2e7aef35700bf488116ceb94a36d0f5f1b7bc3bb",
144+
},
145+
{
146+
buf: buffer.slice(0, 102400),
147+
expected: "bc3e3d41a1146b069abffad3c0d44860cf664390afce4d9661f7902e7943e085",
148+
},
149+
];
150+
151+
for (const testCase of testCases) {
152+
const result = blake3Hex(testCase.buf);
153+
console.log(result);
154+
155+
if (result !== testCase.expected) {
156+
console.error(`Test case failed: ${testCase.buf.length} bytes`);
157+
console.error(`Expected: ${testCase.expected}`);
158+
console.error(`Actual: ${result}`);
159+
process.exit(1);
160+
}
161+
}
162+
163+
console.log("All test cases passed");

0 commit comments

Comments
 (0)