@atlasauth/pca-ratchet 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Atlas Authorization
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,57 @@
1
- # Temporary Holding Version
1
+ # @atlasauth/pca-ratchet
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The PCA Capability Ratchet: two cryptographic primitives that replace bookkeeping in Proof-Carrying Authority with math.
4
+
5
+ 1. **Puncturable forward-secure capability keys.** A GGM puncturable-PRF tree of one-time Ed25519 leaf keys under a Merkle-root commitment. Signing at a leaf permanently punctures it, so a spent action can never be re-signed (cryptographic one-time-use instead of a server-side counter check).
6
+ 2. **Homomorphic risk accumulator.** Pedersen commitments on ristretto255 plus a zero-knowledge range proof that the committed total risk stays at or under a budget ceiling, without revealing individual risks.
7
+
8
+ Small adapters map a PCActn `counter` to a leaf index and core risk scores to accumulator units.
9
+
10
+ ## Install
11
+
12
+ ```sh
13
+ npm i @atlasauth/pca-ratchet @atlasauth/pca
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```ts
19
+ import {
20
+ deriveRatchetRoot, signAtLeaf, verifyLeafSignature, isLeafAvailable,
21
+ commitRisk, addCommitments, proveBudget, verifyBudget,
22
+ counterToLeafIndex, riskToUnits,
23
+ } from '@atlasauth/pca-ratchet';
24
+
25
+ // 1. One-time-use keys: 2^4 = 16 leaves under one root commitment.
26
+ const seed = crypto.getRandomValues(new Uint8Array(32));
27
+ const { rootCommitment, state } = deriveRatchetRoot(seed, 4);
28
+
29
+ const msg = new TextEncoder().encode('transfer 10 USDC');
30
+ const leaf = counterToLeafIndex(3, 4);
31
+ const { signature, newState } = signAtLeaf(state, leaf, msg); // state is immutable; keep newState
32
+ verifyLeafSignature(rootCommitment, leaf, msg, signature); // true (offline, root only)
33
+ isLeafAvailable(newState, leaf); // false
34
+ signAtLeaf(newState, leaf, msg); // throws RatchetError code 'leaf_punctured'
35
+
36
+ // 2. Budget proof: total risk <= 1000 units, individual risks hidden.
37
+ const risks = [riskToUnits(0.2), riskToUnits(0.35)];
38
+ const commits = risks.map((r) => commitRisk(r));
39
+ const sum = addCommitments(commits.map((c) => c.commitment));
40
+ const proof = proveBudget(risks, commits.map((c) => c.blinding), 1000);
41
+ verifyBudget(sum, 1000, proof); // true
42
+ verifyBudget(sum, 500, proof); // false
43
+ ```
44
+
45
+ ## API
46
+
47
+ - Ratchet: `deriveRatchetRoot`, `signAtLeaf`, `verifyLeafSignature`, `availableLeaves`, `isLeafAvailable`, `RatchetError`, `MAX_RATCHET_DEPTH`.
48
+ - Accumulator: `commitRisk`, `addCommitments`, `openCommitment`, `proveBudget`, `verifyBudget`, `AccumulatorError`, `N_BITS`.
49
+ - Adapters: `counterToLeafIndex`, `leafIndexToCounter`, `leafIndexForAction`, `riskToUnits`, `budgetCeilingUnits`, `RISK_SCALE`.
50
+
51
+ ## Status
52
+
53
+ Experimental. The cryptography here (GGM tree, Pedersen commitments, bit-decomposition range proof) is original and has **not** been independently audited; do not rely on it as the sole control for high-value actions. One-time-use holds only for the holder of the `RatchetState`: if a state is copied or restored from an old backup, spent leaves are available again, so persist the latest state atomically.
54
+
55
+ ## License
56
+
57
+ MIT - see LICENSE
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Mechanism 2 — Homomorphic risk accumulator with a zero-knowledge spend ceiling.
3
+ *
4
+ * Risk is carried as a Pedersen commitment on ristretto255:
5
+ *
6
+ * C = risk·G + blinding·H
7
+ *
8
+ * Commitments add homomorphically, so Σ commitments commits to (Σrisk, Σblinding). A compact
9
+ * bit-decomposition range proof then shows the aggregate satisfies the control-theoretic budget
10
+ * bound Σrisk ≤ bMax WITHOUT revealing the individual risks: it proves the slack
11
+ * (bMax − Σrisk) lies in [0, 2^N) using a Fiat-Shamir OR Sigma-protocol per bit plus a Schnorr
12
+ * proof that the bit-commitments aggregate to the slack commitment.
13
+ *
14
+ * Soundness rests on the hardness of discrete log between G and H (standard Pedersen binding):
15
+ * a prover who could pass the aggregation check for an over-budget aggregate, or open a bit to a
16
+ * value outside {0,1}, would have computed dlog_H(G).
17
+ */
18
+ /** Range-proof bit length: the slack (bMax − Σrisk) must lie in [0, 2^32). */
19
+ export declare const N_BITS = 32;
20
+ export type RiskUnits = number | bigint;
21
+ export type AccumulatorErrorCode = 'invalid_value' | 'length_mismatch' | 'invalid_proof_shape';
22
+ export declare class AccumulatorError extends Error {
23
+ readonly code: AccumulatorErrorCode;
24
+ constructor(code: AccumulatorErrorCode, message: string);
25
+ }
26
+ export interface RiskCommitment {
27
+ /** b64u ristretto255 point C = risk·G + blinding·H. */
28
+ commitment: string;
29
+ /** The blinding scalar (needed to open the commitment or to build a budget proof). */
30
+ blinding: bigint;
31
+ }
32
+ /** A Fiat-Shamir OR proof that one bit commitment opens to 0 or 1 (challenges/responses per branch). */
33
+ export interface BitOrProof {
34
+ e0: string;
35
+ e1: string;
36
+ z0: string;
37
+ z1: string;
38
+ }
39
+ /** A Schnorr proof of knowledge of a discrete log w.r.t. H. */
40
+ export interface SchnorrProof {
41
+ a: string;
42
+ z: string;
43
+ }
44
+ export interface BudgetProof {
45
+ /** Bit length of the range (= N_BITS). */
46
+ n: number;
47
+ /** b64u commitments to each bit of the slack value. */
48
+ bitCommitments: string[];
49
+ /** Per-bit OR proofs that each bit commitment opens to 0 or 1. */
50
+ or: BitOrProof[];
51
+ /** Schnorr proof that Σ 2^i·bitCommitment_i equals the slack commitment (bits aggregate correctly). */
52
+ agg: SchnorrProof;
53
+ }
54
+ /** Commit to a non-negative integer `risk` in units, with a given or fresh random `blinding`. */
55
+ export declare function commitRisk(risk: RiskUnits, blinding?: bigint): RiskCommitment;
56
+ /** Homomorphic sum: a commitment to (Σrisk, Σblinding). Empty input commits to (0, 0) = identity. */
57
+ export declare function addCommitments(commitments: readonly string[]): string;
58
+ /** Check that `commitment` opens to (`risk`, `blinding`). Never throws; malformed input is false. */
59
+ export declare function openCommitment(commitment: string, risk: RiskUnits, blinding: bigint): boolean;
60
+ /**
61
+ * Prove that the committed aggregate satisfies Σrisk ≤ bMax, in zero knowledge over the individual
62
+ * risks. `risks`/`blindings` are the same per-action values used to build the commitments whose sum
63
+ * is passed to {@link verifyBudget}. If the aggregate is over budget (or the slack does not fit in
64
+ * N_BITS), the returned proof is well-formed but will be REJECTED by the verifier — soundness lives
65
+ * in verification, not in the prover trusting its own inputs.
66
+ */
67
+ export declare function proveBudget(risks: readonly RiskUnits[], blindings: readonly bigint[], bMax: RiskUnits): BudgetProof;
68
+ /**
69
+ * Verify a budget proof against the commitment sum and ceiling. Returns true only if every bit
70
+ * commitment opens to 0/1 and they aggregate to the slack commitment bMax·G − commitmentSum — i.e.
71
+ * Σrisk ≤ bMax. Learns nothing about the individual risks. Never throws; malformed input is false.
72
+ */
73
+ export declare function verifyBudget(commitmentSum: string, bMax: RiskUnits, proof: BudgetProof): boolean;
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AccumulatorError = exports.N_BITS = void 0;
4
+ exports.commitRisk = commitRisk;
5
+ exports.addCommitments = addCommitments;
6
+ exports.openCommitment = openCommitment;
7
+ exports.proveBudget = proveBudget;
8
+ exports.verifyBudget = verifyBudget;
9
+ const group_1 = require("./group");
10
+ /**
11
+ * Mechanism 2 — Homomorphic risk accumulator with a zero-knowledge spend ceiling.
12
+ *
13
+ * Risk is carried as a Pedersen commitment on ristretto255:
14
+ *
15
+ * C = risk·G + blinding·H
16
+ *
17
+ * Commitments add homomorphically, so Σ commitments commits to (Σrisk, Σblinding). A compact
18
+ * bit-decomposition range proof then shows the aggregate satisfies the control-theoretic budget
19
+ * bound Σrisk ≤ bMax WITHOUT revealing the individual risks: it proves the slack
20
+ * (bMax − Σrisk) lies in [0, 2^N) using a Fiat-Shamir OR Sigma-protocol per bit plus a Schnorr
21
+ * proof that the bit-commitments aggregate to the slack commitment.
22
+ *
23
+ * Soundness rests on the hardness of discrete log between G and H (standard Pedersen binding):
24
+ * a prover who could pass the aggregation check for an over-budget aggregate, or open a bit to a
25
+ * value outside {0,1}, would have computed dlog_H(G).
26
+ */
27
+ /** Range-proof bit length: the slack (bMax − Σrisk) must lie in [0, 2^32). */
28
+ exports.N_BITS = 32;
29
+ class AccumulatorError extends Error {
30
+ code;
31
+ constructor(code, message) {
32
+ super(message);
33
+ this.name = 'AccumulatorError';
34
+ this.code = code;
35
+ }
36
+ }
37
+ exports.AccumulatorError = AccumulatorError;
38
+ function asUnits(x) {
39
+ if (typeof x === 'bigint') {
40
+ if (x < 0n)
41
+ throw new AccumulatorError('invalid_value', 'risk/budget must be >= 0');
42
+ return x;
43
+ }
44
+ if (!Number.isInteger(x) || x < 0) {
45
+ throw new AccumulatorError('invalid_value', 'risk/budget must be a non-negative integer');
46
+ }
47
+ return BigInt(x);
48
+ }
49
+ /** Commit to a non-negative integer `risk` in units, with a given or fresh random `blinding`. */
50
+ function commitRisk(risk, blinding) {
51
+ const v = asUnits(risk);
52
+ const b = blinding === undefined ? (0, group_1.randScalar)() : (0, group_1.mod)(blinding);
53
+ const C = (0, group_1.add)((0, group_1.mul)(group_1.G, v), (0, group_1.mul)(group_1.H, b));
54
+ return { commitment: (0, group_1.encodePoint)(C), blinding: b };
55
+ }
56
+ /** Homomorphic sum: a commitment to (Σrisk, Σblinding). Empty input commits to (0, 0) = identity. */
57
+ function addCommitments(commitments) {
58
+ let acc = (0, group_1.mul)(group_1.G, 0n); // identity
59
+ for (const c of commitments)
60
+ acc = (0, group_1.add)(acc, (0, group_1.decodePoint)(c));
61
+ return (0, group_1.encodePoint)(acc);
62
+ }
63
+ /** Check that `commitment` opens to (`risk`, `blinding`). Never throws; malformed input is false. */
64
+ function openCommitment(commitment, risk, blinding) {
65
+ try {
66
+ const v = asUnits(risk);
67
+ const expected = (0, group_1.add)((0, group_1.mul)(group_1.G, v), (0, group_1.mul)(group_1.H, (0, group_1.mod)(blinding)));
68
+ return (0, group_1.decodePoint)(commitment).equals(expected);
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ }
74
+ // ---- range proof ----------------------------------------------------------------------
75
+ const CTX_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/budget/ctx/v1');
76
+ const OR_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/budget/bit-or/v1');
77
+ const AGG_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/budget/agg/v1');
78
+ /** The transcript context that binds every challenge to the exact public statement. */
79
+ function contextHash(n, bMaxUnits, commitmentSum, bitCommitments) {
80
+ const parts = [
81
+ CTX_DOMAIN,
82
+ Uint8Array.of(n & 0xff),
83
+ (0, group_1.numberToBytesLE)((0, group_1.mod)(bMaxUnits), 32),
84
+ commitmentSum.toRawBytes(),
85
+ ];
86
+ for (const B of bitCommitments)
87
+ parts.push(B.toRawBytes());
88
+ // Reuse hashToScalar's length-prefixed framing, then serialize the scalar back to 32 bytes.
89
+ return (0, group_1.numberToBytesLE)((0, group_1.hashToScalar)(parts), 32);
90
+ }
91
+ /** Prove bit commitment `B` (= b·G + s·H) opens to 0 or 1, knowing bit `b` and blinding `s`. */
92
+ function proveBit(ctx, index, B, b, s) {
93
+ const P0 = B; // commitment to 0 under H => B = s·H
94
+ const P1 = (0, group_1.sub)(B, group_1.G); // commitment to 1 => B − G = s·H
95
+ const real = b === 1n ? 1 : 0;
96
+ // Simulate the false branch with a random challenge/response.
97
+ const eFake = (0, group_1.randScalar)();
98
+ const zFake = (0, group_1.randScalar)();
99
+ const Pfake = real === 1 ? P0 : P1;
100
+ const aFake = (0, group_1.sub)((0, group_1.mul)(group_1.H, zFake), (0, group_1.mul)(Pfake, eFake));
101
+ // Real branch: honest Schnorr commitment on H.
102
+ const k = (0, group_1.randScalar)();
103
+ const aReal = (0, group_1.mul)(group_1.H, k);
104
+ const a0 = real === 0 ? aReal : aFake;
105
+ const a1 = real === 1 ? aReal : aFake;
106
+ const e = (0, group_1.hashToScalar)([OR_DOMAIN, ctx, Uint8Array.of(index & 0xff), a0.toRawBytes(), a1.toRawBytes()]);
107
+ const eReal = (0, group_1.scalarSub)(e, eFake);
108
+ const zReal = (0, group_1.scalarAdd)(k, (0, group_1.scalarMul)(eReal, s));
109
+ const e0 = real === 0 ? eReal : eFake;
110
+ const e1 = real === 1 ? eReal : eFake;
111
+ const z0 = real === 0 ? zReal : zFake;
112
+ const z1 = real === 1 ? zReal : zFake;
113
+ return { e0: (0, group_1.encodeScalar)(e0), e1: (0, group_1.encodeScalar)(e1), z0: (0, group_1.encodeScalar)(z0), z1: (0, group_1.encodeScalar)(z1) };
114
+ }
115
+ function verifyBit(ctx, index, B, proof) {
116
+ const e0 = (0, group_1.decodeScalar)(proof.e0);
117
+ const e1 = (0, group_1.decodeScalar)(proof.e1);
118
+ const z0 = (0, group_1.decodeScalar)(proof.z0);
119
+ const z1 = (0, group_1.decodeScalar)(proof.z1);
120
+ const P0 = B;
121
+ const P1 = (0, group_1.sub)(B, group_1.G);
122
+ const a0 = (0, group_1.sub)((0, group_1.mul)(group_1.H, z0), (0, group_1.mul)(P0, e0));
123
+ const a1 = (0, group_1.sub)((0, group_1.mul)(group_1.H, z1), (0, group_1.mul)(P1, e1));
124
+ const e = (0, group_1.hashToScalar)([OR_DOMAIN, ctx, Uint8Array.of(index & 0xff), a0.toRawBytes(), a1.toRawBytes()]);
125
+ return (0, group_1.scalarAdd)(e0, e1) === e;
126
+ }
127
+ /** Schnorr proof of knowledge of `w` with `D = w·H`. */
128
+ function proveSchnorr(ctx, D, w) {
129
+ const k = (0, group_1.randScalar)();
130
+ const a = (0, group_1.mul)(group_1.H, k);
131
+ const e = (0, group_1.hashToScalar)([AGG_DOMAIN, ctx, D.toRawBytes(), a.toRawBytes()]);
132
+ const z = (0, group_1.scalarAdd)(k, (0, group_1.scalarMul)(e, w));
133
+ return { a: (0, group_1.encodePoint)(a), z: (0, group_1.encodeScalar)(z) };
134
+ }
135
+ function verifySchnorr(ctx, D, proof) {
136
+ const a = (0, group_1.decodePoint)(proof.a);
137
+ const z = (0, group_1.decodeScalar)(proof.z);
138
+ const e = (0, group_1.hashToScalar)([AGG_DOMAIN, ctx, D.toRawBytes(), a.toRawBytes()]);
139
+ return (0, group_1.mul)(group_1.H, z).equals((0, group_1.add)(a, (0, group_1.mul)(D, e)));
140
+ }
141
+ /**
142
+ * Prove that the committed aggregate satisfies Σrisk ≤ bMax, in zero knowledge over the individual
143
+ * risks. `risks`/`blindings` are the same per-action values used to build the commitments whose sum
144
+ * is passed to {@link verifyBudget}. If the aggregate is over budget (or the slack does not fit in
145
+ * N_BITS), the returned proof is well-formed but will be REJECTED by the verifier — soundness lives
146
+ * in verification, not in the prover trusting its own inputs.
147
+ */
148
+ function proveBudget(risks, blindings, bMax) {
149
+ if (risks.length !== blindings.length) {
150
+ throw new AccumulatorError('length_mismatch', 'risks and blindings must have equal length');
151
+ }
152
+ const bMaxUnits = asUnits(bMax);
153
+ let sumRisk = 0n;
154
+ let sumBlind = 0n;
155
+ for (let i = 0; i < risks.length; i++) {
156
+ sumRisk += asUnits(risks[i] ?? 0n);
157
+ sumBlind = (0, group_1.scalarAdd)(sumBlind, blindings[i] ?? 0n);
158
+ }
159
+ // Commitment sum (= what the verifier is given) and the slack commitment V = bMax·G − C_sum.
160
+ const cSum = (0, group_1.add)((0, group_1.mul)(group_1.G, (0, group_1.mod)(sumRisk)), (0, group_1.mul)(group_1.H, sumBlind));
161
+ const gamma = (0, group_1.mod)(-sumBlind); // blinding of V
162
+ const v = bMaxUnits - sumRisk; // slack (may be negative if over budget)
163
+ const mask = (1n << BigInt(exports.N_BITS)) - 1n;
164
+ const vMasked = v & mask; // low N_BITS bits (correct two's-complement low bits even if v < 0)
165
+ const bitCommitments = [];
166
+ const bitBlindings = [];
167
+ const bits = [];
168
+ for (let i = 0; i < exports.N_BITS; i++) {
169
+ const bit = (vMasked >> BigInt(i)) & 1n;
170
+ const s = (0, group_1.randScalar)();
171
+ bits.push(bit);
172
+ bitBlindings.push(s);
173
+ bitCommitments.push((0, group_1.add)((0, group_1.mul)(group_1.G, bit), (0, group_1.mul)(group_1.H, s)));
174
+ }
175
+ const ctx = contextHash(exports.N_BITS, bMaxUnits, cSum, bitCommitments);
176
+ const or = [];
177
+ for (let i = 0; i < exports.N_BITS; i++) {
178
+ or.push(proveBit(ctx, i, bitCommitments[i], bits[i], bitBlindings[i]));
179
+ }
180
+ // Aggregation: Σ 2^i·B_i = (Σ 2^i·b_i)·G + (Σ 2^i·s_i)·H = v'·G + sStar·H. When v' = v (in range),
181
+ // D = Σ2^i·B_i − V = (sStar − gamma)·H, a pure H-multiple whose dlog the prover knows.
182
+ let sStar = 0n;
183
+ let aggPoint = (0, group_1.mul)(group_1.G, 0n);
184
+ for (let i = 0; i < exports.N_BITS; i++) {
185
+ const w = 1n << BigInt(i);
186
+ sStar = (0, group_1.scalarAdd)(sStar, (0, group_1.scalarMul)(w, bitBlindings[i]));
187
+ aggPoint = (0, group_1.add)(aggPoint, (0, group_1.mul)(bitCommitments[i], w));
188
+ }
189
+ const V = (0, group_1.sub)((0, group_1.mul)(group_1.G, (0, group_1.mod)(bMaxUnits)), cSum);
190
+ const D = (0, group_1.sub)(aggPoint, V);
191
+ const delta = (0, group_1.scalarSub)(sStar, gamma);
192
+ const agg = proveSchnorr(ctx, D, delta);
193
+ return { n: exports.N_BITS, bitCommitments: bitCommitments.map(group_1.encodePoint), or, agg };
194
+ }
195
+ /**
196
+ * Verify a budget proof against the commitment sum and ceiling. Returns true only if every bit
197
+ * commitment opens to 0/1 and they aggregate to the slack commitment bMax·G − commitmentSum — i.e.
198
+ * Σrisk ≤ bMax. Learns nothing about the individual risks. Never throws; malformed input is false.
199
+ */
200
+ function verifyBudget(commitmentSum, bMax, proof) {
201
+ try {
202
+ if (proof === null || typeof proof !== 'object')
203
+ return false;
204
+ const { n, bitCommitments, or, agg } = proof;
205
+ if (n !== exports.N_BITS || !Array.isArray(bitCommitments) || !Array.isArray(or))
206
+ return false;
207
+ if (bitCommitments.length !== exports.N_BITS || or.length !== exports.N_BITS)
208
+ return false;
209
+ if (agg === null || typeof agg !== 'object')
210
+ return false;
211
+ const bMaxUnits = asUnits(bMax);
212
+ const cSum = (0, group_1.decodePoint)(commitmentSum);
213
+ const B = bitCommitments.map(group_1.decodePoint);
214
+ const ctx = contextHash(exports.N_BITS, bMaxUnits, cSum, B);
215
+ for (let i = 0; i < exports.N_BITS; i++) {
216
+ if (!verifyBit(ctx, i, B[i], or[i]))
217
+ return false;
218
+ }
219
+ let aggPoint = (0, group_1.mul)(group_1.G, 0n);
220
+ for (let i = 0; i < exports.N_BITS; i++) {
221
+ aggPoint = (0, group_1.add)(aggPoint, (0, group_1.mul)(B[i], 1n << BigInt(i)));
222
+ }
223
+ const V = (0, group_1.sub)((0, group_1.mul)(group_1.G, (0, group_1.mod)(bMaxUnits)), cSum);
224
+ const D = (0, group_1.sub)(aggPoint, V);
225
+ return verifySchnorr(ctx, D, agg);
226
+ }
227
+ catch {
228
+ return false;
229
+ }
230
+ }
231
+ //# sourceMappingURL=accumulator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accumulator.js","sourceRoot":"","sources":["../src/accumulator.ts"],"names":[],"mappings":";;;AAmGA,gCAKC;AAGD,wCAIC;AAGD,wCAQC;AAsFD,kCAoDC;AAOD,oCA2BC;AAtSD,mCAmBiB;AAEjB;;;;;;;;;;;;;;;;GAgBG;AAEH,8EAA8E;AACjE,QAAA,MAAM,GAAG,EAAE,CAAC;AAMzB,MAAa,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAuB;IACpC,YAAY,IAA0B,EAAE,OAAe;QACrD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAPD,4CAOC;AAkCD,SAAS,OAAO,CAAC,CAAY;IAC3B,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,GAAG,EAAE;YAAE,MAAM,IAAI,gBAAgB,CAAC,eAAe,EAAE,0BAA0B,CAAC,CAAC;QACpF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,gBAAgB,CAAC,eAAe,EAAE,4CAA4C,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,iGAAiG;AACjG,SAAgB,UAAU,CAAC,IAAe,EAAE,QAAiB;IAC3D,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,MAAM,CAAC,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAA,kBAAU,GAAE,CAAC,CAAC,CAAC,IAAA,WAAG,EAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,EAAE,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,OAAO,EAAE,UAAU,EAAE,IAAA,mBAAW,EAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,qGAAqG;AACrG,SAAgB,cAAc,CAAC,WAA8B;IAC3D,IAAI,GAAG,GAAG,IAAA,WAAG,EAAC,SAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW;IACjC,KAAK,MAAM,CAAC,IAAI,WAAW;QAAE,GAAG,GAAG,IAAA,WAAG,EAAC,GAAG,EAAE,IAAA,mBAAW,EAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,OAAO,IAAA,mBAAW,EAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,qGAAqG;AACrG,SAAgB,cAAc,CAAC,UAAkB,EAAE,IAAe,EAAE,QAAgB;IAClF,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,QAAQ,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,EAAE,IAAA,WAAG,EAAC,SAAC,EAAE,IAAA,WAAG,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvD,OAAO,IAAA,mBAAW,EAAC,UAAU,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,0FAA0F;AAE1F,MAAM,UAAU,GAAG,IAAA,YAAI,EAAC,iCAAiC,CAAC,CAAC;AAC3D,MAAM,SAAS,GAAG,IAAA,YAAI,EAAC,oCAAoC,CAAC,CAAC;AAC7D,MAAM,UAAU,GAAG,IAAA,YAAI,EAAC,iCAAiC,CAAC,CAAC;AAE3D,uFAAuF;AACvF,SAAS,WAAW,CAAC,CAAS,EAAE,SAAiB,EAAE,aAAoB,EAAE,cAAuB;IAC9F,MAAM,KAAK,GAAiB;QAC1B,UAAU;QACV,UAAU,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QACvB,IAAA,uBAAe,EAAC,IAAA,WAAG,EAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QACnC,aAAa,CAAC,UAAU,EAAE;KAC3B,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,cAAc;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3D,4FAA4F;IAC5F,OAAO,IAAA,uBAAe,EAAC,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,gGAAgG;AAChG,SAAS,QAAQ,CAAC,GAAe,EAAE,KAAa,EAAE,CAAQ,EAAE,CAAS,EAAE,CAAS;IAC9E,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,sCAAsC;IACpD,MAAM,EAAE,GAAG,IAAA,WAAG,EAAC,CAAC,EAAE,SAAC,CAAC,CAAC,CAAC,iCAAiC;IACvD,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9B,8DAA8D;IAC9D,MAAM,KAAK,GAAG,IAAA,kBAAU,GAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAA,kBAAU,GAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,KAAK,CAAC,EAAE,IAAA,WAAG,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAEpD,+CAA+C;IAC/C,MAAM,CAAC,GAAG,IAAA,kBAAU,GAAE,CAAC;IACvB,MAAM,KAAK,GAAG,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,CAAC;IAExB,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAC,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACxG,MAAM,KAAK,GAAG,IAAA,iBAAS,EAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAA,iBAAS,EAAC,CAAC,EAAE,IAAA,iBAAS,EAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAEhD,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;IACtC,OAAO,EAAE,EAAE,EAAE,IAAA,oBAAY,EAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAA,oBAAY,EAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAA,oBAAY,EAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAA,oBAAY,EAAC,EAAE,CAAC,EAAE,CAAC;AACpG,CAAC;AAED,SAAS,SAAS,CAAC,GAAe,EAAE,KAAa,EAAE,CAAQ,EAAE,KAAiB;IAC5E,MAAM,EAAE,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC;IACb,MAAM,EAAE,GAAG,IAAA,WAAG,EAAC,CAAC,EAAE,SAAC,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,EAAE,CAAC,EAAE,IAAA,WAAG,EAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,EAAE,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,EAAE,CAAC,EAAE,IAAA,WAAG,EAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAC,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACxG,OAAO,IAAA,iBAAS,EAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,wDAAwD;AACxD,SAAS,YAAY,CAAC,GAAe,EAAE,CAAQ,EAAE,CAAS;IACxD,MAAM,CAAC,GAAG,IAAA,kBAAU,GAAE,CAAC;IACvB,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,CAAC;IACpB,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAC,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,GAAG,IAAA,iBAAS,EAAC,CAAC,EAAE,IAAA,iBAAS,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC,EAAE,IAAA,mBAAW,EAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAA,oBAAY,EAAC,CAAC,CAAC,EAAE,CAAC;AACnD,CAAC;AAED,SAAS,aAAa,CAAC,GAAe,EAAE,CAAQ,EAAE,KAAmB;IACnE,MAAM,CAAC,GAAG,IAAA,mBAAW,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,IAAA,oBAAY,EAAC,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1E,OAAO,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAA,WAAG,EAAC,CAAC,EAAE,IAAA,WAAG,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,WAAW,CAAC,KAA2B,EAAE,SAA4B,EAAE,IAAe;IACpG,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,gBAAgB,CAAC,iBAAiB,EAAE,4CAA4C,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACnC,QAAQ,GAAG,IAAA,iBAAS,EAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,6FAA6F;IAC7F,MAAM,IAAI,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,IAAA,WAAG,EAAC,OAAO,CAAC,CAAC,EAAE,IAAA,WAAG,EAAC,SAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAA,WAAG,EAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,gBAAgB;IAE9C,MAAM,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,yCAAyC;IACxE,MAAM,IAAI,GAAG,CAAC,EAAE,IAAI,MAAM,CAAC,cAAM,CAAC,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,oEAAoE;IAE9F,MAAM,cAAc,GAAY,EAAE,CAAC;IACnC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,IAAA,kBAAU,GAAE,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrB,cAAc,CAAC,IAAI,CAAC,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,GAAG,CAAC,EAAE,IAAA,WAAG,EAAC,SAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,GAAG,GAAG,WAAW,CAAC,cAAM,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;IAEjE,MAAM,EAAE,GAAiB,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,cAAc,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,EAAE,YAAY,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,mGAAmG;IACnG,uFAAuF;IACvF,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,QAAQ,GAAU,IAAA,WAAG,EAAC,SAAC,EAAE,EAAE,CAAC,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1B,KAAK,GAAG,IAAA,iBAAS,EAAC,KAAK,EAAE,IAAA,iBAAS,EAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QACzD,QAAQ,GAAG,IAAA,WAAG,EAAC,QAAQ,EAAE,IAAA,WAAG,EAAC,cAAc,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,IAAA,WAAG,EAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5C,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,IAAA,iBAAS,EAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACtC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IAExC,OAAO,EAAE,CAAC,EAAE,cAAM,EAAE,cAAc,EAAE,cAAc,CAAC,GAAG,CAAC,mBAAW,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC;AACjF,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,aAAqB,EAAE,IAAe,EAAE,KAAkB;IACrF,IAAI,CAAC;QACH,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC9D,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;QAC7C,IAAI,CAAC,KAAK,cAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;QACvF,IAAI,cAAc,CAAC,MAAM,KAAK,cAAM,IAAI,EAAE,CAAC,MAAM,KAAK,cAAM;YAAE,OAAO,KAAK,CAAC;QAC3E,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAE1D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,IAAA,mBAAW,EAAC,aAAa,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,mBAAW,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,WAAW,CAAC,cAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAE,CAAC;gBAAE,OAAO,KAAK,CAAC;QACtD,CAAC;QAED,IAAI,QAAQ,GAAU,IAAA,WAAG,EAAC,SAAC,EAAE,EAAE,CAAC,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,QAAQ,GAAG,IAAA,WAAG,EAAC,QAAQ,EAAE,IAAA,WAAG,EAAC,CAAC,CAAC,CAAC,CAAE,EAAE,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,IAAA,WAAG,EAAC,SAAC,EAAE,IAAA,WAAG,EAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,GAAG,IAAA,WAAG,EAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { type PCActn, type RiskPolicy } from '@atlasauth/pca';
2
+ import { type RiskUnits } from './accumulator';
3
+ /**
4
+ * Thin adapters that bind the two cryptographic mechanisms to the existing PCA bookkeeping they
5
+ * replace. These map values only — they do NOT modify any @atlasauth/pca core type.
6
+ *
7
+ * - Mechanism 1 (ratchet) ↔ the PCActn spend-once `counter`.
8
+ * - Mechanism 2 (accumulator) ↔ the control-theoretic risk budget (RiskPolicy.bMax / kappa,
9
+ * whose cumulative bound is `safetyBound` = bMax/κ, i.e. Σrisk ≤ bMax/κ).
10
+ */
11
+ /**
12
+ * Map a PCActn's spend-once `counter` to a ratchet leaf index. The ratchet replaces the resource
13
+ * server's monotonic-counter check: spending counter `c` signs (and punctures) leaf `c`, so the
14
+ * same counter can never be re-used — "already spent" is enforced by the key no longer existing.
15
+ */
16
+ export declare function counterToLeafIndex(counter: number, depth: number): number;
17
+ /** Inverse of {@link counterToLeafIndex}: a leaf index is the spend-once counter it realizes. */
18
+ export declare function leafIndexToCounter(leafIndex: number): number;
19
+ /** Convenience: the ratchet leaf index for a PCActn, read straight off its `counter` field. */
20
+ export declare function leafIndexForAction(actn: Pick<PCActn, 'counter'>, depth: number): number;
21
+ /**
22
+ * Fixed-point scale for quantizing the core's continuous risk scores (r ∈ [0,1]) and budget into
23
+ * the integer units the Pedersen accumulator commits to. 1000 = millirisk resolution.
24
+ */
25
+ export declare const RISK_SCALE = 1000;
26
+ /** Quantize a core risk score (any finite r ≥ 0) to non-negative integer accumulator units. */
27
+ export declare function riskToUnits(r: number): RiskUnits;
28
+ /**
29
+ * The accumulator's budget ceiling in integer units, derived from a RiskPolicy. This is exactly the
30
+ * core cumulative-risk safety bound Σrisk ≤ bMax/κ (`safetyBound`), quantized — so the zero-knowledge
31
+ * `verifyBudget(..., budgetCeilingUnits(policy), ...)` proves the SAME inequality the control plane
32
+ * enforces, without revealing the per-action risks.
33
+ */
34
+ export declare function budgetCeilingUnits(policy: Pick<RiskPolicy, 'bMax' | 'kappa'>): RiskUnits;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RISK_SCALE = void 0;
4
+ exports.counterToLeafIndex = counterToLeafIndex;
5
+ exports.leafIndexToCounter = leafIndexToCounter;
6
+ exports.leafIndexForAction = leafIndexForAction;
7
+ exports.riskToUnits = riskToUnits;
8
+ exports.budgetCeilingUnits = budgetCeilingUnits;
9
+ const pca_1 = require("@atlasauth/pca");
10
+ const ggm_1 = require("./ggm");
11
+ const ratchet_1 = require("./ratchet");
12
+ const accumulator_1 = require("./accumulator");
13
+ /**
14
+ * Thin adapters that bind the two cryptographic mechanisms to the existing PCA bookkeeping they
15
+ * replace. These map values only — they do NOT modify any @atlasauth/pca core type.
16
+ *
17
+ * - Mechanism 1 (ratchet) ↔ the PCActn spend-once `counter`.
18
+ * - Mechanism 2 (accumulator) ↔ the control-theoretic risk budget (RiskPolicy.bMax / kappa,
19
+ * whose cumulative bound is `safetyBound` = bMax/κ, i.e. Σrisk ≤ bMax/κ).
20
+ */
21
+ // ---- Mechanism 1: ratchet leaf index ↔ PCActn.counter --------------------------------
22
+ /**
23
+ * Map a PCActn's spend-once `counter` to a ratchet leaf index. The ratchet replaces the resource
24
+ * server's monotonic-counter check: spending counter `c` signs (and punctures) leaf `c`, so the
25
+ * same counter can never be re-used — "already spent" is enforced by the key no longer existing.
26
+ */
27
+ function counterToLeafIndex(counter, depth) {
28
+ if (!Number.isInteger(depth) || depth < 1 || depth > ggm_1.MAX_RATCHET_DEPTH) {
29
+ throw new ratchet_1.RatchetError('invalid_depth', `depth must be an integer in [1, ${ggm_1.MAX_RATCHET_DEPTH}]`);
30
+ }
31
+ if (!Number.isSafeInteger(counter) || counter < 0) {
32
+ throw new ratchet_1.RatchetError('leaf_out_of_range', 'counter must be a non-negative safe integer');
33
+ }
34
+ if (counter >= 2 ** depth) {
35
+ throw new ratchet_1.RatchetError('leaf_out_of_range', `counter ${counter} exceeds the ratchet capacity 2^${depth}`);
36
+ }
37
+ return counter;
38
+ }
39
+ /** Inverse of {@link counterToLeafIndex}: a leaf index is the spend-once counter it realizes. */
40
+ function leafIndexToCounter(leafIndex) {
41
+ if (!Number.isSafeInteger(leafIndex) || leafIndex < 0) {
42
+ throw new ratchet_1.RatchetError('leaf_out_of_range', 'leafIndex must be a non-negative safe integer');
43
+ }
44
+ return leafIndex;
45
+ }
46
+ /** Convenience: the ratchet leaf index for a PCActn, read straight off its `counter` field. */
47
+ function leafIndexForAction(actn, depth) {
48
+ return counterToLeafIndex(actn.counter, depth);
49
+ }
50
+ // ---- Mechanism 2: accumulator units ↔ RiskPolicy budget ------------------------------
51
+ /**
52
+ * Fixed-point scale for quantizing the core's continuous risk scores (r ∈ [0,1]) and budget into
53
+ * the integer units the Pedersen accumulator commits to. 1000 = millirisk resolution.
54
+ */
55
+ exports.RISK_SCALE = 1000;
56
+ /** Quantize a core risk score (any finite r ≥ 0) to non-negative integer accumulator units. */
57
+ function riskToUnits(r) {
58
+ if (!Number.isFinite(r) || r < 0) {
59
+ throw new accumulator_1.AccumulatorError('invalid_value', 'risk must be a finite number >= 0');
60
+ }
61
+ return BigInt(Math.round(r * exports.RISK_SCALE));
62
+ }
63
+ /**
64
+ * The accumulator's budget ceiling in integer units, derived from a RiskPolicy. This is exactly the
65
+ * core cumulative-risk safety bound Σrisk ≤ bMax/κ (`safetyBound`), quantized — so the zero-knowledge
66
+ * `verifyBudget(..., budgetCeilingUnits(policy), ...)` proves the SAME inequality the control plane
67
+ * enforces, without revealing the per-action risks.
68
+ */
69
+ function budgetCeilingUnits(policy) {
70
+ const bound = (0, pca_1.safetyBound)(policy);
71
+ if (!Number.isFinite(bound) || bound < 0) {
72
+ throw new accumulator_1.AccumulatorError('invalid_value', 'safety bound (bMax/kappa) must be finite and >= 0');
73
+ }
74
+ return BigInt(Math.floor(bound * exports.RISK_SCALE));
75
+ }
76
+ //# sourceMappingURL=adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":";;;AAqBA,gDAWC;AAGD,gDAKC;AAGD,gDAEC;AAWD,kCAKC;AAQD,gDAMC;AA3ED,wCAA2E;AAC3E,+BAA0C;AAC1C,uCAAyC;AACzC,+CAAiE;AAEjE;;;;;;;GAOG;AAEH,yFAAyF;AAEzF;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,OAAe,EAAE,KAAa;IAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,uBAAiB,EAAE,CAAC;QACvE,MAAM,IAAI,sBAAY,CAAC,eAAe,EAAE,mCAAmC,uBAAiB,GAAG,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,sBAAY,CAAC,mBAAmB,EAAE,6CAA6C,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,IAAI,sBAAY,CAAC,mBAAmB,EAAE,WAAW,OAAO,mCAAmC,KAAK,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iGAAiG;AACjG,SAAgB,kBAAkB,CAAC,SAAiB;IAClD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,sBAAY,CAAC,mBAAmB,EAAE,+CAA+C,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,+FAA+F;AAC/F,SAAgB,kBAAkB,CAAC,IAA6B,EAAE,KAAa;IAC7E,OAAO,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,yFAAyF;AAEzF;;;GAGG;AACU,QAAA,UAAU,GAAG,IAAI,CAAC;AAE/B,+FAA+F;AAC/F,SAAgB,WAAW,CAAC,CAAS;IACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,8BAAgB,CAAC,eAAe,EAAE,mCAAmC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,kBAAU,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,MAA0C;IAC3E,MAAM,KAAK,GAAG,IAAA,iBAAW,EAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,8BAAgB,CAAC,eAAe,EAAE,mDAAmD,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,kBAAU,CAAC,CAAC,CAAC;AAChD,CAAC"}
package/dist/ggm.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ /** Longest tree accepted. Setup derives all 2^depth leaf public keys, so this bounds that cost. */
2
+ export declare const MAX_RATCHET_DEPTH = 20;
3
+ export interface CoverNode {
4
+ /** Distance from the root (0 = root, `depth` = leaf). */
5
+ level: number;
6
+ /** Index of the node within its level, 0 .. 2^level − 1. */
7
+ nodeIndex: number;
8
+ /** The node's GGM seed (secret). */
9
+ seed: Uint8Array;
10
+ }
11
+ /** The GGM root seed, normalized/domain-separated from caller-supplied entropy. */
12
+ export declare function rootSeed(seed: Uint8Array): Uint8Array;
13
+ /** Ed25519 32-byte signing seed for a leaf, derived from that leaf's GGM seed. */
14
+ export declare function leafSigningSeed(leafSeed: Uint8Array): Uint8Array;
15
+ /** b64u Ed25519 public key for a leaf's GGM seed. */
16
+ export declare function leafPublicKey(leafSeed: Uint8Array): string;
17
+ /** Does the subtree of node (level, nodeIndex) contain `leafIndex`? */
18
+ export declare function covers(level: number, nodeIndex: number, leafIndex: number, depth: number): boolean;
19
+ /** Derive the leaf GGM seed for `leafIndex` from a covering node that contains it. */
20
+ export declare function deriveLeafSeed(node: CoverNode, leafIndex: number, depth: number): Uint8Array;
21
+ /**
22
+ * Puncture `leafIndex` out of `node`'s subtree: return the off-path sibling covering nodes that
23
+ * together cover every leaf under `node` EXCEPT `leafIndex`. The on-path seeds (and the leaf seed
24
+ * itself) are never returned — they are dropped, which is what makes the puncture irreversible.
25
+ */
26
+ export declare function punctureSiblings(node: CoverNode, leafIndex: number, depth: number): CoverNode[];
27
+ /** Derive every leaf's public key from the root seed (used once, at setup, for the commitment). */
28
+ export declare function allLeafPublicKeys(root: Uint8Array, depth: number): string[];
29
+ export declare function coverKey(level: number, nodeIndex: number): string;
package/dist/ggm.js ADDED
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_RATCHET_DEPTH = void 0;
4
+ exports.rootSeed = rootSeed;
5
+ exports.leafSigningSeed = leafSigningSeed;
6
+ exports.leafPublicKey = leafPublicKey;
7
+ exports.covers = covers;
8
+ exports.deriveLeafSeed = deriveLeafSeed;
9
+ exports.punctureSiblings = punctureSiblings;
10
+ exports.allLeafPublicKeys = allLeafPublicKeys;
11
+ exports.coverKey = coverKey;
12
+ const hmac_1 = require("@noble/hashes/hmac");
13
+ const sha2_1 = require("@noble/hashes/sha2");
14
+ const ed25519_1 = require("@noble/curves/ed25519");
15
+ const pca_1 = require("@atlasauth/pca");
16
+ const group_1 = require("./group");
17
+ /**
18
+ * GGM binary-tree puncturable PRF (Mechanism 1 internals).
19
+ *
20
+ * A depth-`d` complete binary tree. The root holds a 32-byte seed; every internal node derives
21
+ * its two children with a length-doubling PRG built from HMAC-SHA256 (a PRF):
22
+ *
23
+ * PRG(seed) = ( HMAC(seed, DOMAIN‖0x00), HMAC(seed, DOMAIN‖0x01) )
24
+ *
25
+ * Each of the 2^d leaves derives a one-time Ed25519 signing seed from its own leaf seed
26
+ * (domain-separated again, so a leaf seed and its signing key are not the same bytes).
27
+ *
28
+ * PUNCTURING (forward security). The secret state is NOT the root seed; it is a *co-path*: a
29
+ * set of disjoint "covering" node seeds whose subtrees are exactly the still-available leaves.
30
+ * To puncture leaf i, the covering node above it is expanded down to i, each OFF-PATH sibling
31
+ * seed is retained as a new covering node, and every ON-PATH seed (including leaf i's own) is
32
+ * dropped. Because the PRG is one-way, a dropped seed can never be recovered from the retained
33
+ * siblings — leaf i's signing key is gone forever. See `ratchet.ts` for the public API.
34
+ */
35
+ const PRG_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/ggm-prg/v1');
36
+ const LEAFKEY_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/ggm-leafkey/v1');
37
+ const ROOT_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/ggm-root/v1');
38
+ /** Longest tree accepted. Setup derives all 2^depth leaf public keys, so this bounds that cost. */
39
+ exports.MAX_RATCHET_DEPTH = 20;
40
+ function prgLeft(seed) {
41
+ const m = new Uint8Array(PRG_DOMAIN.length + 1);
42
+ m.set(PRG_DOMAIN);
43
+ m[PRG_DOMAIN.length] = 0x00;
44
+ return (0, hmac_1.hmac)(sha2_1.sha256, seed, m);
45
+ }
46
+ function prgRight(seed) {
47
+ const m = new Uint8Array(PRG_DOMAIN.length + 1);
48
+ m.set(PRG_DOMAIN);
49
+ m[PRG_DOMAIN.length] = 0x01;
50
+ return (0, hmac_1.hmac)(sha2_1.sha256, seed, m);
51
+ }
52
+ /** The GGM root seed, normalized/domain-separated from caller-supplied entropy. */
53
+ function rootSeed(seed) {
54
+ return (0, hmac_1.hmac)(sha2_1.sha256, seed, ROOT_DOMAIN);
55
+ }
56
+ /** Ed25519 32-byte signing seed for a leaf, derived from that leaf's GGM seed. */
57
+ function leafSigningSeed(leafSeed) {
58
+ return (0, hmac_1.hmac)(sha2_1.sha256, leafSeed, LEAFKEY_DOMAIN);
59
+ }
60
+ /** b64u Ed25519 public key for a leaf's GGM seed. */
61
+ function leafPublicKey(leafSeed) {
62
+ return (0, pca_1.b64u)(ed25519_1.ed25519.getPublicKey(leafSigningSeed(leafSeed)));
63
+ }
64
+ /** Does the subtree of node (level, nodeIndex) contain `leafIndex`? */
65
+ function covers(level, nodeIndex, leafIndex, depth) {
66
+ return Math.floor(leafIndex / 2 ** (depth - level)) === nodeIndex;
67
+ }
68
+ /** The bit chosen when descending from `level` towards `leafIndex` (0 = left, 1 = right). */
69
+ function descendBit(level, leafIndex, depth) {
70
+ return Math.floor(leafIndex / 2 ** (depth - level - 1)) % 2;
71
+ }
72
+ /** Derive the leaf GGM seed for `leafIndex` from a covering node that contains it. */
73
+ function deriveLeafSeed(node, leafIndex, depth) {
74
+ let seed = node.seed;
75
+ for (let level = node.level; level < depth; level++) {
76
+ seed = descendBit(level, leafIndex, depth) === 0 ? prgLeft(seed) : prgRight(seed);
77
+ }
78
+ return seed;
79
+ }
80
+ /**
81
+ * Puncture `leafIndex` out of `node`'s subtree: return the off-path sibling covering nodes that
82
+ * together cover every leaf under `node` EXCEPT `leafIndex`. The on-path seeds (and the leaf seed
83
+ * itself) are never returned — they are dropped, which is what makes the puncture irreversible.
84
+ */
85
+ function punctureSiblings(node, leafIndex, depth) {
86
+ const out = [];
87
+ let seed = node.seed;
88
+ let nodeIndex = node.nodeIndex;
89
+ for (let level = node.level; level < depth; level++) {
90
+ const bit = descendBit(level, leafIndex, depth);
91
+ const left = prgLeft(seed);
92
+ const right = prgRight(seed);
93
+ const childBase = nodeIndex * 2;
94
+ out.push({
95
+ level: level + 1,
96
+ nodeIndex: childBase + (1 - bit),
97
+ seed: bit === 0 ? right : left,
98
+ });
99
+ seed = bit === 0 ? left : right;
100
+ nodeIndex = childBase + bit;
101
+ }
102
+ // (level === depth, nodeIndex === leafIndex, seed === leaf seed) is DROPPED.
103
+ return out;
104
+ }
105
+ /** Derive every leaf's public key from the root seed (used once, at setup, for the commitment). */
106
+ function allLeafPublicKeys(root, depth) {
107
+ const out = new Array(2 ** depth);
108
+ const recurse = (seed, level, base) => {
109
+ if (level === depth) {
110
+ out[base] = leafPublicKey(seed);
111
+ return;
112
+ }
113
+ const half = 2 ** (depth - level - 1);
114
+ recurse(prgLeft(seed), level + 1, base);
115
+ recurse(prgRight(seed), level + 1, base + half);
116
+ };
117
+ recurse(root, 0, 0);
118
+ return out;
119
+ }
120
+ function coverKey(level, nodeIndex) {
121
+ return `${level}:${nodeIndex}`;
122
+ }
123
+ //# sourceMappingURL=ggm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ggm.js","sourceRoot":"","sources":["../src/ggm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { RistrettoPoint } from '@noble/curves/ed25519';
2
+ /**
3
+ * Prime-order group layer for the homomorphic risk accumulator (Mechanism 2).
4
+ *
5
+ * Group: ristretto255 (RFC 9496) via @noble/curves. It is a prime-order group of order
6
+ * `L` (the ed25519 subgroup order), which is exactly what a Pedersen commitment / Schnorr
7
+ * Sigma-protocol needs: no cofactor, every non-identity point generates the whole group,
8
+ * and binding rests on the hardness of discrete log between the two independent generators.
9
+ *
10
+ * G = RistrettoPoint.BASE (the standard generator)
11
+ * H = RistrettoPoint.hashToCurve(sha512(label)) ("nothing-up-my-sleeve": nobody knows
12
+ * dlog_G(H), which is what makes the
13
+ * commitment binding)
14
+ *
15
+ * All Pedersen/Schnorr arithmetic is done on bigint scalars reduced mod L.
16
+ */
17
+ export type Point = InstanceType<typeof RistrettoPoint>;
18
+ /** Prime order of ristretto255 (= ed25519 subgroup order L). */
19
+ export declare const L: bigint;
20
+ /** The standard generator G. */
21
+ export declare const G: Point;
22
+ /** The identity element (commitment to 0 with blinding 0). */
23
+ export declare const ZERO: Point;
24
+ /**
25
+ * The second Pedersen generator H, derived by hash-to-group of a constant domain-separation
26
+ * label — independent of G, and with an unknown discrete log relative to G (nobody chose it
27
+ * with a known offset). Deterministic: the same label always yields the same H.
28
+ */
29
+ export declare const H: Point;
30
+ /** Reduce an integer into the scalar field [0, L). */
31
+ export declare function mod(x: bigint): bigint;
32
+ export declare function scalarAdd(a: bigint, b: bigint): bigint;
33
+ export declare function scalarSub(a: bigint, b: bigint): bigint;
34
+ export declare function scalarMul(a: bigint, b: bigint): bigint;
35
+ /**
36
+ * Scalar multiplication `k·P` that tolerates k ≡ 0 (mod L) by returning the identity —
37
+ * @noble's `multiply` rejects 0 and values ≥ L, so we reduce first and special-case 0.
38
+ */
39
+ export declare function mul(P: Point, k: bigint): Point;
40
+ export declare function add(a: Point, b: Point): Point;
41
+ export declare function sub(a: Point, b: Point): Point;
42
+ /** A uniformly random non-zero scalar in [1, L). */
43
+ export declare function randScalar(): bigint;
44
+ export declare function numberToBytesLE(n: bigint, len: number): Uint8Array;
45
+ export declare function bytesToNumberLE(b: Uint8Array): bigint;
46
+ export declare function encodePoint(P: Point): string;
47
+ /** Decode a wire point; throws on a non-canonical / invalid ristretto encoding. */
48
+ export declare function decodePoint(s: string): Point;
49
+ export declare function encodeScalar(k: bigint): string;
50
+ export declare function decodeScalar(s: string): bigint;
51
+ /**
52
+ * Length-prefixed concatenation so distinct part sequences can never collide (each part is
53
+ * prefixed with its 4-byte big-endian length). The transcript is hashed with SHA-512 and the
54
+ * digest reduced mod L to yield a challenge scalar.
55
+ */
56
+ export declare function hashToScalar(parts: Uint8Array[]): bigint;
57
+ export declare function utf8(s: string): Uint8Array;
package/dist/group.js ADDED
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.H = exports.ZERO = exports.G = exports.L = void 0;
4
+ exports.mod = mod;
5
+ exports.scalarAdd = scalarAdd;
6
+ exports.scalarSub = scalarSub;
7
+ exports.scalarMul = scalarMul;
8
+ exports.mul = mul;
9
+ exports.add = add;
10
+ exports.sub = sub;
11
+ exports.randScalar = randScalar;
12
+ exports.numberToBytesLE = numberToBytesLE;
13
+ exports.bytesToNumberLE = bytesToNumberLE;
14
+ exports.encodePoint = encodePoint;
15
+ exports.decodePoint = decodePoint;
16
+ exports.encodeScalar = encodeScalar;
17
+ exports.decodeScalar = decodeScalar;
18
+ exports.hashToScalar = hashToScalar;
19
+ exports.utf8 = utf8;
20
+ const ed25519_1 = require("@noble/curves/ed25519");
21
+ const sha2_1 = require("@noble/hashes/sha2");
22
+ const utils_1 = require("@noble/hashes/utils");
23
+ const pca_1 = require("@atlasauth/pca");
24
+ /** Prime order of ristretto255 (= ed25519 subgroup order L). */
25
+ exports.L = ed25519_1.ed25519.CURVE.n;
26
+ /** The standard generator G. */
27
+ exports.G = ed25519_1.RistrettoPoint.BASE;
28
+ /** The identity element (commitment to 0 with blinding 0). */
29
+ exports.ZERO = ed25519_1.RistrettoPoint.ZERO;
30
+ const H_LABEL = 'atlas-pca-ratchet/pedersen-generator-H/v1';
31
+ /**
32
+ * The second Pedersen generator H, derived by hash-to-group of a constant domain-separation
33
+ * label — independent of G, and with an unknown discrete log relative to G (nobody chose it
34
+ * with a known offset). Deterministic: the same label always yields the same H.
35
+ */
36
+ exports.H = ed25519_1.RistrettoPoint.hashToCurve((0, sha2_1.sha512)(new TextEncoder().encode(H_LABEL)));
37
+ /** Reduce an integer into the scalar field [0, L). */
38
+ function mod(x) {
39
+ const r = x % exports.L;
40
+ return r < 0n ? r + exports.L : r;
41
+ }
42
+ function scalarAdd(a, b) {
43
+ return mod(a + b);
44
+ }
45
+ function scalarSub(a, b) {
46
+ return mod(a - b);
47
+ }
48
+ function scalarMul(a, b) {
49
+ return mod(a * b);
50
+ }
51
+ /**
52
+ * Scalar multiplication `k·P` that tolerates k ≡ 0 (mod L) by returning the identity —
53
+ * @noble's `multiply` rejects 0 and values ≥ L, so we reduce first and special-case 0.
54
+ */
55
+ function mul(P, k) {
56
+ const s = mod(k);
57
+ return s === 0n ? exports.ZERO : P.multiply(s);
58
+ }
59
+ function add(a, b) {
60
+ return a.add(b);
61
+ }
62
+ function sub(a, b) {
63
+ return a.subtract(b);
64
+ }
65
+ /** A uniformly random non-zero scalar in [1, L). */
66
+ function randScalar() {
67
+ for (;;) {
68
+ const s = mod(bytesToNumberLE((0, utils_1.randomBytes)(64)));
69
+ if (s !== 0n)
70
+ return s;
71
+ }
72
+ }
73
+ // ---- little-endian scalar <-> bytes ---------------------------------------------------
74
+ function numberToBytesLE(n, len) {
75
+ if (n < 0n)
76
+ throw new RangeError('numberToBytesLE: negative');
77
+ const out = new Uint8Array(len);
78
+ let x = n;
79
+ for (let i = 0; i < len; i++) {
80
+ out[i] = Number(x & 0xffn);
81
+ x >>= 8n;
82
+ }
83
+ if (x !== 0n)
84
+ throw new RangeError('numberToBytesLE: overflow');
85
+ return out;
86
+ }
87
+ function bytesToNumberLE(b) {
88
+ let x = 0n;
89
+ for (let i = b.length - 1; i >= 0; i--) {
90
+ x = (x << 8n) | BigInt(b[i] ?? 0);
91
+ }
92
+ return x;
93
+ }
94
+ // ---- wire encoding (base64url, shared with @atlasauth/pca) ----------------------------
95
+ function encodePoint(P) {
96
+ return (0, pca_1.b64u)(P.toRawBytes());
97
+ }
98
+ /** Decode a wire point; throws on a non-canonical / invalid ristretto encoding. */
99
+ function decodePoint(s) {
100
+ return ed25519_1.RistrettoPoint.fromHex((0, pca_1.unb64u)(s));
101
+ }
102
+ function encodeScalar(k) {
103
+ return (0, pca_1.b64u)(numberToBytesLE(mod(k), 32));
104
+ }
105
+ function decodeScalar(s) {
106
+ return mod(bytesToNumberLE((0, pca_1.unb64u)(s)));
107
+ }
108
+ // ---- Fiat-Shamir transcript -----------------------------------------------------------
109
+ /**
110
+ * Length-prefixed concatenation so distinct part sequences can never collide (each part is
111
+ * prefixed with its 4-byte big-endian length). The transcript is hashed with SHA-512 and the
112
+ * digest reduced mod L to yield a challenge scalar.
113
+ */
114
+ function hashToScalar(parts) {
115
+ let total = 0;
116
+ for (const p of parts)
117
+ total += 4 + p.length;
118
+ const buf = new Uint8Array(total);
119
+ let o = 0;
120
+ for (const p of parts) {
121
+ buf[o] = (p.length >>> 24) & 0xff;
122
+ buf[o + 1] = (p.length >>> 16) & 0xff;
123
+ buf[o + 2] = (p.length >>> 8) & 0xff;
124
+ buf[o + 3] = p.length & 0xff;
125
+ o += 4;
126
+ buf.set(p, o);
127
+ o += p.length;
128
+ }
129
+ return mod(bytesToNumberLE((0, sha2_1.sha512)(buf)));
130
+ }
131
+ function utf8(s) {
132
+ return new TextEncoder().encode(s);
133
+ }
134
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @atlasauth/pca-ratchet — the PCA Capability Ratchet.
3
+ *
4
+ * Two original cryptographic primitives that replace PCA bookkeeping with cryptography:
5
+ *
6
+ * 1. Puncturable forward-secure capability keys (ratchet.ts): a GGM puncturable-PRF tree of
7
+ * one-time Ed25519 keys under a Merkle-root commitment. Signing a leaf permanently punctures
8
+ * it — cryptographic one-time-use for the PCActn spend-once counter.
9
+ *
10
+ * 2. Homomorphic risk accumulator (accumulator.ts): Pedersen commitments on ristretto255 with a
11
+ * zero-knowledge range proof that the committed aggregate stays under the control-theoretic
12
+ * budget ceiling (Σrisk ≤ bMax/κ) without revealing individual risks.
13
+ *
14
+ * adapters.ts binds both to the @atlasauth/pca core (PCActn.counter, RiskPolicy budget) without
15
+ * modifying it.
16
+ */
17
+ export { type RatchetErrorCode, type RatchetSignature, type RatchetState, RatchetError, deriveRatchetRoot, signAtLeaf, verifyLeafSignature, availableLeaves, isLeafAvailable, } from './ratchet';
18
+ export { MAX_RATCHET_DEPTH } from './ggm';
19
+ export { type AccumulatorErrorCode, type RiskUnits, type RiskCommitment, type BitOrProof, type SchnorrProof, type BudgetProof, N_BITS, AccumulatorError, commitRisk, addCommitments, openCommitment, proveBudget, verifyBudget, } from './accumulator';
20
+ export { RISK_SCALE, counterToLeafIndex, leafIndexToCounter, leafIndexForAction, riskToUnits, budgetCeilingUnits, } from './adapters';
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ /**
3
+ * @atlasauth/pca-ratchet — the PCA Capability Ratchet.
4
+ *
5
+ * Two original cryptographic primitives that replace PCA bookkeeping with cryptography:
6
+ *
7
+ * 1. Puncturable forward-secure capability keys (ratchet.ts): a GGM puncturable-PRF tree of
8
+ * one-time Ed25519 keys under a Merkle-root commitment. Signing a leaf permanently punctures
9
+ * it — cryptographic one-time-use for the PCActn spend-once counter.
10
+ *
11
+ * 2. Homomorphic risk accumulator (accumulator.ts): Pedersen commitments on ristretto255 with a
12
+ * zero-knowledge range proof that the committed aggregate stays under the control-theoretic
13
+ * budget ceiling (Σrisk ≤ bMax/κ) without revealing individual risks.
14
+ *
15
+ * adapters.ts binds both to the @atlasauth/pca core (PCActn.counter, RiskPolicy budget) without
16
+ * modifying it.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.budgetCeilingUnits = exports.riskToUnits = exports.leafIndexForAction = exports.leafIndexToCounter = exports.counterToLeafIndex = exports.RISK_SCALE = exports.verifyBudget = exports.proveBudget = exports.openCommitment = exports.addCommitments = exports.commitRisk = exports.AccumulatorError = exports.N_BITS = exports.MAX_RATCHET_DEPTH = exports.isLeafAvailable = exports.availableLeaves = exports.verifyLeafSignature = exports.signAtLeaf = exports.deriveRatchetRoot = exports.RatchetError = void 0;
20
+ var ratchet_1 = require("./ratchet");
21
+ Object.defineProperty(exports, "RatchetError", { enumerable: true, get: function () { return ratchet_1.RatchetError; } });
22
+ Object.defineProperty(exports, "deriveRatchetRoot", { enumerable: true, get: function () { return ratchet_1.deriveRatchetRoot; } });
23
+ Object.defineProperty(exports, "signAtLeaf", { enumerable: true, get: function () { return ratchet_1.signAtLeaf; } });
24
+ Object.defineProperty(exports, "verifyLeafSignature", { enumerable: true, get: function () { return ratchet_1.verifyLeafSignature; } });
25
+ Object.defineProperty(exports, "availableLeaves", { enumerable: true, get: function () { return ratchet_1.availableLeaves; } });
26
+ Object.defineProperty(exports, "isLeafAvailable", { enumerable: true, get: function () { return ratchet_1.isLeafAvailable; } });
27
+ var ggm_1 = require("./ggm");
28
+ Object.defineProperty(exports, "MAX_RATCHET_DEPTH", { enumerable: true, get: function () { return ggm_1.MAX_RATCHET_DEPTH; } });
29
+ var accumulator_1 = require("./accumulator");
30
+ Object.defineProperty(exports, "N_BITS", { enumerable: true, get: function () { return accumulator_1.N_BITS; } });
31
+ Object.defineProperty(exports, "AccumulatorError", { enumerable: true, get: function () { return accumulator_1.AccumulatorError; } });
32
+ Object.defineProperty(exports, "commitRisk", { enumerable: true, get: function () { return accumulator_1.commitRisk; } });
33
+ Object.defineProperty(exports, "addCommitments", { enumerable: true, get: function () { return accumulator_1.addCommitments; } });
34
+ Object.defineProperty(exports, "openCommitment", { enumerable: true, get: function () { return accumulator_1.openCommitment; } });
35
+ Object.defineProperty(exports, "proveBudget", { enumerable: true, get: function () { return accumulator_1.proveBudget; } });
36
+ Object.defineProperty(exports, "verifyBudget", { enumerable: true, get: function () { return accumulator_1.verifyBudget; } });
37
+ var adapters_1 = require("./adapters");
38
+ Object.defineProperty(exports, "RISK_SCALE", { enumerable: true, get: function () { return adapters_1.RISK_SCALE; } });
39
+ Object.defineProperty(exports, "counterToLeafIndex", { enumerable: true, get: function () { return adapters_1.counterToLeafIndex; } });
40
+ Object.defineProperty(exports, "leafIndexToCounter", { enumerable: true, get: function () { return adapters_1.leafIndexToCounter; } });
41
+ Object.defineProperty(exports, "leafIndexForAction", { enumerable: true, get: function () { return adapters_1.leafIndexForAction; } });
42
+ Object.defineProperty(exports, "riskToUnits", { enumerable: true, get: function () { return adapters_1.riskToUnits; } });
43
+ Object.defineProperty(exports, "budgetCeilingUnits", { enumerable: true, get: function () { return adapters_1.budgetCeilingUnits; } });
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAEH,qCAUmB;AANjB,uGAAA,YAAY,OAAA;AACZ,4GAAA,iBAAiB,OAAA;AACjB,qGAAA,UAAU,OAAA;AACV,8GAAA,mBAAmB,OAAA;AACnB,0GAAA,eAAe,OAAA;AACf,0GAAA,eAAe,OAAA;AAGjB,6BAA0C;AAAjC,wGAAA,iBAAiB,OAAA;AAE1B,6CAcuB;AAPrB,qGAAA,MAAM,OAAA;AACN,+GAAA,gBAAgB,OAAA;AAChB,yGAAA,UAAU,OAAA;AACV,6GAAA,cAAc,OAAA;AACd,6GAAA,cAAc,OAAA;AACd,0GAAA,WAAW,OAAA;AACX,2GAAA,YAAY,OAAA;AAGd,uCAOoB;AANlB,sGAAA,UAAU,OAAA;AACV,8GAAA,kBAAkB,OAAA;AAClB,8GAAA,kBAAkB,OAAA;AAClB,8GAAA,kBAAkB,OAAA;AAClB,uGAAA,WAAW,OAAA;AACX,8GAAA,kBAAkB,OAAA"}
@@ -0,0 +1,65 @@
1
+ import { type InclusionProof } from '@atlasauth/pca';
2
+ import { type CoverNode } from './ggm';
3
+ /**
4
+ * Mechanism 1 — Puncturable forward-secure capability keys (cryptographic one-time-use).
5
+ *
6
+ * A capability holder commits, up front, to a Merkle root over 2^depth one-time Ed25519 leaf
7
+ * keys (a GGM puncturable PRF tree; see ggm.ts). Signing at leaf `i` produces an offline-verifiable
8
+ * signature AND returns a new state in which leaf `i` is PUNCTURED: its key material is dropped and
9
+ * can never be re-derived, so the same leaf can never sign twice. This replaces the resource
10
+ * server's spend-once counter bookkeeping with cryptography — "already spent" becomes "key no
11
+ * longer exists", provable without shared state.
12
+ */
13
+ export type RatchetErrorCode = 'invalid_depth' | 'invalid_seed' | 'leaf_out_of_range' | 'leaf_punctured';
14
+ export declare class RatchetError extends Error {
15
+ readonly code: RatchetErrorCode;
16
+ constructor(code: RatchetErrorCode, message: string);
17
+ }
18
+ /** An offline-verifiable one-time signature at a ratchet leaf. */
19
+ export interface RatchetSignature {
20
+ /** b64u Ed25519 signature (64 bytes) under the leaf's one-time key. */
21
+ edSig: string;
22
+ /** b64u Ed25519 public key (32 bytes) of the signing leaf. */
23
+ leafPubKey: string;
24
+ /** Merkle inclusion proof that `leafPubKey` is the leaf at this index under the root commitment. */
25
+ merklePath: InclusionProof;
26
+ }
27
+ /**
28
+ * The live ratchet. `leafPubKeys` are public (safe to retain; needed to build Merkle proofs).
29
+ * `covering` is the SECRET co-path: disjoint GGM seeds whose subtrees are exactly the leaves that
30
+ * can still sign. Punctured leaves are absent from every covering subtree.
31
+ */
32
+ export interface RatchetState {
33
+ readonly depth: number;
34
+ readonly leafCount: number;
35
+ readonly rootCommitment: string;
36
+ readonly leafPubKeys: readonly string[];
37
+ readonly covering: ReadonlyMap<string, CoverNode>;
38
+ }
39
+ /**
40
+ * Build a ratchet from a root `seed` (≥ 32 bytes of entropy) and tree `depth`. Returns the public
41
+ * `rootCommitment` (a Merkle root over all 2^depth leaf public keys) and the live `state`.
42
+ */
43
+ export declare function deriveRatchetRoot(seed: Uint8Array, depth: number): {
44
+ rootCommitment: string;
45
+ state: RatchetState;
46
+ };
47
+ /**
48
+ * Sign `message` at leaf `leafIndex`, then puncture that leaf. Returns the signature and a new
49
+ * state with the leaf's key permanently dropped. Throws {@link RatchetError} if the leaf is out of
50
+ * range or already punctured (cryptographic one-time-use: a spent leaf can never sign again).
51
+ */
52
+ export declare function signAtLeaf(state: RatchetState, leafIndex: number, message: Uint8Array): {
53
+ signature: RatchetSignature;
54
+ newState: RatchetState;
55
+ };
56
+ /**
57
+ * Verify a ratchet signature offline against the root commitment, with no shared state: the
58
+ * Ed25519 signature must be valid under `leafPubKey`, and `merklePath` must prove `leafPubKey` is
59
+ * the leaf at `leafIndex` under `rootCommitment`. Never throws; any malformed input returns false.
60
+ */
61
+ export declare function verifyLeafSignature(rootCommitment: string, leafIndex: number, message: Uint8Array, signature: RatchetSignature): boolean;
62
+ /** Indices of leaves that can still sign (not yet punctured), sorted ascending. */
63
+ export declare function availableLeaves(state: RatchetState): number[];
64
+ /** Whether leaf `leafIndex` can still sign. */
65
+ export declare function isLeafAvailable(state: RatchetState, leafIndex: number): boolean;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RatchetError = void 0;
4
+ exports.deriveRatchetRoot = deriveRatchetRoot;
5
+ exports.signAtLeaf = signAtLeaf;
6
+ exports.verifyLeafSignature = verifyLeafSignature;
7
+ exports.availableLeaves = availableLeaves;
8
+ exports.isLeafAvailable = isLeafAvailable;
9
+ const ed25519_1 = require("@noble/curves/ed25519");
10
+ const pca_1 = require("@atlasauth/pca");
11
+ const ggm_1 = require("./ggm");
12
+ const group_1 = require("./group");
13
+ class RatchetError extends Error {
14
+ code;
15
+ constructor(code, message) {
16
+ super(message);
17
+ this.name = 'RatchetError';
18
+ this.code = code;
19
+ }
20
+ }
21
+ exports.RatchetError = RatchetError;
22
+ const SIG_DOMAIN = (0, group_1.utf8)('atlas-pca-ratchet/leaf-sig/v1\0');
23
+ /** Domain-separated signed message: binds the leaf index so a signature cannot be lifted elsewhere. */
24
+ function leafSigMessage(leafIndex, message) {
25
+ const idx = new Uint8Array(8);
26
+ let x = BigInt(leafIndex);
27
+ for (let i = 7; i >= 0; i--) {
28
+ idx[i] = Number(x & 0xffn);
29
+ x >>= 8n;
30
+ }
31
+ const out = new Uint8Array(SIG_DOMAIN.length + 8 + message.length);
32
+ out.set(SIG_DOMAIN, 0);
33
+ out.set(idx, SIG_DOMAIN.length);
34
+ out.set(message, SIG_DOMAIN.length + 8);
35
+ return out;
36
+ }
37
+ /**
38
+ * Build a ratchet from a root `seed` (≥ 32 bytes of entropy) and tree `depth`. Returns the public
39
+ * `rootCommitment` (a Merkle root over all 2^depth leaf public keys) and the live `state`.
40
+ */
41
+ function deriveRatchetRoot(seed, depth) {
42
+ if (!Number.isInteger(depth) || depth < 1 || depth > ggm_1.MAX_RATCHET_DEPTH) {
43
+ throw new RatchetError('invalid_depth', `depth must be an integer in [1, ${ggm_1.MAX_RATCHET_DEPTH}]`);
44
+ }
45
+ if (!(seed instanceof Uint8Array) || seed.length < 32) {
46
+ throw new RatchetError('invalid_seed', 'seed must be a Uint8Array of at least 32 bytes');
47
+ }
48
+ const root = (0, ggm_1.rootSeed)(seed);
49
+ const leafPubKeys = (0, ggm_1.allLeafPublicKeys)(root, depth);
50
+ const rootCommitment = (0, pca_1.merkleRoot)(leafPubKeys.slice());
51
+ const covering = new Map([[(0, ggm_1.coverKey)(0, 0), { level: 0, nodeIndex: 0, seed: root }]]);
52
+ return {
53
+ rootCommitment,
54
+ state: { depth, leafCount: 2 ** depth, rootCommitment, leafPubKeys, covering },
55
+ };
56
+ }
57
+ /** Find the (unique) covering node whose subtree contains `leafIndex`, or undefined if punctured. */
58
+ function findCovering(state, leafIndex) {
59
+ for (const node of state.covering.values()) {
60
+ if ((0, ggm_1.covers)(node.level, node.nodeIndex, leafIndex, state.depth))
61
+ return node;
62
+ }
63
+ return undefined;
64
+ }
65
+ /**
66
+ * Sign `message` at leaf `leafIndex`, then puncture that leaf. Returns the signature and a new
67
+ * state with the leaf's key permanently dropped. Throws {@link RatchetError} if the leaf is out of
68
+ * range or already punctured (cryptographic one-time-use: a spent leaf can never sign again).
69
+ */
70
+ function signAtLeaf(state, leafIndex, message) {
71
+ if (!Number.isInteger(leafIndex) || leafIndex < 0 || leafIndex >= state.leafCount) {
72
+ throw new RatchetError('leaf_out_of_range', `leaf ${leafIndex} is out of range [0, ${state.leafCount})`);
73
+ }
74
+ const node = findCovering(state, leafIndex);
75
+ if (node === undefined) {
76
+ throw new RatchetError('leaf_punctured', `leaf ${leafIndex} is already punctured (spent) and cannot sign`);
77
+ }
78
+ const leafSeed = (0, ggm_1.deriveLeafSeed)(node, leafIndex, state.depth);
79
+ const signingSeed = (0, ggm_1.leafSigningSeed)(leafSeed);
80
+ const edSig = (0, pca_1.b64u)(ed25519_1.ed25519.sign(leafSigMessage(leafIndex, message), signingSeed));
81
+ const leafPubKey = (0, ggm_1.leafPublicKey)(leafSeed);
82
+ const merklePath = (0, pca_1.merkleProof)(state.leafPubKeys.slice(), leafIndex);
83
+ // Puncture: replace the covering node with its off-path siblings; the on-path (and leaf) seeds vanish.
84
+ const covering = new Map(state.covering);
85
+ covering.delete((0, ggm_1.coverKey)(node.level, node.nodeIndex));
86
+ for (const sib of (0, ggm_1.punctureSiblings)(node, leafIndex, state.depth)) {
87
+ covering.set((0, ggm_1.coverKey)(sib.level, sib.nodeIndex), sib);
88
+ }
89
+ return {
90
+ signature: { edSig, leafPubKey, merklePath },
91
+ newState: { ...state, covering },
92
+ };
93
+ }
94
+ /**
95
+ * Verify a ratchet signature offline against the root commitment, with no shared state: the
96
+ * Ed25519 signature must be valid under `leafPubKey`, and `merklePath` must prove `leafPubKey` is
97
+ * the leaf at `leafIndex` under `rootCommitment`. Never throws; any malformed input returns false.
98
+ */
99
+ function verifyLeafSignature(rootCommitment, leafIndex, message, signature) {
100
+ try {
101
+ if (signature === null || typeof signature !== 'object')
102
+ return false;
103
+ const { edSig, leafPubKey, merklePath } = signature;
104
+ if (typeof edSig !== 'string' || typeof leafPubKey !== 'string' || merklePath === null || typeof merklePath !== 'object') {
105
+ return false;
106
+ }
107
+ if (merklePath.index !== leafIndex)
108
+ return false;
109
+ if (!(0, pca_1.verifyB64u)(leafPubKey, leafSigMessage(leafIndex, message), edSig))
110
+ return false;
111
+ return (0, pca_1.verifyInclusion)(rootCommitment, merklePath, leafPubKey);
112
+ }
113
+ catch {
114
+ return false;
115
+ }
116
+ }
117
+ /** Indices of leaves that can still sign (not yet punctured), sorted ascending. */
118
+ function availableLeaves(state) {
119
+ const out = [];
120
+ for (const node of state.covering.values()) {
121
+ const span = 2 ** (state.depth - node.level);
122
+ const base = node.nodeIndex * span;
123
+ for (let i = 0; i < span; i++)
124
+ out.push(base + i);
125
+ }
126
+ return out.sort((a, b) => a - b);
127
+ }
128
+ /** Whether leaf `leafIndex` can still sign. */
129
+ function isLeafAvailable(state, leafIndex) {
130
+ return findCovering(state, leafIndex) !== undefined;
131
+ }
132
+ //# sourceMappingURL=ratchet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratchet.js","sourceRoot":"","sources":["../src/ratchet.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,59 @@
1
1
  {
2
2
  "name": "@atlasauth/pca-ratchet",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.2.0",
4
+ "description": "PCA Capability Ratchet: puncturable forward-secure capability keys (cryptographic one-time-use — a spent action can never be re-signed) plus a homomorphic Pedersen risk accumulator for zero-knowledge proof of the Sigma-risk <= budget ceiling across a delegation chain.",
5
+ "keywords": [
6
+ "forward secrecy",
7
+ "puncturable keys",
8
+ "pedersen commitments",
9
+ "one-time use",
10
+ "agent authorization",
11
+ "proof-carrying authority",
12
+ "pca",
13
+ "ai agents"
14
+ ],
15
+ "license": "MIT",
16
+ "homepage": "https://github.com/Atlas-Authorization/pca#readme",
17
+ "bugs": {
18
+ "url": "https://github.com/Atlas-Authorization/pca/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/Atlas-Authorization/pca.git",
23
+ "directory": "packages/pca-ratchet"
24
+ },
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "dependencies": {
35
+ "@noble/curves": "^1.6.0",
36
+ "@noble/hashes": "^1.5.0",
37
+ "@atlasauth/pca": "0.2.0"
38
+ },
39
+ "devDependencies": {
40
+ "typescript": "^5.6.3",
41
+ "vitest": "^2.1.4"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "engines": {
49
+ "node": ">=20"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "build": "tsc -p tsconfig.build.json",
56
+ "typecheck": "tsc -p tsconfig.json --noEmit",
57
+ "test": "vitest run"
58
+ }
6
59
  }