@rolly-dev/wasm-signer 0.1.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.
- package/README.md +115 -0
- package/dist/node/README.md +115 -0
- package/dist/node/package.json +1 -0
- package/dist/node/rolly_wasm_signer.d.ts +120 -0
- package/dist/node/rolly_wasm_signer.js +328 -0
- package/dist/node/rolly_wasm_signer_bg.wasm +0 -0
- package/dist/node/rolly_wasm_signer_bg.wasm.d.ts +15 -0
- package/dist/web/README.md +115 -0
- package/dist/web/rolly_wasm_signer.d.ts +160 -0
- package/dist/web/rolly_wasm_signer.js +415 -0
- package/dist/web/rolly_wasm_signer_bg.wasm +0 -0
- package/dist/web/rolly_wasm_signer_bg.wasm.d.ts +15 -0
- package/js/browser.mjs +13 -0
- package/js/node.cjs +15 -0
- package/js/node.mjs +16 -0
- package/js/react.mjs +57 -0
- package/package.json +52 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# @rolly/wasm-signer
|
|
2
|
+
|
|
3
|
+
Client-side Poseidon2 hashing and bet authentication for the Rolly ZK-Rollup casino.
|
|
4
|
+
|
|
5
|
+
Built with Rust → WebAssembly (via `wasm-pack`), using the same Poseidon2 hasher
|
|
6
|
+
and Goldilocks field as the plonky2 proving circuit.
|
|
7
|
+
|
|
8
|
+
## Build
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# requires: cargo, wasm-pack
|
|
12
|
+
npm run build
|
|
13
|
+
# → dist/node/ (Node.js, CJS, sync init)
|
|
14
|
+
# → dist/web/ (Browser, ESM, async init)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Node.js (CommonJS)
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const {
|
|
23
|
+
poseidon2_hash,
|
|
24
|
+
derive_session_key,
|
|
25
|
+
session_public_key,
|
|
26
|
+
create_bet_auth,
|
|
27
|
+
} = require('@rolly/wasm-signer');
|
|
28
|
+
|
|
29
|
+
const hash = poseidon2_hash(BigUint64Array.from([1n, 2n, 3n]));
|
|
30
|
+
// → BigUint64Array(4)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Node.js (ESM)
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
import {
|
|
37
|
+
poseidon2_hash,
|
|
38
|
+
derive_session_key,
|
|
39
|
+
create_bet_auth,
|
|
40
|
+
} from '@rolly/wasm-signer';
|
|
41
|
+
|
|
42
|
+
const hash = poseidon2_hash(BigUint64Array.from([1n, 2n, 3n]));
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### React
|
|
46
|
+
|
|
47
|
+
```jsx
|
|
48
|
+
import { useRollyWasm } from '@rolly/wasm-signer/react';
|
|
49
|
+
|
|
50
|
+
function BetButton({ sessionKey, amount, nonce }) {
|
|
51
|
+
const { ready, create_bet_auth } = useRollyWasm();
|
|
52
|
+
|
|
53
|
+
if (!ready) return <span>Loading...</span>;
|
|
54
|
+
|
|
55
|
+
const handleBet = () => {
|
|
56
|
+
const auth = create_bet_auth(sessionKey, BigInt(amount), BigInt(nonce));
|
|
57
|
+
// send auth to server...
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return <button onClick={handleBet}>Place Bet</button>;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Browser (vanilla ESM)
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<script type="module">
|
|
68
|
+
import { init, poseidon2_hash } from '@rolly/wasm-signer';
|
|
69
|
+
|
|
70
|
+
await init(); // loads .wasm, must be called once
|
|
71
|
+
const h = poseidon2_hash(BigUint64Array.from([1n, 2n]));
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Manual init (advanced)
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
import init, { poseidon2_hash } from '@rolly/wasm-signer/init';
|
|
79
|
+
|
|
80
|
+
// custom wasm URL or ArrayBuffer
|
|
81
|
+
await init('/assets/rolly_wasm_signer_bg.wasm');
|
|
82
|
+
poseidon2_hash(BigUint64Array.from([1n]));
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API
|
|
86
|
+
|
|
87
|
+
| Function | Input | Output | Description |
|
|
88
|
+
|----------------------------|--------------------------------|-------------------|------------------------------------------------|
|
|
89
|
+
| `poseidon2_hash` | `BigUint64Array` | `BigUint64Array(4)` | Hash N field elements |
|
|
90
|
+
| `poseidon2_two_to_one` | `BigUint64Array(4)` × 2 | `BigUint64Array(4)` | Merkle hash: H(left‖right) |
|
|
91
|
+
| `derive_session_key` | `Uint8Array(32)` | `BigUint64Array(4)` | MetaMask sig → session key |
|
|
92
|
+
| `session_public_key` | `BigUint64Array(4)` | `BigUint64Array(4)` | session_pk = H(session_key) |
|
|
93
|
+
| `create_bet_auth` | `(BigUint64Array(4), bigint, bigint)` | `BigUint64Array(4)` | MAC = H(sk‖amount_lo‖amount_hi‖nonce) |
|
|
94
|
+
| `compute_server_seed_hash` | `BigUint64Array(8)` | `BigUint64Array(4)` | Full hash of server seed |
|
|
95
|
+
| `seed_hash_truncated` | `BigUint64Array(8)` | `BigUint64Array(2)` | First 2 elements (circuit leaf format) |
|
|
96
|
+
| `goldilocks_modulus` | — | `bigint` | Returns p = 2^64 - 2^32 + 1 |
|
|
97
|
+
| `goldilocks_reduce` | `bigint` | `bigint` | Reduce mod p |
|
|
98
|
+
|
|
99
|
+
## Bundler notes
|
|
100
|
+
|
|
101
|
+
**Vite** — add to `optimizeDeps.exclude`:
|
|
102
|
+
```js
|
|
103
|
+
optimizeDeps: { exclude: ['@rolly/wasm-signer'] }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Webpack 5** — enable WASM experiments:
|
|
107
|
+
```js
|
|
108
|
+
module.exports = { experiments: { asyncWebAssembly: true } };
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Next.js** — conditional exports auto-resolve: Node.js entry on server, browser entry on client.
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Full Poseidon2 hash of an 8-element server seed.
|
|
6
|
+
*
|
|
7
|
+
* Returns all 4 hash elements. Note: the circuit stores only the
|
|
8
|
+
* **first 2 elements** as the leaf commitment (see `seed_hash_truncated`).
|
|
9
|
+
* This full variant is useful for client-side verification where all
|
|
10
|
+
* 4 elements may be needed.
|
|
11
|
+
*
|
|
12
|
+
* `server_seed` must be exactly 8 elements.
|
|
13
|
+
*/
|
|
14
|
+
export function compute_server_seed_hash(server_seed: BigUint64Array): BigUint64Array;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a `bet_auth` MAC that proves the user authorized this specific bet.
|
|
18
|
+
*
|
|
19
|
+
* ```text
|
|
20
|
+
* bet_auth = Poseidon2(
|
|
21
|
+
* session_key[0..4], // 4 field elements (private)
|
|
22
|
+
* amount_lo, // lower 32 bits of bet_amount
|
|
23
|
+
* amount_hi, // upper 32 bits of bet_amount
|
|
24
|
+
* nonce, // monotonic counter, prevents replay
|
|
25
|
+
* )
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* The circuit verifies two things:
|
|
29
|
+
* 1. `session_pk == Poseidon2(session_key)` — knowledge of key
|
|
30
|
+
* 2. `bet_auth == Poseidon2(session_key ‖ amount_lo ‖ amount_hi ‖ nonce)`
|
|
31
|
+
*
|
|
32
|
+
* The lo/hi split matches `src/circuit/main_circuit.rs` witness assignment:
|
|
33
|
+
* `amount as u32` / `(amount >> 32) as u32`, both via `from_canonical_u32`.
|
|
34
|
+
*
|
|
35
|
+
* **Parameters**
|
|
36
|
+
* - `session_key` : 4 × u64 (private, from `derive_session_key`)
|
|
37
|
+
* - `bet_amount` : u64 (in smallest currency units)
|
|
38
|
+
* - `nonce` : u64 (incrementing per-session counter)
|
|
39
|
+
*
|
|
40
|
+
* **Returns**: 4 × u64 (`bet_auth` hash)
|
|
41
|
+
*/
|
|
42
|
+
export function create_bet_auth(session_key: BigUint64Array, bet_amount: bigint, nonce: bigint): BigUint64Array;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Derive a session key from 32 bytes of entropy (e.g. MetaMask signature).
|
|
46
|
+
*
|
|
47
|
+
* **Algorithm**: split 32 bytes into 4 × 8 bytes, interpret each chunk as
|
|
48
|
+
* little-endian u64, reduce mod p, then hash:
|
|
49
|
+
* `session_key = Poseidon2(reduced_chunks)`
|
|
50
|
+
*
|
|
51
|
+
* The reduction via `from_noncanonical_u64` is necessary because raw
|
|
52
|
+
* signature bytes can produce values >= p.
|
|
53
|
+
*
|
|
54
|
+
* ```js
|
|
55
|
+
* const sig = ethers.getBytes(metaMaskSignature).slice(0, 32);
|
|
56
|
+
* const sk = derive_session_key(new Uint8Array(sig));
|
|
57
|
+
* // sk.length === 4
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function derive_session_key(sig_bytes: Uint8Array): BigUint64Array;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Returns the Goldilocks prime: p = 2^64 - 2^32 + 1.
|
|
64
|
+
*/
|
|
65
|
+
export function goldilocks_modulus(): bigint;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Reduce an arbitrary u64 to its canonical representative mod p.
|
|
69
|
+
*
|
|
70
|
+
* Values already < p are returned unchanged. Values >= p are reduced.
|
|
71
|
+
* This uses `from_noncanonical_u64` internally (no panic on large values).
|
|
72
|
+
*/
|
|
73
|
+
export function goldilocks_reduce(value: bigint): bigint;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Poseidon2 hash of an arbitrary number of Goldilocks field elements.
|
|
77
|
+
*
|
|
78
|
+
* Mirrors `builder.hash_n_to_hash_no_pad::<Poseidon2Hash>(...)` inside
|
|
79
|
+
* the circuit and `Poseidon2Hash::hash_no_pad` in `src/block_builder`.
|
|
80
|
+
*
|
|
81
|
+
* **Input** : `BigUint64Array` — each element must be < `GOLDILOCKS_P`.
|
|
82
|
+
* **Output**: `BigUint64Array` of length 4 (one `HashOut`).
|
|
83
|
+
*
|
|
84
|
+
* ```js
|
|
85
|
+
* const h = poseidon2_hash(BigUint64Array.from([1n, 2n, 3n]));
|
|
86
|
+
* // h.length === 4
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export function poseidon2_hash(input: BigUint64Array): BigUint64Array;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Merkle-tree hash: Poseidon2(left[4] ‖ right[4]).
|
|
93
|
+
*
|
|
94
|
+
* Identical to `poseidon_hash(left, right)` in `src/merkletree/hash.rs`.
|
|
95
|
+
* Input ordering is critical — `left` concatenated before `right`.
|
|
96
|
+
*
|
|
97
|
+
* Both arrays **must** have exactly 4 elements (one `HashOut` each).
|
|
98
|
+
*/
|
|
99
|
+
export function poseidon2_two_to_one(left: BigUint64Array, right: BigUint64Array): BigUint64Array;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Truncated seed hash — first 2 elements of `Poseidon2(server_seed)`.
|
|
103
|
+
*
|
|
104
|
+
* This is the exact format stored in the Merkle-tree leaf and verified
|
|
105
|
+
* by the circuit. Matches `seed_hash_truncated` in
|
|
106
|
+
* `src/block_builder/builder.rs` and `src/circuit/main_circuit.rs`.
|
|
107
|
+
*
|
|
108
|
+
* Returns `BigUint64Array` of length 2: `[h[0], h[1]]`.
|
|
109
|
+
*/
|
|
110
|
+
export function seed_hash_truncated(server_seed: BigUint64Array): BigUint64Array;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Compute the public key for a session: `session_pk = Poseidon2(session_key)`.
|
|
114
|
+
*
|
|
115
|
+
* The public key is stored in the user-asset Merkle leaf and verified
|
|
116
|
+
* inside the circuit (the prover must know the preimage `session_key`).
|
|
117
|
+
*
|
|
118
|
+
* `session_key` must be exactly 4 elements (output of `derive_session_key`).
|
|
119
|
+
*/
|
|
120
|
+
export function session_public_key(session_key: BigUint64Array): BigUint64Array;
|
|
121
|
+
|
|
122
|
+
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
123
|
+
|
|
124
|
+
export interface InitOutput {
|
|
125
|
+
readonly memory: WebAssembly.Memory;
|
|
126
|
+
readonly compute_server_seed_hash: (a: number, b: number, c: number) => void;
|
|
127
|
+
readonly create_bet_auth: (a: number, b: number, c: number, d: bigint, e: bigint) => void;
|
|
128
|
+
readonly derive_session_key: (a: number, b: number, c: number) => void;
|
|
129
|
+
readonly goldilocks_reduce: (a: bigint) => bigint;
|
|
130
|
+
readonly poseidon2_hash: (a: number, b: number, c: number) => void;
|
|
131
|
+
readonly poseidon2_two_to_one: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
132
|
+
readonly seed_hash_truncated: (a: number, b: number, c: number) => void;
|
|
133
|
+
readonly session_public_key: (a: number, b: number, c: number) => void;
|
|
134
|
+
readonly goldilocks_modulus: () => bigint;
|
|
135
|
+
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
136
|
+
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
137
|
+
readonly __wbindgen_export2: (a: number, b: number, c: number) => void;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Instantiates the given `module`, which can either be bytes or
|
|
144
|
+
* a precompiled `WebAssembly.Module`.
|
|
145
|
+
*
|
|
146
|
+
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
|
147
|
+
*
|
|
148
|
+
* @returns {InitOutput}
|
|
149
|
+
*/
|
|
150
|
+
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
154
|
+
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
155
|
+
*
|
|
156
|
+
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
|
157
|
+
*
|
|
158
|
+
* @returns {Promise<InitOutput>}
|
|
159
|
+
*/
|
|
160
|
+
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/* @ts-self-types="./rolly_wasm_signer.d.ts" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Full Poseidon2 hash of an 8-element server seed.
|
|
5
|
+
*
|
|
6
|
+
* Returns all 4 hash elements. Note: the circuit stores only the
|
|
7
|
+
* **first 2 elements** as the leaf commitment (see `seed_hash_truncated`).
|
|
8
|
+
* This full variant is useful for client-side verification where all
|
|
9
|
+
* 4 elements may be needed.
|
|
10
|
+
*
|
|
11
|
+
* `server_seed` must be exactly 8 elements.
|
|
12
|
+
* @param {BigUint64Array} server_seed
|
|
13
|
+
* @returns {BigUint64Array}
|
|
14
|
+
*/
|
|
15
|
+
export function compute_server_seed_hash(server_seed) {
|
|
16
|
+
try {
|
|
17
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
18
|
+
const ptr0 = passArray64ToWasm0(server_seed, wasm.__wbindgen_export);
|
|
19
|
+
const len0 = WASM_VECTOR_LEN;
|
|
20
|
+
wasm.compute_server_seed_hash(retptr, ptr0, len0);
|
|
21
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
22
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
23
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
24
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
25
|
+
return v2;
|
|
26
|
+
} finally {
|
|
27
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Create a `bet_auth` MAC that proves the user authorized this specific bet.
|
|
33
|
+
*
|
|
34
|
+
* ```text
|
|
35
|
+
* bet_auth = Poseidon2(
|
|
36
|
+
* session_key[0..4], // 4 field elements (private)
|
|
37
|
+
* amount_lo, // lower 32 bits of bet_amount
|
|
38
|
+
* amount_hi, // upper 32 bits of bet_amount
|
|
39
|
+
* nonce, // monotonic counter, prevents replay
|
|
40
|
+
* )
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* The circuit verifies two things:
|
|
44
|
+
* 1. `session_pk == Poseidon2(session_key)` — knowledge of key
|
|
45
|
+
* 2. `bet_auth == Poseidon2(session_key ‖ amount_lo ‖ amount_hi ‖ nonce)`
|
|
46
|
+
*
|
|
47
|
+
* The lo/hi split matches `src/circuit/main_circuit.rs` witness assignment:
|
|
48
|
+
* `amount as u32` / `(amount >> 32) as u32`, both via `from_canonical_u32`.
|
|
49
|
+
*
|
|
50
|
+
* **Parameters**
|
|
51
|
+
* - `session_key` : 4 × u64 (private, from `derive_session_key`)
|
|
52
|
+
* - `bet_amount` : u64 (in smallest currency units)
|
|
53
|
+
* - `nonce` : u64 (incrementing per-session counter)
|
|
54
|
+
*
|
|
55
|
+
* **Returns**: 4 × u64 (`bet_auth` hash)
|
|
56
|
+
* @param {BigUint64Array} session_key
|
|
57
|
+
* @param {bigint} bet_amount
|
|
58
|
+
* @param {bigint} nonce
|
|
59
|
+
* @returns {BigUint64Array}
|
|
60
|
+
*/
|
|
61
|
+
export function create_bet_auth(session_key, bet_amount, nonce) {
|
|
62
|
+
try {
|
|
63
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
64
|
+
const ptr0 = passArray64ToWasm0(session_key, wasm.__wbindgen_export);
|
|
65
|
+
const len0 = WASM_VECTOR_LEN;
|
|
66
|
+
wasm.create_bet_auth(retptr, ptr0, len0, bet_amount, nonce);
|
|
67
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
68
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
69
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
70
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
71
|
+
return v2;
|
|
72
|
+
} finally {
|
|
73
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Derive a session key from 32 bytes of entropy (e.g. MetaMask signature).
|
|
79
|
+
*
|
|
80
|
+
* **Algorithm**: split 32 bytes into 4 × 8 bytes, interpret each chunk as
|
|
81
|
+
* little-endian u64, reduce mod p, then hash:
|
|
82
|
+
* `session_key = Poseidon2(reduced_chunks)`
|
|
83
|
+
*
|
|
84
|
+
* The reduction via `from_noncanonical_u64` is necessary because raw
|
|
85
|
+
* signature bytes can produce values >= p.
|
|
86
|
+
*
|
|
87
|
+
* ```js
|
|
88
|
+
* const sig = ethers.getBytes(metaMaskSignature).slice(0, 32);
|
|
89
|
+
* const sk = derive_session_key(new Uint8Array(sig));
|
|
90
|
+
* // sk.length === 4
|
|
91
|
+
* ```
|
|
92
|
+
* @param {Uint8Array} sig_bytes
|
|
93
|
+
* @returns {BigUint64Array}
|
|
94
|
+
*/
|
|
95
|
+
export function derive_session_key(sig_bytes) {
|
|
96
|
+
try {
|
|
97
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
98
|
+
const ptr0 = passArray8ToWasm0(sig_bytes, wasm.__wbindgen_export);
|
|
99
|
+
const len0 = WASM_VECTOR_LEN;
|
|
100
|
+
wasm.derive_session_key(retptr, ptr0, len0);
|
|
101
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
102
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
103
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
104
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
105
|
+
return v2;
|
|
106
|
+
} finally {
|
|
107
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Returns the Goldilocks prime: p = 2^64 - 2^32 + 1.
|
|
113
|
+
* @returns {bigint}
|
|
114
|
+
*/
|
|
115
|
+
export function goldilocks_modulus() {
|
|
116
|
+
const ret = wasm.goldilocks_modulus();
|
|
117
|
+
return BigInt.asUintN(64, ret);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Reduce an arbitrary u64 to its canonical representative mod p.
|
|
122
|
+
*
|
|
123
|
+
* Values already < p are returned unchanged. Values >= p are reduced.
|
|
124
|
+
* This uses `from_noncanonical_u64` internally (no panic on large values).
|
|
125
|
+
* @param {bigint} value
|
|
126
|
+
* @returns {bigint}
|
|
127
|
+
*/
|
|
128
|
+
export function goldilocks_reduce(value) {
|
|
129
|
+
const ret = wasm.goldilocks_reduce(value);
|
|
130
|
+
return BigInt.asUintN(64, ret);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Poseidon2 hash of an arbitrary number of Goldilocks field elements.
|
|
135
|
+
*
|
|
136
|
+
* Mirrors `builder.hash_n_to_hash_no_pad::<Poseidon2Hash>(...)` inside
|
|
137
|
+
* the circuit and `Poseidon2Hash::hash_no_pad` in `src/block_builder`.
|
|
138
|
+
*
|
|
139
|
+
* **Input** : `BigUint64Array` — each element must be < `GOLDILOCKS_P`.
|
|
140
|
+
* **Output**: `BigUint64Array` of length 4 (one `HashOut`).
|
|
141
|
+
*
|
|
142
|
+
* ```js
|
|
143
|
+
* const h = poseidon2_hash(BigUint64Array.from([1n, 2n, 3n]));
|
|
144
|
+
* // h.length === 4
|
|
145
|
+
* ```
|
|
146
|
+
* @param {BigUint64Array} input
|
|
147
|
+
* @returns {BigUint64Array}
|
|
148
|
+
*/
|
|
149
|
+
export function poseidon2_hash(input) {
|
|
150
|
+
try {
|
|
151
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
152
|
+
const ptr0 = passArray64ToWasm0(input, wasm.__wbindgen_export);
|
|
153
|
+
const len0 = WASM_VECTOR_LEN;
|
|
154
|
+
wasm.poseidon2_hash(retptr, ptr0, len0);
|
|
155
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
156
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
157
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
158
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
159
|
+
return v2;
|
|
160
|
+
} finally {
|
|
161
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Merkle-tree hash: Poseidon2(left[4] ‖ right[4]).
|
|
167
|
+
*
|
|
168
|
+
* Identical to `poseidon_hash(left, right)` in `src/merkletree/hash.rs`.
|
|
169
|
+
* Input ordering is critical — `left` concatenated before `right`.
|
|
170
|
+
*
|
|
171
|
+
* Both arrays **must** have exactly 4 elements (one `HashOut` each).
|
|
172
|
+
* @param {BigUint64Array} left
|
|
173
|
+
* @param {BigUint64Array} right
|
|
174
|
+
* @returns {BigUint64Array}
|
|
175
|
+
*/
|
|
176
|
+
export function poseidon2_two_to_one(left, right) {
|
|
177
|
+
try {
|
|
178
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
179
|
+
const ptr0 = passArray64ToWasm0(left, wasm.__wbindgen_export);
|
|
180
|
+
const len0 = WASM_VECTOR_LEN;
|
|
181
|
+
const ptr1 = passArray64ToWasm0(right, wasm.__wbindgen_export);
|
|
182
|
+
const len1 = WASM_VECTOR_LEN;
|
|
183
|
+
wasm.poseidon2_two_to_one(retptr, ptr0, len0, ptr1, len1);
|
|
184
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
185
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
186
|
+
var v3 = getArrayU64FromWasm0(r0, r1).slice();
|
|
187
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
188
|
+
return v3;
|
|
189
|
+
} finally {
|
|
190
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Truncated seed hash — first 2 elements of `Poseidon2(server_seed)`.
|
|
196
|
+
*
|
|
197
|
+
* This is the exact format stored in the Merkle-tree leaf and verified
|
|
198
|
+
* by the circuit. Matches `seed_hash_truncated` in
|
|
199
|
+
* `src/block_builder/builder.rs` and `src/circuit/main_circuit.rs`.
|
|
200
|
+
*
|
|
201
|
+
* Returns `BigUint64Array` of length 2: `[h[0], h[1]]`.
|
|
202
|
+
* @param {BigUint64Array} server_seed
|
|
203
|
+
* @returns {BigUint64Array}
|
|
204
|
+
*/
|
|
205
|
+
export function seed_hash_truncated(server_seed) {
|
|
206
|
+
try {
|
|
207
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
208
|
+
const ptr0 = passArray64ToWasm0(server_seed, wasm.__wbindgen_export);
|
|
209
|
+
const len0 = WASM_VECTOR_LEN;
|
|
210
|
+
wasm.seed_hash_truncated(retptr, ptr0, len0);
|
|
211
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
212
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
213
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
214
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
215
|
+
return v2;
|
|
216
|
+
} finally {
|
|
217
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Compute the public key for a session: `session_pk = Poseidon2(session_key)`.
|
|
223
|
+
*
|
|
224
|
+
* The public key is stored in the user-asset Merkle leaf and verified
|
|
225
|
+
* inside the circuit (the prover must know the preimage `session_key`).
|
|
226
|
+
*
|
|
227
|
+
* `session_key` must be exactly 4 elements (output of `derive_session_key`).
|
|
228
|
+
* @param {BigUint64Array} session_key
|
|
229
|
+
* @returns {BigUint64Array}
|
|
230
|
+
*/
|
|
231
|
+
export function session_public_key(session_key) {
|
|
232
|
+
try {
|
|
233
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
234
|
+
const ptr0 = passArray64ToWasm0(session_key, wasm.__wbindgen_export);
|
|
235
|
+
const len0 = WASM_VECTOR_LEN;
|
|
236
|
+
wasm.session_public_key(retptr, ptr0, len0);
|
|
237
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
238
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
239
|
+
var v2 = getArrayU64FromWasm0(r0, r1).slice();
|
|
240
|
+
wasm.__wbindgen_export2(r0, r1 * 8, 8);
|
|
241
|
+
return v2;
|
|
242
|
+
} finally {
|
|
243
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function __wbg_get_imports() {
|
|
248
|
+
const import0 = {
|
|
249
|
+
__proto__: null,
|
|
250
|
+
__wbg___wbindgen_throw_be289d5034ed271b: function(arg0, arg1) {
|
|
251
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
return {
|
|
255
|
+
__proto__: null,
|
|
256
|
+
"./rolly_wasm_signer_bg.js": import0,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function getArrayU64FromWasm0(ptr, len) {
|
|
261
|
+
ptr = ptr >>> 0;
|
|
262
|
+
return getBigUint64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let cachedBigUint64ArrayMemory0 = null;
|
|
266
|
+
function getBigUint64ArrayMemory0() {
|
|
267
|
+
if (cachedBigUint64ArrayMemory0 === null || cachedBigUint64ArrayMemory0.byteLength === 0) {
|
|
268
|
+
cachedBigUint64ArrayMemory0 = new BigUint64Array(wasm.memory.buffer);
|
|
269
|
+
}
|
|
270
|
+
return cachedBigUint64ArrayMemory0;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
let cachedDataViewMemory0 = null;
|
|
274
|
+
function getDataViewMemory0() {
|
|
275
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
276
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
277
|
+
}
|
|
278
|
+
return cachedDataViewMemory0;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getStringFromWasm0(ptr, len) {
|
|
282
|
+
ptr = ptr >>> 0;
|
|
283
|
+
return decodeText(ptr, len);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let cachedUint8ArrayMemory0 = null;
|
|
287
|
+
function getUint8ArrayMemory0() {
|
|
288
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
289
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
290
|
+
}
|
|
291
|
+
return cachedUint8ArrayMemory0;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function passArray64ToWasm0(arg, malloc) {
|
|
295
|
+
const ptr = malloc(arg.length * 8, 8) >>> 0;
|
|
296
|
+
getBigUint64ArrayMemory0().set(arg, ptr / 8);
|
|
297
|
+
WASM_VECTOR_LEN = arg.length;
|
|
298
|
+
return ptr;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function passArray8ToWasm0(arg, malloc) {
|
|
302
|
+
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
303
|
+
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
304
|
+
WASM_VECTOR_LEN = arg.length;
|
|
305
|
+
return ptr;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
309
|
+
cachedTextDecoder.decode();
|
|
310
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
311
|
+
let numBytesDecoded = 0;
|
|
312
|
+
function decodeText(ptr, len) {
|
|
313
|
+
numBytesDecoded += len;
|
|
314
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
315
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
316
|
+
cachedTextDecoder.decode();
|
|
317
|
+
numBytesDecoded = len;
|
|
318
|
+
}
|
|
319
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
let WASM_VECTOR_LEN = 0;
|
|
323
|
+
|
|
324
|
+
let wasmModule, wasm;
|
|
325
|
+
function __wbg_finalize_init(instance, module) {
|
|
326
|
+
wasm = instance.exports;
|
|
327
|
+
wasmModule = module;
|
|
328
|
+
cachedBigUint64ArrayMemory0 = null;
|
|
329
|
+
cachedDataViewMemory0 = null;
|
|
330
|
+
cachedUint8ArrayMemory0 = null;
|
|
331
|
+
return wasm;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async function __wbg_load(module, imports) {
|
|
335
|
+
if (typeof Response === 'function' && module instanceof Response) {
|
|
336
|
+
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
337
|
+
try {
|
|
338
|
+
return await WebAssembly.instantiateStreaming(module, imports);
|
|
339
|
+
} catch (e) {
|
|
340
|
+
const validResponse = module.ok && expectedResponseType(module.type);
|
|
341
|
+
|
|
342
|
+
if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
|
|
343
|
+
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);
|
|
344
|
+
|
|
345
|
+
} else { throw e; }
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const bytes = await module.arrayBuffer();
|
|
350
|
+
return await WebAssembly.instantiate(bytes, imports);
|
|
351
|
+
} else {
|
|
352
|
+
const instance = await WebAssembly.instantiate(module, imports);
|
|
353
|
+
|
|
354
|
+
if (instance instanceof WebAssembly.Instance) {
|
|
355
|
+
return { instance, module };
|
|
356
|
+
} else {
|
|
357
|
+
return instance;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function expectedResponseType(type) {
|
|
362
|
+
switch (type) {
|
|
363
|
+
case 'basic': case 'cors': case 'default': return true;
|
|
364
|
+
}
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function initSync(module) {
|
|
370
|
+
if (wasm !== undefined) return wasm;
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
if (module !== undefined) {
|
|
374
|
+
if (Object.getPrototypeOf(module) === Object.prototype) {
|
|
375
|
+
({module} = module)
|
|
376
|
+
} else {
|
|
377
|
+
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const imports = __wbg_get_imports();
|
|
382
|
+
if (!(module instanceof WebAssembly.Module)) {
|
|
383
|
+
module = new WebAssembly.Module(module);
|
|
384
|
+
}
|
|
385
|
+
const instance = new WebAssembly.Instance(module, imports);
|
|
386
|
+
return __wbg_finalize_init(instance, module);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function __wbg_init(module_or_path) {
|
|
390
|
+
if (wasm !== undefined) return wasm;
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
if (module_or_path !== undefined) {
|
|
394
|
+
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
|
395
|
+
({module_or_path} = module_or_path)
|
|
396
|
+
} else {
|
|
397
|
+
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (module_or_path === undefined) {
|
|
402
|
+
module_or_path = new URL('rolly_wasm_signer_bg.wasm', import.meta.url);
|
|
403
|
+
}
|
|
404
|
+
const imports = __wbg_get_imports();
|
|
405
|
+
|
|
406
|
+
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
|
407
|
+
module_or_path = fetch(module_or_path);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
|
411
|
+
|
|
412
|
+
return __wbg_finalize_init(instance, module);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export { initSync, __wbg_init as default };
|
|
Binary file
|