@aztec/bb.js 0.0.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +3 -0
  2. package/dest/async_map/index.d.ts +10 -0
  3. package/dest/async_map/index.d.ts.map +1 -0
  4. package/dest/async_map/index.js +16 -0
  5. package/dest/barretenberg-threads.wasm +0 -0
  6. package/dest/barretenberg.wasm +0 -0
  7. package/dest/barretenberg_api/blake2s.test.d.ts +2 -0
  8. package/dest/barretenberg_api/blake2s.test.d.ts.map +1 -0
  9. package/dest/barretenberg_api/blake2s.test.js +30 -0
  10. package/dest/barretenberg_api/common.test.d.ts +2 -0
  11. package/dest/barretenberg_api/common.test.d.ts.map +1 -0
  12. package/dest/barretenberg_api/common.test.js +18 -0
  13. package/dest/barretenberg_api/index.d.ts +101 -0
  14. package/dest/barretenberg_api/index.d.ts.map +1 -0
  15. package/dest/barretenberg_api/index.js +371 -0
  16. package/dest/barretenberg_api/pedersen.test.d.ts +2 -0
  17. package/dest/barretenberg_api/pedersen.test.d.ts.map +1 -0
  18. package/dest/barretenberg_api/pedersen.test.js +69 -0
  19. package/dest/barretenberg_api/schnorr.test.d.ts +2 -0
  20. package/dest/barretenberg_api/schnorr.test.d.ts.map +1 -0
  21. package/dest/barretenberg_api/schnorr.test.js +113 -0
  22. package/dest/barretenberg_binder/heap_allocator.d.ts +22 -0
  23. package/dest/barretenberg_binder/heap_allocator.d.ts.map +1 -0
  24. package/dest/barretenberg_binder/heap_allocator.js +59 -0
  25. package/dest/barretenberg_binder/heap_allocator_sync.d.ts +22 -0
  26. package/dest/barretenberg_binder/heap_allocator_sync.d.ts.map +1 -0
  27. package/dest/barretenberg_binder/heap_allocator_sync.js +58 -0
  28. package/dest/barretenberg_binder/index.d.ts +32 -0
  29. package/dest/barretenberg_binder/index.d.ts.map +1 -0
  30. package/dest/barretenberg_binder/index.js +73 -0
  31. package/dest/barretenberg_wasm/barretenberg_wasm.d.ts +49 -0
  32. package/dest/barretenberg_wasm/barretenberg_wasm.d.ts.map +1 -0
  33. package/dest/barretenberg_wasm/barretenberg_wasm.js +190 -0
  34. package/dest/barretenberg_wasm/barretenberg_wasm.test.d.ts +2 -0
  35. package/dest/barretenberg_wasm/barretenberg_wasm.test.d.ts.map +1 -0
  36. package/dest/barretenberg_wasm/barretenberg_wasm.test.js +43 -0
  37. package/dest/barretenberg_wasm/browser/index.d.ts +8 -0
  38. package/dest/barretenberg_wasm/browser/index.d.ts.map +1 -0
  39. package/dest/barretenberg_wasm/browser/index.js +26 -0
  40. package/dest/barretenberg_wasm/browser/worker.d.ts +2 -0
  41. package/dest/barretenberg_wasm/browser/worker.d.ts.map +1 -0
  42. package/dest/barretenberg_wasm/browser/worker.js +11 -0
  43. package/dest/barretenberg_wasm/index.d.ts +2 -0
  44. package/dest/barretenberg_wasm/index.d.ts.map +1 -0
  45. package/dest/barretenberg_wasm/index.js +2 -0
  46. package/dest/barretenberg_wasm/node/index.d.ts +17 -0
  47. package/dest/barretenberg_wasm/node/index.d.ts.map +1 -0
  48. package/dest/barretenberg_wasm/node/index.js +40 -0
  49. package/dest/barretenberg_wasm/node/node_endpoint.d.ts +8 -0
  50. package/dest/barretenberg_wasm/node/node_endpoint.d.ts.map +1 -0
  51. package/dest/barretenberg_wasm/node/node_endpoint.js +28 -0
  52. package/dest/barretenberg_wasm/node/worker.d.ts +2 -0
  53. package/dest/barretenberg_wasm/node/worker.d.ts.map +1 -0
  54. package/dest/barretenberg_wasm/node/worker.js +9 -0
  55. package/dest/barretenberg_wasm.js +2 -0
  56. package/dest/barretenberg_wasm.js.LICENSE.txt +5 -0
  57. package/dest/bigint-array/index.d.ts +3 -0
  58. package/dest/bigint-array/index.d.ts.map +1 -0
  59. package/dest/bigint-array/index.js +21 -0
  60. package/dest/bindgen/function_declaration.d.ts +11 -0
  61. package/dest/bindgen/function_declaration.d.ts.map +1 -0
  62. package/dest/bindgen/function_declaration.js +2 -0
  63. package/dest/bindgen/index.d.ts +2 -0
  64. package/dest/bindgen/index.d.ts.map +1 -0
  65. package/dest/bindgen/index.js +15 -0
  66. package/dest/bindgen/mappings.d.ts +4 -0
  67. package/dest/bindgen/mappings.d.ts.map +1 -0
  68. package/dest/bindgen/mappings.js +63 -0
  69. package/dest/bindgen/rust.d.ts +2 -0
  70. package/dest/bindgen/rust.d.ts.map +1 -0
  71. package/dest/bindgen/rust.js +43 -0
  72. package/dest/bindgen/to_camel_case.d.ts +2 -0
  73. package/dest/bindgen/to_camel_case.d.ts.map +1 -0
  74. package/dest/bindgen/to_camel_case.js +11 -0
  75. package/dest/bindgen/typescript.d.ts +2 -0
  76. package/dest/bindgen/typescript.d.ts.map +1 -0
  77. package/dest/bindgen/typescript.js +80 -0
  78. package/dest/crs/browser/cached_net_crs.d.ts +25 -0
  79. package/dest/crs/browser/cached_net_crs.d.ts.map +1 -0
  80. package/dest/crs/browser/cached_net_crs.js +54 -0
  81. package/dest/crs/browser/index.d.ts +2 -0
  82. package/dest/crs/browser/index.d.ts.map +1 -0
  83. package/dest/crs/browser/index.js +2 -0
  84. package/dest/crs/index.d.ts +2 -0
  85. package/dest/crs/index.d.ts.map +1 -0
  86. package/dest/crs/index.js +2 -0
  87. package/dest/crs/net_crs.d.ts +36 -0
  88. package/dest/crs/net_crs.d.ts.map +1 -0
  89. package/dest/crs/net_crs.js +59 -0
  90. package/dest/crs/node/file_crs.d.ts +37 -0
  91. package/dest/crs/node/file_crs.d.ts.map +1 -0
  92. package/dest/crs/node/file_crs.js +51 -0
  93. package/dest/crs/node/index.d.ts +31 -0
  94. package/dest/crs/node/index.d.ts.map +1 -0
  95. package/dest/crs/node/index.js +41 -0
  96. package/dest/examples/simple.rawtest.d.ts +2 -0
  97. package/dest/examples/simple.rawtest.d.ts.map +1 -0
  98. package/dest/examples/simple.rawtest.js +24 -0
  99. package/dest/examples/simple.test.d.ts +2 -0
  100. package/dest/examples/simple.test.d.ts.map +1 -0
  101. package/dest/examples/simple.test.js +22 -0
  102. package/dest/factory/index.d.ts +21 -0
  103. package/dest/factory/index.d.ts.map +1 -0
  104. package/dest/factory/index.js +34 -0
  105. package/dest/index.d.ts +4 -0
  106. package/dest/index.d.ts.map +1 -0
  107. package/dest/index.html +1 -0
  108. package/dest/index.js +4 -0
  109. package/dest/main-dev.d.ts +3 -0
  110. package/dest/main-dev.d.ts.map +1 -0
  111. package/dest/main-dev.js +3 -0
  112. package/dest/main.d.ts +10 -0
  113. package/dest/main.d.ts.map +1 -0
  114. package/dest/main.js +288 -0
  115. package/dest/random/browser/index.d.ts +2 -0
  116. package/dest/random/browser/index.d.ts.map +1 -0
  117. package/dest/random/browser/index.js +31 -0
  118. package/dest/random/index.d.ts +2 -0
  119. package/dest/random/index.d.ts.map +1 -0
  120. package/dest/random/index.js +2 -0
  121. package/dest/random/node/index.d.ts +2 -0
  122. package/dest/random/node/index.d.ts.map +1 -0
  123. package/dest/random/node/index.js +5 -0
  124. package/dest/serialize/buffer_reader.d.ts +28 -0
  125. package/dest/serialize/buffer_reader.d.ts.map +1 -0
  126. package/dest/serialize/buffer_reader.js +66 -0
  127. package/dest/serialize/index.d.ts +4 -0
  128. package/dest/serialize/index.d.ts.map +1 -0
  129. package/dest/serialize/index.js +4 -0
  130. package/dest/serialize/output_type.d.ts +11 -0
  131. package/dest/serialize/output_type.d.ts.map +1 -0
  132. package/dest/serialize/output_type.js +44 -0
  133. package/dest/serialize/serialize.d.ts +53 -0
  134. package/dest/serialize/serialize.d.ts.map +1 -0
  135. package/dest/serialize/serialize.js +139 -0
  136. package/dest/simple_test.js +2 -0
  137. package/dest/simple_test.js.LICENSE.txt +14 -0
  138. package/dest/types/fields.d.ts +33 -0
  139. package/dest/types/fields.d.ts.map +1 -0
  140. package/dest/types/fields.js +86 -0
  141. package/dest/types/fixed_size_buffer.d.ts +26 -0
  142. package/dest/types/fixed_size_buffer.d.ts.map +1 -0
  143. package/dest/types/fixed_size_buffer.js +54 -0
  144. package/dest/types/index.d.ts +6 -0
  145. package/dest/types/index.d.ts.map +1 -0
  146. package/dest/types/index.js +6 -0
  147. package/dest/types/point.d.ts +17 -0
  148. package/dest/types/point.d.ts.map +1 -0
  149. package/dest/types/point.js +32 -0
  150. package/dest/types/ptr.d.ts +13 -0
  151. package/dest/types/ptr.d.ts.map +1 -0
  152. package/dest/types/ptr.js +20 -0
  153. package/dest/types/raw_buffer.d.ts +3 -0
  154. package/dest/types/raw_buffer.d.ts.map +1 -0
  155. package/dest/types/raw_buffer.js +5 -0
  156. package/package.json +79 -0
  157. package/src/async_map/index.ts +15 -0
  158. package/src/barretenberg_api/blake2s.test.ts +39 -0
  159. package/src/barretenberg_api/common.test.ts +21 -0
  160. package/src/barretenberg_api/index.ts +461 -0
  161. package/src/barretenberg_api/pedersen.test.ts +84 -0
  162. package/src/barretenberg_api/schnorr.test.ts +169 -0
  163. package/src/barretenberg_binder/heap_allocator.ts +62 -0
  164. package/src/barretenberg_binder/heap_allocator_sync.ts +61 -0
  165. package/src/barretenberg_binder/index.ts +76 -0
  166. package/src/barretenberg_wasm/barretenberg_wasm.test.ts +52 -0
  167. package/src/barretenberg_wasm/barretenberg_wasm.ts +222 -0
  168. package/src/barretenberg_wasm/browser/index.ts +32 -0
  169. package/src/barretenberg_wasm/browser/worker.ts +13 -0
  170. package/src/barretenberg_wasm/index.ts +1 -0
  171. package/src/barretenberg_wasm/node/index.ts +46 -0
  172. package/src/barretenberg_wasm/node/node_endpoint.ts +28 -0
  173. package/src/barretenberg_wasm/node/worker.ts +10 -0
  174. package/src/bigint-array/index.ts +21 -0
  175. package/src/bindgen/function_declaration.ts +11 -0
  176. package/src/bindgen/index.ts +17 -0
  177. package/src/bindgen/mappings.ts +66 -0
  178. package/src/bindgen/rust.ts +52 -0
  179. package/src/bindgen/to_camel_case.ts +10 -0
  180. package/src/bindgen/typescript.ts +91 -0
  181. package/src/crs/browser/cached_net_crs.ts +60 -0
  182. package/src/crs/browser/index.ts +1 -0
  183. package/src/crs/index.ts +1 -0
  184. package/src/crs/net_crs.ts +69 -0
  185. package/src/crs/node/file_crs.ts +60 -0
  186. package/src/crs/node/index.ts +48 -0
  187. package/src/examples/simple.rawtest.ts +32 -0
  188. package/src/examples/simple.test.ts +27 -0
  189. package/src/factory/index.ts +36 -0
  190. package/src/index.html +9 -0
  191. package/src/index.ts +3 -0
  192. package/src/main-dev.ts +2 -0
  193. package/src/main.ts +329 -0
  194. package/src/random/browser/index.ts +32 -0
  195. package/src/random/index.ts +1 -0
  196. package/src/random/node/index.ts +5 -0
  197. package/src/serialize/buffer_reader.ts +82 -0
  198. package/src/serialize/index.ts +3 -0
  199. package/src/serialize/output_type.ts +53 -0
  200. package/src/serialize/serialize.ts +157 -0
  201. package/src/types/fields.ts +98 -0
  202. package/src/types/fixed_size_buffer.ts +59 -0
  203. package/src/types/index.ts +5 -0
  204. package/src/types/point.ts +35 -0
  205. package/src/types/ptr.ts +20 -0
  206. package/src/types/raw_buffer.ts +3 -0
