Compare commits
849
Commits
v3.2.1
...
quantus-crypto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e5b479db4
|
||
|
|
0b1cfe35b3
|
||
|
|
e8bf9e20c7
|
||
|
|
a6d3685c59
|
||
|
|
8323e442d9
|
||
|
|
b882f914e7
|
||
|
|
02a3f004d7
|
||
|
|
1f1f5729ab
|
||
|
|
6eb04f63ac
|
||
|
|
65286fb3ec | ||
|
|
f55a3e75a2 | ||
|
|
6c8b0afd8d | ||
|
|
9c6611087c | ||
|
|
dc34df3b54 | ||
|
|
8bf7e88458 | ||
|
|
e8f1fb3aed | ||
|
|
ba6155880e | ||
|
|
1e696a5520 | ||
|
|
b6c704eca8 | ||
|
|
c7053fa112 | ||
|
|
d76ab093a8 | ||
|
|
4a54a37ae1 | ||
|
|
0eb433f3c2 | ||
|
|
278ecc7210 | ||
|
|
03fe7dcb1d | ||
|
|
d99abde915 | ||
|
|
06502e8fe8 | ||
|
|
f3004fdb31 | ||
|
|
f5834e684f | ||
|
|
d7a1060824 | ||
|
|
c6f8748878 | ||
|
|
24a46c7262 | ||
|
|
78a282bda3 | ||
|
|
1713dccba3 | ||
|
|
0a22251212 | ||
|
|
540d46717b | ||
|
|
e5112e690d | ||
|
|
2f8c91fc15 | ||
|
|
6d552f1ced | ||
|
|
afa992b40b | ||
|
|
401c6e5763 | ||
|
|
76d051b16e | ||
|
|
5b69d5aadc | ||
|
|
780323538a | ||
|
|
042d653852 | ||
|
|
da47390fa4 | ||
|
|
488abd68bb | ||
|
|
d926ee63f4 | ||
|
|
6777f8ef5e | ||
|
|
1001083009 | ||
|
|
898b067081 | ||
|
|
acc07b9345 | ||
|
|
bc572b16d5 | ||
|
|
91d2530ea8 | ||
|
|
e679298d8d | ||
|
|
949ad77dab | ||
|
|
24ce35ae43 | ||
|
|
9e22f34720 | ||
|
|
2b867b2e91 | ||
|
|
230593ee17 | ||
|
|
60a3b8916c | ||
|
|
1f20fdf377 | ||
|
|
64dcd40bee | ||
|
|
f3948b90f7 | ||
|
|
83da578b60 | ||
|
|
407ec8e1a1 | ||
|
|
aa30920183 | ||
|
|
35d56606bd | ||
|
|
4083abb1dd | ||
|
|
c6cb3a9226 | ||
|
|
04d46701b1 | ||
|
|
61f4c5eb7d | ||
|
|
d0e99aebef | ||
|
|
dc752685d7 | ||
|
|
9bf3c1be07 | ||
|
|
32bd2172aa | ||
|
|
1f58821cd4 | ||
|
|
8352373fdd | ||
|
|
610fcee9cd | ||
|
|
b086928d01 | ||
|
|
8b3bd58e79 | ||
|
|
e6fd1e20a5 | ||
|
|
22075f8262 | ||
|
|
c8805a09dd | ||
|
|
758066b4ea | ||
|
|
da7c71c32f | ||
|
|
cb38c6f1c5 | ||
|
|
39d5b3bcce | ||
|
|
41c7af32c9 | ||
|
|
68d698502d | ||
|
|
3d4a87af6a | ||
|
|
77b1e338cf | ||
|
|
3af17400ba | ||
|
|
e16029776f | ||
|
|
61624a627b | ||
|
|
c964570806 | ||
|
|
f32846d41b | ||
|
|
705b08765b | ||
|
|
4f6771e758 | ||
|
|
731dee91e4 | ||
|
|
b82e28ad4e | ||
|
|
6d5b3f5404 | ||
|
|
1f643dd705 | ||
|
|
af9491f7fd | ||
|
|
7377da8e7e | ||
|
|
32fa12c3fa | ||
|
|
6aabb2f869 | ||
|
|
0edb0289a9 | ||
|
|
004996d772 | ||
|
|
7611fd1788 | ||
|
|
e4f85e2358 | ||
|
|
6c5e7deaa5 | ||
|
|
1f024c1da0 | ||
|
|
26b6cf843a | ||
|
|
8e54efe4a5 | ||
|
|
daecf47197 | ||
|
|
6f5ed67aad | ||
|
|
8556566c1d | ||
|
|
e28a5ffd4b | ||
|
|
7f3ca3159d | ||
|
|
3a3214e602 | ||
|
|
319f33bec1 | ||
|
|
a8f5189252 | ||
|
|
ee26a6ef98 | ||
|
|
71291442bb | ||
|
|
f26f855942 | ||
|
|
3a06871f82 | ||
|
|
279da24ca1 | ||
|
|
af81a69ba6 | ||
|
|
0b39c9d2f1 | ||
|
|
7d2de26fdb | ||
|
|
fc370eedb2 | ||
|
|
792baf352c | ||
|
|
a79d6ded77 | ||
|
|
51b45133d9 | ||
|
|
b3c934d602 | ||
|
|
25cd084f30 | ||
|
|
9df575ad7b | ||
|
|
0175ac56a7 | ||
|
|
e589fba3b1 | ||
|
|
570c46e889 | ||
|
|
4d002c7563 | ||
|
|
6aeaa69a8b | ||
|
|
4565f85077 | ||
|
|
0d0dcbf005 | ||
|
|
7e38ff8faf | ||
|
|
5640651945 | ||
|
|
657ac95ad9 | ||
|
|
23441ec34d | ||
|
|
b7768c369c | ||
|
|
646eabf516 | ||
|
|
ac36b68a5e | ||
|
|
390edd8b6d | ||
|
|
083eba1d8f | ||
|
|
0a70cc7cfb | ||
|
|
034f625118 | ||
|
|
919c4aa7d4 | ||
|
|
85350b15d2 | ||
|
|
fcc48bf20a | ||
|
|
c408836bc6 | ||
|
|
194d1a6cd4 | ||
|
|
fbb7d77f06 | ||
|
|
1536cd9b48 | ||
|
|
695ccae218 | ||
|
|
bd8d729765 | ||
|
|
2453c8728b | ||
|
|
f39f0d72f2 | ||
|
|
89739683f5 | ||
|
|
7f0c60b4f0 | ||
|
|
6ee5b6da86 | ||
|
|
68575449f1 | ||
|
|
ea7035a484 | ||
|
|
cbb7cd94f7 | ||
|
|
d0af71031f | ||
|
|
929401b8b6 | ||
|
|
778879b1c1 | ||
|
|
cadb0d9123 | ||
|
|
4e505bbe29 | ||
|
|
72cbdf6eaa | ||
|
|
a032cbce6e | ||
|
|
12a5b0da0f | ||
|
|
f1129ddcbb | ||
|
|
7d2a29d231 | ||
|
|
c5550ad559 | ||
|
|
d1fd2a74a4 | ||
|
|
f1d678132a | ||
|
|
784422a129 | ||
|
|
0a6b25fbdd | ||
|
|
6bc249181b | ||
|
|
a47fb3bff9 | ||
|
|
d21c3fc639 | ||
|
|
7da2f705dc | ||
|
|
69278851bc | ||
|
|
41dbf12257 | ||
|
|
7a8ce5ea3a | ||
|
|
7d24e46947 | ||
|
|
2bd507af55 | ||
|
|
7232fd88b5 | ||
|
|
dbfd08942a | ||
|
|
5d7a167d19 | ||
|
|
b5478b52b4 | ||
|
|
66f4af6dda | ||
|
|
74344c862c | ||
|
|
783476fd8d | ||
|
|
0a7af910e1 | ||
|
|
478cd6ffcf | ||
|
|
df61ff95ca | ||
|
|
9137bd9848 | ||
|
|
3479d7f63b | ||
|
|
a718bcbb0c | ||
|
|
ec1958dfde | ||
|
|
a1f6452a7d | ||
|
|
13e8c6af1d | ||
|
|
56f98e67a1 | ||
|
|
5023c02a73 | ||
|
|
3b286e6034 | ||
|
|
bccb16f691 | ||
|
|
aeae6c137e | ||
|
|
2a2bd06284 | ||
|
|
1310dca729 | ||
|
|
34f2b544f0 | ||
|
|
dde2f92445 | ||
|
|
b9ad508d27 | ||
|
|
ca7e44c25a | ||
|
|
a0de0ac427 | ||
|
|
2893343bf2 | ||
|
|
8b70740a18 | ||
|
|
5e54136fff | ||
|
|
35b4c38be4 | ||
|
|
e1b24a61c6 | ||
|
|
a71d353fff | ||
|
|
218d2b9217 | ||
|
|
0429de0429 | ||
|
|
5f18253ba8 | ||
|
|
b17de3422a | ||
|
|
935f92dd5b | ||
|
|
ea79adf45d | ||
|
|
e71807c2a3 | ||
|
|
04365b87a5 | ||
|
|
f5856d091b | ||
|
|
45554b753f | ||
|
|
5967b48515 | ||
|
|
2d85a62bb7 | ||
|
|
39ca57f059 | ||
|
|
5a08739f24 | ||
|
|
fe09bc21ed | ||
|
|
8706cdb9c2 | ||
|
|
498a58d95a | ||
|
|
2501f771a7 | ||
|
|
55aef41eee | ||
|
|
e14c249ae2 | ||
|
|
561abdbf0d | ||
|
|
964432c184 | ||
|
|
4944d228cd | ||
|
|
de4a6c69fe | ||
|
|
f3ffb229ff | ||
|
|
3910ad5241 | ||
|
|
e8cc388f3a | ||
|
|
888a5d00ed | ||
|
|
dcd5533149 | ||
|
|
f3a5b7e373 | ||
|
|
6f06fe6b2a | ||
|
|
ac96179904 | ||
|
|
c37f707b15 | ||
|
|
80f40a500c | ||
|
|
445863a940 | ||
|
|
30a8ab0d8c | ||
|
|
4a239f5ed5 | ||
|
|
3db8d49d11 | ||
|
|
9885b65cf0 | ||
|
|
5c867e0cd4 | ||
|
|
00b79f4f9f | ||
|
|
0f82e9c5d8 | ||
|
|
007fc9923a | ||
|
|
ccfe31d9b5 | ||
|
|
f921359f64 | ||
|
|
4463395dfe | ||
|
|
f4080e5754 | ||
|
|
c6bb302f9c | ||
|
|
6d7ace4291 | ||
|
|
53a62bec02 | ||
|
|
263caf3238 | ||
|
|
6e0d56e955 | ||
|
|
cf9d894556 | ||
|
|
1c1a10f14b | ||
|
|
7d3ce85684 | ||
|
|
5fd16cda08 | ||
|
|
87fc9d9ee1 | ||
|
|
bf1a4b7b7f | ||
|
|
4c10357c41 | ||
|
|
4ceb620462 | ||
|
|
97ef0b0dd6 | ||
|
|
a27a5ccf3c | ||
|
|
8e47fb20a1 | ||
|
|
a014aea1b4 | ||
|
|
18cb000218 | ||
|
|
0cb6566bab | ||
|
|
9ae9de4ac9 | ||
|
|
04ac7dd00d | ||
|
|
5a4a2fde71 | ||
|
|
71237d7df7 | ||
|
|
424b3fe653 | ||
|
|
7b56956fdd | ||
|
|
a991236fa3 | ||
|
|
168e862e3a | ||
|
|
1dfc6660ba | ||
|
|
21b47e7924 | ||
|
|
d6ce0d1bf8 | ||
|
|
c5cd242033 | ||
|
|
73d21079a4 | ||
|
|
e0edfa3cec | ||
|
|
674b3c7c12 | ||
|
|
16ecd2b8c2 | ||
|
|
ee575c2589 | ||
|
|
57c6b454f6 | ||
|
|
e66f1830b0 | ||
|
|
ea93565e11 | ||
|
|
8eabfef781 | ||
|
|
9bb9e8d241 | ||
|
|
6da8edae2c | ||
|
|
eae8054c0e | ||
|
|
fd7f9caca9 | ||
|
|
e12cffa958 | ||
|
|
7519e48482 | ||
|
|
24780d5723 | ||
|
|
06d74925ec | ||
|
|
6144148bc3 | ||
|
|
39d8fd81e0 | ||
|
|
a90ccb9718 | ||
|
|
2a28c02965 | ||
|
|
b032b2baf0 | ||
|
|
e111622377 | ||
|
|
21a5e14552 | ||
|
|
71d23d0d34 | ||
|
|
650320a18b | ||
|
|
e0172f3a7d | ||
|
|
8db05486c0 | ||
|
|
22328a1368 | ||
|
|
7dd2cf97e6 | ||
|
|
2191a78e19 | ||
|
|
856d97740e | ||
|
|
b80f22abae | ||
|
|
9dfc893309 | ||
|
|
1087c5b1cf | ||
|
|
781632d134 | ||
|
|
1e149c5844 | ||
|
|
8ba4a5afb3 | ||
|
|
5ec9f9f52e | ||
|
|
1a343bc065 | ||
|
|
3eff5e7a18 | ||
|
|
ed5f749d38 | ||
|
|
ab02a865b0 | ||
|
|
16fb3fe24c | ||
|
|
0378fba23c | ||
|
|
429eff7c2e | ||
|
|
068343a2cb | ||
|
|
5f91e4da6e | ||
|
|
d73f3598e4 | ||
|
|
a8e512a3d3 | ||
|
|
e35ceda7db | ||
|
|
2fc192f2d4 | ||
|
|
7c1c54a413 | ||
|
|
b2bf04e475 | ||
|
|
f0d95d63ad | ||
|
|
c2aba270ff | ||
|
|
59a2ba5135 | ||
|
|
77b3674d01 | ||
|
|
34779964ce | ||
|
|
a9aa786332 | ||
|
|
cd86d0bf35 | ||
|
|
6ce3e3d67c | ||
|
|
af4ed8a1db | ||
|
|
57248e7ce4 | ||
|
|
fe91118385 | ||
|
|
b36cd04348 | ||
|
|
8ae4176af6 | ||
|
|
775b64f1bd | ||
|
|
66ebae8c62 | ||
|
|
c925bcf8d9 | ||
|
|
beb995d507 | ||
|
|
1523a53e10 | ||
|
|
188f7d3edc | ||
|
|
6da14ce25b | ||
|
|
9cacf07fe3 | ||
|
|
d0258cb3f3 | ||
|
|
b5ae0089d1 | ||
|
|
e07bd1eb00 | ||
|
|
6d79a71d93 | ||
|
|
c3289ca919 | ||
|
|
b7648e5883 | ||
|
|
03b487ae81 | ||
|
|
b1350bd8b4 | ||
|
|
1516d23ea4 | ||
|
|
9abaae980f | ||
|
|
370a529668 | ||
|
|
b7486f4f3b | ||
|
|
ff4a877ef9 | ||
|
|
e0f741db37 | ||
|
|
3107861322 | ||
|
|
7eff345003 | ||
|
|
00f7da2136 | ||
|
|
150a143163 | ||
|
|
f31ec881ef | ||
|
|
0b838d2055 | ||
|
|
b68aefe64d | ||
|
|
9340c296ee | ||
|
|
132ed20d18 | ||
|
|
2927c37776 | ||
|
|
ac63788ecd | ||
|
|
0a64c9d329 | ||
|
|
81c9f3aa33 | ||
|
|
6fae33074a | ||
|
|
679b282061 | ||
|
|
396b4cb598 | ||
|
|
8b67b82047 | ||
|
|
da7d771898 | ||
|
|
42b5942886 | ||
|
|
d848c42bd3 | ||
|
|
e9d034928f | ||
|
|
2f042819ac | ||
|
|
2177d2f2cc | ||
|
|
4d974e4d7f | ||
|
|
cb05a1782a | ||
|
|
5f7cb7641a | ||
|
|
ff62f24cd4 | ||
|
|
d45dfb7dd2 | ||
|
|
1d4de873cb | ||
|
|
edfc1f0610 | ||
|
|
a662a23d19 | ||
|
|
7cff1c8736 | ||
|
|
6bfdebcff5 | ||
|
|
5b3158cb15 | ||
|
|
baa3439646 | ||
|
|
ac040bd62b | ||
|
|
e0a9e33623 | ||
|
|
b29f959dda | ||
|
|
7a5ec9d347 | ||
|
|
28ddad0549 | ||
|
|
615746a323 | ||
|
|
e49d5a3219 | ||
|
|
a31f7cac0d | ||
|
|
9b65fe6c86 | ||
|
|
3b5dcd41d9 | ||
|
|
f4db1385fc | ||
|
|
1b844254fe | ||
|
|
bf924e5da0 | ||
|
|
da37be391e | ||
|
|
2a44054387 | ||
|
|
4c85c4d336 | ||
|
|
03030ae93f | ||
|
|
ed438e8877 | ||
|
|
e7700787b2 | ||
|
|
6cccb7b9b0 | ||
|
|
f8678ed024 | ||
|
|
9b48e3dd36 | ||
|
|
f5db698705 | ||
|
|
2a24642220 | ||
|
|
5cd8ea6926 | ||
|
|
633b33430a | ||
|
|
341e57eeb5 | ||
|
|
2a9b79f086 | ||
|
|
fc5a7bf9ce | ||
|
|
fbb57dc9ca | ||
|
|
2358984605 | ||
|
|
28ae0b8963 | ||
|
|
4e316440b9 | ||
|
|
f9c65c8fb2 | ||
|
|
d3c5d1a617 | ||
|
|
b57cdaef14 | ||
|
|
1f2ad4ea36 | ||
|
|
4c3537d869 | ||
|
|
6f1ff9f276 | ||
|
|
34ab9d3354 | ||
|
|
635aeb1465 | ||
|
|
adf9b57dd6 | ||
|
|
669aa9f53b | ||
|
|
399d439aa7 | ||
|
|
29ecaa46c2 | ||
|
|
614c88e6c3 | ||
|
|
49ab036894 | ||
|
|
c552006b38 | ||
|
|
b01f35cde5 | ||
|
|
a85615f12b | ||
|
|
04285faf55 | ||
|
|
962b880fa6 | ||
|
|
e75ebd07a0 | ||
|
|
a601a8d034 | ||
|
|
13826c371e | ||
|
|
0355bb4769 | ||
|
|
2e14af5693 | ||
|
|
135b99ee63 | ||
|
|
f4851dc4d8 | ||
|
|
8f31b00608 | ||
|
|
0ac2977788 | ||
|
|
ef30070360 | ||
|
|
3b9ac03b70 | ||
|
|
84f2e0da77 | ||
|
|
b0a5eaf20e | ||
|
|
1fec165bac | ||
|
|
5838ac1e69 | ||
|
|
dfd83c2463 | ||
|
|
b25d8dfd4b | ||
|
|
21ee330e9b | ||
|
|
599f6300c0 | ||
|
|
1916a4e10c | ||
|
|
0fd619c4f7 | ||
|
|
54c600a676 | ||
|
|
763cd473b4 | ||
|
|
e435c1e7b8 | ||
|
|
59bf7495b4 | ||
|
|
ec36f55ed8 | ||
|
|
03f38cb07b | ||
|
|
36719449c2 | ||
|
|
efb0c51648 | ||
|
|
2faf907296 | ||
|
|
33b77fed37 | ||
|
|
8cc2a167e1 | ||
|
|
09f33968b9 | ||
|
|
346720f384 | ||
|
|
aeade5636a | ||
|
|
9f3c8f1f74 | ||
|
|
3d1e48ec4b | ||
|
|
cbffca3984 | ||
|
|
9d6427d9da | ||
|
|
368cb6806f | ||
|
|
9795eaf31c | ||
|
|
b4f7b0b177 | ||
|
|
44048626cd | ||
|
|
7fb8a1cb93 | ||
|
|
2d544e7bc3 | ||
|
|
0f0a8131c5 | ||
|
|
f7e6acbf9c | ||
|
|
eb445e79e2 | ||
|
|
ddee3dfd25 | ||
|
|
8b7e6b90a1 | ||
|
|
dd571dd35f | ||
|
|
c4e4414bbf | ||
|
|
221b50e905 | ||
|
|
42598dc36b | ||
|
|
ea9d986a48 | ||
|
|
64b10dd4ad | ||
|
|
729b46ee5f | ||
|
|
0dfb491e9d | ||
|
|
63585ff3a7 | ||
|
|
698e62d70a | ||
|
|
ab9ca9f49d | ||
|
|
257080e1f9 | ||
|
|
068c83b9fb | ||
|
|
cb86c48bc4 | ||
|
|
f0ceed5454 | ||
|
|
f0e4b29d73 | ||
|
|
4d23c75fa4 | ||
|
|
0ae73cbad3 | ||
|
|
44b70b745a | ||
|
|
3bf0e29d94 | ||
|
|
60759e7a1a | ||
|
|
28f4457e0a | ||
|
|
aca9e2655b | ||
|
|
567ebe69d0 | ||
|
|
6c3b30fe53 | ||
|
|
e9b2ba93c4 | ||
|
|
a9fa4ce1a5 | ||
|
|
18e2ab6389 | ||
|
|
917b654c63 | ||
|
|
c7a202525c | ||
|
|
4c80c9bd0f | ||
|
|
480d8e2dc8 | ||
|
|
73a4c5d37f | ||
|
|
b003749832 | ||
|
|
0ef6797ce9 | ||
|
|
0013bbc14d | ||
|
|
93c4f62b3d | ||
|
|
0008428ae0 | ||
|
|
49818a5aef | ||
|
|
9acb068f26 | ||
|
|
2e35918650 | ||
|
|
c6877b7207 | ||
|
|
af598af917 | ||
|
|
fd98695a1c | ||
|
|
737c373706 | ||
|
|
2fe9d88068 | ||
|
|
81f6e8b214 | ||
|
|
b484c66f9c | ||
|
|
a30354dd22 | ||
|
|
98ba005cbc | ||
|
|
5ef4c0c3e3 | ||
|
|
748cf146c2 | ||
|
|
9d86641a09 | ||
|
|
4940a58942 | ||
|
|
56560d767b | ||
|
|
c024262479 | ||
|
|
91616be8c1 | ||
|
|
14bf2209c1 | ||
|
|
26352dfb2c | ||
|
|
56a5bc7f4e | ||
|
|
c5cca3da2d | ||
|
|
b8b72adc38 | ||
|
|
e69571d469 | ||
|
|
859bef5d24 | ||
|
|
1b6ffdd728 | ||
|
|
cedfc3ddc2 | ||
|
|
317d837c26 | ||
|
|
10e42c4a5f | ||
|
|
ccd71cc6fe | ||
|
|
4981ca3f50 | ||
|
|
20f9969b90 | ||
|
|
f34deb94be | ||
|
|
b98d787dd9 | ||
|
|
fa8ab999d3 | ||
|
|
b9e7d5a2c1 | ||
|
|
6b8634462d | ||
|
|
f3706b4975 | ||
|
|
66c70aba9a | ||
|
|
2ee13d5063 | ||
|
|
b81eb9037d | ||
|
|
2a261ab180 | ||
|
|
b3facfeafe | ||
|
|
edbd81d6a6 | ||
|
|
c22c861534 | ||
|
|
b256423ee7 | ||
|
|
cda39039ea | ||
|
|
64242926e2 | ||
|
|
a6357d8b23 | ||
|
|
84387bc56d | ||
|
|
3d1dee1164 | ||
|
|
b9c627d4c3 | ||
|
|
c588a37cc3 | ||
|
|
372bfccb68 | ||
|
|
be4f3ce82c | ||
|
|
d7ced7c0e4 | ||
|
|
3454f0685c | ||
|
|
3810eff007 | ||
|
|
a03283fe32 | ||
|
|
96d016f0a4 | ||
|
|
622e60990a | ||
|
|
112fbaa97d | ||
|
|
516cf8347c | ||
|
|
9f0fff863f | ||
|
|
44c77e5bf3 | ||
|
|
1fa4de4276 | ||
|
|
9f6aa8dd33 | ||
|
|
f5563c9ed3 | ||
|
|
32245f5b61 | ||
|
|
edcd6ee44b | ||
|
|
93fae330ae | ||
|
|
2f13511810 | ||
|
|
9d1b58917b | ||
|
|
0eb06843f7 | ||
|
|
a977c8fc9f | ||
|
|
c33ccd1cf9 | ||
|
|
55c3107e91 | ||
|
|
387334854e | ||
|
|
19a852bee3 | ||
|
|
4c06f8c69b | ||
|
|
39deef5b8b | ||
|
|
bc605481d2 | ||
|
|
60dc2ce9c5 | ||
|
|
7ba258f750 | ||
|
|
4ec72cac9e | ||
|
|
cd4ec3ece5 | ||
|
|
30385b85e4 | ||
|
|
27bef46818 | ||
|
|
2b4ed56dcb | ||
|
|
e167eba7d8 | ||
|
|
272050938f | ||
|
|
3ee381512b | ||
|
|
a2d5affb88 | ||
|
|
2b759aab12 | ||
|
|
223d7bf514 | ||
|
|
fa2eb4e214 | ||
|
|
7689afb616 | ||
|
|
10002e9ec5 | ||
|
|
b2a0af0df4 | ||
|
|
4966fd2837 | ||
|
|
421d36d159 | ||
|
|
74270adba7 | ||
|
|
2b97759fa7 | ||
|
|
b8b9784763 | ||
|
|
8439d5c668 | ||
|
|
cb3a0f667a | ||
|
|
adf21a5fc2 | ||
|
|
4c28fadc07 | ||
|
|
2849a05507 | ||
|
|
801ed235cf | ||
|
|
98433c7399 | ||
|
|
b537dcf3f4 | ||
|
|
eaf8ecf2c1 | ||
|
|
9f232459d9 | ||
|
|
b92661cfe0 | ||
|
|
6ca4470752 | ||
|
|
6cecb67edd | ||
|
|
91388ca10d | ||
|
|
11e2acbdb5 | ||
|
|
4e3d1b631c | ||
|
|
4f06de4844 | ||
|
|
affb3c57e3 | ||
|
|
39e762a419 | ||
|
|
fe966c8576 | ||
|
|
12c90dfb53 | ||
|
|
03aabfd6d1 | ||
|
|
49b3cf552b | ||
|
|
6300012c32 | ||
|
|
9d0773c185 | ||
|
|
96bd2f466e | ||
|
|
c6151e1a7d | ||
|
|
c0c6671bd0 | ||
|
|
2b9d90ff49 | ||
|
|
2caa6fb41a | ||
|
|
df00473ae2 | ||
|
|
2acce9283f | ||
|
|
7971624cf9 | ||
|
|
e353fe7f2c | ||
|
|
e797e7a7e4 | ||
|
|
cb91f766c7 | ||
|
|
c983de54f6 | ||
|
|
9d9b983694 | ||
|
|
6db930d03d | ||
|
|
0233a868ab | ||
|
|
ed98d4820e | ||
|
|
971d40ba18 | ||
|
|
f3e1e30838 | ||
|
|
bff8604c8a | ||
|
|
6cf4fc0989 | ||
|
|
308374c7da | ||
|
|
06bb7ae090 | ||
|
|
b236d50c3c | ||
|
|
e2ac301993 | ||
|
|
d6bdcaccd7 | ||
|
|
a7f0e68443 | ||
|
|
dc24ab5804 | ||
|
|
d5512418d2 | ||
|
|
7a8e570dfa | ||
|
|
3794a30b4b | ||
|
|
700acfe764 | ||
|
|
9b8d6e0b64 | ||
|
|
3575f57a2a | ||
|
|
8838651405 | ||
|
|
6cb8f2254a | ||
|
|
72c2a70a32 | ||
|
|
51b1d12aab | ||
|
|
93159192bb | ||
|
|
d208694d05 | ||
|
|
e7cb8a4907 | ||
|
|
01dfe6e35c | ||
|
|
a5d4c4b43c | ||
|
|
9a5107534d | ||
|
|
d50d04318e | ||
|
|
a0afa3cef6 | ||
|
|
cf20e027af | ||
|
|
b68ab94939 | ||
|
|
af94bc472d | ||
|
|
289b102b38 | ||
|
|
ba6cbc2247 | ||
|
|
379b574b84 | ||
|
|
f1c44a65b1 | ||
|
|
7ddb5ebbe5 | ||
|
|
afd2fe3228 | ||
|
|
292197a3a2 | ||
|
|
8fac7feabd | ||
|
|
ca69955332 | ||
|
|
eacb24a133 | ||
|
|
21b3dbbb94 | ||
|
|
57ff683121 | ||
|
|
8b7e35ad0b | ||
|
|
0732f053b8 | ||
|
|
831a72b519 | ||
|
|
a5dad40521 | ||
|
|
e8263b2597 | ||
|
|
9d6c0afc8e | ||
|
|
6393d078e8 | ||
|
|
c62f6493d9 | ||
|
|
e8737c403e | ||
|
|
f279a89dc7 | ||
|
|
30463cfe75 | ||
|
|
c1405bbe2e | ||
|
|
7d9dafd9e1 | ||
|
|
e0e3634714 | ||
|
|
a5818af5fe | ||
|
|
6ebec52ffc | ||
|
|
ebd96dea49 | ||
|
|
d692383d80 | ||
|
|
cefc8c97ec | ||
|
|
8ce18ff065 | ||
|
|
40a97d2206 | ||
|
|
e111d9e91d | ||
|
|
faf407d62d | ||
|
|
cf5759a324 | ||
|
|
d220a69ab1 | ||
|
|
4d8dde58dc | ||
|
|
c5b98fcd5b | ||
|
|
482576be81 | ||
|
|
fdea2aa4dc | ||
|
|
e4dbdc570d | ||
|
|
7f3146ce64 | ||
|
|
1bf001b2f3 | ||
|
|
2a99496e9a | ||
|
|
59ba89a032 | ||
|
|
be9786fc4c | ||
|
|
629140e6c3 | ||
|
|
5f46f9e698 | ||
|
|
d4daf14c77 | ||
|
|
cfdaab8f86 | ||
|
|
70ca570a66 | ||
|
|
ab7e12a30d | ||
|
|
87a95b9ab2 | ||
|
|
9aff03c5b6 | ||
|
|
adfa4fb099 | ||
|
|
5e8b3c1c24 | ||
|
|
714b9ebf48 | ||
|
|
c93dbd2d2e | ||
|
|
7139f1fe42 | ||
|
|
7e490f1f96 | ||
|
|
b6aa432b26 | ||
|
|
547e31ffef | ||
|
|
092ee15603 | ||
|
|
dd52d5158e | ||
|
|
88d8f79e3c | ||
|
|
3a1a75f99f | ||
|
|
422c23dbbd | ||
|
|
13fd02d455 | ||
|
|
b75e2e4778 | ||
|
|
43222700be | ||
|
|
05abb02b64 | ||
|
|
bf1590ab70 | ||
|
|
f9b5b9f55f | ||
|
|
25d9e21b38 | ||
|
|
77641fc43d | ||
|
|
90865fe9c1 | ||
|
|
15fbfc3c51 | ||
|
|
340b6a0cd6 | ||
|
|
064e13268a | ||
|
|
641ea0f9d8 | ||
|
|
98bc7147e3 | ||
|
|
3d9e5d49b8 | ||
|
|
8bdcfbb049 | ||
|
|
13dcd606ea | ||
|
|
6576688f92 | ||
|
|
33e63df4ad | ||
|
|
e910e9fc77 | ||
|
|
a00b36d50d | ||
|
|
0f6e143a6f | ||
|
|
854d209be8 | ||
|
|
3f50efb951 | ||
|
|
aceaa90466 | ||
|
|
63622edcf4 | ||
|
|
4a1c0563cb | ||
|
|
b34181f104 | ||
|
|
141a067b85 | ||
|
|
4c48d91f8e |
@@ -1 +0,0 @@
|
||||
4
|
||||
@@ -1,5 +0,0 @@
|
||||
exclude_patterns:
|
||||
- "**/*.spec.js"
|
||||
- "**/*.spec.ts"
|
||||
- "docs/**/*.js"
|
||||
- "**/test/**/*.js"
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright 2019-2021 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const base = require('@polkadot/dev/config/eslint.cjs');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
ignorePatterns: [
|
||||
'.eslintrc.js',
|
||||
'.github/**',
|
||||
'.vscode/**',
|
||||
'.yarn/**',
|
||||
'**/binaryen/*',
|
||||
'**/build/*',
|
||||
'**/coverage/*',
|
||||
'**/node_modules/*',
|
||||
'**/pkg/*',
|
||||
'**/target/*'
|
||||
],
|
||||
parserOptions: {
|
||||
...base.parserOptions,
|
||||
project: [
|
||||
'./tsconfig.json'
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,86 @@
|
||||
<!--
|
||||
|
||||
For general support, howto, coding and bundling questions, please
|
||||
use the Substrate & Polkadot StackExchange at
|
||||
|
||||
https://substrate.stackexchange.com/
|
||||
|
||||
and get other ecosystem developers involved. This issues in this
|
||||
repository are meant for the tracking of feature requests and bug
|
||||
reports.
|
||||
|
||||
While all issues are looked at non-bug and non-features would take
|
||||
quite a bit longer to get to and may yield less than satisfactory
|
||||
responses in this format.
|
||||
|
||||
Additionally, please ensure you have done a search on the existing
|
||||
and closed issues before logging a new request. This saves time on
|
||||
all sides.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
* **I'm submitting a ...**
|
||||
|
||||
<!---
|
||||
|
||||
REQUIRED:
|
||||
|
||||
Classify the type of report your are submitting
|
||||
|
||||
-->
|
||||
|
||||
- [ ] Bug report
|
||||
- [ ] Feature request
|
||||
- [ ] Support request
|
||||
- [ ] Other
|
||||
|
||||
|
||||
* **What is the current behavior and expected behavior?**
|
||||
|
||||
<!---
|
||||
|
||||
REQUIRED:
|
||||
|
||||
If you're describing a bug, tell us what should happen. If you're
|
||||
suggesting a change/improvement, tell us how it should work.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
* **What is the motivation for changing the behavior?**
|
||||
|
||||
<!---
|
||||
|
||||
OPTIONAL:
|
||||
|
||||
Suggest a motivation for the request or ideas how to implement the
|
||||
addition or change
|
||||
|
||||
-->
|
||||
|
||||
|
||||
* **Please tell us about your environment:**
|
||||
|
||||
<!---
|
||||
|
||||
REQUIRED:
|
||||
|
||||
Include as many relevant details about the environment in which you
|
||||
experienced the issue. Also ensure that you have tested against the
|
||||
latest stable releases if you believe this to be a bug
|
||||
|
||||
-->
|
||||
|
||||
- Version:
|
||||
- Environment:
|
||||
|
||||
- [ ] Node.js
|
||||
- [ ] Browser
|
||||
- [ ] Other (limited support for other environments)
|
||||
|
||||
- Language:
|
||||
|
||||
- [ ] JavaScript
|
||||
- [ ] TypeScript (include tsc --version)
|
||||
- [ ] Other
|
||||
@@ -0,0 +1,16 @@
|
||||
name: bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
approve:
|
||||
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && (!github.event.pull_request || github.event.pull_request.head.repo.full_name == github.repository)"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: jacogr/action-approve@795afd1dd096a2071d7ec98740661af4e853b7da
|
||||
with:
|
||||
authors: jacogr, TarikGul, valentinfernandez1
|
||||
labels: -auto
|
||||
token: ${{ secrets.GH_PAT_BOT }}
|
||||
@@ -0,0 +1,16 @@
|
||||
name: bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: jacogr/action-merge@d2d64b4545acd93b0a9575177d3d215ae3f92029
|
||||
with:
|
||||
checks: pr (build),pr (lint),pr (test)
|
||||
labels: -auto
|
||||
strategy: squash
|
||||
token: ${{ secrets.GH_PAT_BOT }}
|
||||
@@ -0,0 +1,25 @@
|
||||
name: 'Lock Threads'
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '20 1/3 * * *'
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
YARN_ENABLE_SCRIPTS: false
|
||||
steps:
|
||||
- uses: dessant/lock-threads@c1b35aecc5cdb1a34539d14196df55838bb2f836
|
||||
with:
|
||||
github-token: ${{ secrets.GH_PAT_BOT }}
|
||||
issue-inactive-days: '7'
|
||||
issue-comment: >
|
||||
This thread has been automatically locked since there has not been
|
||||
any recent activity after it was closed. Please open a new issue
|
||||
if you think you have a related problem or query.
|
||||
pr-inactive-days: '2'
|
||||
pr-comment: >
|
||||
This pull request has been automatically locked since there
|
||||
has not been any recent activity after it was closed.
|
||||
Please open a new issue for related bugs.
|
||||
@@ -3,15 +3,28 @@ on: [pull_request]
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
step: ['lint', 'test', 'build']
|
||||
name: ${{ matrix.step }}
|
||||
step: ['lint', 'test', 'build', 'deno']
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
YARN_ENABLE_SCRIPTS: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
- uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v1.42.x
|
||||
- name: ${{ matrix.step }}
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
run: |
|
||||
yarn install --immutable | grep -v 'YN0013'
|
||||
./scripts/install-build-deps.sh
|
||||
yarn install --immutable
|
||||
if [ "${{ matrix.step }}" != "lint" ]; then
|
||||
./scripts/install-build-deps.sh
|
||||
fi
|
||||
yarn polkadot-dev-deno-map
|
||||
yarn ${{ matrix.step }}
|
||||
|
||||
@@ -6,30 +6,31 @@ on:
|
||||
|
||||
jobs:
|
||||
master:
|
||||
if: "! startsWith(github.event.head_commit.message, '[CI Skip]')"
|
||||
strategy:
|
||||
matrix:
|
||||
step: ['build:release']
|
||||
name: ${{ matrix.step }}
|
||||
if: "! startsWith(github.event.head_commit.message, '[CI Skip]') && github.repository == 'polkadot-js/wasm'"
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
YARN_ENABLE_SCRIPTS: false
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
GH_PAT: ${{ secrets.GH_PAT_BOT }}
|
||||
GH_RELEASE_GITHUB_API_TOKEN: ${{ secrets.GH_PAT_BOT }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GH_PAT }}
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GH_PAT_BOT }}
|
||||
ref: ${{ github.ref }}
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'lts/*'
|
||||
- name: Set Execute Permissions
|
||||
run: chmod +x ./scripts/*
|
||||
- name: Run Install Build Deps
|
||||
run: bash ./scripts/install-build-deps.sh
|
||||
- name: build
|
||||
env:
|
||||
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
GH_RELEASE_GITHUB_API_TOKEN: ${{ secrets.GH_PAT }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: |
|
||||
yarn install --immutable | grep -v 'YN0013'
|
||||
./scripts/install-build-deps.sh
|
||||
yarn install --immutable
|
||||
yarn ${{ matrix.step }}
|
||||
|
||||
dummy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: dummy
|
||||
run: |
|
||||
echo "Dummy skip step"
|
||||
|
||||
+7
-2
@@ -1,15 +1,19 @@
|
||||
binaryen/
|
||||
binaryen-quantus/
|
||||
bindgen/
|
||||
bindgen-quantus/
|
||||
build/
|
||||
build-docs/
|
||||
build-*/
|
||||
build-test/
|
||||
bytes/
|
||||
coverage/
|
||||
docs/.vuepress/dist/
|
||||
node_modules/
|
||||
pkg/
|
||||
target/
|
||||
tmp/
|
||||
wabt/
|
||||
/import_map.json
|
||||
/mod.ts
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
@@ -26,5 +30,6 @@ lerna-debug.log*
|
||||
npm-debug.log*
|
||||
package-lock.json
|
||||
report.*.json
|
||||
tsconfig.*buildinfo
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Jaco <jacogr@gmail.com>
|
||||
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> <action@github.com>
|
||||
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Github Actions <action@github.com>
|
||||
@@ -0,0 +1,4 @@
|
||||
build
|
||||
coverage
|
||||
packages
|
||||
scripts
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module.exports = require('@polkadot/dev/config/prettier.cjs');
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"eslint.enable": true,
|
||||
"eslint.experimental.useFlatConfig": true
|
||||
}
|
||||
Vendored
File diff suppressed because one or more lines are too long
-77
File diff suppressed because one or more lines are too long
Vendored
-55
File diff suppressed because one or more lines are too long
+934
File diff suppressed because one or more lines are too long
+9
-7
@@ -1,13 +1,15 @@
|
||||
compressionLevel: mixed
|
||||
|
||||
enableGlobalCache: false
|
||||
|
||||
enableImmutableInstalls: false
|
||||
|
||||
enableProgressBars: false
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
|
||||
spec: "@yarnpkg/plugin-version"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-2.4.0.cjs
|
||||
yarnPath: .yarn/releases/yarn-4.6.0.cjs
|
||||
|
||||
+340
@@ -1,5 +1,345 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 7.5.4 Dec 9, 2025
|
||||
|
||||
Changes:
|
||||
|
||||
- Bump polkadot-js dependencies ([#605](https://github.com/polkadot-js/wasm/pull/605))
|
||||
|
||||
|
||||
## 7.5.3 Nov 24, 2025
|
||||
|
||||
Changes:
|
||||
|
||||
- Bump @polkadot dependencies ([#603](https://github.com/polkadot-js/wasm/pull/603))
|
||||
|
||||
|
||||
## 7.5.2 Nov 10, 2025
|
||||
|
||||
Changes:
|
||||
|
||||
- Fix/Revert asm build ([#599](https://github.com/polkadot-js/wasm/pull/599))
|
||||
- Bump @polkadot dependencies ([#601](https://github.com/polkadot-js/wasm/pull/601))
|
||||
|
||||
|
||||
## 7.5.1 aug 25, 2025
|
||||
|
||||
Changes:
|
||||
|
||||
- Bump yarn to 4.5.1 ([#573](https://github.com/polkadot-js/wasm/pull/573))
|
||||
- Update comments and labels from 2024 to 2025 ([#574](https://github.com/polkadot-js/wasm/pull/574))
|
||||
- Bump yarn to 4.6.0 ([#575](https://github.com/polkadot-js/wasm/pull/575))
|
||||
- Set execute for build script in CI ([#576](https://github.com/polkadot-js/wasm/pull/576))
|
||||
- Set permissions on all scripts ([#577](https://github.com/polkadot-js/wasm/pull/577))
|
||||
- Bump dev to 0.83.2 ([#578](https://github.com/polkadot-js/wasm/pull/578))
|
||||
- chore: added check in ext_secp_recover for signature normalization ([#579](https://github.com/polkadot-js/wasm/pull/579))
|
||||
- chore: Improve CI ([#580](https://github.com/polkadot-js/wasm/pull/580))
|
||||
- Revert CI improvements and wasm-bindgen version ([#583](https://github.com/polkadot-js/wasm/pull/583))
|
||||
- Added validation checks in PBKDF2 and Scrypt hashing functions ([#584](https://github.com/polkadot-js/wasm/pull/584))
|
||||
- Rollback wasm-bindgen version change ([#586](https://github.com/polkadot-js/wasm/pull/586))
|
||||
- Fix rust version to 1.84 ([#587](https://github.com/polkadot-js/wasm/pull/587))
|
||||
- Default to installed rust version ([#588](https://github.com/polkadot-js/wasm/pull/588))
|
||||
- Default to nightly rust version ([#589](https://github.com/polkadot-js/wasm/pull/589))
|
||||
- Ci Fix ([#590](https://github.com/polkadot-js/wasm/pull/590))
|
||||
- Read lock file ([#591](https://github.com/polkadot-js/wasm/pull/591))
|
||||
- Setup nightly as default ([#592](https://github.com/polkadot-js/wasm/pull/592))
|
||||
- Tweak install-build-deps.sh script ([#593](https://github.com/polkadot-js/wasm/pull/593))
|
||||
- Remove ASM build ([#594](https://github.com/polkadot-js/wasm/pull/594))
|
||||
- Bump @polkadot deps ([#595](https://github.com/polkadot-js/wasm/pull/595))
|
||||
|
||||
|
||||
## 7.4.1 Oct 20, 2024
|
||||
|
||||
- Bump dev deps to 0.81.2
|
||||
- Bump TS
|
||||
- Ensure CJS is exported correctly
|
||||
- Bump yarn
|
||||
- Add missing sideEffect declarations
|
||||
- Set Deno build in CI to 1.42.x
|
||||
|
||||
|
||||
## 7.3.2 Dec 6, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Apply fixes for OOB array access
|
||||
|
||||
|
||||
## 7.3.1 Nov 17, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Drop support for Node 16 (EOL 11 Sep 2023)
|
||||
|
||||
|
||||
## 7.2.2 Aug 17, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust cjs exports for consistency
|
||||
- Adjust usage of `?.` as per (latest) linting rules
|
||||
|
||||
|
||||
## 7.2.1 May 13, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust `cjs/bytes.js` generation to follow `export.<var> = ...` form
|
||||
- Add `module` to `package.json` export map (ESM-only)
|
||||
|
||||
|
||||
## 7.1.2 Apr 28, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Apply `readonly` specifiers to private class fields where applicable
|
||||
- Adjust compilation output for `__internal__` class fields
|
||||
|
||||
|
||||
## 7.1.1 Apr 22, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Add `wasm-util` as dependency where `x-randomvalues` is a peer
|
||||
- Drop support for Node 14 (EOL 30 Apr 2023)
|
||||
|
||||
|
||||
## 7.0.3 Mar 11, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Use consistent `.js` imports in source files (TS moduleResolution)
|
||||
|
||||
|
||||
## 7.0.2 Mar 4, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Update to latest `@polkadot/dev` (w/ tsc jsx detection output changes)
|
||||
|
||||
|
||||
## 7.0.1 Mar 4, 2023
|
||||
|
||||
Changes:
|
||||
|
||||
- Swap TS -> JS compiler to use tsc (from babel)
|
||||
- Adjust all tests to use `node:test` runner (ESM & CJS variants)
|
||||
|
||||
|
||||
## 6.4.1 Dec 3, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Add `/*#__PURE__*/` annotations for specific `export const something = someFunction(...)`
|
||||
|
||||
|
||||
## 6.3.1 Jul 21, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Optimize packed WASM base64 decoding loop
|
||||
- Adjust test environment (no duplication)
|
||||
- Adjust CI check steps, align with other org repos
|
||||
- Remove unneeded `import_map.in.json` for Deno tests
|
||||
|
||||
|
||||
## 6.2.3 Jul 7, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Optimize WASM init with pre-allocated buffers
|
||||
- Additional platform-specific tests
|
||||
|
||||
|
||||
## 6.2.2 Jul 4, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Protect against potential low-level double-sign leak in dalek-ed25519 (Don't use provided input pubKey, see https://github.com/MystenLabs/ed25519-unsafe-libs)
|
||||
|
||||
|
||||
## 6.2.1 Jul 1, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Add missing `peerDependencies` to `wasm-crypto` (`bridge` requirement)
|
||||
- Adjust `WebAssembly.{Memory, ModuleImports}` usage to cater for non-dom TS
|
||||
|
||||
|
||||
## 6.1.5 Jun 23, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust build outputs for Deno targets
|
||||
|
||||
|
||||
## 6.1.4 Jun 22, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust build outputs for Deno targets
|
||||
|
||||
|
||||
## 6.1.3 Jun 21, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Fix bundle publish (from dev bump)
|
||||
|
||||
|
||||
## 6.1.2 Jun 21, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust assert usage in all internal non-test code
|
||||
- Additional comments where missing
|
||||
|
||||
|
||||
## 6.1.1 May 13, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust init, allow RN with default ASM.js-only fallback
|
||||
- Split `wasm-{bridge, util}` packages for internal re-use
|
||||
|
||||
|
||||
## 6.0.1 Apr 9, 2022
|
||||
|
||||
- **Breaking change** In this major version the commonjs outputs are moved to a sub-folder. Since the `export` map and `main` field in `package.json` does reflect this change, there should be no usage changes. However the packages here will all need to be on the same version for internal linkage.
|
||||
|
||||
Changes:
|
||||
|
||||
- Update ed25519 secret key format return description
|
||||
- Output commonjs files under the `cjs/**` root
|
||||
|
||||
|
||||
## 5.1.1 Mar 27, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Swap from `libsecp256k1` to `secp256k1` (this aligns with the Substrate use)
|
||||
- Adjust `wasm-crypto/init*` to also export `initWasm(): Promise<void>` (optional manual init)
|
||||
- Allow for `wasm-crypto/initNone` with no defined Wasm or Asm interfaces
|
||||
- Fix initialization on React Native with only ASM
|
||||
|
||||
|
||||
## 5.0.1 Mar 19, 2022
|
||||
|
||||
- **Breaking change** For users of React Native, you are now required to add `import '@polkadot/wasm-crypto/initOnlyAsm'` at your project top-level to ensure that asm.js is initialized. (Or alternatively `import '@polkadot/wasm-crypto/initWasmAsm'` to future-proof when WASM does become available)
|
||||
- **Breaking change** For users who used to map the `data` and `empty` of the internal `wasm-crypto-{wasm, asmjs}` packages in their bundlers, swap to one of the `@polkadot/wasm-crypto/init*` top-level imports to set the type of interfaces you would prefer. A full writeup of the rationale and other options can be found [in the FAQ](https://polkadot.js.org/docs/util-crypto/FAQ#i-dont-have-wasm-available-in-my-environment)
|
||||
|
||||
Changes:
|
||||
|
||||
- Add (optional) `@polkadot/wasm-crypto/init{OnlyAsm, OnlyWasm, WasmAsm}` to allow specific interface types
|
||||
- Add work-around for lazy secp256k1 init in asm.js environments
|
||||
- Optimize asm.js output size
|
||||
- Use latest `wasm-bindgen`, `binaryen` & `wabt` packages in build
|
||||
- Additional workaround for Vite bundling
|
||||
|
||||
|
||||
## 4.6.1 Mar 12, 2022
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust ed25519 internals, consistency in code
|
||||
- Ensure package path is available under ESM & CJS
|
||||
- JS wrapped bytes interoperability test
|
||||
- Adjust for bundlers where `import.meta.url` is undefined
|
||||
|
||||
|
||||
## 4.5.1 Dec 3, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Add `secp256k1{Compress, Expand, Recover, Sign}` functions
|
||||
- Remove all occurences of `.unwrap()` (match everywhere)
|
||||
- Adjust and optimize WASM function JS interface construction
|
||||
- Simplify base64 bytes decoding on construction
|
||||
|
||||
|
||||
## 4.4.1 Nov 22, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Add `hmacSha256` & `hmacSha512` functions
|
||||
|
||||
|
||||
## 4.3.1 Nov 19, 2021
|
||||
|
||||
Contributed:
|
||||
|
||||
- Updated package.json to include repo (Thanks to https://github.com/v-zhzhou)
|
||||
|
||||
Changes:
|
||||
|
||||
- Add `keccak512` function
|
||||
- Add `sha256` function
|
||||
|
||||
|
||||
## 4.2.1 Aug 28, 2021
|
||||
|
||||
Contributed:
|
||||
|
||||
- Add sr25519 agreement external (Thanks to https://github.com/shelvenzhou)
|
||||
|
||||
Changes:
|
||||
|
||||
- Adjust tests to align with JS coding standards
|
||||
- Allow for optional build with Rust stable bootstrap
|
||||
|
||||
|
||||
## 4.1.2 Jul 9, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Bump `@polkadot/dev` to allow for bundles with new-format
|
||||
|
||||
|
||||
## 4.1.1 Jul 7, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Add an explicit `engines` field to `package.json`
|
||||
- Allow building as a completely stand-alone browser bundle (experimental)
|
||||
|
||||
|
||||
## 4.0.2 Mar 5, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Add import indirection for both CJS & ESM (where generated source file is commonjs)
|
||||
|
||||
|
||||
## 4.0.1 Mar 4, 2021
|
||||
|
||||
**Important** In the 4.0 version the default package type has been changed to ESM modules by default. This should not affect usage, however since the output formats changed, a new major version is required.
|
||||
|
||||
Changes:
|
||||
|
||||
- Build to ESM by default (with cjs versions via export map)
|
||||
|
||||
|
||||
## 3.2.4 Feb 24, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Cleanup implicit dependencies, perform base64 decoding using base64-js
|
||||
|
||||
|
||||
## 3.2.3 Feb 16, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Change package detect import to use `.js` source, not `.json`
|
||||
|
||||
|
||||
## 3.2.2 Jan 24, 2021
|
||||
|
||||
Changes:
|
||||
|
||||
- Remove `module` field in `package.json`
|
||||
|
||||
|
||||
## 3.2.1 Jan 22, 2021
|
||||
|
||||
Contributed:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
618 Jaco 2024 (#559)
|
||||
19 Tarik Gul Bump dev to 0.83.2 (#578)
|
||||
12 Valentin Fernandez 7.5.1 (#596)
|
||||
10 rajk93 7.5.4 (#606)
|
||||
1 Evgeny Fixed type (#121)
|
||||
1 Shunfan Zhou Support sr25519 agreement (#209)
|
||||
1 Steve Degosserie Expose Schnorrkel's VRF capabilities (#170)
|
||||
1 Zhongpeng Zhou Update package.json to include the repository (#220)
|
||||
@@ -1,9 +1,3 @@
|
||||
[](https://polkadot.js.org)
|
||||

|
||||
[](https://www.npmjs.com/package/@polkadot/wasm-crypto)
|
||||
[](https://www.npmjs.com/package/@polkadot/wasm-crypto)
|
||||
[](https://codeclimate.com/github/polkadot-js/wasm/maintainability)
|
||||
|
||||
# @polkadot/wasm
|
||||
|
||||
Various WASM wrappers around Rust crates
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright 2019-2021 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
module.exports = require('@polkadot/dev/config/babel-config-cjs.cjs');
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import baseConfig from '@polkadot/dev/config/eslint';
|
||||
|
||||
export default [
|
||||
...baseConfig,
|
||||
{
|
||||
ignores: [
|
||||
'mod.ts'
|
||||
]
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"imports": {
|
||||
"https://esm.sh/v90/@types/bn.js@~5.2/index.d.ts": "https://esm.sh/v90/@types/bn.js@5.1.0/index.d.ts"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2019-2021 @polkadot/wasm-crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const config = require('@polkadot/dev/config/jest.cjs');
|
||||
|
||||
module.exports = Object.assign({}, config, {
|
||||
moduleNameMapper: {
|
||||
'@polkadot/wasm-crypto-asmjs(.*)$': '<rootDir>/packages/wasm-crypto-asmjs/build/$1',
|
||||
'@polkadot/wasm-crypto-wasm(.*)$': '<rootDir>/packages/wasm-crypto-wasm/build/$1',
|
||||
// eslint-disable-next-line sort-keys
|
||||
'@polkadot/wasm-crypto(.*)$': '<rootDir>/packages/wasm-crypto/src/$1'
|
||||
},
|
||||
modulePathIgnorePatterns: [
|
||||
'<rootDir>/packages/wasm-crypto-asmjs/build',
|
||||
'<rootDir>/packages/wasm-crypto-wasm/build',
|
||||
'<rootDir>/packages/wasm-crypto/build'
|
||||
],
|
||||
resolver: '@polkadot/dev/config/jest-resolver.cjs'
|
||||
});
|
||||
+42
-16
@@ -1,32 +1,58 @@
|
||||
{
|
||||
"repository": "https://github.com/polkadot-js/wasm",
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"license": "Apache-2",
|
||||
"bugs": "https://github.com/polkadot-js/wasm/issues",
|
||||
"engines": {
|
||||
"node": ">=18.14"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/wasm#readme",
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@4.6.0",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/wasm.git"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "7.5.4",
|
||||
"versions": {
|
||||
"git": "7.5.4",
|
||||
"npm": "7.5.4"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"resolutions": {
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yarn build:wasm",
|
||||
"build:js": "./scripts/build-js.sh",
|
||||
"build:quantus": "./scripts/build-quantus.sh",
|
||||
"build:quantus:js": "./scripts/build-quantus-js.sh",
|
||||
"build:release": "polkadot-ci-ghact-build",
|
||||
"build:rollup": "polkadot-exec-rollup --config",
|
||||
"build:wasm": "./scripts/build.sh",
|
||||
"lint": "polkadot-dev-run-lint",
|
||||
"clean": "./scripts/clean.sh",
|
||||
"deno": "yarn deno:build && yarn deno:check",
|
||||
"deno:build": "WITH_DENO=1 yarn build",
|
||||
"deno:check": "deno check --import-map=import_map.json mod.ts",
|
||||
"lint": "polkadot-dev-run-lint",
|
||||
"postinstall": "polkadot-dev-yarn-only",
|
||||
"test": "yarn test:wasm:rust",
|
||||
"test:wasm:js": "yarn test:wasm:js:jest && yarn test:wasm:js:node",
|
||||
"test:wasm:js:jest": "polkadot-dev-run-test ./test/jest.spec.js",
|
||||
"test:wasm:js:node": "cd packages/wasm-crypto && node ./test/wasm.js && node ./test/asm.js",
|
||||
"test:wasm:rust": "cd packages/wasm-crypto && RUST_BACKTRACE=full cargo test --release -- --nocapture"
|
||||
"test": "yarn test:wasm-crypto:rust && yarn test:quantus-crypto:rust",
|
||||
"test:js": "yarn test:wasm-crypto:js",
|
||||
"test:quantus-crypto:js": "./scripts/test-quantus-js.sh",
|
||||
"test:quantus-crypto:rust": "cd packages/quantus-crypto && RUST_BACKTRACE=full cargo test --release",
|
||||
"test:wasm-crypto:deno": "deno test --allow-read --import-map=import_map.json packages/wasm-crypto/test/deno.ts",
|
||||
"test:wasm-crypto:js": "yarn test:wasm-crypto:js:jest && yarn test:wasm-crypto:js:node",
|
||||
"test:wasm-crypto:js:jest": "polkadot-dev-run-test --env node --loader ./packages/wasm-crypto/test/loader-build.js",
|
||||
"test:wasm-crypto:js:node": "node --no-warnings --loader ./packages/wasm-crypto/test/loader-build.js ./packages/wasm-crypto/test/wasm.js && node --no-warnings --loader ./packages/wasm-crypto/test/loader-build.js ./packages/wasm-crypto/test/asm.js",
|
||||
"test:wasm-crypto:rust": "cd packages/wasm-crypto && RUST_BACKTRACE=full cargo test --release -- --test-threads=1 --nocapture"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
"@polkadot/dev": "^0.61.24",
|
||||
"fflate": "^0.6.0",
|
||||
"override-require": "^1.1.1"
|
||||
"@polkadot/dev": "^0.83.3",
|
||||
"@polkadot/util": "^14.0.1",
|
||||
"@types/node": "^20.16.1",
|
||||
"fflate": "^0.8.2"
|
||||
},
|
||||
"version": "3.2.1"
|
||||
"resolutions": {
|
||||
"typescript": "^5.5.4"
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+955
@@ -0,0 +1,955 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bip39"
|
||||
version = "2.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc"
|
||||
dependencies = [
|
||||
"bitcoin_hashes",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.14.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bca4c7abb40c8817d77403c880988cfd484f23ab2365726afb2f798363e2c4a2"
|
||||
dependencies = [
|
||||
"hex-conservative",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34"
|
||||
|
||||
[[package]]
|
||||
name = "fixed-hash"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hex-conservative"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3fef046dca3ca91ee1408a8c1b80ab777e80a4d308d1bf4e7adb3fcb047e08"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keccak-hash"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce2bd4c29270e724d3eaadf7bdc8700af4221fc0ed771b855eadcd1b98d52851"
|
||||
dependencies = [
|
||||
"primitive-types",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.189"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "plonky2_maybe_rayon"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1e554181dc95243b8d9948ae7bae5759c7fb2502fed28f671f95ef38079406"
|
||||
|
||||
[[package]]
|
||||
name = "plonky2_util"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c32c137808ca984ab2458b612b7eb0462d853ee041a3136e83d54b96074c7610"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primitive-types"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e4722c697a58a99d5d06a08c30821d7c082a4632198de1eaa5a6c22ef42373"
|
||||
dependencies = [
|
||||
"fixed-hash",
|
||||
"uint",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-plonky2"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd331d489a309f88e2d0e35a2b996932c7d92038b91ccc656a0a8e6b11b6977"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"critical-section",
|
||||
"hashbrown",
|
||||
"itertools",
|
||||
"keccak-hash",
|
||||
"log",
|
||||
"num",
|
||||
"once_cell",
|
||||
"plonky2_maybe_rayon",
|
||||
"plonky2_util",
|
||||
"qp-plonky2-core",
|
||||
"qp-plonky2-field",
|
||||
"qp-plonky2-verifier",
|
||||
"qp-poseidon-core",
|
||||
"rand 0.10.1",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-plonky2-core"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b81a3a9fce99f7bd45b8578f8d9b6a33507d34c2eb2c47c969b464db1ad601d3"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"hashbrown",
|
||||
"itertools",
|
||||
"keccak-hash",
|
||||
"log",
|
||||
"num",
|
||||
"plonky2_util",
|
||||
"qp-plonky2-field",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-plonky2-field"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1630d418ddce9feba18d3364596711d07074851757301350de313eef0a31af4f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"num",
|
||||
"plonky2_util",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-plonky2-verifier"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "944da5dec21ee476d561f6c38caddf45e829f3cc5fccbc76f6ece03660378dbe"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"critical-section",
|
||||
"hashbrown",
|
||||
"itertools",
|
||||
"keccak-hash",
|
||||
"log",
|
||||
"num",
|
||||
"once_cell",
|
||||
"plonky2_util",
|
||||
"qp-plonky2-core",
|
||||
"qp-plonky2-field",
|
||||
"qp-poseidon-core",
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"unroll",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-poseidon-core"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5872607e25ea4ee5fb37e64bf1462168e1a36a4e719cdc8a105533c708253918"
|
||||
|
||||
[[package]]
|
||||
name = "qp-rusty-crystals-dilithium"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "789877c169226a35d2ea686bbd9d506becc693f7bb0ee91acc03f74491e80c0f"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-rusty-crystals-hdwallet"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51ec6c3db4055c217a503c45d0c101cf3c10d4fc1e562f0588aa55dda4f60a4d"
|
||||
dependencies = [
|
||||
"bip39",
|
||||
"getrandom 0.2.17",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"qp-poseidon-core",
|
||||
"qp-rusty-crystals-dilithium",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"unicode-normalization",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-wormhole-circuit"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55167daf965a3616b74184171148b94c64b3a48771d6433a1a43377a6e46c6e8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hex",
|
||||
"qp-plonky2",
|
||||
"qp-wormhole-inputs",
|
||||
"qp-zk-circuits-common",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-wormhole-inputs"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c07863a2211a17b46319289c5ef22e5670a3fb8653386bb366c418193254793"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qp-zk-circuits-common"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dec45510701f160fdb730bdb622d6cdd0a62547e607c9b1ecb19558202797f81"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"qp-plonky2",
|
||||
"qp-poseidon-core",
|
||||
"qp-wormhole-inputs",
|
||||
"rand 0.8.6",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quantus_crypto"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"qp-poseidon-core",
|
||||
"qp-rusty-crystals-dilithium",
|
||||
"qp-rusty-crystals-hdwallet",
|
||||
"qp-wormhole-circuit",
|
||||
"qp-zk-circuits-common",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.150"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cf0ded5c4e56918d8f8a339e1bb67d038d3bc6d144ac407904015ba2e4cde9b"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crunchy",
|
||||
"hex",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unroll"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ad948c1cb799b1a70f836077721a92a35ac177d4daddf4c20a633786d4cf618"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.5",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.128"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
@@ -0,0 +1,47 @@
|
||||
# Quantus post-quantum crypto, compiled to WASM for the browser.
|
||||
#
|
||||
# Deliberately a separate crate from `wasm-crypto` rather than more files inside
|
||||
# it: that package is built with `nightly-2022-06-24` (see scripts/rust-version.sh)
|
||||
# against a 2019-era dependency set, and the ML-DSA crates use inline `const {}`
|
||||
# blocks that need Rust >= 1.79. The two cannot share a Cargo graph, and bumping
|
||||
# the older one would mean rewriting upstream's sr25519/ed25519 build — which is
|
||||
# the thing we most want to leave alone so rebases stay boring. See quantus/wasm#1.
|
||||
|
||||
[package]
|
||||
authors = ["Quantus Network Developers <hello@quantus.com>"]
|
||||
description = "WASM bindings to the Quantus chain's post-quantum crypto crates."
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
name = "quantus_crypto"
|
||||
publish = false
|
||||
repository = "https://git.lair.cafe/quantus/wasm"
|
||||
resolver = "2"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
# The crates the runtime itself uses. Versions match quantus-apps/quantus_sdk's
|
||||
# rust bridge, which is the other non-Rust consumer of exactly this surface.
|
||||
qp-poseidon-core = "3.1.0"
|
||||
qp-rusty-crystals-dilithium = { version = "4.1.1", default-features = false, features = ["ml-dsa-65", "ml-dsa-87"] }
|
||||
qp-rusty-crystals-hdwallet = { version = "4.1.1", default-features = false, features = ["ml-dsa-65", "ml-dsa-87"] }
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
# The chain's own nullifier, for known-answer tests only. It pulls in plonky2,
|
||||
# which has no place in the shipped WASM: the port in rs/hdwallet.rs has to
|
||||
# agree with it, and these tests are how that is shown rather than asserted.
|
||||
qp-wormhole-circuit = { version = "=4.3.0", default-features = false, features = ["std"] }
|
||||
qp-zk-circuits-common = { version = "=4.3.0" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
incremental = false
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
panic = "abort"
|
||||
rpath = false
|
||||
@@ -0,0 +1,76 @@
|
||||
# @quantus/crypto
|
||||
|
||||
Quantus post-quantum crypto for the browser: ML-DSA-65 and ML-DSA-87 signatures,
|
||||
Poseidon2-over-Goldilocks account-id hashing, and hardened BIP44 key derivation.
|
||||
|
||||
Every function delegates to the crates the Quantus runtime itself uses —
|
||||
`qp-rusty-crystals-dilithium`, `qp-poseidon-core`, `qp-rusty-crystals-hdwallet` —
|
||||
rather than reimplementing them. A browser wallet that disagreed with the chain
|
||||
about a key or a signature would produce perfectly well-formed output that the
|
||||
chain rejects, and nothing on this side could tell.
|
||||
|
||||
## Why a separate package from `@polkadot/wasm-crypto`
|
||||
|
||||
They cannot share a Cargo build. `wasm-crypto` is compiled with
|
||||
`nightly-2022-06-24` against a 2019-era dependency set; the ML-DSA crates use
|
||||
inline `const {}` blocks that require Rust >= 1.79. Modernising the older build
|
||||
would mean rewriting upstream's sr25519/ed25519 crypto, which is the thing most
|
||||
worth leaving untouched so rebases onto upstream stay boring.
|
||||
|
||||
What *is* shared is the packaging: the WASM is zlib-compressed and base64'd into
|
||||
the JS at build time, so nothing is fetched at runtime. That matters because the
|
||||
consumer is an MV3 service worker under `script-src 'self' 'wasm-unsafe-eval'`,
|
||||
which can compile WASM but cannot usefully fetch it, and because callers like
|
||||
`pair.sign()` are synchronous and have no `await` to give.
|
||||
|
||||
`@polkadot/wasm-bridge` is deliberately not used: its `Bridge` implements
|
||||
wasm-bindgen 0.2.79's JS-heap ABI, while this crate builds with 0.2.128, which
|
||||
uses externref tables. wasm-bindgen's own generated glue plus `initSync` is both
|
||||
smaller and correct.
|
||||
|
||||
The only runtime dependency is `fflate`, for zlib inflate. Base64 decoding is
|
||||
fifteen lines here rather than a dependency. Both were originally taken from
|
||||
`@polkadot/wasm-util`, which turned out to cost more than it saved: its index
|
||||
re-exports `packageDetect`, dragging in a `@polkadot/util` peer dependency for a
|
||||
side effect we do not want, and being a workspace package it resolved through its
|
||||
*own* repo's node_modules when this package was consumed by symlink from another
|
||||
checkout — which is exactly how `quantus/common` consumes it during development.
|
||||
|
||||
## Scheme selector
|
||||
|
||||
`Scheme.MlDsa87 = 0`, `Scheme.MlDsa65 = 1` — these are the chain's own
|
||||
`DilithiumSignatureScheme` variant indices, so the number threaded through this
|
||||
API is the byte that ends up on the wire. New accounts use ML-DSA-65; ML-DSA-87
|
||||
is legacy and must be supported but never chosen.
|
||||
|
||||
## Signing context
|
||||
|
||||
ML-DSA hashes a context into the signature. Quantus extrinsics on spec >= 148 are
|
||||
verified under `QUANTUS_EXTRINSIC`, earlier specs under the empty context. A
|
||||
signature made under the wrong one is cryptographically valid, rejected by the
|
||||
chain, and indistinguishable locally — so use `contextForSpec(specVersion)`
|
||||
rather than picking one by hand. Nothing here guesses on your behalf.
|
||||
|
||||
## Sizes come from the crate
|
||||
|
||||
`sizes(scheme)` returns the public/secret/signature lengths rather than exposing
|
||||
constants to copy. They are consensus-critical — the runtime decodes a fixed-size
|
||||
array with no compact length prefix — and a JS constant that drifted would
|
||||
re-frame every byte after the signature while looking entirely healthy.
|
||||
|
||||
## Building
|
||||
|
||||
```sh
|
||||
yarn install-build-deps # downloads wasm-bindgen 0.2.128 and binaryen
|
||||
./scripts/build-quantus.sh
|
||||
```
|
||||
|
||||
The Rust toolchain is pinned in `rust-toolchain.toml` to the same channel the
|
||||
chain builds its runtime with.
|
||||
|
||||
## Tests
|
||||
|
||||
`cargo test` runs conformance tests whose expected values come from the `quantus`
|
||||
CLI, not from this crate — the dev-genesis account ids, HD derivation at both
|
||||
schemes' default paths, and context separation. A test that pinned our own output
|
||||
would keep passing through exactly the drift they exist to catch.
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"author": "Quantus Network Developers <hello@quantus.com>",
|
||||
"bugs": "https://git.lair.cafe/quantus/wasm/issues",
|
||||
"description": "Quantus post-quantum crypto (ML-DSA, Poseidon2, HD derivation) for the browser",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"homepage": "https://git.lair.cafe/quantus/wasm/src/branch/main/packages/quantus-crypto#readme",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@quantus/crypto",
|
||||
"repository": {
|
||||
"directory": "packages/quantus-crypto",
|
||||
"type": "git",
|
||||
"url": "https://git.lair.cafe/quantus/wasm.git"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"version": "0.3.0",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"fflate": "^0.8.2",
|
||||
"tslib": "^2.7.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Matches the chain's toolchain (chain/rust-toolchain), so this crate is built by
|
||||
# the same compiler that builds the runtime it has to agree with. Upstream's
|
||||
# `wasm-crypto` keeps its own nightly-2022-06-24 pin; the two builds are separate
|
||||
# on purpose. See quantus/wasm#1.
|
||||
[toolchain]
|
||||
channel = "1.93.0"
|
||||
targets = ["wasm32-unknown-unknown"]
|
||||
profile = "minimal"
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
// An array indexer rather than a Map: the input is ASCII by construction, so it
|
||||
// cannot overflow, and array access is measurably faster on the hot loop.
|
||||
const MAP = new Array<number>(256);
|
||||
|
||||
for (let i = 0; i < CHARS.length; i++) {
|
||||
MAP[CHARS.charCodeAt(i)] = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode base64 into a caller-supplied buffer.
|
||||
*
|
||||
* Deliberately not `atob` or `Buffer.from`: the first is browser-only, the second
|
||||
* node-only, and this runs in an MV3 service worker, a Worker, node tests and a
|
||||
* bundled extension page. The output length is known at build time, so the
|
||||
* caller provides the buffer and there is no growth or reallocation.
|
||||
*
|
||||
* This is a reimplementation of `@polkadot/wasm-util`'s base64Decode, which was
|
||||
* the dependency it replaced. That package's index re-exports `packageDetect`,
|
||||
* dragging in a `@polkadot/util` peer dependency for a side effect we do not
|
||||
* want, and being a workspace package it resolved through its own repo's
|
||||
* node_modules when consumed by symlink from another checkout. Fifteen lines is
|
||||
* cheaper than either problem.
|
||||
*/
|
||||
export function base64Decode (data: string, out: Uint8Array): Uint8Array {
|
||||
let byte = 0;
|
||||
let bits = 0;
|
||||
let pos = 0;
|
||||
|
||||
for (let i = 0; i < data.length && pos < out.length; i++) {
|
||||
const value = MAP[data.charCodeAt(i)];
|
||||
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte = (byte << 6) | value;
|
||||
bits += 6;
|
||||
|
||||
if (bits >= 8) {
|
||||
bits -= 8;
|
||||
out[pos++] = (byte >>> bits) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export declare const lenIn: number;
|
||||
export declare const lenOut: number;
|
||||
export declare const bytes: string;
|
||||
@@ -0,0 +1,10 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Generated as part of the build, do not edit
|
||||
|
||||
export const lenIn = 0;
|
||||
|
||||
export const lenOut = 0;
|
||||
|
||||
export const bytes = '';
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { ext_mldsa_derive, ext_mldsa_from_seed, ext_mldsa_is_scheme, ext_mldsa_sign, ext_mldsa_sizes, ext_mldsa_verify, ext_poseidon_hash, ext_wormhole_addresses, ext_wormhole_nullifiers } from './generated/quantus_crypto.js';
|
||||
import { initWasm } from './init.js';
|
||||
import { Scheme } from './scheme.js';
|
||||
|
||||
export interface Keypair {
|
||||
publicKey: Uint8Array;
|
||||
secretKey: Uint8Array;
|
||||
}
|
||||
|
||||
export interface Sizes {
|
||||
/** Public key length: 1952 for ML-DSA-65, 2592 for ML-DSA-87. */
|
||||
publicKey: number;
|
||||
/** Secret key length: 4032 / 4896. */
|
||||
secretKey: number;
|
||||
/** Signature length: 3309 / 4627. */
|
||||
signature: number;
|
||||
/** `signature ‖ publicKey`, the runtime's wire form: 5261 / 7219. */
|
||||
signatureWithPublicKey: number;
|
||||
}
|
||||
|
||||
function ready (): void {
|
||||
const error = initWasm();
|
||||
|
||||
if (error) {
|
||||
throw new Error(`@quantus/crypto: WASM unavailable: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key and signature sizes for a scheme, read from the crate rather than
|
||||
* hardcoded here.
|
||||
*
|
||||
* These are consensus-critical — the runtime decodes a fixed-size array off the
|
||||
* wire — so a constant that drifted from the crate would re-frame every byte
|
||||
* after the signature while looking entirely healthy. Ask, don't assume.
|
||||
*/
|
||||
export function sizes (scheme: Scheme): Sizes {
|
||||
ready();
|
||||
|
||||
const raw = new DataView(ext_mldsa_sizes(scheme).buffer);
|
||||
|
||||
return {
|
||||
publicKey: raw.getUint32(0, true),
|
||||
secretKey: raw.getUint32(4, true),
|
||||
signature: raw.getUint32(8, true),
|
||||
signatureWithPublicKey: raw.getUint32(12, true)
|
||||
};
|
||||
}
|
||||
|
||||
/** Whether this build supports `scheme`. */
|
||||
export function isScheme (scheme: number): scheme is Scheme {
|
||||
ready();
|
||||
|
||||
return ext_mldsa_is_scheme(scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* The account id for a public key — Poseidon2 over Goldilocks, 32 bytes out.
|
||||
*
|
||||
* This is the step that has no Substrate equivalent. There, an `AccountId32`
|
||||
* *is* the public key; here it is a one-way hash of it, which is why a Quantus
|
||||
* signature has to carry its public key inside itself and why nothing can
|
||||
* recover a key from an address.
|
||||
*/
|
||||
export function accountFromPublicKey (publicKey: Uint8Array): Uint8Array {
|
||||
ready();
|
||||
|
||||
return ext_poseidon_hash(publicKey);
|
||||
}
|
||||
|
||||
/** A keypair from 32 bytes of entropy — FIPS 204 `ML-DSA.KeyGen_internal`. */
|
||||
export function keypairFromSeed (seed: Uint8Array, scheme: Scheme): Keypair {
|
||||
ready();
|
||||
|
||||
return split(ext_mldsa_from_seed(seed, scheme), scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* A keypair from a BIP39 mnemonic at a hardened Quantus derivation path.
|
||||
*
|
||||
* `path` must be hardened at every level — lattice keys have no public
|
||||
* derivability, so there is no soft-junction equivalent and one is rejected
|
||||
* rather than reinterpreted.
|
||||
*/
|
||||
export function keypairFromMnemonic (mnemonic: string, password: string, path: string, scheme: Scheme): Keypair {
|
||||
ready();
|
||||
|
||||
return split(ext_mldsa_derive(mnemonic, password, path, scheme), scheme);
|
||||
}
|
||||
|
||||
/** Which wormhole branch: where deposits arrive, or where a send returns its change. */
|
||||
export enum WormholeBranch {
|
||||
Receive = 0,
|
||||
Change = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Consecutive wormhole addresses for one account and branch, as 32-byte account
|
||||
* ids.
|
||||
*
|
||||
* Paths are `m/44'/189189189'/<account>'/<branch>'/<index>'`, the mobile
|
||||
* wallet's. A wormhole address has no key: it is a double Poseidon hash of a
|
||||
* secret the path yields, and funds leave it only through a ZK proof of that
|
||||
* secret. Only the addresses cross into JavaScript; the secrets are derived and
|
||||
* wiped inside WASM.
|
||||
*
|
||||
* The recovery phrase is stretched once per call, so ask for a window of
|
||||
* addresses at once rather than looping over single ones. At most 1000 per call.
|
||||
*/
|
||||
export function wormholeAddresses (mnemonic: string, password: string, account: number, branch: WormholeBranch, start: number, count: number): Uint8Array[] {
|
||||
ready();
|
||||
|
||||
const flat = ext_wormhole_addresses(mnemonic, password, account, branch, start, count);
|
||||
const out: Uint8Array[] = [];
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
out.push(flat.slice(i * 32, (i + 1) * 32));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nullifiers for a run of wormhole addresses, one per deposit transfer count.
|
||||
*
|
||||
* A deposit to a wormhole address is spent when its nullifier is in
|
||||
* `Wormhole::UsedNullifiers`. For each address `start..start + addresses` on
|
||||
* `branch` of `account`, this returns the nullifiers for transfer counts
|
||||
* `first..first + count`: `result[a][c]` belongs to address `start + a` and
|
||||
* transfer count `first + c`.
|
||||
*
|
||||
* Check them locally, against a copy of the whole spent set. Never look one up
|
||||
* by key or send it to a service: exits publish their nullifiers, so whoever
|
||||
* sees yours can name your exits. At most 100,000 per call; the recovery phrase
|
||||
* is stretched once per call.
|
||||
*/
|
||||
export function wormholeNullifiers (mnemonic: string, password: string, account: number, branch: WormholeBranch, start: number, addresses: number, first: number, count: number): Uint8Array[][] {
|
||||
ready();
|
||||
|
||||
const flat = ext_wormhole_nullifiers(mnemonic, password, account, branch, start, addresses, BigInt(first), count);
|
||||
const out: Uint8Array[][] = [];
|
||||
|
||||
for (let a = 0; a < addresses; a++) {
|
||||
const row: Uint8Array[] = [];
|
||||
|
||||
for (let c = 0; c < count; c++) {
|
||||
const at = (a * count + c) * 32;
|
||||
|
||||
row.push(flat.slice(at, at + 32));
|
||||
}
|
||||
|
||||
out.push(row);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign under a FIPS 204 context.
|
||||
*
|
||||
* `context` is not optional in spirit: extrinsics on spec >= 148 verify under
|
||||
* `QUANTUS_EXTRINSIC` and earlier ones under the empty context, and the wrong
|
||||
* choice yields a valid signature that the chain rejects with nothing locally
|
||||
* able to tell. Use `contextForSpec` rather than picking one by hand.
|
||||
*
|
||||
* Returns the bare signature. The runtime's wire form is `signature ‖ publicKey`
|
||||
* — see {@link signatureWithPublicKey} — but only the caller knows which it
|
||||
* wants.
|
||||
*/
|
||||
export function sign (message: Uint8Array, { publicKey, secretKey }: Keypair, context: Uint8Array, scheme: Scheme): Uint8Array {
|
||||
ready();
|
||||
|
||||
return ext_mldsa_sign(secretKey, publicKey, message, context, scheme);
|
||||
}
|
||||
|
||||
/** Verify a bare signature under a context. */
|
||||
export function verify (message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array, context: Uint8Array, scheme: Scheme): boolean {
|
||||
ready();
|
||||
|
||||
return ext_mldsa_verify(publicKey, message, signature, context, scheme);
|
||||
}
|
||||
|
||||
/**
|
||||
* `signature ‖ publicKey` — what a signed extrinsic actually carries.
|
||||
*
|
||||
* The runtime encodes this as a fixed-size array with **no compact length
|
||||
* prefix**, preceded by the scheme's enum variant byte. Getting that framing
|
||||
* wrong re-frames every byte after it into something that still decodes.
|
||||
*/
|
||||
export function signatureWithPublicKey (signature: Uint8Array, publicKey: Uint8Array): Uint8Array {
|
||||
const out = new Uint8Array(signature.length + publicKey.length);
|
||||
|
||||
out.set(signature);
|
||||
out.set(publicKey, signature.length);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/** The crate returns `secretKey ‖ publicKey`, matching `ext_ed_from_seed`. */
|
||||
function split (pair: Uint8Array, scheme: Scheme): Keypair {
|
||||
const { secretKey } = sizes(scheme);
|
||||
|
||||
return {
|
||||
publicKey: pair.subarray(secretKey),
|
||||
secretKey: pair.subarray(0, secretKey)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Derive a keypair from a BIP39 mnemonic at a hardened derivation path.
|
||||
*
|
||||
* Lattice keys have no public derivability, so there is no soft-junction
|
||||
* equivalent and the crate rejects any unhardened path outright. The Quantus
|
||||
* convention is:
|
||||
*
|
||||
* ```text
|
||||
* m/44'/189189'/<account>'/0'/<0 for ML-DSA-87 | 1 for ML-DSA-65>'
|
||||
* ```
|
||||
*
|
||||
* with the account index at the third level and the *scheme* carried in the
|
||||
* trailing index. That is unusual, and it is what `quantus-cli` and the mobile
|
||||
* wallet already use — deriving anything else produces addresses no other
|
||||
* Quantus tool can find.
|
||||
*
|
||||
* The seeding matters as much as the path. This goes mnemonic → 64-byte BIP39
|
||||
* seed → HMAC-SHA512 chain keyed with the literal string `"Dilithium seed"`.
|
||||
* Substrate's own `mnemonicToMiniSecret` is a *different* derivation and is the
|
||||
* default reach in the polkadot-js codebase; using it here would yield a
|
||||
* well-formed key for an account nobody owns.
|
||||
*
|
||||
* * mnemonic: BIP39 phrase, 12/15/18/21/24 words
|
||||
* * password: BIP39 passphrase; empty string for none
|
||||
* * path: hardened derivation path, e.g. `m/44'/189189'/0'/0'/1'`
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the secret key followed by the public key, as
|
||||
* `ext_mldsa_from_seed` returns.
|
||||
*/
|
||||
export function ext_mldsa_derive(mnemonic: string, password: string, path: string, scheme: number): Uint8Array;
|
||||
|
||||
/**
|
||||
* Generate a keypair from 32 bytes of entropy.
|
||||
*
|
||||
* This is FIPS 204 `ML-DSA.KeyGen_internal` with no Quantus-specific step: the
|
||||
* crate expands the seed as `SHAKE256(seed ‖ k ‖ ℓ)`, so the parameter set is
|
||||
* absorbed into the expansion and the same 32 bytes yield independent keys per
|
||||
* scheme. That is why the dev accounts (`[0u8; 32]`, `[1u8; 32]`, `[2u8; 32]`)
|
||||
* and HD-derived accounts can share this one entry point.
|
||||
*
|
||||
* * seed: UIntArray with 32 elements
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the secret key followed by the public key, matching the
|
||||
* ordering `ext_ed_from_seed` uses. Split it at the secret length from
|
||||
* `ext_mldsa_sizes`.
|
||||
*/
|
||||
export function ext_mldsa_from_seed(seed: Uint8Array, scheme: number): Uint8Array;
|
||||
|
||||
/**
|
||||
* Whether `scheme` names a parameter set this build supports.
|
||||
*
|
||||
* `dispatch!` falls back to ML-DSA-87 for anything unrecognised, which is the
|
||||
* right default but a poor way to discover a typo. Callers that accept a scheme
|
||||
* from storage or from a user should check here first.
|
||||
*/
|
||||
export function ext_mldsa_is_scheme(scheme: number): boolean;
|
||||
|
||||
/**
|
||||
* Sign a message under a FIPS 204 context.
|
||||
*
|
||||
* Signing is deterministic — no hedging randomness — because that is what the
|
||||
* runtime does (`hedge: None`), and a wallet that hedged would produce a
|
||||
* different signature each time for the same input, which makes the
|
||||
* byte-for-byte agreement tests in quantus/wasm#2 impossible to write.
|
||||
*
|
||||
* `ctx` is domain separation and it is **not** optional in practice: extrinsics
|
||||
* on spec >= 148 are verified under `QUANTUS_EXTRINSIC`, earlier specs under the
|
||||
* empty context, and a signature made under the wrong one is valid, rejected by
|
||||
* the chain, and indistinguishable locally. The caller chooses; this function
|
||||
* does not guess.
|
||||
*
|
||||
* * secret: UIntArray, secret-key length for the scheme
|
||||
* * public: UIntArray, public-key length for the scheme
|
||||
* * message: arbitrary length UIntArray
|
||||
* * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the signature alone. The runtime's wire format is
|
||||
* `signature ‖ public`; concatenating is the caller's job because only the
|
||||
* caller knows whether it wants the wire form or the bare signature.
|
||||
*/
|
||||
export function ext_mldsa_sign(secret: Uint8Array, _public: Uint8Array, message: Uint8Array, ctx: Uint8Array, scheme: number): Uint8Array;
|
||||
|
||||
/**
|
||||
* Key and signature sizes for a parameter set, as
|
||||
* `[public, secret, signature, signature_with_public]`.
|
||||
*
|
||||
* Exported so that nothing on the JS side has to hardcode 1952/4032/3309/5261 or
|
||||
* 2592/4896/4627/7219. Those numbers are consensus-critical — the runtime reads a
|
||||
* fixed-size array off the wire — and a JS constant that drifted from the crate
|
||||
* would mis-frame every byte after the signature while looking entirely healthy.
|
||||
* Ask the crate instead.
|
||||
*
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is four u32 lengths, little-endian, 16 bytes total.
|
||||
*/
|
||||
export function ext_mldsa_sizes(scheme: number): Uint8Array;
|
||||
|
||||
/**
|
||||
* Verify a signature against a message and public key under a context.
|
||||
*
|
||||
* * public: UIntArray, public-key length for the scheme
|
||||
* * message: arbitrary length UIntArray
|
||||
* * signature: UIntArray, signature length for the scheme
|
||||
* * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*/
|
||||
export function ext_mldsa_verify(_public: Uint8Array, message: Uint8Array, signature: Uint8Array, ctx: Uint8Array, scheme: number): boolean;
|
||||
|
||||
/**
|
||||
* Poseidon2-over-Goldilocks hash of arbitrary bytes.
|
||||
*
|
||||
* This is the account-id derivation. On Substrate an `AccountId32` *is* the
|
||||
* public key; on Quantus it is `hash_bytes(public_key)`, which is why a Quantus
|
||||
* signature has to carry its public key along — the address cannot give it back.
|
||||
*
|
||||
* `qp_poseidon_core::hash_bytes` is `IdentifyAccount for DilithiumSigner` in the
|
||||
* runtime, so this is the same function the chain uses to decide who signed
|
||||
* something, reached through the same crate rather than a port of it.
|
||||
*
|
||||
* * data: arbitrary length UIntArray
|
||||
*
|
||||
* * returned vector is 32 bytes.
|
||||
*/
|
||||
export function ext_poseidon_hash(data: Uint8Array): Uint8Array;
|
||||
|
||||
/**
|
||||
* Derive consecutive wormhole addresses for one account and branch.
|
||||
*
|
||||
* A wormhole address is not a key. The path yields a 32-byte **secret**, and
|
||||
* the address is `poseidon(poseidon(salt ‖ secret))`; funds leave it only
|
||||
* through a ZK proof of knowing that secret. So this returns the addresses and
|
||||
* nothing else. The secrets and the intermediate `first_hash` stay inside this
|
||||
* call and are wiped on drop by the crate's sensitive types.
|
||||
*
|
||||
* Paths are `m/44'/189189189'/<account>'/<change>'/<index>'`, as the mobile
|
||||
* wallet derives them: change `0` is the receive branch, `1` the change branch.
|
||||
*
|
||||
* The BIP39 seed is stretched once for the whole batch. Stretching per address
|
||||
* is PBKDF2 with 2048 rounds each time, and a gap-limit window is dozens of
|
||||
* addresses.
|
||||
*
|
||||
* * mnemonic: BIP39 phrase
|
||||
* * password: BIP39 passphrase; empty string for none
|
||||
* * account, change, start, count: which addresses; count <= WORMHOLE_MAX_BATCH
|
||||
*
|
||||
* * returned vector is `count` 32-byte account ids, concatenated
|
||||
*/
|
||||
export function ext_wormhole_addresses(mnemonic: string, password: string, account: number, change: number, start: number, count: number): Uint8Array;
|
||||
|
||||
/**
|
||||
* Nullifiers for a run of wormhole addresses' deposits, by transfer count.
|
||||
*
|
||||
* A deposit to a wormhole address is spent when its nullifier is in
|
||||
* `Wormhole::UsedNullifiers`. The nullifier is
|
||||
*
|
||||
* ```text
|
||||
* poseidon2(poseidon2(salt("~nullif~") ‖ secret ‖ transfer_count))
|
||||
* ```
|
||||
*
|
||||
* where `transfer_count` is the address's counter when the deposit landed. It
|
||||
* needs the address's secret, which is why this takes the recovery phrase and
|
||||
* why a nullifier should never be sent anywhere to be checked: exits publish
|
||||
* nullifiers, so whoever sees yours can name your exits.
|
||||
*
|
||||
* For addresses `m/44'/189189189'/<account>'/<change>'/<index>'` with index in
|
||||
* `start..start + addresses`, and transfer counts `first..first + count` for
|
||||
* each. The BIP39 seed is stretched once for the whole run.
|
||||
*
|
||||
* Ported onto `qp-poseidon-core` rather than calling `qp-wormhole-circuit`,
|
||||
* which would bring plonky2 into the WASM. The port is pinned to the circuit
|
||||
* crate's own `Nullifier::from_preimage` by the tests.
|
||||
*
|
||||
* * returned vector is `addresses * count` 32-byte nullifiers: address by
|
||||
* address, and by transfer count within each
|
||||
*/
|
||||
export function ext_wormhole_nullifiers(mnemonic: string, password: string, account: number, change: number, start: number, addresses: number, first: bigint, count: number): Uint8Array;
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly ext_mldsa_derive: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number, number, number];
|
||||
readonly ext_mldsa_from_seed: (a: number, b: number, c: number) => [number, number, number, number];
|
||||
readonly ext_mldsa_is_scheme: (a: number) => number;
|
||||
readonly ext_mldsa_sign: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number];
|
||||
readonly ext_mldsa_sizes: (a: number) => [number, number];
|
||||
readonly ext_mldsa_verify: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => number;
|
||||
readonly ext_poseidon_hash: (a: number, b: number) => [number, number];
|
||||
readonly ext_wormhole_addresses: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number, number, number];
|
||||
readonly ext_wormhole_nullifiers: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: bigint, j: number) => [number, number, number, number];
|
||||
readonly __wbindgen_externrefs: WebAssembly.Table;
|
||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __externref_table_dealloc: (a: number) => void;
|
||||
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_start: () => void;
|
||||
}
|
||||
|
||||
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||
|
||||
/**
|
||||
* Instantiates the given `module`, which can either be bytes or
|
||||
* a precompiled `WebAssembly.Module`.
|
||||
*
|
||||
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
||||
*
|
||||
* @returns {InitOutput}
|
||||
*/
|
||||
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
||||
|
||||
/**
|
||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||
*
|
||||
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
||||
*
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||
@@ -0,0 +1,503 @@
|
||||
/* @ts-self-types="./quantus_crypto.d.ts" */
|
||||
|
||||
/**
|
||||
* Derive a keypair from a BIP39 mnemonic at a hardened derivation path.
|
||||
*
|
||||
* Lattice keys have no public derivability, so there is no soft-junction
|
||||
* equivalent and the crate rejects any unhardened path outright. The Quantus
|
||||
* convention is:
|
||||
*
|
||||
* ```text
|
||||
* m/44'/189189'/<account>'/0'/<0 for ML-DSA-87 | 1 for ML-DSA-65>'
|
||||
* ```
|
||||
*
|
||||
* with the account index at the third level and the *scheme* carried in the
|
||||
* trailing index. That is unusual, and it is what `quantus-cli` and the mobile
|
||||
* wallet already use — deriving anything else produces addresses no other
|
||||
* Quantus tool can find.
|
||||
*
|
||||
* The seeding matters as much as the path. This goes mnemonic → 64-byte BIP39
|
||||
* seed → HMAC-SHA512 chain keyed with the literal string `"Dilithium seed"`.
|
||||
* Substrate's own `mnemonicToMiniSecret` is a *different* derivation and is the
|
||||
* default reach in the polkadot-js codebase; using it here would yield a
|
||||
* well-formed key for an account nobody owns.
|
||||
*
|
||||
* * mnemonic: BIP39 phrase, 12/15/18/21/24 words
|
||||
* * password: BIP39 passphrase; empty string for none
|
||||
* * path: hardened derivation path, e.g. `m/44'/189189'/0'/0'/1'`
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the secret key followed by the public key, as
|
||||
* `ext_mldsa_from_seed` returns.
|
||||
* @param {string} mnemonic
|
||||
* @param {string} password
|
||||
* @param {string} path
|
||||
* @param {number} scheme
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_mldsa_derive(mnemonic, password, path, scheme) {
|
||||
const ptr0 = passStringToWasm0(mnemonic, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passStringToWasm0(path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_mldsa_derive(ptr0, len0, ptr1, len1, ptr2, len2, scheme);
|
||||
if (ret[3]) {
|
||||
throw takeFromExternrefTable0(ret[2]);
|
||||
}
|
||||
var v4 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a keypair from 32 bytes of entropy.
|
||||
*
|
||||
* This is FIPS 204 `ML-DSA.KeyGen_internal` with no Quantus-specific step: the
|
||||
* crate expands the seed as `SHAKE256(seed ‖ k ‖ ℓ)`, so the parameter set is
|
||||
* absorbed into the expansion and the same 32 bytes yield independent keys per
|
||||
* scheme. That is why the dev accounts (`[0u8; 32]`, `[1u8; 32]`, `[2u8; 32]`)
|
||||
* and HD-derived accounts can share this one entry point.
|
||||
*
|
||||
* * seed: UIntArray with 32 elements
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the secret key followed by the public key, matching the
|
||||
* ordering `ext_ed_from_seed` uses. Split it at the secret length from
|
||||
* `ext_mldsa_sizes`.
|
||||
* @param {Uint8Array} seed
|
||||
* @param {number} scheme
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_mldsa_from_seed(seed, scheme) {
|
||||
const ptr0 = passArray8ToWasm0(seed, wasm.__wbindgen_malloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_mldsa_from_seed(ptr0, len0, scheme);
|
||||
if (ret[3]) {
|
||||
throw takeFromExternrefTable0(ret[2]);
|
||||
}
|
||||
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether `scheme` names a parameter set this build supports.
|
||||
*
|
||||
* `dispatch!` falls back to ML-DSA-87 for anything unrecognised, which is the
|
||||
* right default but a poor way to discover a typo. Callers that accept a scheme
|
||||
* from storage or from a user should check here first.
|
||||
* @param {number} scheme
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function ext_mldsa_is_scheme(scheme) {
|
||||
const ret = wasm.ext_mldsa_is_scheme(scheme);
|
||||
return ret !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sign a message under a FIPS 204 context.
|
||||
*
|
||||
* Signing is deterministic — no hedging randomness — because that is what the
|
||||
* runtime does (`hedge: None`), and a wallet that hedged would produce a
|
||||
* different signature each time for the same input, which makes the
|
||||
* byte-for-byte agreement tests in quantus/wasm#2 impossible to write.
|
||||
*
|
||||
* `ctx` is domain separation and it is **not** optional in practice: extrinsics
|
||||
* on spec >= 148 are verified under `QUANTUS_EXTRINSIC`, earlier specs under the
|
||||
* empty context, and a signature made under the wrong one is valid, rejected by
|
||||
* the chain, and indistinguishable locally. The caller chooses; this function
|
||||
* does not guess.
|
||||
*
|
||||
* * secret: UIntArray, secret-key length for the scheme
|
||||
* * public: UIntArray, public-key length for the scheme
|
||||
* * message: arbitrary length UIntArray
|
||||
* * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is the signature alone. The runtime's wire format is
|
||||
* `signature ‖ public`; concatenating is the caller's job because only the
|
||||
* caller knows whether it wants the wire form or the bare signature.
|
||||
* @param {Uint8Array} secret
|
||||
* @param {Uint8Array} _public
|
||||
* @param {Uint8Array} message
|
||||
* @param {Uint8Array} ctx
|
||||
* @param {number} scheme
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_mldsa_sign(secret, _public, message, ctx, scheme) {
|
||||
const ptr0 = passArray8ToWasm0(secret, wasm.__wbindgen_malloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passArray8ToWasm0(_public, wasm.__wbindgen_malloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passArray8ToWasm0(message, wasm.__wbindgen_malloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
const ptr3 = passArray8ToWasm0(ctx, wasm.__wbindgen_malloc);
|
||||
const len3 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_mldsa_sign(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, scheme);
|
||||
if (ret[3]) {
|
||||
throw takeFromExternrefTable0(ret[2]);
|
||||
}
|
||||
var v5 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key and signature sizes for a parameter set, as
|
||||
* `[public, secret, signature, signature_with_public]`.
|
||||
*
|
||||
* Exported so that nothing on the JS side has to hardcode 1952/4032/3309/5261 or
|
||||
* 2592/4896/4627/7219. Those numbers are consensus-critical — the runtime reads a
|
||||
* fixed-size array off the wire — and a JS constant that drifted from the crate
|
||||
* would mis-frame every byte after the signature while looking entirely healthy.
|
||||
* Ask the crate instead.
|
||||
*
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
*
|
||||
* * returned vector is four u32 lengths, little-endian, 16 bytes total.
|
||||
* @param {number} scheme
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_mldsa_sizes(scheme) {
|
||||
const ret = wasm.ext_mldsa_sizes(scheme);
|
||||
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a signature against a message and public key under a context.
|
||||
*
|
||||
* * public: UIntArray, public-key length for the scheme
|
||||
* * message: arbitrary length UIntArray
|
||||
* * signature: UIntArray, signature length for the scheme
|
||||
* * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
* * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
* @param {Uint8Array} _public
|
||||
* @param {Uint8Array} message
|
||||
* @param {Uint8Array} signature
|
||||
* @param {Uint8Array} ctx
|
||||
* @param {number} scheme
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function ext_mldsa_verify(_public, message, signature, ctx, scheme) {
|
||||
const ptr0 = passArray8ToWasm0(_public, wasm.__wbindgen_malloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passArray8ToWasm0(message, wasm.__wbindgen_malloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ptr2 = passArray8ToWasm0(signature, wasm.__wbindgen_malloc);
|
||||
const len2 = WASM_VECTOR_LEN;
|
||||
const ptr3 = passArray8ToWasm0(ctx, wasm.__wbindgen_malloc);
|
||||
const len3 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_mldsa_verify(ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, scheme);
|
||||
return ret !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poseidon2-over-Goldilocks hash of arbitrary bytes.
|
||||
*
|
||||
* This is the account-id derivation. On Substrate an `AccountId32` *is* the
|
||||
* public key; on Quantus it is `hash_bytes(public_key)`, which is why a Quantus
|
||||
* signature has to carry its public key along — the address cannot give it back.
|
||||
*
|
||||
* `qp_poseidon_core::hash_bytes` is `IdentifyAccount for DilithiumSigner` in the
|
||||
* runtime, so this is the same function the chain uses to decide who signed
|
||||
* something, reached through the same crate rather than a port of it.
|
||||
*
|
||||
* * data: arbitrary length UIntArray
|
||||
*
|
||||
* * returned vector is 32 bytes.
|
||||
* @param {Uint8Array} data
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_poseidon_hash(data) {
|
||||
const ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_poseidon_hash(ptr0, len0);
|
||||
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derive consecutive wormhole addresses for one account and branch.
|
||||
*
|
||||
* A wormhole address is not a key. The path yields a 32-byte **secret**, and
|
||||
* the address is `poseidon(poseidon(salt ‖ secret))`; funds leave it only
|
||||
* through a ZK proof of knowing that secret. So this returns the addresses and
|
||||
* nothing else. The secrets and the intermediate `first_hash` stay inside this
|
||||
* call and are wiped on drop by the crate's sensitive types.
|
||||
*
|
||||
* Paths are `m/44'/189189189'/<account>'/<change>'/<index>'`, as the mobile
|
||||
* wallet derives them: change `0` is the receive branch, `1` the change branch.
|
||||
*
|
||||
* The BIP39 seed is stretched once for the whole batch. Stretching per address
|
||||
* is PBKDF2 with 2048 rounds each time, and a gap-limit window is dozens of
|
||||
* addresses.
|
||||
*
|
||||
* * mnemonic: BIP39 phrase
|
||||
* * password: BIP39 passphrase; empty string for none
|
||||
* * account, change, start, count: which addresses; count <= WORMHOLE_MAX_BATCH
|
||||
*
|
||||
* * returned vector is `count` 32-byte account ids, concatenated
|
||||
* @param {string} mnemonic
|
||||
* @param {string} password
|
||||
* @param {number} account
|
||||
* @param {number} change
|
||||
* @param {number} start
|
||||
* @param {number} count
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_wormhole_addresses(mnemonic, password, account, change, start, count) {
|
||||
const ptr0 = passStringToWasm0(mnemonic, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_wormhole_addresses(ptr0, len0, ptr1, len1, account, change, start, count);
|
||||
if (ret[3]) {
|
||||
throw takeFromExternrefTable0(ret[2]);
|
||||
}
|
||||
var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nullifiers for a run of wormhole addresses' deposits, by transfer count.
|
||||
*
|
||||
* A deposit to a wormhole address is spent when its nullifier is in
|
||||
* `Wormhole::UsedNullifiers`. The nullifier is
|
||||
*
|
||||
* ```text
|
||||
* poseidon2(poseidon2(salt("~nullif~") ‖ secret ‖ transfer_count))
|
||||
* ```
|
||||
*
|
||||
* where `transfer_count` is the address's counter when the deposit landed. It
|
||||
* needs the address's secret, which is why this takes the recovery phrase and
|
||||
* why a nullifier should never be sent anywhere to be checked: exits publish
|
||||
* nullifiers, so whoever sees yours can name your exits.
|
||||
*
|
||||
* For addresses `m/44'/189189189'/<account>'/<change>'/<index>'` with index in
|
||||
* `start..start + addresses`, and transfer counts `first..first + count` for
|
||||
* each. The BIP39 seed is stretched once for the whole run.
|
||||
*
|
||||
* Ported onto `qp-poseidon-core` rather than calling `qp-wormhole-circuit`,
|
||||
* which would bring plonky2 into the WASM. The port is pinned to the circuit
|
||||
* crate's own `Nullifier::from_preimage` by the tests.
|
||||
*
|
||||
* * returned vector is `addresses * count` 32-byte nullifiers: address by
|
||||
* address, and by transfer count within each
|
||||
* @param {string} mnemonic
|
||||
* @param {string} password
|
||||
* @param {number} account
|
||||
* @param {number} change
|
||||
* @param {number} start
|
||||
* @param {number} addresses
|
||||
* @param {bigint} first
|
||||
* @param {number} count
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function ext_wormhole_nullifiers(mnemonic, password, account, change, start, addresses, first, count) {
|
||||
const ptr0 = passStringToWasm0(mnemonic, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.ext_wormhole_nullifiers(ptr0, len0, ptr1, len1, account, change, start, addresses, first, count);
|
||||
if (ret[3]) {
|
||||
throw takeFromExternrefTable0(ret[2]);
|
||||
}
|
||||
var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
||||
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
||||
return v3;
|
||||
}
|
||||
function __wbg_get_imports() {
|
||||
const import0 = {
|
||||
__proto__: null,
|
||||
__wbg_Error_67e7344beaa85059: function(arg0, arg1) {
|
||||
const ret = Error(getStringFromWasm0(arg0, arg1));
|
||||
return ret;
|
||||
},
|
||||
__wbindgen_init_externref_table: function() {
|
||||
const table = wasm.__wbindgen_externrefs;
|
||||
const offset = table.grow(4);
|
||||
table.set(0, undefined);
|
||||
table.set(offset + 0, undefined);
|
||||
table.set(offset + 1, null);
|
||||
table.set(offset + 2, true);
|
||||
table.set(offset + 3, false);
|
||||
},
|
||||
};
|
||||
return {
|
||||
__proto__: null,
|
||||
"./quantus_crypto_bg.js": import0,
|
||||
};
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
return decodeText(ptr >>> 0, len);
|
||||
}
|
||||
|
||||
let cachedUint8ArrayMemory0 = null;
|
||||
function getUint8ArrayMemory0() {
|
||||
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8ArrayMemory0;
|
||||
}
|
||||
|
||||
function passArray8ToWasm0(arg, malloc) {
|
||||
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
||||
getUint8ArrayMemory0().set(arg, ptr / 1);
|
||||
WASM_VECTOR_LEN = arg.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length, 1) >>> 0;
|
||||
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len, 1) >>> 0;
|
||||
|
||||
const mem = getUint8ArrayMemory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = cachedTextEncoder.encodeInto(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function takeFromExternrefTable0(idx) {
|
||||
const value = wasm.__wbindgen_externrefs.get(idx);
|
||||
wasm.__externref_table_dealloc(idx);
|
||||
return value;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
cachedTextDecoder.decode();
|
||||
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
||||
let numBytesDecoded = 0;
|
||||
function decodeText(ptr, len) {
|
||||
numBytesDecoded += len;
|
||||
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
||||
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
cachedTextDecoder.decode();
|
||||
numBytesDecoded = len;
|
||||
}
|
||||
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
const cachedTextEncoder = new TextEncoder();
|
||||
|
||||
if (!('encodeInto' in cachedTextEncoder)) {
|
||||
cachedTextEncoder.encodeInto = function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
let wasmModule, wasmInstance, wasm;
|
||||
function __wbg_finalize_init(instance, module) {
|
||||
wasmInstance = instance;
|
||||
wasm = instance.exports;
|
||||
wasmModule = module;
|
||||
cachedUint8ArrayMemory0 = null;
|
||||
wasm.__wbindgen_start();
|
||||
return wasm;
|
||||
}
|
||||
|
||||
async function __wbg_load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (!module.ok) {
|
||||
throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
|
||||
}
|
||||
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
} catch (e) {
|
||||
const validResponse = expectedResponseType(module.type);
|
||||
|
||||
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else { throw e; }
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
function expectedResponseType(type) {
|
||||
switch (type) {
|
||||
case 'basic': case 'cors': case 'default': return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function initSync(module) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
|
||||
if (module !== undefined) {
|
||||
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||
({module} = module)
|
||||
} else {
|
||||
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||
}
|
||||
}
|
||||
|
||||
const imports = __wbg_get_imports();
|
||||
if (!(module instanceof WebAssembly.Module)) {
|
||||
module = new WebAssembly.Module(module);
|
||||
}
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
export { initSync };
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export { accountFromPublicKey, isScheme, keypairFromMnemonic, keypairFromSeed, sign, signatureWithPublicKey, sizes, verify, WormholeBranch, wormholeAddresses, wormholeNullifiers } from './crypto.js';
|
||||
export type { Keypair, Sizes } from './crypto.js';
|
||||
export { initWasm, isReady } from './init.js';
|
||||
export { contextForSpec, EXTRINSIC_CONTEXT, EXTRINSIC_MIN_SPEC, Scheme, SCHEME_NAME } from './scheme.js';
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { unzlibSync } from 'fflate';
|
||||
|
||||
import { base64Decode } from './base64.js';
|
||||
|
||||
import { bytes, lenOut } from './bytes.js';
|
||||
import { initSync } from './generated/quantus_crypto.js';
|
||||
|
||||
/**
|
||||
* Instantiate the WASM, synchronously, from bytes compiled into this file.
|
||||
*
|
||||
* Three constraints shape this, and all three rule out the obvious approach:
|
||||
*
|
||||
* - the background context is an **MV3 service worker**, so there is no DOM, no
|
||||
* reliable `fetch` of extension-relative URLs at arbitrary times, and the
|
||||
* worker can be killed and cold-started between any two messages
|
||||
* - the extension CSP is `script-src 'self' 'wasm-unsafe-eval'`, which permits
|
||||
* compiling WASM but not fetching it from anywhere interesting
|
||||
* - callers are synchronous — `pair.sign()` in the keyring has no `await` to give
|
||||
*
|
||||
* So the WASM is zlib-compressed, base64'd into `bytes.js` at build time, and
|
||||
* instantiated here with wasm-bindgen's `initSync`. Nothing is fetched, and the
|
||||
* whole module is ready before the first call returns.
|
||||
*
|
||||
* Deliberately *not* using `@polkadot/wasm-bridge`: its `Bridge` implements
|
||||
* wasm-bindgen 0.2.79's JS-heap ABI, and this crate is built with 0.2.128, which
|
||||
* uses externref tables. See quantus/wasm#1.
|
||||
*/
|
||||
|
||||
let initialised = false;
|
||||
let initError: string | null = null;
|
||||
|
||||
/**
|
||||
* Ensure the WASM is instantiated. Idempotent and cheap after the first call.
|
||||
*
|
||||
* Returns `null` on success, or the failure reason. It does not throw: a caller
|
||||
* deciding whether to offer a Quantus account at all wants to ask, and an
|
||||
* exception thrown from module scope in a service worker is hard to attribute.
|
||||
*/
|
||||
export function initWasm (): string | null {
|
||||
if (initialised) {
|
||||
return initError;
|
||||
}
|
||||
|
||||
initialised = true;
|
||||
|
||||
try {
|
||||
initSync({ module: unzlibSync(base64Decode(bytes, new Uint8Array(lenOut))) });
|
||||
} catch (error) {
|
||||
initError = (error as Error).message;
|
||||
}
|
||||
|
||||
return initError;
|
||||
}
|
||||
|
||||
/** Whether the WASM is available. Callers that can fall back should ask first. */
|
||||
export function isReady (): boolean {
|
||||
return initWasm() === null;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Quantus post-quantum crypto for the browser.
|
||||
//!
|
||||
//! Every function here delegates to the crates the Quantus runtime itself uses
|
||||
//! (`qp-rusty-crystals-dilithium`, `qp-poseidon-core`, `qp-rusty-crystals-hdwallet`)
|
||||
//! rather than reimplementing anything. That is the whole point: a browser wallet
|
||||
//! that disagreed with the chain about a key or a signature would produce
|
||||
//! perfectly well-formed output that the chain rejects, and nothing on this side
|
||||
//! could tell.
|
||||
|
||||
#[path = "rs/hdwallet.rs"]
|
||||
pub mod hdwallet;
|
||||
|
||||
#[path = "rs/mldsa.rs"]
|
||||
pub mod mldsa;
|
||||
|
||||
#[path = "rs/poseidon.rs"]
|
||||
pub mod poseidon;
|
||||
|
||||
#[path = "rs/scheme.rs"]
|
||||
pub mod scheme;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "rs/tests.rs"]
|
||||
mod tests;
|
||||
@@ -0,0 +1,231 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::scheme::dispatch;
|
||||
|
||||
/// Derive a keypair from a BIP39 mnemonic at a hardened derivation path.
|
||||
///
|
||||
/// Lattice keys have no public derivability, so there is no soft-junction
|
||||
/// equivalent and the crate rejects any unhardened path outright. The Quantus
|
||||
/// convention is:
|
||||
///
|
||||
/// ```text
|
||||
/// m/44'/189189'/<account>'/0'/<0 for ML-DSA-87 | 1 for ML-DSA-65>'
|
||||
/// ```
|
||||
///
|
||||
/// with the account index at the third level and the *scheme* carried in the
|
||||
/// trailing index. That is unusual, and it is what `quantus-cli` and the mobile
|
||||
/// wallet already use — deriving anything else produces addresses no other
|
||||
/// Quantus tool can find.
|
||||
///
|
||||
/// The seeding matters as much as the path. This goes mnemonic → 64-byte BIP39
|
||||
/// seed → HMAC-SHA512 chain keyed with the literal string `"Dilithium seed"`.
|
||||
/// Substrate's own `mnemonicToMiniSecret` is a *different* derivation and is the
|
||||
/// default reach in the polkadot-js codebase; using it here would yield a
|
||||
/// well-formed key for an account nobody owns.
|
||||
///
|
||||
/// * mnemonic: BIP39 phrase, 12/15/18/21/24 words
|
||||
/// * password: BIP39 passphrase; empty string for none
|
||||
/// * path: hardened derivation path, e.g. `m/44'/189189'/0'/0'/1'`
|
||||
/// * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
///
|
||||
/// * returned vector is the secret key followed by the public key, as
|
||||
/// `ext_mldsa_from_seed` returns.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_derive(mnemonic: &str, password: &str, path: &str, scheme: u32) -> Result<Vec<u8>, JsError> {
|
||||
mldsa_derive(mnemonic, password, path, scheme).map_err(|e| JsError::new(&e))
|
||||
}
|
||||
|
||||
/// The body of [`ext_mldsa_derive`]. See [`crate::mldsa::mldsa_from_seed`] for why
|
||||
/// this is split from its binding.
|
||||
pub fn mldsa_derive(mnemonic: &str, password: &str, path: &str, scheme: u32) -> Result<Vec<u8>, String> {
|
||||
// An empty passphrase and no passphrase are the same thing in BIP39, but the
|
||||
// crate distinguishes `None` from `Some("")` in its signature, so normalise
|
||||
// here rather than leaving each caller to pick one.
|
||||
let password = if password.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(password)
|
||||
};
|
||||
|
||||
dispatch!(scheme, _dsa, hd, {
|
||||
let pair = hd::derive_key_from_mnemonic(mnemonic, password, path)
|
||||
.map_err(alloc_error)?;
|
||||
let mut out = pair.secret().to_bytes().to_vec();
|
||||
|
||||
out.extend_from_slice(&pair.public().to_bytes());
|
||||
|
||||
Ok(out)
|
||||
})
|
||||
}
|
||||
|
||||
/// Render a derivation failure as a string.
|
||||
///
|
||||
/// Kept separate so the error text stays whatever the crate said — a bad
|
||||
/// mnemonic, an unhardened path and a path that is too deep are different
|
||||
/// mistakes and a user can only fix the one they made.
|
||||
fn alloc_error(e: qp_rusty_crystals_hdwallet::HDLatticeError) -> String {
|
||||
format!("{e}")
|
||||
}
|
||||
|
||||
/// The largest number of wormhole addresses one call derives. Each is a Poseidon
|
||||
/// hash over an HMAC-SHA512 chain; the bound keeps a caller from asking for a
|
||||
/// million of them and locking the page.
|
||||
pub const WORMHOLE_MAX_BATCH: u32 = 1000;
|
||||
|
||||
/// Derive consecutive wormhole addresses for one account and branch.
|
||||
///
|
||||
/// A wormhole address is not a key. The path yields a 32-byte **secret**, and
|
||||
/// the address is `poseidon(poseidon(salt ‖ secret))`; funds leave it only
|
||||
/// through a ZK proof of knowing that secret. So this returns the addresses and
|
||||
/// nothing else. The secrets and the intermediate `first_hash` stay inside this
|
||||
/// call and are wiped on drop by the crate's sensitive types.
|
||||
///
|
||||
/// Paths are `m/44'/189189189'/<account>'/<change>'/<index>'`, as the mobile
|
||||
/// wallet derives them: change `0` is the receive branch, `1` the change branch.
|
||||
///
|
||||
/// The BIP39 seed is stretched once for the whole batch. Stretching per address
|
||||
/// is PBKDF2 with 2048 rounds each time, and a gap-limit window is dozens of
|
||||
/// addresses.
|
||||
///
|
||||
/// * mnemonic: BIP39 phrase
|
||||
/// * password: BIP39 passphrase; empty string for none
|
||||
/// * account, change, start, count: which addresses; count <= WORMHOLE_MAX_BATCH
|
||||
///
|
||||
/// * returned vector is `count` 32-byte account ids, concatenated
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_wormhole_addresses(mnemonic: &str, password: &str, account: u32, change: u32, start: u32, count: u32) -> Result<Vec<u8>, JsError> {
|
||||
wormhole_addresses(mnemonic, password, account, change, start, count).map_err(|e| JsError::new(&e))
|
||||
}
|
||||
|
||||
/// The body of [`ext_wormhole_addresses`], split from its binding for the same
|
||||
/// reason as [`mldsa_derive`].
|
||||
pub fn wormhole_addresses(mnemonic: &str, password: &str, account: u32, change: u32, start: u32, count: u32) -> Result<Vec<u8>, String> {
|
||||
use qp_rusty_crystals_hdwallet::{generate_wormhole_from_seed, mnemonic_to_seed, SensitiveBytes64};
|
||||
|
||||
if count > WORMHOLE_MAX_BATCH {
|
||||
return Err(format!("At most {WORMHOLE_MAX_BATCH} wormhole addresses per call, asked for {count}"));
|
||||
}
|
||||
|
||||
if start.checked_add(count).is_none_or(|end| end > 0x8000_0000) {
|
||||
return Err(format!("Wormhole address indices must stay below 2^31, asked for {start} + {count}"));
|
||||
}
|
||||
|
||||
let password = if password.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(password)
|
||||
};
|
||||
let mut seed = SensitiveBytes64::zeroed();
|
||||
|
||||
mnemonic_to_seed(mnemonic.to_string(), password, &mut seed).map_err(alloc_error)?;
|
||||
|
||||
let mut out = Vec::with_capacity(count as usize * 32);
|
||||
|
||||
for index in start..start + count {
|
||||
let path = format!("m/44'/189189189'/{account}'/{change}'/{index}'");
|
||||
let pair = generate_wormhole_from_seed(&seed, &path).map_err(alloc_error)?;
|
||||
|
||||
out.extend_from_slice(pair.address());
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Salt the chain's nullifier derivation starts from: `NULLIFIER_SALT` in
|
||||
/// `qp-wormhole-circuit`.
|
||||
const NULLIFIER_SALT: &str = "~nullif~";
|
||||
|
||||
/// The largest number of nullifiers one call computes.
|
||||
pub const NULLIFIER_MAX_BATCH: u32 = 100_000;
|
||||
|
||||
/// Nullifiers for a run of wormhole addresses' deposits, by transfer count.
|
||||
///
|
||||
/// A deposit to a wormhole address is spent when its nullifier is in
|
||||
/// `Wormhole::UsedNullifiers`. The nullifier is
|
||||
///
|
||||
/// ```text
|
||||
/// poseidon2(poseidon2(salt("~nullif~") ‖ secret ‖ transfer_count))
|
||||
/// ```
|
||||
///
|
||||
/// where `transfer_count` is the address's counter when the deposit landed. It
|
||||
/// needs the address's secret, which is why this takes the recovery phrase and
|
||||
/// why a nullifier should never be sent anywhere to be checked: exits publish
|
||||
/// nullifiers, so whoever sees yours can name your exits.
|
||||
///
|
||||
/// For addresses `m/44'/189189189'/<account>'/<change>'/<index>'` with index in
|
||||
/// `start..start + addresses`, and transfer counts `first..first + count` for
|
||||
/// each. The BIP39 seed is stretched once for the whole run.
|
||||
///
|
||||
/// Ported onto `qp-poseidon-core` rather than calling `qp-wormhole-circuit`,
|
||||
/// which would bring plonky2 into the WASM. The port is pinned to the circuit
|
||||
/// crate's own `Nullifier::from_preimage` by the tests.
|
||||
///
|
||||
/// * returned vector is `addresses * count` 32-byte nullifiers: address by
|
||||
/// address, and by transfer count within each
|
||||
#[wasm_bindgen]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn ext_wormhole_nullifiers(mnemonic: &str, password: &str, account: u32, change: u32, start: u32, addresses: u32, first: u64, count: u32) -> Result<Vec<u8>, JsError> {
|
||||
wormhole_nullifiers(mnemonic, password, account, change, start, addresses, first, count).map_err(|e| JsError::new(&e))
|
||||
}
|
||||
|
||||
/// The body of [`ext_wormhole_nullifiers`].
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn wormhole_nullifiers(mnemonic: &str, password: &str, account: u32, change: u32, start: u32, addresses: u32, first: u64, count: u32) -> Result<Vec<u8>, String> {
|
||||
use qp_rusty_crystals_hdwallet::{generate_wormhole_from_seed, mnemonic_to_seed, SensitiveBytes64};
|
||||
|
||||
let total = addresses as u64 * count as u64;
|
||||
|
||||
if total > NULLIFIER_MAX_BATCH as u64 {
|
||||
return Err(format!("At most {NULLIFIER_MAX_BATCH} nullifiers per call, asked for {total}"));
|
||||
}
|
||||
|
||||
if start.checked_add(addresses).is_none_or(|end| end > 0x8000_0000) {
|
||||
return Err(format!("Wormhole address indices must stay below 2^31, asked for {start} + {addresses}"));
|
||||
}
|
||||
|
||||
first.checked_add(count as u64).ok_or("Transfer counts overflow")?;
|
||||
|
||||
let password = if password.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(password)
|
||||
};
|
||||
let mut seed = SensitiveBytes64::zeroed();
|
||||
|
||||
mnemonic_to_seed(mnemonic.to_string(), password, &mut seed).map_err(alloc_error)?;
|
||||
|
||||
let mut out = Vec::with_capacity(total as usize * 32);
|
||||
|
||||
for index in start..start + addresses {
|
||||
let path = format!("m/44'/189189189'/{account}'/{change}'/{index}'");
|
||||
let pair = generate_wormhole_from_seed(&seed, &path).map_err(alloc_error)?;
|
||||
|
||||
for transfer_count in first..first + count as u64 {
|
||||
out.extend_from_slice(&nullifier(pair.secret().as_bytes(), transfer_count));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// One nullifier from a wormhole secret and a transfer count.
|
||||
pub fn nullifier(secret: &[u8; 32], transfer_count: u64) -> [u8; 32] {
|
||||
use qp_poseidon_core::{
|
||||
hash_twice,
|
||||
serialization::{bytes_to_digest_lossy, string_to_felts, u64_to_felts},
|
||||
};
|
||||
|
||||
let salt = string_to_felts(NULLIFIER_SALT);
|
||||
let secret_felts = bytes_to_digest_lossy(secret);
|
||||
let count_felts = u64_to_felts(transfer_count);
|
||||
let mut preimage = Vec::with_capacity(salt.len() + secret_felts.len() + count_felts.len());
|
||||
|
||||
preimage.extend_from_slice(&salt);
|
||||
preimage.extend_from_slice(&secret_felts);
|
||||
preimage.extend_from_slice(&count_felts);
|
||||
|
||||
hash_twice(&preimage)
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
use crate::scheme::dispatch;
|
||||
|
||||
/// Key and signature sizes for a parameter set, as
|
||||
/// `[public, secret, signature, signature_with_public]`.
|
||||
///
|
||||
/// Exported so that nothing on the JS side has to hardcode 1952/4032/3309/5261 or
|
||||
/// 2592/4896/4627/7219. Those numbers are consensus-critical — the runtime reads a
|
||||
/// fixed-size array off the wire — and a JS constant that drifted from the crate
|
||||
/// would mis-frame every byte after the signature while looking entirely healthy.
|
||||
/// Ask the crate instead.
|
||||
///
|
||||
/// * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
///
|
||||
/// * returned vector is four u32 lengths, little-endian, 16 bytes total.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_sizes(scheme: u32) -> Vec<u8> {
|
||||
dispatch!(scheme, dsa, _hd, {
|
||||
let sizes: [u32; 4] = [
|
||||
dsa::PUBLICKEYBYTES as u32,
|
||||
dsa::SECRETKEYBYTES as u32,
|
||||
dsa::SIGNBYTES as u32,
|
||||
(dsa::SIGNBYTES + dsa::PUBLICKEYBYTES) as u32,
|
||||
];
|
||||
|
||||
sizes.iter().flat_map(|n| n.to_le_bytes()).collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Whether `scheme` names a parameter set this build supports.
|
||||
///
|
||||
/// `dispatch!` falls back to ML-DSA-87 for anything unrecognised, which is the
|
||||
/// right default but a poor way to discover a typo. Callers that accept a scheme
|
||||
/// from storage or from a user should check here first.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_is_scheme(scheme: u32) -> bool {
|
||||
scheme == crate::scheme::ML_DSA_87 || scheme == crate::scheme::ML_DSA_65
|
||||
}
|
||||
|
||||
/// Generate a keypair from 32 bytes of entropy.
|
||||
///
|
||||
/// This is FIPS 204 `ML-DSA.KeyGen_internal` with no Quantus-specific step: the
|
||||
/// crate expands the seed as `SHAKE256(seed ‖ k ‖ ℓ)`, so the parameter set is
|
||||
/// absorbed into the expansion and the same 32 bytes yield independent keys per
|
||||
/// scheme. That is why the dev accounts (`[0u8; 32]`, `[1u8; 32]`, `[2u8; 32]`)
|
||||
/// and HD-derived accounts can share this one entry point.
|
||||
///
|
||||
/// * seed: UIntArray with 32 elements
|
||||
/// * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
///
|
||||
/// * returned vector is the secret key followed by the public key, matching the
|
||||
/// ordering `ext_ed_from_seed` uses. Split it at the secret length from
|
||||
/// `ext_mldsa_sizes`.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_from_seed(seed: &[u8], scheme: u32) -> Result<Vec<u8>, JsError> {
|
||||
mldsa_from_seed(seed, scheme).map_err(|e| JsError::new(&e))
|
||||
}
|
||||
|
||||
/// The body of [`ext_mldsa_from_seed`], without the binding layer.
|
||||
///
|
||||
/// Split out because `JsError` cannot be constructed on a non-wasm target — it
|
||||
/// panics with "cannot call wasm-bindgen imported functions on non-wasm targets" —
|
||||
/// so anything that returns one is untestable by `cargo test`. The error paths are
|
||||
/// exactly what most needs testing, so the logic lives here and the exported
|
||||
/// wrapper does nothing but translate.
|
||||
pub fn mldsa_from_seed(seed: &[u8], scheme: u32) -> Result<Vec<u8>, String> {
|
||||
if seed.len() != 32 {
|
||||
return Err("expected a 32 byte seed".into());
|
||||
}
|
||||
|
||||
// `SensitiveBytes32::from` takes the buffer mutably and the crate zeroes it
|
||||
// after use, so the copy we hand it is destroyed rather than left on the
|
||||
// stack. Do not replace this with a by-value clone of `seed`.
|
||||
let mut entropy = [0u8; 32];
|
||||
|
||||
entropy.copy_from_slice(seed);
|
||||
|
||||
let mut entropy = qp_rusty_crystals_dilithium::SensitiveBytes32::from(&mut entropy);
|
||||
|
||||
dispatch!(scheme, dsa, _hd, {
|
||||
let pair = dsa::Keypair::generate(&mut entropy);
|
||||
let mut out = pair.secret().to_bytes().to_vec();
|
||||
|
||||
out.extend_from_slice(&pair.public().to_bytes());
|
||||
|
||||
Ok(out)
|
||||
})
|
||||
}
|
||||
|
||||
/// Sign a message under a FIPS 204 context.
|
||||
///
|
||||
/// Signing is deterministic — no hedging randomness — because that is what the
|
||||
/// runtime does (`hedge: None`), and a wallet that hedged would produce a
|
||||
/// different signature each time for the same input, which makes the
|
||||
/// byte-for-byte agreement tests in quantus/wasm#2 impossible to write.
|
||||
///
|
||||
/// `ctx` is domain separation and it is **not** optional in practice: extrinsics
|
||||
/// on spec >= 148 are verified under `QUANTUS_EXTRINSIC`, earlier specs under the
|
||||
/// empty context, and a signature made under the wrong one is valid, rejected by
|
||||
/// the chain, and indistinguishable locally. The caller chooses; this function
|
||||
/// does not guess.
|
||||
///
|
||||
/// * secret: UIntArray, secret-key length for the scheme
|
||||
/// * public: UIntArray, public-key length for the scheme
|
||||
/// * message: arbitrary length UIntArray
|
||||
/// * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
/// * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
///
|
||||
/// * returned vector is the signature alone. The runtime's wire format is
|
||||
/// `signature ‖ public`; concatenating is the caller's job because only the
|
||||
/// caller knows whether it wants the wire form or the bare signature.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_sign(secret: &[u8], public: &[u8], message: &[u8], ctx: &[u8], scheme: u32) -> Result<Vec<u8>, JsError> {
|
||||
mldsa_sign(secret, public, message, ctx, scheme).map_err(|e| JsError::new(&e))
|
||||
}
|
||||
|
||||
/// The body of [`ext_mldsa_sign`]. See [`mldsa_from_seed`] for why this is split.
|
||||
pub fn mldsa_sign(secret: &[u8], public: &[u8], message: &[u8], ctx: &[u8], scheme: u32) -> Result<Vec<u8>, String> {
|
||||
if ctx.len() > 255 {
|
||||
return Err("context must be at most 255 bytes".into());
|
||||
}
|
||||
|
||||
dispatch!(scheme, dsa, _hd, {
|
||||
// `from_parts` re-derives the public key from the secret and rejects a
|
||||
// mismatch, so a corrupted or mixed-up pair fails here rather than
|
||||
// producing a signature that silently will not verify.
|
||||
let secret = dsa::SecretKey::from_bytes(secret)
|
||||
.map_err(|_| "invalid secret key".to_string())?;
|
||||
let public = dsa::PublicKey::from_bytes(public)
|
||||
.map_err(|_| "invalid public key".to_string())?;
|
||||
let pair = dsa::Keypair::from_parts(secret, public)
|
||||
.map_err(|_| "secret and public key do not correspond".to_string())?;
|
||||
|
||||
pair
|
||||
.sign(message, Some(ctx), None)
|
||||
.map(|sig| sig.to_vec())
|
||||
.map_err(|_| "signing failed".to_string())
|
||||
})
|
||||
}
|
||||
|
||||
/// Verify a signature against a message and public key under a context.
|
||||
///
|
||||
/// * public: UIntArray, public-key length for the scheme
|
||||
/// * message: arbitrary length UIntArray
|
||||
/// * signature: UIntArray, signature length for the scheme
|
||||
/// * ctx: UIntArray, at most 255 elements; empty for no context
|
||||
/// * scheme: 0 for ML-DSA-87, 1 for ML-DSA-65
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_mldsa_verify(public: &[u8], message: &[u8], signature: &[u8], ctx: &[u8], scheme: u32) -> bool {
|
||||
if ctx.len() > 255 {
|
||||
return false;
|
||||
}
|
||||
|
||||
dispatch!(scheme, dsa, _hd, {
|
||||
match dsa::PublicKey::from_bytes(public) {
|
||||
Ok(public) => public.verify(message, signature, Some(ctx)),
|
||||
Err(_) => false
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
/// Poseidon2-over-Goldilocks hash of arbitrary bytes.
|
||||
///
|
||||
/// This is the account-id derivation. On Substrate an `AccountId32` *is* the
|
||||
/// public key; on Quantus it is `hash_bytes(public_key)`, which is why a Quantus
|
||||
/// signature has to carry its public key along — the address cannot give it back.
|
||||
///
|
||||
/// `qp_poseidon_core::hash_bytes` is `IdentifyAccount for DilithiumSigner` in the
|
||||
/// runtime, so this is the same function the chain uses to decide who signed
|
||||
/// something, reached through the same crate rather than a port of it.
|
||||
///
|
||||
/// * data: arbitrary length UIntArray
|
||||
///
|
||||
/// * returned vector is 32 bytes.
|
||||
#[wasm_bindgen]
|
||||
pub fn ext_poseidon_hash(data: &[u8]) -> Vec<u8> {
|
||||
qp_poseidon_core::hash_bytes(data).to_vec()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Which ML-DSA parameter set a call refers to.
|
||||
//!
|
||||
//! The selector is the chain's own signature-enum variant index, not a private
|
||||
//! numbering: `DilithiumSignatureScheme::Dilithium87` is variant 0 and
|
||||
//! `Dilithium65` is variant 1, and that byte is what a signed extrinsic carries
|
||||
//! on the wire. Reusing it here means the number threaded through this API is
|
||||
//! the number that ends up in the extrinsic, so there is no mapping table to get
|
||||
//! backwards between here and `TYPE_PREFIX` in the keyring.
|
||||
|
||||
/// ML-DSA-87 — the legacy scheme, used by accounts created before the scheme was
|
||||
/// recorded, and by the dev-genesis accounts.
|
||||
pub const ML_DSA_87: u32 = 0;
|
||||
|
||||
/// ML-DSA-65 — what new accounts use.
|
||||
pub const ML_DSA_65: u32 = 1;
|
||||
|
||||
/// Runs `$body` with `$dsa` and `$hd` bound to the parameter-set modules named by
|
||||
/// `$scheme`.
|
||||
///
|
||||
/// An unrecognised selector resolves to ML-DSA-87 rather than panicking: 0 is the
|
||||
/// legacy scheme and the safest thing an out-of-range value can mean. Callers
|
||||
/// that care validate first — see `ext_mldsa_is_scheme`.
|
||||
macro_rules! dispatch {
|
||||
($scheme:expr, $dsa:ident, $hd:ident, $body:block) => {
|
||||
match $scheme {
|
||||
$crate::scheme::ML_DSA_65 => {
|
||||
#[allow(unused_imports)]
|
||||
use qp_rusty_crystals_dilithium::ml_dsa_65 as $dsa;
|
||||
#[allow(unused_imports)]
|
||||
use qp_rusty_crystals_hdwallet::ml_dsa_65 as $hd;
|
||||
$body
|
||||
},
|
||||
_ => {
|
||||
#[allow(unused_imports)]
|
||||
use qp_rusty_crystals_dilithium::ml_dsa_87 as $dsa;
|
||||
#[allow(unused_imports)]
|
||||
use qp_rusty_crystals_hdwallet::ml_dsa_87 as $hd;
|
||||
$body
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use dispatch;
|
||||
@@ -0,0 +1,303 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
//! Conformance against the chain, not against ourselves.
|
||||
//!
|
||||
//! Every expected value here came from an independent implementation — the
|
||||
//! `quantus` CLI 2.2.2 — and not from running this crate and writing down what
|
||||
//! it said. A test that pins our own output would keep passing through exactly
|
||||
//! the kind of drift these exist to catch.
|
||||
//!
|
||||
//! Addresses are pinned as raw account-id bytes rather than SS58 strings so this
|
||||
//! file needs no base58 dependency; the SS58 rendering at prefix 189 is pinned on
|
||||
//! the JS side, which is where it is actually used.
|
||||
|
||||
use crate::{hdwallet::{mldsa_derive, wormhole_addresses}, mldsa::*, poseidon::*, scheme::*};
|
||||
|
||||
/// FIPS 204 context for on-chain extrinsic signatures, spec >= 148.
|
||||
/// `chain:primitives/dilithium-crypto/src/signing_context.rs`.
|
||||
const EXTRINSIC: &[u8] = b"QUANTUS_EXTRINSIC";
|
||||
|
||||
fn account_of(seed_fill: u8, scheme: u32) -> Vec<u8> {
|
||||
let pair = mldsa_from_seed(&[seed_fill; 32], scheme).expect("keygen");
|
||||
let secret_len = secret_len(scheme);
|
||||
|
||||
ext_poseidon_hash(&pair[secret_len..])
|
||||
}
|
||||
|
||||
fn secret_len(scheme: u32) -> usize {
|
||||
let sizes = ext_mldsa_sizes(scheme);
|
||||
|
||||
u32::from_le_bytes(sizes[4..8].try_into().unwrap()) as usize
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sizes_match_the_parameter_sets() {
|
||||
// [public, secret, signature, signature_with_public]
|
||||
let s87: Vec<u32> = ext_mldsa_sizes(ML_DSA_87).chunks(4).map(|c| u32::from_le_bytes(c.try_into().unwrap())).collect();
|
||||
let s65: Vec<u32> = ext_mldsa_sizes(ML_DSA_65).chunks(4).map(|c| u32::from_le_bytes(c.try_into().unwrap())).collect();
|
||||
|
||||
assert_eq!(s87, vec![2592, 4896, 4627, 7219]);
|
||||
assert_eq!(s65, vec![1952, 4032, 3309, 5261]);
|
||||
}
|
||||
|
||||
/// The dev accounts endowed at genesis, from `chain:primitives/dilithium-crypto/src/pair.rs`.
|
||||
///
|
||||
/// Expected values are the account ids behind the SS58 addresses that
|
||||
/// `quantus developer create-test-wallets` prints:
|
||||
///
|
||||
/// ```text
|
||||
/// crystal_alice qzk1Nxai3dZD9Cn5kwGcgL6mKxsfxwqdis7kDQJ52aJS2vSn7
|
||||
/// dilithium_bob qzkYEQv8tQsmniZYdame3Cku18RL5g9bGK9Pdydq5TMPdpE3y
|
||||
/// crystal_charlie qzntBpmqHZF1jxC8KJKpuxcYuHST892jyXBqRctpAxd1WQ9BL
|
||||
/// ```
|
||||
///
|
||||
/// They are ML-DSA-87 and come from the seed directly with no HD derivation, so
|
||||
/// this pins the legacy scheme and the raw-seed path in one go.
|
||||
#[test]
|
||||
fn dev_account_ids_match_the_cli() {
|
||||
assert_eq!(
|
||||
hex(&account_of(0, ML_DSA_87)),
|
||||
"1883df2ae47d1fd428a6b8237ad7b59cf0facccaacac4541ef7758be44b3c333",
|
||||
"crystal_alice"
|
||||
);
|
||||
assert_eq!(
|
||||
hex(&account_of(1, ML_DSA_87)),
|
||||
"300bb607ba60e89461d2f9005668231ceb30237b33db53a614164b8590965519",
|
||||
"dilithium_bob"
|
||||
);
|
||||
assert_eq!(
|
||||
hex(&account_of(2, ML_DSA_87)),
|
||||
"97bc5f2db1efa23fb71f6737fcb26e41e448aff07447011369df81ce43555465",
|
||||
"crystal_charlie"
|
||||
);
|
||||
}
|
||||
|
||||
/// The same 32 bytes must give different keys per parameter set — FIPS 204
|
||||
/// absorbs `(k, ℓ)` into the seed expansion. If these ever collided it would mean
|
||||
/// the scheme selector was being ignored somewhere.
|
||||
#[test]
|
||||
fn schemes_are_independent_for_the_same_seed() {
|
||||
assert_ne!(account_of(0, ML_DSA_87), account_of(0, ML_DSA_65));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signs_and_verifies_under_the_extrinsic_context() {
|
||||
for scheme in [ML_DSA_87, ML_DSA_65] {
|
||||
let pair = mldsa_from_seed(&[7u8; 32], scheme).expect("keygen");
|
||||
let (secret, public) = pair.split_at(secret_len(scheme));
|
||||
let message = b"the payload the chain will see";
|
||||
let signature = mldsa_sign(secret, public, message, EXTRINSIC, scheme).expect("sign");
|
||||
|
||||
assert!(ext_mldsa_verify(public, message, &signature, EXTRINSIC, scheme));
|
||||
|
||||
// The whole point of the context. A signature made for an extrinsic must
|
||||
// not verify as anything else, and vice versa — this is what makes the
|
||||
// spec-148 boundary detectable instead of a silent chain rejection.
|
||||
assert!(!ext_mldsa_verify(public, message, &signature, b"", scheme));
|
||||
assert!(!ext_mldsa_verify(public, b"tampered", &signature, EXTRINSIC, scheme));
|
||||
}
|
||||
}
|
||||
|
||||
/// The runtime signs with `hedge: None`. If this crate ever introduced hedging
|
||||
/// randomness the golden vectors in quantus/wasm#2 would become unwritable, and
|
||||
/// nothing else would notice.
|
||||
#[test]
|
||||
fn signing_is_deterministic() {
|
||||
let pair = mldsa_from_seed(&[9u8; 32], ML_DSA_65).expect("keygen");
|
||||
let (secret, public) = pair.split_at(secret_len(ML_DSA_65));
|
||||
let once = mldsa_sign(secret, public, b"m", EXTRINSIC, ML_DSA_65).expect("sign");
|
||||
let twice = mldsa_sign(secret, public, b"m", EXTRINSIC, ML_DSA_65).expect("sign");
|
||||
|
||||
assert_eq!(once, twice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_bad_input() {
|
||||
assert!(mldsa_from_seed(&[0u8; 16], ML_DSA_65).is_err(), "short seed");
|
||||
|
||||
let pair = mldsa_from_seed(&[1u8; 32], ML_DSA_65).expect("keygen");
|
||||
let (secret, public) = pair.split_at(secret_len(ML_DSA_65));
|
||||
|
||||
assert!(mldsa_sign(secret, public, b"m", &[0u8; 256], ML_DSA_65).is_err(), "context > 255");
|
||||
assert!(mldsa_sign(&secret[1..], public, b"m", EXTRINSIC, ML_DSA_65).is_err(), "truncated secret");
|
||||
|
||||
// A pair whose halves do not correspond must fail at import rather than
|
||||
// produce a signature that silently will not verify.
|
||||
let other = mldsa_from_seed(&[2u8; 32], ML_DSA_65).expect("keygen");
|
||||
let other_public = &other[secret_len(ML_DSA_65)..];
|
||||
|
||||
assert!(mldsa_sign(secret, other_public, b"m", EXTRINSIC, ML_DSA_65).is_err(), "mismatched pair");
|
||||
}
|
||||
|
||||
/// The well-known Substrate development phrase. Public by design — it is in
|
||||
/// polkadot-sdk, in polkadot-js, and in every tutorial — so pinning it here
|
||||
/// commits no secret. Any account it derives is assumed compromised.
|
||||
const DEV_PHRASE: &str = "bottom drive obey lake curtain smoke basket hold race lonely fit walk";
|
||||
|
||||
/// HD derivation at the Quantus BIP44 path, cross-checked against
|
||||
/// `quantus wallet import --mnemonic-file <DEV_PHRASE> --scheme <s>`, which
|
||||
/// printed:
|
||||
///
|
||||
/// ```text
|
||||
/// ml-dsa-65 m/44'/189189'/0'/0'/1' qzq29m9WvneDAeXbtgueKCREtNe1rVVs6bXSMLmjr6shqvwq6
|
||||
/// ml-dsa-87 m/44'/189189'/0'/0'/0' qzjrYTUnnE5NduTZKxe9dESCMTZg7nTueKM3bwhnkRdD1iYV4
|
||||
/// ```
|
||||
///
|
||||
/// This pins the whole derivation chain at once: BIP39 to a 64-byte seed (*not*
|
||||
/// Substrate's `mnemonicToMiniSecret`), the HMAC-SHA512 walk keyed with
|
||||
/// "Dilithium seed", the trailing hardened index carrying the scheme, and the
|
||||
/// Poseidon2 account-id hash on the end.
|
||||
#[test]
|
||||
fn hd_derivation_matches_the_cli() {
|
||||
let cases = [
|
||||
(ML_DSA_65, "m/44'/189189'/0'/0'/1'", "f647dbdefebcfcf726ba078a83481ffc6f4f33004fdfb4cedacf5a5391bc8f00"),
|
||||
(ML_DSA_87, "m/44'/189189'/0'/0'/0'", "11c6a314e003cdee3dc51cf6569175360141578d054c38d7a70840a65cc0e990")
|
||||
];
|
||||
|
||||
for (scheme, path, expected) in cases {
|
||||
let pair = mldsa_derive(DEV_PHRASE, "", path, scheme).expect("derive");
|
||||
let account = ext_poseidon_hash(&pair[secret_len(scheme)..]);
|
||||
|
||||
assert_eq!(hex(&account), expected, "{path}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Lattice keys have no public derivability, so the crate rejects unhardened
|
||||
/// paths outright rather than inventing a meaning for them. A wallet that
|
||||
/// silently hardened a soft path would put funds at an address the user did not
|
||||
/// ask for.
|
||||
#[test]
|
||||
fn derivation_rejects_bad_input() {
|
||||
assert!(mldsa_derive(DEV_PHRASE, "", "m/44'/189189'/0'/0'/1", ML_DSA_65).is_err(), "unhardened");
|
||||
assert!(mldsa_derive("not a mnemonic at all", "", "m/44'/189189'/0'/0'/1'", ML_DSA_65).is_err(), "bad phrase");
|
||||
assert!(mldsa_derive(DEV_PHRASE, "", "not a path", ML_DSA_65).is_err(), "bad path");
|
||||
}
|
||||
|
||||
/// A BIP39 passphrase must change the result, and an empty string must mean
|
||||
/// "no passphrase" rather than "a passphrase that happens to be empty" — the
|
||||
/// two are the same in BIP39 but the crate's signature distinguishes them, and
|
||||
/// normalising in the wrong direction would silently fork every address.
|
||||
#[test]
|
||||
fn passphrase_is_honoured_and_empty_means_none() {
|
||||
let path = "m/44'/189189'/0'/0'/1'";
|
||||
let none = mldsa_derive(DEV_PHRASE, "", path, ML_DSA_65).expect("derive");
|
||||
let with = mldsa_derive(DEV_PHRASE, "hunter2", path, ML_DSA_65).expect("derive");
|
||||
|
||||
assert_ne!(none, with);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scheme_validation() {
|
||||
assert!(ext_mldsa_is_scheme(ML_DSA_87));
|
||||
assert!(ext_mldsa_is_scheme(ML_DSA_65));
|
||||
assert!(!ext_mldsa_is_scheme(2));
|
||||
}
|
||||
|
||||
fn hex(bytes: &[u8]) -> String {
|
||||
bytes.iter().map(|b| format!("{b:02x}")).collect()
|
||||
}
|
||||
|
||||
/// The chain node's own wormhole vector, `node/src/tests/data/quantus_key_test_data.rs`:
|
||||
/// `TEST_MNEMONIC` at `m/44'/189189189'/0'/0'/0'` is `TEST_WORMHOLE_ADDRESS`,
|
||||
/// `qzpWh4AEtsgCyEbv4WBgFWnB9bcdF2L2jVDuyjXP9mSTyBaeU`. The mobile wallet's SDK
|
||||
/// pins the same pair (`generate_keys_test.dart`), so three implementations agree.
|
||||
#[test]
|
||||
fn wormhole_address_matches_the_node() {
|
||||
const MNEMONIC: &str = "orchard answer curve patient visual flower maze noise retreat penalty cage small earth domain scan pitch bottom crunch theme club client swap slice raven";
|
||||
|
||||
let batch = wormhole_addresses(MNEMONIC, "", 0, 0, 0, 3).expect("derive");
|
||||
|
||||
assert_eq!(batch.len(), 96);
|
||||
assert_eq!(hex(&batch[..32]), "dfcfd6e59c75d208e84f54a887537bcf7b04265790ec79960bf49de123404d0e");
|
||||
|
||||
// A batch is the same as asking for each index on its own: the seed is
|
||||
// stretched once, but every address still gets its own path.
|
||||
for i in 0..3u32 {
|
||||
let one = wormhole_addresses(MNEMONIC, "", 0, 0, i, 1).expect("derive one");
|
||||
|
||||
assert_eq!(one, batch[(i as usize * 32)..(i as usize + 1) * 32].to_vec());
|
||||
}
|
||||
|
||||
// Receive and change branches, and account indices, are different addresses.
|
||||
assert_ne!(wormhole_addresses(MNEMONIC, "", 0, 1, 0, 1).unwrap(), batch[..32].to_vec());
|
||||
assert_ne!(wormhole_addresses(MNEMONIC, "", 1, 0, 0, 1).unwrap(), batch[..32].to_vec());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wormhole_addresses_refuse_unbounded_requests() {
|
||||
const MNEMONIC: &str = "orchard answer curve patient visual flower maze noise retreat penalty cage small earth domain scan pitch bottom crunch theme club client swap slice raven";
|
||||
|
||||
assert!(wormhole_addresses(MNEMONIC, "", 0, 0, 0, 1001).is_err());
|
||||
assert!(wormhole_addresses(MNEMONIC, "", 0, 0, 0x7fff_ffff, 2).is_err());
|
||||
assert!(wormhole_addresses("not a mnemonic", "", 0, 0, 0, 1).is_err());
|
||||
}
|
||||
|
||||
/// The port of the nullifier agrees with the chain's circuit crate.
|
||||
///
|
||||
/// `qp_wormhole_circuit::nullifier::Nullifier::from_preimage` is what the proof
|
||||
/// commits to and what `Wormhole::UsedNullifiers` records, so it is the
|
||||
/// reference. Secrets span the edge the lossy 8-bytes-per-felt encoding cares
|
||||
/// about (limbs at and above the Goldilocks prime), and transfer counts span
|
||||
/// both 32-bit limbs.
|
||||
#[test]
|
||||
fn nullifier_matches_the_circuit() {
|
||||
use crate::hdwallet::nullifier;
|
||||
use qp_wormhole_circuit::nullifier::Nullifier;
|
||||
use qp_zk_circuits_common::utils::{digest_to_bytes, BytesDigest};
|
||||
|
||||
let secrets: Vec<[u8; 32]> = vec![
|
||||
[0u8; 32],
|
||||
[0xff; 32],
|
||||
core::array::from_fn(|i| i as u8),
|
||||
core::array::from_fn(|i| (i as u8).wrapping_mul(97).wrapping_add(13)),
|
||||
// every limb is the Goldilocks prime 2^64 - 2^32 + 1, big-endian
|
||||
[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01].repeat(4).try_into().unwrap(),
|
||||
];
|
||||
let counts = [0u64, 1, 41_683, u32::MAX as u64, 1u64 << 32, u64::MAX];
|
||||
let mut compared = 0;
|
||||
|
||||
for secret in &secrets {
|
||||
for &count in &counts {
|
||||
let digest = BytesDigest::try_from(*secret);
|
||||
// The circuit's BytesDigest refuses a non-canonical limb; where it
|
||||
// does, the chain can never produce that secret's nullifier either.
|
||||
let Ok(digest) = digest else { continue };
|
||||
let expected = digest_to_bytes(Nullifier::from_preimage(digest, count).hash);
|
||||
|
||||
assert_eq!(hex(&nullifier(secret, count)), hex(expected.as_ref()), "secret {} count {count}", hex(secret));
|
||||
compared += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Skipping is for the non-canonical edge only; a test that compared
|
||||
// nothing would pass just as well.
|
||||
assert!(compared >= 18, "only {compared} cases compared");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wormhole_nullifiers_follow_each_address_secret() {
|
||||
use crate::hdwallet::{nullifier, wormhole_nullifiers};
|
||||
use qp_rusty_crystals_hdwallet::derive_wormhole_from_mnemonic;
|
||||
|
||||
const MNEMONIC: &str = "orchard answer curve patient visual flower maze noise retreat penalty cage small earth domain scan pitch bottom crunch theme club client swap slice raven";
|
||||
|
||||
// addresses 2 and 3 on the change branch, transfer counts 5..8
|
||||
let batch = wormhole_nullifiers(MNEMONIC, "", 0, 1, 2, 2, 5, 3).unwrap();
|
||||
|
||||
assert_eq!(batch.len(), 2 * 3 * 32);
|
||||
|
||||
for (a, index) in [2u32, 3].into_iter().enumerate() {
|
||||
let pair = derive_wormhole_from_mnemonic(MNEMONIC, None, &format!("m/44'/189189189'/0'/1'/{index}'")).unwrap();
|
||||
|
||||
for c in 0..3usize {
|
||||
let at = (a * 3 + c) * 32;
|
||||
|
||||
assert_eq!(batch[at..at + 32].to_vec(), nullifier(pair.secret().as_bytes(), 5 + c as u64).to_vec(), "address {index} count {}", 5 + c);
|
||||
}
|
||||
}
|
||||
|
||||
assert!(wormhole_nullifiers(MNEMONIC, "", 0, 0, 0, 40, 0, 2_501).is_err());
|
||||
assert!(wormhole_nullifiers(MNEMONIC, "", 0, 0, 0, 1, u64::MAX, 2).is_err());
|
||||
assert!(wormhole_nullifiers(MNEMONIC, "", 0, 0, 0x7fff_ffff, 2, 0, 1).is_err());
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/**
|
||||
* Which ML-DSA parameter set a call refers to.
|
||||
*
|
||||
* These are the chain's own `DilithiumSignatureScheme` variant indices, not a
|
||||
* private numbering — the value here is the byte a signed extrinsic carries on
|
||||
* the wire. Keeping them identical means the keyring's `TYPE_PREFIX` is the
|
||||
* identity function on a scheme, with no table to get backwards.
|
||||
*/
|
||||
export enum Scheme {
|
||||
/** ML-DSA-87. Legacy: accounts created before the scheme was recorded, and the dev-genesis accounts. */
|
||||
MlDsa87 = 0,
|
||||
/** ML-DSA-65. What new accounts use. */
|
||||
MlDsa65 = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* The name each scheme is stored under, matching `quantus-cli` and the mobile
|
||||
* wallet so a wallet exported from one tool imports into another.
|
||||
*/
|
||||
export const SCHEME_NAME: Record<Scheme, string> = {
|
||||
[Scheme.MlDsa87]: 'ml-dsa-87',
|
||||
[Scheme.MlDsa65]: 'ml-dsa-65'
|
||||
};
|
||||
|
||||
/**
|
||||
* FIPS 204 context for on-chain extrinsic signatures.
|
||||
*
|
||||
* Only from spec 148 onward — earlier runtimes verify under the empty context,
|
||||
* and a signature made under the wrong one is valid, rejected by the chain, and
|
||||
* indistinguishable locally. Callers pass the spec version and get the right
|
||||
* answer from {@link contextForSpec}; nothing here guesses.
|
||||
*/
|
||||
export const EXTRINSIC_CONTEXT = new TextEncoder().encode('QUANTUS_EXTRINSIC');
|
||||
|
||||
/** First spec version that verifies extrinsics under {@link EXTRINSIC_CONTEXT}. */
|
||||
export const EXTRINSIC_MIN_SPEC = 148;
|
||||
|
||||
/** The signing context a runtime at `specVersion` expects. */
|
||||
export function contextForSpec (specVersion: number): Uint8Array {
|
||||
return specVersion >= EXTRINSIC_MIN_SPEC
|
||||
? EXTRINSIC_CONTEXT
|
||||
: new Uint8Array();
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2026 @quantus/crypto authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Consumes the *built* package exactly as quantus/common will — a plain import of
|
||||
// build output, nothing reaching into src or poking the wasm by hand. Run after
|
||||
// ./scripts/build-quantus.sh.
|
||||
//
|
||||
// This exists because the unit tests in src/rs/tests.rs cannot catch packaging
|
||||
// faults. A wasm that is valid before `wasm-opt` and broken after it passes every
|
||||
// cargo test and fails here, which is exactly how binaryen 105's mishandling of
|
||||
// externref tables was found.
|
||||
|
||||
import {
|
||||
accountFromPublicKey, contextForSpec, EXTRINSIC_MIN_SPEC, initWasm,
|
||||
isReady, keypairFromMnemonic, keypairFromSeed, Scheme, SCHEME_NAME,
|
||||
sign, signatureWithPublicKey, sizes, verify, WormholeBranch, wormholeAddresses, wormholeNullifiers
|
||||
} from '@quantus/crypto';
|
||||
|
||||
let fail = 0;
|
||||
const eq = (l, g, w) => { const ok = String(g) === String(w); if (!ok) fail++;
|
||||
console.log(`${ok ? 'PASS' : 'FAIL'} ${l}`); if (!ok) console.log(` got ${g}\n want ${w}`); };
|
||||
|
||||
eq('initWasm() returns no error', initWasm(), 'null');
|
||||
eq('isReady()', isReady(), true);
|
||||
|
||||
const s65 = sizes(Scheme.MlDsa65);
|
||||
eq('ML-DSA-65 sizes', JSON.stringify(s65), '{"publicKey":1952,"secretKey":4032,"signature":3309,"signatureWithPublicKey":5261}');
|
||||
eq('scheme name', SCHEME_NAME[Scheme.MlDsa65], 'ml-dsa-65');
|
||||
eq('variant byte is the enum value', Scheme.MlDsa87, 0);
|
||||
|
||||
// crystal_alice, via the public API only
|
||||
const pair87 = keypairFromSeed(new Uint8Array(32), Scheme.MlDsa87);
|
||||
eq('crystal_alice account id',
|
||||
Buffer.from(accountFromPublicKey(pair87.publicKey)).toString('hex'),
|
||||
'1883df2ae47d1fd428a6b8237ad7b59cf0facccaacac4541ef7758be44b3c333');
|
||||
|
||||
// HD derivation, dev phrase, ML-DSA-65 default path
|
||||
const DEV = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk';
|
||||
const hd = keypairFromMnemonic(DEV, '', "m/44'/189189'/0'/0'/1'", Scheme.MlDsa65);
|
||||
eq('dev phrase account id (ML-DSA-65)',
|
||||
Buffer.from(accountFromPublicKey(hd.publicKey)).toString('hex'),
|
||||
'f647dbdefebcfcf726ba078a83481ffc6f4f33004fdfb4cedacf5a5391bc8f00');
|
||||
|
||||
// the signing-context boundary
|
||||
const msg = new TextEncoder().encode('extrinsic payload');
|
||||
const ctx = contextForSpec(EXTRINSIC_MIN_SPEC);
|
||||
const sig = sign(msg, hd, ctx, Scheme.MlDsa65);
|
||||
eq('signature length', sig.length, s65.signature);
|
||||
eq('verifies at spec 148', verify(msg, sig, hd.publicKey, ctx, Scheme.MlDsa65), true);
|
||||
eq('does NOT verify at spec 147', verify(msg, sig, hd.publicKey, contextForSpec(147), Scheme.MlDsa65), false);
|
||||
eq('contextForSpec(147) is empty', contextForSpec(147).length, 0);
|
||||
|
||||
// the wire form
|
||||
eq('sig || pk length', signatureWithPublicKey(sig, hd.publicKey).length, s65.signatureWithPublicKey);
|
||||
|
||||
// wormhole: the chain node's TEST_WORMHOLE_ADDRESS (qzpWh4AEtsgCyEbv4WBgFWnB9bcdF2L2jVDuyjXP9mSTyBaeU)
|
||||
const NODE_PHRASE = 'orchard answer curve patient visual flower maze noise retreat penalty cage small earth domain scan pitch bottom crunch theme club client swap slice raven';
|
||||
const wh = wormholeAddresses(NODE_PHRASE, '', 0, WormholeBranch.Receive, 0, 2);
|
||||
eq('wormhole address count', wh.length, 2);
|
||||
eq('wormhole receive 0 is the node test address',
|
||||
Buffer.from(wh[0]).toString('hex'),
|
||||
'dfcfd6e59c75d208e84f54a887537bcf7b04265790ec79960bf49de123404d0e');
|
||||
eq('change branch differs', Buffer.from(wormholeAddresses(NODE_PHRASE, '', 0, WormholeBranch.Change, 0, 1)[0]).toString('hex') !== Buffer.from(wh[0]).toString('hex'), true);
|
||||
|
||||
// nullifiers: shape, determinism, and the cost of a wallet account's precompute
|
||||
const n = wormholeNullifiers(NODE_PHRASE, '', 0, WormholeBranch.Receive, 0, 2, 7, 3);
|
||||
eq('nullifier shape', `${n.length}x${n[0].length}x${n[0][0].length}`, '2x3x32');
|
||||
eq('nullifiers differ by count', Buffer.from(n[0][0]).equals(Buffer.from(n[0][1])), false);
|
||||
eq('nullifiers differ by address', Buffer.from(n[0][0]).equals(Buffer.from(n[1][0])), false);
|
||||
eq('a sub-range agrees', Buffer.from(wormholeNullifiers(NODE_PHRASE, '', 0, WormholeBranch.Receive, 1, 1, 8, 1)[0][0]).toString('hex'), Buffer.from(n[1][1]).toString('hex'));
|
||||
const t0 = performance.now();
|
||||
wormholeNullifiers(NODE_PHRASE, '', 0, WormholeBranch.Receive, 0, 20, 0, 256);
|
||||
wormholeNullifiers(NODE_PHRASE, '', 0, WormholeBranch.Change, 0, 20, 0, 256);
|
||||
console.log(` 40 addresses x 256 counts: ${Math.round(performance.now() - t0)} ms`);
|
||||
|
||||
process.exit(fail ? 1 : 0);
|
||||
@@ -0,0 +1 @@
|
||||
vendor/
|
||||
@@ -0,0 +1,69 @@
|
||||
# Browser probes
|
||||
|
||||
`cargo test` and the consumer test both run in node, and node is neither a
|
||||
browser nor a service worker. These two probes cover what node cannot: does the
|
||||
WASM instantiate with **no DOM**, under the **extension's own CSP**, and what does
|
||||
a cold start cost.
|
||||
|
||||
Build first with `./scripts/build-quantus.sh`, stage `vendor/` (below), then run
|
||||
`node serve.mjs` from this directory.
|
||||
|
||||
## `index.html` + `worker.js` — automated
|
||||
|
||||
A module Worker, served with the exact `extension_pages` CSP from both extension
|
||||
manifests:
|
||||
|
||||
```
|
||||
script-src 'self' 'wasm-unsafe-eval'; object-src 'self'
|
||||
```
|
||||
|
||||
A module Worker has no `window` and no `document`, which is the property that
|
||||
matters — an MV3 service worker has neither either. Result on Firefox:
|
||||
|
||||
```
|
||||
hasDOM: false hasWindow: false
|
||||
initWasm: ok (9.0 ms cold)
|
||||
keygen: 1.0 ms
|
||||
account: matches quantus-cli
|
||||
sign: 3.0 ms (4627 bytes)
|
||||
verify: 1.0 ms ok
|
||||
ctx sep: ok (rejected under spec-147 ctx)
|
||||
```
|
||||
|
||||
9 ms to base64-decode 146 KB, zlib-inflate it to 234 KB and instantiate. That is
|
||||
the number the MV3 lifetime question turns on: a service worker killed between
|
||||
messages pays this on every wake, and 9 ms is not a problem. Those are ML-DSA-87
|
||||
timings — the larger parameter set — so ML-DSA-65 is cheaper still.
|
||||
|
||||
The CSP is genuinely enforced here, not merely declared: an earlier version of
|
||||
this page used an inline `<script>` and Firefox blocked it, which is why
|
||||
`main.js` exists as a separate file.
|
||||
|
||||
## `manifest.json` + `sw.js` — manual
|
||||
|
||||
The real thing: an MV3 extension whose background service worker imports the
|
||||
package at module scope and signs once. Loading an unpacked extension needs an OS
|
||||
file dialog, so this cannot be driven from a script — load it by hand via
|
||||
`chrome://extensions` → Developer mode → Load unpacked, then click the toolbar
|
||||
icon.
|
||||
|
||||
It covers what the Worker probe cannot: `chrome.runtime` messaging, and the
|
||||
actual MV3 kill-and-restart lifecycle rather than a stand-in for it.
|
||||
|
||||
## Staging `vendor/`
|
||||
|
||||
Both probes import from `./vendor/`, which is not checked in. Populate it from a
|
||||
build:
|
||||
|
||||
```sh
|
||||
mkdir -p vendor
|
||||
cp -r ../../build vendor/quantus-crypto
|
||||
cp -r ../../../wasm-util/build vendor/wasm-util
|
||||
sed -i "s|from '@polkadot/wasm-util/base64'|from '../wasm-util/base64.js'|; \
|
||||
s|from '@polkadot/wasm-util/fflate'|from '../wasm-util/fflate.js'|" \
|
||||
vendor/quantus-crypto/init.js
|
||||
```
|
||||
|
||||
The rewrite is needed because a browser cannot resolve bare specifiers. A real
|
||||
extension build does this with a bundler; here it is one `sed` rather than a
|
||||
build step, because the probe exists to test the WASM, not the bundler.
|
||||
@@ -0,0 +1,5 @@
|
||||
<!doctype html><meta charset="utf-8"><title>quantus-crypto worker probe</title>
|
||||
<body style="font:13px ui-monospace,monospace;padding:16px;background:#111;color:#ddd">
|
||||
<h3 style="font:600 14px system-ui">@quantus/crypto in a module Worker under the extension CSP</h3>
|
||||
<pre id="out">running…</pre>
|
||||
<script type="module" src="./main.js"></script>
|
||||
@@ -0,0 +1,3 @@
|
||||
const w = new Worker('./worker.js', { type: 'module' });
|
||||
w.onmessage = (e) => { document.getElementById('out').textContent = e.data; };
|
||||
w.onerror = (e) => { document.getElementById('out').textContent = 'worker error: ' + (e.message || 'see console'); };
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "quantus-crypto MV3 probe",
|
||||
"version": "0.0.1",
|
||||
"description": "Loads @quantus/crypto in an MV3 service worker and signs once.",
|
||||
"background": { "service_worker": "sw.js", "type": "module" },
|
||||
"action": { "default_title": "probe", "default_popup": "popup.html" },
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<!doctype html><meta charset="utf-8"><title>quantus-crypto probe</title>
|
||||
<body style="font:13px system-ui;padding:12px;min-width:380px">
|
||||
<pre id="out">running…</pre>
|
||||
<script type="module" src="popup.js"></script>
|
||||
@@ -0,0 +1,4 @@
|
||||
const out = document.getElementById('out');
|
||||
chrome.runtime.sendMessage({ probe: true }, (r) => {
|
||||
out.textContent = r ? r.text : `no response: ${chrome.runtime.lastError?.message}`;
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import http from 'node:http';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
const types = { '.html': 'text/html', '.js': 'text/javascript', '.json': 'application/json', '.wasm': 'application/wasm' };
|
||||
http.createServer((req, res) => {
|
||||
const p = path.join(process.cwd(), decodeURIComponent(req.url.split('?')[0]));
|
||||
const f = fs.existsSync(p) && fs.statSync(p).isDirectory() ? path.join(p, 'index.html') : p;
|
||||
if (!fs.existsSync(f)) { res.writeHead(404); return res.end('nope'); }
|
||||
res.writeHead(200, {
|
||||
'Content-Type': types[path.extname(f)] || 'application/octet-stream',
|
||||
// exactly the extension_pages CSP from both manifests
|
||||
'Content-Security-Policy': "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
|
||||
});
|
||||
fs.createReadStream(f).pipe(res);
|
||||
}).listen(8731, () => console.log('probe on http://127.0.0.1:8731'));
|
||||
@@ -0,0 +1,52 @@
|
||||
// MV3 service worker. Imports @quantus/crypto at module scope — i.e. on every
|
||||
// cold start, which is what actually needs proving: the worker is killed between
|
||||
// messages and must re-instantiate a 146 KB inlined base64 wasm each time.
|
||||
import {
|
||||
accountFromPublicKey, contextForSpec, initWasm, keypairFromSeed,
|
||||
Scheme, sign, verify
|
||||
} from './vendor/quantus-crypto/index.js';
|
||||
|
||||
const hex = (u8) => [...u8].map((b) => b.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
function probe () {
|
||||
const lines = [];
|
||||
const t0 = performance.now();
|
||||
const err = initWasm();
|
||||
const tInit = performance.now() - t0;
|
||||
|
||||
lines.push(`context: ${typeof window === 'undefined' ? 'service worker (no DOM)' : 'page'}`);
|
||||
lines.push(`initWasm: ${err === null ? 'ok' : 'FAILED — ' + err} (${tInit.toFixed(1)} ms)`);
|
||||
|
||||
if (err) return lines.join('\n');
|
||||
|
||||
const t1 = performance.now();
|
||||
const pair = keypairFromSeed(new Uint8Array(32), Scheme.MlDsa87);
|
||||
const tKeygen = performance.now() - t1;
|
||||
const account = hex(accountFromPublicKey(pair.publicKey));
|
||||
const expected = '1883df2ae47d1fd428a6b8237ad7b59cf0facccaacac4541ef7758be44b3c333';
|
||||
|
||||
lines.push(`keygen: ${tKeygen.toFixed(1)} ms`);
|
||||
lines.push(`account: ${account.slice(0, 24)}… ${account === expected ? 'matches quantus-cli' : 'MISMATCH'}`);
|
||||
|
||||
const msg = new TextEncoder().encode('extrinsic payload');
|
||||
const ctx = contextForSpec(148);
|
||||
const t2 = performance.now();
|
||||
const sig = sign(msg, pair, ctx, Scheme.MlDsa87);
|
||||
const tSign = performance.now() - t2;
|
||||
|
||||
lines.push(`sign: ${tSign.toFixed(1)} ms (${sig.length} bytes)`);
|
||||
lines.push(`verify: ${verify(msg, sig, pair.publicKey, ctx, Scheme.MlDsa87) ? 'ok' : 'FAILED'}`);
|
||||
lines.push(`ctx sep: ${verify(msg, sig, pair.publicKey, contextForSpec(147), Scheme.MlDsa87) ? 'FAILED (verified under wrong ctx)' : 'ok (rejected under spec 147 ctx)'}`);
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
chrome.runtime.onMessage.addListener((_m, _s, respond) => {
|
||||
try {
|
||||
respond({ text: probe() });
|
||||
} catch (e) {
|
||||
respond({ text: `threw: ${e && e.message ? e.message : e}\n${e && e.stack ? e.stack : ''}` });
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
// A module Worker: no DOM, no window, same CSP as the extension pages.
|
||||
import { accountFromPublicKey, contextForSpec, initWasm, keypairFromSeed, Scheme, sign, verify } from './vendor/quantus-crypto/index.js';
|
||||
|
||||
const hex = (u8) => [...u8].map((b) => b.toString(16).padStart(2, '0')).join('');
|
||||
const lines = [];
|
||||
const t0 = performance.now();
|
||||
const err = initWasm();
|
||||
const tInit = performance.now() - t0;
|
||||
|
||||
lines.push(`hasDOM: ${typeof document !== 'undefined'} hasWindow: ${typeof window !== 'undefined'}`);
|
||||
lines.push(`initWasm: ${err === null ? 'ok' : 'FAILED - ' + err} (${tInit.toFixed(1)} ms cold)`);
|
||||
|
||||
if (err === null) {
|
||||
const t1 = performance.now();
|
||||
const pair = keypairFromSeed(new Uint8Array(32), Scheme.MlDsa87);
|
||||
const tKeygen = performance.now() - t1;
|
||||
const account = hex(accountFromPublicKey(pair.publicKey));
|
||||
lines.push(`keygen: ${tKeygen.toFixed(1)} ms`);
|
||||
lines.push(`account: ${account === '1883df2ae47d1fd428a6b8237ad7b59cf0facccaacac4541ef7758be44b3c333' ? 'matches quantus-cli' : 'MISMATCH ' + account}`);
|
||||
const msg = new TextEncoder().encode('extrinsic payload');
|
||||
const ctx = contextForSpec(148);
|
||||
const t2 = performance.now();
|
||||
const sig = sign(msg, pair, ctx, Scheme.MlDsa87);
|
||||
const tSign = performance.now() - t2;
|
||||
const t3 = performance.now();
|
||||
const ok = verify(msg, sig, pair.publicKey, ctx, Scheme.MlDsa87);
|
||||
const tVerify = performance.now() - t3;
|
||||
lines.push(`sign: ${tSign.toFixed(1)} ms (${sig.length} bytes)`);
|
||||
lines.push(`verify: ${tVerify.toFixed(1)} ms ${ok ? 'ok' : 'FAILED'}`);
|
||||
lines.push(`ctx sep: ${verify(msg, sig, pair.publicKey, contextForSpec(147), Scheme.MlDsa87) ? 'FAILED' : 'ok (rejected under spec-147 ctx)'}`);
|
||||
}
|
||||
postMessage(lines.join('\n'));
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "..",
|
||||
"composite": false,
|
||||
"declaration": true,
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src",
|
||||
"emitDeclarationOnly": false
|
||||
},
|
||||
"exclude": [
|
||||
"**/*.spec.ts"
|
||||
],
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# @polkadot/wasm-bridge
|
||||
|
||||
A re-usable bridge between JS & WASM interfaces. It is used internally by `@polkadot/wasm-crypto`.
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"bugs": "https://github.com/polkadot-js/wasm/issues",
|
||||
"description": "A bridge layer between JS and Wasm",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/wasm/tree/master/packages/wasm-bridge#readme",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@polkadot/wasm-bridge",
|
||||
"repository": {
|
||||
"directory": "packages/wasm-bridge",
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/wasm.git"
|
||||
},
|
||||
"sideEffects": [
|
||||
"./packageDetect.js",
|
||||
"./packageDetect.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "7.5.4",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@polkadot/wasm-util": "7.5.4",
|
||||
"tslib": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util": "^14.0.1",
|
||||
"@polkadot/x-randomvalues": "^14.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "*",
|
||||
"@polkadot/x-randomvalues": "*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// A number of functions are "unsafe" and purposefully so - it is
|
||||
// assumed that where the bridge is used, it is correctly wrapped
|
||||
// in a safeguard (see withWasm in the wasm-crypto package) which
|
||||
// then ensures that the internal wasm instance here is available
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import type { BridgeBase, InitFn, InitPromise, WasmBaseInstance, WasmImports } from './types.js';
|
||||
|
||||
import { stringToU8a, u8aToString } from '@polkadot/util';
|
||||
|
||||
import { Wbg } from './wbg.js';
|
||||
|
||||
/**
|
||||
* @name Bridge
|
||||
* @description
|
||||
* Creates a bridge between the JS and WASM environments.
|
||||
*
|
||||
* For any bridge it is passed an function which is then called internally at the
|
||||
* time of initialization. This affectively implements the layer between WASM and
|
||||
* the native environment, providing all the plumbing needed for the Wbg classes.
|
||||
*/
|
||||
export class Bridge<C extends WasmBaseInstance> implements BridgeBase<C> {
|
||||
readonly #createWasm: InitFn<C>;
|
||||
readonly #heap: unknown[];
|
||||
readonly #wbg: WasmImports;
|
||||
|
||||
#cachegetInt32: Int32Array | null;
|
||||
#cachegetUint8: Uint8Array | null;
|
||||
#heapNext: number;
|
||||
#wasm: C | null;
|
||||
#wasmError: string | null;
|
||||
#wasmPromise: InitPromise<C> | null;
|
||||
#type: 'asm' | 'wasm' | 'none';
|
||||
|
||||
constructor (createWasm: InitFn<C>) {
|
||||
this.#createWasm = createWasm;
|
||||
this.#cachegetInt32 = null;
|
||||
this.#cachegetUint8 = null;
|
||||
this.#heap = new Array(32)
|
||||
.fill(undefined)
|
||||
.concat(undefined, null, true, false);
|
||||
this.#heapNext = this.#heap.length;
|
||||
this.#type = 'none';
|
||||
this.#wasm = null;
|
||||
this.#wasmError = null;
|
||||
this.#wasmPromise = null;
|
||||
this.#wbg = { ...new Wbg(this) };
|
||||
}
|
||||
|
||||
/** @description Returns the init error */
|
||||
get error (): string | null {
|
||||
return this.#wasmError;
|
||||
}
|
||||
|
||||
/** @description Returns the init type */
|
||||
get type (): 'asm' | 'wasm' | 'none' {
|
||||
return this.#type;
|
||||
}
|
||||
|
||||
/** @description Returns the created wasm interface */
|
||||
get wasm (): C | null {
|
||||
return this.#wasm;
|
||||
}
|
||||
|
||||
/** @description Performs the wasm initialization */
|
||||
async init (createWasm?: InitFn<C>): Promise<C | null> {
|
||||
if (!this.#wasmPromise || createWasm) {
|
||||
this.#wasmPromise = (createWasm || this.#createWasm)(this.#wbg);
|
||||
}
|
||||
|
||||
const { error, type, wasm } = await this.#wasmPromise;
|
||||
|
||||
this.#type = type;
|
||||
this.#wasm = wasm;
|
||||
this.#wasmError = error;
|
||||
|
||||
return this.#wasm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Gets an object from the heap
|
||||
*/
|
||||
getObject (idx: number): unknown {
|
||||
return this.#heap[idx];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Removes an object from the heap
|
||||
*/
|
||||
dropObject (idx: number) {
|
||||
if (idx < 36) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#heap[idx] = this.#heapNext;
|
||||
this.#heapNext = idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieves and removes an object to the heap
|
||||
*/
|
||||
takeObject (idx: number): unknown {
|
||||
const ret = this.getObject(idx);
|
||||
|
||||
this.dropObject(idx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Adds an object to the heap
|
||||
*/
|
||||
addObject (obj: unknown): number {
|
||||
if (this.#heapNext === this.#heap.length) {
|
||||
this.#heap.push(this.#heap.length + 1);
|
||||
}
|
||||
|
||||
const idx = this.#heapNext;
|
||||
|
||||
this.#heapNext = this.#heap[idx] as number;
|
||||
this.#heap[idx] = obj;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieve an Int32 in the WASM interface
|
||||
*/
|
||||
getInt32 (): Int32Array {
|
||||
if (this.#cachegetInt32 === null || this.#cachegetInt32.buffer !== this.#wasm!.memory.buffer) {
|
||||
this.#cachegetInt32 = new Int32Array(this.#wasm!.memory.buffer);
|
||||
}
|
||||
|
||||
return this.#cachegetInt32;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieve an Uint8Array in the WASM interface
|
||||
*/
|
||||
getUint8 (): Uint8Array {
|
||||
if (this.#cachegetUint8 === null || this.#cachegetUint8.buffer !== this.#wasm!.memory.buffer) {
|
||||
this.#cachegetUint8 = new Uint8Array(this.#wasm!.memory.buffer);
|
||||
}
|
||||
|
||||
return this.#cachegetUint8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieves an Uint8Array in the WASM interface
|
||||
*/
|
||||
getU8a (ptr: number, len: number): Uint8Array {
|
||||
return this.getUint8().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieves a string in the WASM interface
|
||||
*/
|
||||
getString (ptr: number, len: number): string {
|
||||
return u8aToString(this.getU8a(ptr, len));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Allocates an Uint8Array in the WASM interface
|
||||
*/
|
||||
allocU8a (arg: Uint8Array): [number, number] {
|
||||
const ptr = this.#wasm!.__wbindgen_malloc(arg.length * 1);
|
||||
|
||||
this.getUint8().set(arg, ptr / 1);
|
||||
|
||||
return [ptr, arg.length];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Allocates a string in the WASM interface
|
||||
*/
|
||||
allocString (arg: string): [number, number] {
|
||||
return this.allocU8a(stringToU8a(arg));
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieves an Uint8Array from the WASM interface
|
||||
*/
|
||||
resultU8a (): Uint8Array {
|
||||
const r0 = this.getInt32()[8 / 4 + 0];
|
||||
const r1 = this.getInt32()[8 / 4 + 1];
|
||||
const ret = this.getU8a(r0, r1).slice();
|
||||
|
||||
this.#wasm!.__wbindgen_free(r0, r1 * 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @description Retrieve a string from the WASM interface
|
||||
*/
|
||||
resultString (): string {
|
||||
return u8aToString(this.resultU8a());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export * from './bridge.js';
|
||||
export * from './init.js';
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './packageDetect.js';
|
||||
|
||||
export * from './bundle.js';
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { InitFn, InitPromise, InitResult, WasmBaseInstance, WasmImports } from './types.js';
|
||||
|
||||
/**
|
||||
* @name createWasmFn
|
||||
* @description
|
||||
* Create a WASM (or ASM.js) creator interface based on the supplied information.
|
||||
*
|
||||
* It will attempt to create a WASM interface first and if this fails or is not available in
|
||||
* the environment, will fallback to attempting to create an ASM.js interface.
|
||||
*/
|
||||
export function createWasmFn <C extends WasmBaseInstance> (root: 'crypto', wasmBytes: null | Uint8Array, asmFn: null | ((wbg: WasmImports) => C)): InitFn<C> {
|
||||
return async (wbg: WasmImports): InitPromise<C> => {
|
||||
const result: InitResult<C> = {
|
||||
error: null,
|
||||
type: 'none',
|
||||
wasm: null
|
||||
};
|
||||
|
||||
try {
|
||||
if (!wasmBytes?.length) {
|
||||
throw new Error('No WebAssembly provided for initialization');
|
||||
} else if (typeof WebAssembly !== 'object' || typeof WebAssembly.instantiate !== 'function') {
|
||||
throw new Error('WebAssembly is not available in your environment');
|
||||
}
|
||||
|
||||
const source = await WebAssembly.instantiate(wasmBytes, { wbg });
|
||||
|
||||
result.wasm = source.instance.exports as unknown as C;
|
||||
result.type = 'wasm';
|
||||
} catch (error) {
|
||||
// if we have a valid supplied asm.js, return that
|
||||
if (typeof asmFn === 'function') {
|
||||
result.wasm = asmFn(wbg);
|
||||
result.type = 'asm';
|
||||
} else {
|
||||
result.error = `FATAL: Unable to initialize @polkadot/wasm-${root}:: ${(error as Error).message}`;
|
||||
|
||||
console.error(result.error);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export * from './index.js';
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
// (packageInfo imports will be kept as-is, user-editable)
|
||||
|
||||
import { detectPackage } from '@polkadot/util';
|
||||
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
|
||||
detectPackage(packageInfo, null, []);
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
|
||||
export const packageInfo = { name: '@polkadot/wasm-bridge', path: 'auto', type: 'auto', version: '7.5.4' };
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Use non-strong types instead of WasmImports which may not
|
||||
// be available as part of the TS environment types (it needs dom)
|
||||
export type WasmImports = Record<string, (...args: never[]) => unknown>;
|
||||
|
||||
// Use non-strong types instead of WebAssembly.Memory which may not
|
||||
// be available as part of the TS environment types (it needs dom)
|
||||
export interface WasmMemory { buffer: ArrayBuffer }
|
||||
|
||||
export declare interface InitResult<C extends WasmBaseInstance> {
|
||||
error: string | null;
|
||||
type: 'asm' | 'wasm' | 'none';
|
||||
wasm: C | null;
|
||||
}
|
||||
|
||||
export type InitPromise <C extends WasmBaseInstance> = Promise<InitResult<C>>;
|
||||
|
||||
export type InitFn <C extends WasmBaseInstance> = (wbg: WasmImports) => InitPromise<C>;
|
||||
|
||||
export interface BridgeBase<C extends WasmBaseInstance> extends InitResult<C> {
|
||||
init (createWasm?: InitFn<C>): Promise<C | null>;
|
||||
getObject (idx: number): unknown;
|
||||
dropObject (idx: number): void;
|
||||
takeObject (idx: number): unknown;
|
||||
addObject (obj: unknown): number;
|
||||
getInt32 (): Int32Array;
|
||||
getUint8 (): Uint8Array;
|
||||
getU8a (ptr: number, len: number): Uint8Array;
|
||||
getString (ptr: number, len: number): string;
|
||||
allocU8a (arg: Uint8Array): [number, number];
|
||||
allocString (arg: string): [number, number];
|
||||
resultU8a (): Uint8Array;
|
||||
resultString (): string;
|
||||
}
|
||||
|
||||
export interface WasmBindGen {
|
||||
__wbindgen_exn_store (a: number): void;
|
||||
__wbindgen_free (a: number, b: number): void;
|
||||
__wbindgen_malloc (a: number): number;
|
||||
__wbindgen_realloc (a: number, b: number, c: number): number;
|
||||
}
|
||||
|
||||
export interface WasmBaseInstance extends WasmBindGen {
|
||||
memory: WasmMemory;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-bridge authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { BridgeBase, WasmBaseInstance } from './types.js';
|
||||
|
||||
import { getRandomValues } from '@polkadot/x-randomvalues';
|
||||
|
||||
const DEFAULT_CRYPTO = { getRandomValues };
|
||||
const DEFAULT_SELF = { crypto: DEFAULT_CRYPTO };
|
||||
|
||||
/**
|
||||
* @name Wbg
|
||||
* @description
|
||||
* This defines the internal interfaces that wasm-bindgen used to communicate
|
||||
* with the host layer. None of these functions are available to the user, rather
|
||||
* they are called internally from the WASM code itself.
|
||||
*
|
||||
* The interfaces here are exposed in the imports on the created WASM interfaces.
|
||||
*
|
||||
* Internally the implementation does a thin layer into the supplied bridge.
|
||||
*/
|
||||
export class Wbg<C extends WasmBaseInstance> {
|
||||
readonly #bridge: BridgeBase<C>;
|
||||
|
||||
constructor (bridge: BridgeBase<C>) {
|
||||
this.#bridge = bridge;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
abort = (): never => {
|
||||
throw new Error('abort');
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbindgen_is_undefined = (idx: number): boolean => {
|
||||
return this.#bridge.getObject(idx) === undefined;
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbindgen_throw = (ptr: number, len: number): boolean => {
|
||||
throw new Error(this.#bridge.getString(ptr, len));
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_self_1b7a39e3a92c949c = (): number => {
|
||||
return this.#bridge.addObject(DEFAULT_SELF);
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_require_604837428532a733 = (ptr: number, len: number): never => {
|
||||
throw new Error(`Unable to require ${this.#bridge.getString(ptr, len)}`);
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_crypto_968f1772287e2df0 = (_idx: number): number => {
|
||||
return this.#bridge.addObject(DEFAULT_CRYPTO);
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_getRandomValues_a3d34b4fee3c2869 = (_idx: number): number => {
|
||||
return this.#bridge.addObject(DEFAULT_CRYPTO.getRandomValues);
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_getRandomValues_f5e14ab7ac8e995d = (_arg0: number, ptr: number, len: number): void => {
|
||||
DEFAULT_CRYPTO.getRandomValues(this.#bridge.getU8a(ptr, len));
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbg_randomFillSync_d5bd2d655fdf256a = (_idx: number, _ptr: number, _len: number): never => {
|
||||
throw new Error('randomFillsync is not available');
|
||||
|
||||
// getObject(idx).randomFillSync(getU8a(ptr, len));
|
||||
};
|
||||
|
||||
/** @internal */
|
||||
__wbindgen_object_drop_ref = (idx: number): void => {
|
||||
this.#bridge.takeObject(idx);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "..",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"exclude": [
|
||||
"**/mod.ts"
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
## @polkadot/wasm-crypto-asmjs
|
||||
|
||||
Asm.js build outputs.
|
||||
@@ -1,19 +1,32 @@
|
||||
{
|
||||
"name": "@polkadot/wasm-crypto-asmjs",
|
||||
"version": "3.2.1",
|
||||
"description": "Asm.js content for wasm-crypto",
|
||||
"browser": "empty.js",
|
||||
"main": "empty.js",
|
||||
"module": "empty.mjs",
|
||||
"react-native": "data.js",
|
||||
"sideEffects": false,
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"maintainers": [],
|
||||
"contributors": [],
|
||||
"license": "Apache-2.0",
|
||||
"bugs": "https://github.com/polkadot-js/wasm/issues",
|
||||
"homepage": "https://github.com/polkadot-js/wasm",
|
||||
"description": "Asm.js content for wasm-crypto",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/wasm/tree/master/packages/wasm-crypto-asmjs#readme",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@polkadot/wasm-crypto-asmjs",
|
||||
"repository": {
|
||||
"directory": "packages/wasm-crypto-asmjs",
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/wasm.git"
|
||||
},
|
||||
"sideEffects": [
|
||||
"./packageDetect.js",
|
||||
"./packageDetect.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "7.5.4",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5"
|
||||
"tslib": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util": "^14.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export { asmJsInit } from './cjs/data.js';
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-wasm authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const data = require('../data.js');
|
||||
|
||||
module.exports = data;
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export declare const asmJsInit: null;
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
const asmJsInit = null;
|
||||
|
||||
exports.asmJsInit = asmJsInit;
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export declare const asmJsInit: null;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2019-2021 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const asmJsInit = null;
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright 2019-2021 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export const asmJsInit = null;
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './packageDetect.js';
|
||||
|
||||
export * from './bundle.js';
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export * from './index.js';
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
// (packageInfo imports will be kept as-is, user-editable)
|
||||
|
||||
import { detectPackage } from '@polkadot/util';
|
||||
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
|
||||
detectPackage(packageInfo, null, []);
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto-asmjs authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
|
||||
export const packageInfo = { name: '@polkadot/wasm-crypto-asmjs', path: 'auto', type: 'auto', version: '7.5.4' };
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "..",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"exclude": [
|
||||
"**/mod.ts"
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
## @polkadot/wasm-crypto-init
|
||||
|
||||
Internal `@polkadot/wasm-crypto` initialization functions for Browser, Node & RN.
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"author": "Jaco Greeff <jacogr@gmail.com>",
|
||||
"bugs": "https://github.com/polkadot-js/wasm/issues",
|
||||
"description": "Init handlers for wasm-crypto",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"homepage": "https://github.com/polkadot-js/wasm/tree/master/packages/wasm-crypto-init#readme",
|
||||
"license": "Apache-2.0",
|
||||
"name": "@polkadot/wasm-crypto-init",
|
||||
"repository": {
|
||||
"directory": "packages/wasm-crypto-init",
|
||||
"type": "git",
|
||||
"url": "https://github.com/polkadot-js/wasm.git"
|
||||
},
|
||||
"sideEffects": [
|
||||
"./packageDetect.js",
|
||||
"./packageDetect.cjs"
|
||||
],
|
||||
"type": "module",
|
||||
"version": "7.5.4",
|
||||
"browser": "wasm.js",
|
||||
"main": "wasm.js",
|
||||
"react-native": "asm.js",
|
||||
"dependencies": {
|
||||
"@polkadot/wasm-bridge": "7.5.4",
|
||||
"@polkadot/wasm-crypto-asmjs": "7.5.4",
|
||||
"@polkadot/wasm-crypto-wasm": "7.5.4",
|
||||
"@polkadot/wasm-util": "7.5.4",
|
||||
"tslib": "^2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@polkadot/util": "^14.0.1",
|
||||
"@polkadot/x-randomvalues": "^14.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@polkadot/util": "*",
|
||||
"@polkadot/x-randomvalues": "*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { InitFn } from '@polkadot/wasm-bridge/types';
|
||||
import type { WasmCryptoInstance } from './types.js';
|
||||
|
||||
import { createWasmFn } from '@polkadot/wasm-bridge';
|
||||
import { asmJsInit } from '@polkadot/wasm-crypto-asmjs';
|
||||
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
|
||||
/**
|
||||
* @name createWasm
|
||||
* @description
|
||||
* Creates an interface using only ASM.js
|
||||
*/
|
||||
export const createWasm: InitFn<WasmCryptoInstance> = /*#__PURE__*/ createWasmFn('crypto', null, asmJsInit);
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { InitFn } from '@polkadot/wasm-bridge/types';
|
||||
import type { WasmCryptoInstance } from './types.js';
|
||||
|
||||
import { createWasmFn } from '@polkadot/wasm-bridge';
|
||||
import { asmJsInit } from '@polkadot/wasm-crypto-asmjs';
|
||||
import { wasmBytes } from '@polkadot/wasm-crypto-wasm';
|
||||
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
|
||||
/**
|
||||
* @name createWasm
|
||||
* @description
|
||||
* Creates an interface using WASM and a fallback ASM.js
|
||||
*/
|
||||
export const createWasm: InitFn<WasmCryptoInstance> = /*#__PURE__*/ createWasmFn('crypto', wasmBytes, asmJsInit);
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export * from './wasm.js';
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
export * from './wasm.js';
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { InitFn } from '@polkadot/wasm-bridge/types';
|
||||
import type { WasmCryptoInstance } from './types.js';
|
||||
|
||||
import { createWasmFn } from '@polkadot/wasm-bridge';
|
||||
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
|
||||
/**
|
||||
* @name createWasm
|
||||
* @description
|
||||
* Creates an interface using no WASM and no ASM.js
|
||||
*/
|
||||
export const createWasm: InitFn<WasmCryptoInstance> = /*#__PURE__*/ createWasmFn('crypto', null, null);
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
// (packageInfo imports will be kept as-is, user-editable)
|
||||
|
||||
import { detectPackage } from '@polkadot/util';
|
||||
import { packageInfo as bridgeInfo } from '@polkadot/wasm-bridge/packageInfo';
|
||||
import { packageInfo as asmInfo } from '@polkadot/wasm-crypto-asmjs/packageInfo';
|
||||
import { packageInfo as wasmInfo } from '@polkadot/wasm-crypto-wasm/packageInfo';
|
||||
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
|
||||
detectPackage(packageInfo, null, [asmInfo, bridgeInfo, wasmInfo]);
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @polkadot/dev
|
||||
|
||||
export const packageInfo = { name: '@polkadot/wasm-crypto-init', path: 'auto', type: 'auto', version: '7.5.4' };
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { WasmBaseInstance } from '@polkadot/wasm-bridge/types';
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
// wasm-pack build output (formatted) from pkg/wasm_bg.d.ts
|
||||
export interface WasmCryptoInstance extends WasmBaseInstance {
|
||||
// exposed functions
|
||||
|
||||
ext_bip39_generate(resLen: 8, words: number): void;
|
||||
|
||||
ext_bip39_to_entropy(resLen: 8, ptrPhrase: number, lenPhrase: number): void;
|
||||
|
||||
ext_bip39_to_mini_secret(resLen: 8, ptrPhrase: number, lenPhrase: number, ptrPass: number, lenPass: number): void;
|
||||
|
||||
ext_bip39_to_seed(resLen: 8, ptrPhrase: number, lenPhrase: number, ptrPass: number, lenPass: number): void;
|
||||
|
||||
ext_bip39_validate(ptrPhrase: number, lenPhrase: number): number;
|
||||
|
||||
ext_ed_from_seed(resLen: 8, ptrSeed: number, lenSeed: number): void;
|
||||
|
||||
ext_ed_sign(resLen: 8, ptrPub: number, lenPub: number, ptrSec: number, lenSec: number, ptrMsg: number, lenMsg: number): void;
|
||||
|
||||
ext_ed_verify(ptrSig: number, lenSig: number, ptrMsg: number, lenMsg: number, ptrPub: number, lenPub: number): number;
|
||||
|
||||
ext_blake2b(resLen: 8, ptrData: number, lenData: number, ptrKey: number, lenKey: number, size: number): void;
|
||||
|
||||
ext_hmac_sha256(resLen: 8, ptrKey: number, lenKey: number, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_hmac_sha512(resLen: 8, ptrKey: number, lenKey: number, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_keccak256(resLen: 8, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_keccak512(resLen: 8, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_pbkdf2(resLen: 8, ptrData: number, lenData: number, ptrSalt: number, lenSalt: number, rounds: number): void;
|
||||
|
||||
ext_scrypt(resLen: 8, ptrPass: number, lenPass: number, ptrSalt: number, lenSalt: number, log2n: number, r: number, p: number): void;
|
||||
|
||||
ext_sha256(resLen: 8, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_sha512(resLen: 8, ptrData: number, lenData: number): void;
|
||||
|
||||
ext_twox(resLen: 8, ptrData: number, lenData: number, rounds: number): void;
|
||||
|
||||
ext_secp_from_seed(reslen: 8, ptrSec: number, lenSec: number): void;
|
||||
|
||||
ext_secp_pub_compress(resLen: 8, ptrPub: number, lenPub: number): void;
|
||||
|
||||
ext_secp_pub_expand(resLen: 8, ptrPub: number, lenPub: number): void;
|
||||
|
||||
ext_secp_recover(resLen: 8, ptrMsgHash: number, lenMsgHash: number, ptrSig: number, lenSig: number, recovery: number): void;
|
||||
|
||||
ext_secp_sign(resLen: 8, ptrMsgHash: number, lenMsgHash: number, ptrSec: number, lenSec: number): void;
|
||||
|
||||
ext_sr_derive_keypair_hard(resLen: 8, ptrPair: number, lenPair: number, ptrCc: number, lenCc: number): void;
|
||||
|
||||
ext_sr_derive_keypair_soft(resLen: 8, ptrPub: number, lenPub: number, ptrCc: number, lenCc: number): void;
|
||||
|
||||
ext_sr_derive_public_soft(resLen: 8, ptrPub: number, lenPub: number, ptrCc: number, lenCc: number): void;
|
||||
|
||||
ext_sr_from_seed(resLen: 8, ptrSeed: number, lenSeed: number): void;
|
||||
|
||||
ext_sr_sign(resLen: 8, ptrPub: number, lenPub: number, ptrSec: number, lenSec: number, ptrMsg: number, lenMsg: number): void;
|
||||
|
||||
ext_sr_verify(ptrSig: number, lenSig: number, ptrMsg: number, lenMsg: number, ptrPub: number, lenPub: number): number;
|
||||
|
||||
ext_sr_agree(resLen: 8, ptrPub: number, lenPub: number, ptrSec: number, lenSec: number): void;
|
||||
|
||||
ext_vrf_sign(resLen: 8, ptrSec: number, lenSec: number, ptrCtx: number, lenCtx: number, ptrMsg: number, lenMsg: number, ptrExtra: number, lenExtra: number): void;
|
||||
|
||||
ext_vrf_verify(ptrPub: number, lenPub: number, ptrCtx: number, lenCtx: number, ptrMsg: number, lenMsg: number, ptrExtra: number, lenExtra: number, ptrProof: number, lenProof: number): number;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019-2026 @polkadot/wasm-crypto-init authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { InitFn } from '@polkadot/wasm-bridge/types';
|
||||
import type { WasmCryptoInstance } from './types.js';
|
||||
|
||||
import { createWasmFn } from '@polkadot/wasm-bridge';
|
||||
import { wasmBytes } from '@polkadot/wasm-crypto-wasm';
|
||||
|
||||
export { packageInfo } from './packageInfo.js';
|
||||
|
||||
/**
|
||||
* @name createWasm
|
||||
* @description
|
||||
* Creates an interface using only WASM
|
||||
*/
|
||||
export const createWasm: InitFn<WasmCryptoInstance> = /*#__PURE__*/ createWasmFn('crypto', wasmBytes, null);
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "..",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"exclude": [
|
||||
"**/mod.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../wasm-bridge/tsconfig.build.json" },
|
||||
{ "path": "../wasm-crypto-asmjs/tsconfig.build.json" },
|
||||
{ "path": "../wasm-crypto-wasm/tsconfig.build.json" }
|
||||
]
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user