@@ -0,0 +1,36 @@
1
+ import { BarretenbergApi, BarretenbergApiSync } from '../barretenberg_api/index.js';
2
+ import { BarretenbergBinder, BarretenbergBinderSync } from '../barretenberg_binder/index.js';
3
+ import { BarretenbergWasm, BarretenbergWasmWorker } from '../barretenberg_wasm/index.js';
4
+
5
+ /**
6
+ * Returns a single threaded, synchronous, barretenberg api.
7
+ * Can be used on the main thread to perform small light-weight requests like hashing etc.
8
+ */
9
+ export async function newBarretenbergApiSync() {
10
+ return new BarretenbergApiSync(new BarretenbergBinderSync(await BarretenbergWasm.new()));
11
+ }
12
+
13
+ export class BarretenbergApiAsync extends BarretenbergApi {
14
+ constructor(private worker: any, private wasm: BarretenbergWasmWorker) {
15
+ super(new BarretenbergBinder(wasm));
16
+ }
17
+
18
+ async getNumThreads() {
19
+ return await this.wasm.getNumThreads();
20
+ }
21
+
22
+ async destroy() {
23
+ await this.wasm.destroy();
24
+ await this.worker.terminate();
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Returns a multi threaded, asynchronous, barretenberg api.
30
+ * It runs in a worker, and so can be used within the browser to execute long running, multi-threaded requests
31
+ * like proof construction etc.
32
+ */
33
+ export async function newBarretenbergApiAsync(threads?: number) {
34
+ const { wasm, worker } = await BarretenbergWasm.newWorker(threads);
35
+ return new BarretenbergApiAsync(worker, wasm);
36
+ }
package/src/index.html ADDED
@@ -0,0 +1,9 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>My App</title>
5
+ </head>
6
+ <body>
7
+ <script src="simple_test.js"></script>
8
+ </body>
9
+ </html>
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './crs/index.js';
2
+ export * from './barretenberg_wasm/index.js';
3
+ export * from './barretenberg_api/index.js';
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env -S node --loader ts-node/esm --no-warnings
2
+ import './main.js';
package/src/main.ts ADDED
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env -S node --no-warnings
2
+ import { Crs } from './crs/index.js';
3
+ import createDebug from 'debug';
4
+ import { BarretenbergApiAsync, newBarretenbergApiAsync } from './factory/index.js';
5
+ import { readFileSync, writeFileSync } from 'fs';
6
+ import { gunzipSync } from 'zlib';
7
+ import { RawBuffer } from './types/index.js';
8
+ import { numToUInt32BE } from './serialize/serialize.js';
9
+ import { Command } from 'commander';
10
+
11
+ createDebug.log = console.error.bind(console);
12
+ const debug = createDebug('bb.js');
13
+ // createDebug.enable('*');
14
+
15
+ // Maximum we support.
16
+ const MAX_CIRCUIT_SIZE = 2 ** 19;
17
+
18
+ function getBytecode(jsonPath: string) {
19
+ const json = readFileSync(jsonPath, 'utf-8');
20
+ const parsed = JSON.parse(json);
21
+ const buffer = Buffer.from(parsed.bytecode, 'base64');
22
+ const decompressed = gunzipSync(buffer);
23
+ return decompressed;
24
+ }
25
+
26
+ function getWitness(witnessPath: string) {
27
+ const data = readFileSync(witnessPath);
28
+ return Buffer.concat([numToUInt32BE(data.length / 32), data]);
29
+ }
30
+
31
+ async function getCircuitSize(jsonPath: string, api: BarretenbergApiAsync) {
32
+ const bytecode = getBytecode(jsonPath);
33
+ const [exact, total, subgroup] = await api.acirGetCircuitSizes(new RawBuffer(bytecode));
34
+ return { exact, total, subgroup };
35
+ }
36
+
37
+ async function init(jsonPath: string) {
38
+ const api = await newBarretenbergApiAsync();
39
+
40
+ // First compute circuit size.
41
+ const circuitSizes = await getCircuitSize(jsonPath, api);
42
+ debug(`circuit size: ${circuitSizes.total}`);
43
+
44
+ if (circuitSizes.subgroup > MAX_CIRCUIT_SIZE) {
45
+ throw new Error(`Circuit size of ${circuitSizes.subgroup} exceeds max supported of ${MAX_CIRCUIT_SIZE}`);
46
+ }
47
+
48
+ // Plus 1 needed! (Move +1 into Crs?)
49
+ const crs = await Crs.new(circuitSizes.subgroup + 1);
50
+
51
+ // Important to init slab allocator as first thing, to ensure maximum memory efficiency.
52
+ await api.commonInitSlabAllocator(circuitSizes.subgroup);
53
+
54
+ // Load CRS into wasm global CRS state.
55
+ // TODO: Make RawBuffer be default behaviour, and have a specific Vector type for when wanting length prefixed.
56
+ await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
57
+
58
+ const acirComposer = await api.acirNewAcirComposer();
59
+ return { api, acirComposer, circuitSize: circuitSizes.subgroup };
60
+ }
61
+
62
+ async function initLite() {
63
+ const api = await newBarretenbergApiAsync(1);
64
+
65
+ // Plus 1 needed! (Move +1 into Crs?)
66
+ const crs = await Crs.new(1);
67
+
68
+ // Load CRS into wasm global CRS state.
69
+ await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
70
+
71
+ const acirComposer = await api.acirNewAcirComposer();
72
+ return { api, acirComposer };
73
+ }
74
+
75
+ export async function proveAndVerify(jsonPath: string, witnessPath: string, isRecursive: boolean) {
76
+ const { api, acirComposer, circuitSize } = await init(jsonPath);
77
+ try {
78
+ debug('initing proving key...');
79
+ const bytecode = getBytecode(jsonPath);
80
+ await api.acirInitProvingKey(acirComposer, new RawBuffer(bytecode), circuitSize);
81
+
82
+ // const circuitSize = await api.acirGetExactCircuitSize(acirComposer);
83
+ // debug(`circuit size: ${circuitSize}`);
84
+
85
+ debug('initing verification key...');
86
+ await api.acirInitVerificationKey(acirComposer);
87
+
88
+ debug(`creating proof...`);
89
+ const witness = getWitness(witnessPath);
90
+ const proof = await api.acirCreateProof(acirComposer, new RawBuffer(bytecode), new RawBuffer(witness), isRecursive);
91
+ debug(`done.`);
92
+
93
+ const verified = await api.acirVerifyProof(acirComposer, proof, isRecursive);
94
+ console.log(`verified: ${verified}`);
95
+ return verified;
96
+ } finally {
97
+ await api.destroy();
98
+ }
99
+ }
100
+
101
+ export async function prove(jsonPath: string, witnessPath: string, isRecursive: boolean, outputPath: string) {
102
+ const { api, acirComposer, circuitSize } = await init(jsonPath);
103
+ try {
104
+ debug('initing proving key...');
105
+ const bytecode = getBytecode(jsonPath);
106
+ await api.acirInitProvingKey(acirComposer, new RawBuffer(bytecode), circuitSize);
107
+
108
+ // const circuitSize = await api.acirGetExactCircuitSize(acirComposer);
109
+ // debug(`circuit size: ${circuitSize}`);
110
+
111
+ debug(`creating proof...`);
112
+ const witness = getWitness(witnessPath);
113
+ const proof = await api.acirCreateProof(acirComposer, new RawBuffer(bytecode), new RawBuffer(witness), isRecursive);
114
+ debug(`done.`);
115
+
116
+ writeFileSync(outputPath, proof);
117
+ console.log(`proof written to: ${outputPath}`);
118
+ } finally {
119
+ await api.destroy();
120
+ }
121
+ }
122
+
123
+ export async function gateCount(jsonPath: string) {
124
+ const api = await newBarretenbergApiAsync(1);
125
+ try {
126
+ const circuitSizes = await getCircuitSize(jsonPath, api);
127
+ console.log(`${circuitSizes.exact}`);
128
+ } finally {
129
+ await api.destroy();
130
+ }
131
+ }
132
+
133
+ export async function verify(jsonPath: string, proofPath: string, isRecursive: boolean, vkPath?: string) {
134
+ if (vkPath) {
135
+ const { api, acirComposer } = await initLite();
136
+ try {
137
+ await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
138
+ const verified = await api.acirVerifyProof(acirComposer, readFileSync(proofPath), isRecursive);
139
+ console.log(`verified: ${verified}`);
140
+ return verified;
141
+ } finally {
142
+ await api.destroy();
143
+ }
144
+ } else {
145
+ const { api, acirComposer, circuitSize } = await init(jsonPath);
146
+ try {
147
+ debug('initing proving key...');
148
+ const bytecode = getBytecode(jsonPath);
149
+ await api.acirInitProvingKey(acirComposer, new RawBuffer(bytecode), circuitSize);
150
+
151
+ debug('initing verification key...');
152
+ await api.acirInitVerificationKey(acirComposer);
153
+
154
+ const verified = await api.acirVerifyProof(acirComposer, readFileSync(proofPath), isRecursive);
155
+ console.log(`verified: ${verified}`);
156
+ return verified;
157
+ } finally {
158
+ await api.destroy();
159
+ }
160
+ }
161
+ }
162
+
163
+ export async function contract(jsonPath: string, outputPath: string) {
164
+ const { api, acirComposer, circuitSize } = await init(jsonPath);
165
+ try {
166
+ debug('initing proving key...');
167
+ const bytecode = getBytecode(jsonPath);
168
+ await api.acirInitProvingKey(acirComposer, new RawBuffer(bytecode), circuitSize);
169
+
170
+ debug('initing verification key...');
171
+ await api.acirInitVerificationKey(acirComposer);
172
+
173
+ const contract = await api.acirGetSolidityVerifier(acirComposer);
174
+ if (outputPath === '-') {
175
+ console.log(contract);
176
+ } else {
177
+ writeFileSync(outputPath, contract);
178
+ console.log(`contract written to: ${outputPath}`);
179
+ }
180
+ } finally {
181
+ await api.destroy();
182
+ }
183
+ }
184
+
185
+ export async function writeVk(jsonPath: string, outputPath: string) {
186
+ const { api, acirComposer, circuitSize } = await init(jsonPath);
187
+ try {
188
+ debug('initing proving key...');
189
+ const bytecode = getBytecode(jsonPath);
190
+ await api.acirInitProvingKey(acirComposer, new RawBuffer(bytecode), circuitSize);
191
+
192
+ debug('initing verification key...');
193
+ const vk = await api.acirGetVerificationKey(acirComposer);
194
+ if (outputPath === '-') {
195
+ process.stdout.write(vk);
196
+ } else {
197
+ writeFileSync(outputPath, vk);
198
+ console.log(`vk written to: ${outputPath}`);
199
+ }
200
+ } finally {
201
+ await api.destroy();
202
+ }
203
+ }
204
+
205
+ export async function proofAsFields(proofPath: string, numInnerPublicInputs: number, outputPath: string) {
206
+ const { api, acirComposer } = await initLite();
207
+
208
+ try {
209
+ debug('serializing proof byte array into field elements');
210
+ const proofAsFields = await api.acirSerializeProofIntoFields(
211
+ acirComposer,
212
+ readFileSync(proofPath),
213
+ numInnerPublicInputs,
214
+ );
215
+
216
+ writeFileSync(outputPath, JSON.stringify(proofAsFields.map(f => f.toString())));
217
+ debug('done.');
218
+ } finally {
219
+ await api.destroy();
220
+ }
221
+ }
222
+
223
+ export async function vkAsFields(vkPath: string, vkeyOutputPath: string) {
224
+ const { api, acirComposer } = await initLite();
225
+
226
+ try {
227
+ debug('serializing vk byte array into field elements');
228
+ await api.acirLoadVerificationKey(acirComposer, new RawBuffer(readFileSync(vkPath)));
229
+ const [vkAsFields, vkHash] = await api.acirSerializeVerificationKeyIntoFields(acirComposer);
230
+ const output = [vkHash, ...vkAsFields].map(f => f.toString());
231
+ writeFileSync(vkeyOutputPath, JSON.stringify(output));
232
+ debug('done.');
233
+ } finally {
234
+ await api.destroy();
235
+ }
236
+ }
237
+
238
+ // nargo use bb.js: backend -> bb.js
239
+ // backend prove --data-dir data --witness /foo/bar/witness.tr --json /foo/bar/main.json
240
+ // backend verify ...
241
+ // backend get_total_num_gates --data-dir data --json /foo/bar/main.json
242
+ // backend get_sol_contract --data-dir data --json /foo/bar/main.json --output
243
+ // backend get_features
244
+ // OPTIONAL stateful backend:
245
+ // backend start
246
+ // backend stop
247
+
248
+ const program = new Command();
249
+
250
+ program
251
+ .command('prove_and_verify')
252
+ .description('Generate a proof and verify it. Process exits with success or failure code.')
253
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
254
+ .option('-w, --witness-path <path>', 'Specify the witness path', './target/witness.tr')
255
+ .option('-r, --recursive', 'prove and verify using recursive prover and verifier', false)
256
+ .action(async ({ jsonPath, witnessPath, recursive }) => {
257
+ const result = await proveAndVerify(jsonPath, witnessPath, recursive);
258
+ process.exit(result ? 0 : 1);
259
+ });
260
+
261
+ program
262
+ .command('prove')
263
+ .description('Generate a proof and write it to a file.')
264
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
265
+ .option('-w, --witness-path <path>', 'Specify the witness path', './target/witness.tr')
266
+ .option('-r, --recursive', 'prove using recursive prover', false)
267
+ .option('-o, --output-dir <path>', 'Specify the proof output dir', './proofs')
268
+ .requiredOption('-n, --name <filename>', 'Output file name.')
269
+ .action(async ({ jsonPath, witnessPath, recursive, outputDir, name }) => {
270
+ await prove(jsonPath, witnessPath, recursive, outputDir + '/' + name);
271
+ });
272
+
273
+ program
274
+ .command('gates')
275
+ .description('Print gate count to standard output.')
276
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
277
+ .action(async ({ jsonPath }) => {
278
+ await gateCount(jsonPath);
279
+ });
280
+
281
+ program
282
+ .command('verify')
283
+ .description('Verify a proof. Process exists with success or failure code.')
284
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
285
+ .requiredOption('-p, --proof-path <path>', 'Specify the path to the proof')
286
+ .option('-r, --recursive', 'prove using recursive prover', false)
287
+ .option('-v, --vk <path>', 'path to a verification key. avoids recomputation.')
288
+ .action(async ({ jsonPath, proofPath, recursive, vk }) => {
289
+ await verify(jsonPath, proofPath, recursive, vk);
290
+ });
291
+
292
+ program
293
+ .command('contract')
294
+ .description('Output solidity verification key contract.')
295
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
296
+ .option('-o, --output-path <path>', 'Specify the path to write the contract', '-')
297
+ .action(async ({ jsonPath, outputPath }) => {
298
+ await contract(jsonPath, outputPath);
299
+ });
300
+
301
+ program
302
+ .command('write_vk')
303
+ .description('Output verification key.')
304
+ .option('-j, --json-path <path>', 'Specify the JSON path', './target/main.json')
305
+ .requiredOption('-o, --output-path <path>', 'Specify the path to write the key')
306
+ .action(async ({ jsonPath, outputPath }) => {
307
+ await writeVk(jsonPath, outputPath);
308
+ });
309
+
310
+ program
311
+ .command('proof_as_fields')
312
+ .description('Return the proof as fields elements')
313
+ .requiredOption('-p, --proof-path <path>', 'Specify the proof path')
314
+ .requiredOption('-n, --num-public-inputs <number>', 'Specify the number of public inputs')
315
+ .requiredOption('-o, --output-path <path>', 'Specify the JSON path to write the proof fields')
316
+ .action(async ({ proofPath, numPublicInputs, outputPath }) => {
317
+ await proofAsFields(proofPath, numPublicInputs, outputPath);
318
+ });
319
+
320
+ program
321
+ .command('vk_as_fields')
322
+ .description('Return the verifiation key represented as fields elements. Also return the verification key hash.')
323
+ .requiredOption('-i, --input-path <path>', 'Specifies the vk path (output from write_vk)')
324
+ .requiredOption('-o, --output-path <path>', 'Specify the JSON path to write the verification key fields and key hash')
325
+ .action(async ({ inputPath, outputPath }) => {
326
+ await vkAsFields(inputPath, outputPath);
327
+ });
328
+
329
+ program.name('bb.js').parse(process.argv);
@@ -0,0 +1,32 @@
1
+ export const randomBytes = (len: number) => {
2
+ const getWebCrypto = () => {
3
+ if (typeof window !== 'undefined' && window.crypto) return window.crypto;
4
+ if (typeof self !== 'undefined' && self.crypto) return self.crypto;
5
+ return undefined;
6
+ };
7
+
8
+ const crypto = getWebCrypto();
9
+ if (!crypto) {
10
+ throw new Error('randomBytes UnsupportedEnvironment');
11
+ }
12
+
13
+ const buf = new Uint8Array(len);
14
+
15
+ // limit of Crypto.getRandomValues()
16
+ // https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
17
+ const MAX_BYTES = 65536;
18
+
19
+ if (len > MAX_BYTES) {
20
+ // this is the max bytes crypto.getRandomValues
21
+ // can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
22
+ for (let generated = 0; generated < len; generated += MAX_BYTES) {
23
+ // buffer.slice automatically checks if the end is past the end of
24
+ // the buffer so we don't have to here
25
+ crypto.getRandomValues(buf.subarray(generated, generated + MAX_BYTES));
26
+ }
27
+ } else {
28
+ crypto.getRandomValues(buf);
29
+ }
30
+
31
+ return buf;
32
+ };
@@ -0,0 +1 @@
1
+ export * from './node/index.js';
@@ -0,0 +1,5 @@
1
+ import { randomBytes as cryptoRandomBytes } from 'crypto';
2
+
3
+ export function randomBytes(len: number) {
4
+ return new Uint8Array(cryptoRandomBytes(len));
5
+ }
@@ -0,0 +1,82 @@
1
+ export class BufferReader {
2
+ private index: number;
3
+ constructor(private buffer: Uint8Array, offset = 0) {
4
+ this.index = offset;
5
+ }
6
+
7
+ public static asReader(bufferOrReader: Uint8Array | BufferReader) {
8
+ return bufferOrReader instanceof BufferReader ? bufferOrReader : new BufferReader(bufferOrReader);
9
+ }
10
+
11
+ public readNumber(): number {
12
+ const dataView = new DataView(this.buffer.buffer, this.buffer.byteOffset + this.index, 4);
13
+ this.index += 4;
14
+ return dataView.getUint32(0, false);
15
+ }
16
+
17
+ public readBoolean(): boolean {
18
+ this.index += 1;
19
+ return Boolean(this.buffer.at(this.index - 1));
20
+ }
21
+
22
+ public readBytes(n: number): Uint8Array {
23
+ this.index += n;
24
+ return this.buffer.slice(this.index - n, this.index);
25
+ }
26
+
27
+ public readNumberVector(): number[] {
28
+ return this.readVector({
29
+ fromBuffer: (reader: BufferReader) => reader.readNumber(),
30
+ });
31
+ }
32
+
33
+ public readVector<T>(itemDeserializer: { fromBuffer: (reader: BufferReader) => T }): T[] {
34
+ const size = this.readNumber();
35
+ const result = new Array<T>(size);
36
+ for (let i = 0; i < size; i++) {
37
+ result[i] = itemDeserializer.fromBuffer(this);
38
+ }
39
+ return result;
40
+ }
41
+
42
+ public readArray<T>(
43
+ size: number,
44
+ itemDeserializer: {
45
+ fromBuffer: (reader: BufferReader) => T;
46
+ },
47
+ ): T[] {
48
+ const result = new Array<T>(size);
49
+ for (let i = 0; i < size; i++) {
50
+ result[i] = itemDeserializer.fromBuffer(this);
51
+ }
52
+ return result;
53
+ }
54
+
55
+ public readObject<T>(deserializer: { fromBuffer: (reader: BufferReader) => T }): T {
56
+ return deserializer.fromBuffer(this);
57
+ }
58
+
59
+ public peekBytes(n?: number) {
60
+ return this.buffer.subarray(this.index, n ? this.index + n : undefined);
61
+ }
62
+
63
+ public readString(): string {
64
+ return new TextDecoder().decode(this.readBuffer());
65
+ }
66
+
67
+ public readBuffer(): Uint8Array {
68
+ const size = this.readNumber();
69
+ return this.readBytes(size);
70
+ }
71
+
72
+ public readMap<T>(deserializer: { fromBuffer: (reader: BufferReader) => T }): { [key: string]: T } {
73
+ const numEntries = this.readNumber();
74
+ const map: { [key: string]: T } = {};
75
+ for (let i = 0; i < numEntries; i++) {
76
+ const key = this.readString();
77
+ const value = this.readObject<T>(deserializer);
78
+ map[key] = value;
79
+ }
80
+ return map;
81
+ }
82
+ }
@@ -0,0 +1,3 @@
1
+ export * from './buffer_reader.js';
2
+ export * from './output_type.js';
3
+ export * from './serialize.js';
@@ -0,0 +1,53 @@
1
+ import { BufferReader } from './buffer_reader.js';
2
+
3
+ export interface OutputType<T = any> {
4
+ SIZE_IN_BYTES?: number;
5
+ fromBuffer: (b: Uint8Array | BufferReader) => T;
6
+ }
7
+
8
+ export function BoolDeserializer(): OutputType {
9
+ return {
10
+ SIZE_IN_BYTES: 1,
11
+ fromBuffer: (buf: Uint8Array | BufferReader) => {
12
+ const reader = BufferReader.asReader(buf);
13
+ return reader.readBoolean();
14
+ },
15
+ };
16
+ }
17
+
18
+ export function NumberDeserializer(): OutputType {
19
+ return {
20
+ SIZE_IN_BYTES: 4,
21
+ fromBuffer: (buf: Uint8Array | BufferReader) => {
22
+ const reader = BufferReader.asReader(buf);
23
+ return reader.readNumber();
24
+ },
25
+ };
26
+ }
27
+
28
+ export function VectorDeserializer<T>(t: OutputType<T>): OutputType {
29
+ return {
30
+ fromBuffer: (buf: Uint8Array | BufferReader) => {
31
+ const reader = BufferReader.asReader(buf);
32
+ return reader.readVector(t);
33
+ },
34
+ };
35
+ }
36
+
37
+ export function BufferDeserializer(): OutputType {
38
+ return {
39
+ fromBuffer: (buf: Uint8Array | BufferReader) => {
40
+ const reader = BufferReader.asReader(buf);
41
+ return reader.readBuffer();
42
+ },
43
+ };
44
+ }
45
+
46
+ export function StringDeserializer(): OutputType {
47
+ return {
48
+ fromBuffer: (buf: Uint8Array | BufferReader) => {
49
+ const reader = BufferReader.asReader(buf);
50
+ return reader.readString();
51
+ },
52
+ };
53
+ }