@bolyra/sdk 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.
@@ -0,0 +1,82 @@
1
+ /** EdDSA identity for a human participant */
2
+ export interface HumanIdentity {
3
+ /** EdDSA secret scalar (KEEP PRIVATE) */
4
+ secret: bigint;
5
+ /** Baby Jubjub public key coordinates */
6
+ publicKey: {
7
+ x: bigint;
8
+ y: bigint;
9
+ };
10
+ /** Poseidon2(Ax, Ay) — leaf in humanTree */
11
+ commitment: bigint;
12
+ }
13
+ /** AI agent credential */
14
+ export interface AgentCredential {
15
+ modelHash: bigint;
16
+ operatorPublicKey: {
17
+ x: bigint;
18
+ y: bigint;
19
+ };
20
+ permissionBitmask: bigint;
21
+ expiryTimestamp: bigint;
22
+ /** EdDSA signature of operator over credential commitment */
23
+ signature: {
24
+ R8: {
25
+ x: bigint;
26
+ y: bigint;
27
+ };
28
+ S: bigint;
29
+ };
30
+ /** Poseidon5(modelHash, Ax, Ay, bitmask, expiry) — leaf in agentTree */
31
+ commitment: bigint;
32
+ }
33
+ /** Permission bits (cumulative encoding) */
34
+ export declare enum Permission {
35
+ READ_DATA = 0,
36
+ WRITE_DATA = 1,
37
+ FINANCIAL_SMALL = 2,// < $100
38
+ FINANCIAL_MEDIUM = 3,// < $10,000 (implies SMALL)
39
+ FINANCIAL_UNLIMITED = 4,// unlimited (implies MEDIUM + SMALL)
40
+ SIGN_ON_BEHALF = 5,
41
+ SUB_DELEGATE = 6,
42
+ ACCESS_PII = 7
43
+ }
44
+ /** Result of a mutual handshake verification */
45
+ export interface HandshakeResult {
46
+ /** Human's nullifier (unique per scope) */
47
+ humanNullifier: bigint;
48
+ /** Agent's nullifier (unique per session) */
49
+ agentNullifier: bigint;
50
+ /** Session nonce used */
51
+ sessionNonce: bigint;
52
+ /** Agent's scope commitment (chain seed for delegation) */
53
+ scopeCommitment: bigint;
54
+ /** Whether the handshake was verified on-chain */
55
+ verified: boolean;
56
+ }
57
+ /** Result of a delegation */
58
+ export interface DelegationResult {
59
+ /** New scope commitment for the next hop */
60
+ newScopeCommitment: bigint;
61
+ /** Delegation nullifier (unique per delegation per session) */
62
+ delegationNullifier: bigint;
63
+ /** Hop number in the chain (0-indexed) */
64
+ hopIndex: number;
65
+ }
66
+ /** Proof with public signals ready for on-chain verification */
67
+ export interface Proof {
68
+ proof: any;
69
+ publicSignals: string[];
70
+ }
71
+ /** Configuration for the SDK */
72
+ export interface BolyraConfig {
73
+ /** RPC URL for the target chain (default: Base Sepolia) */
74
+ rpcUrl?: string;
75
+ /** Address of the IdentityRegistry contract */
76
+ registryAddress?: string;
77
+ /** Path to circuit WASM files (default: bundled) */
78
+ circuitDir?: string;
79
+ /** Path to zkey files (default: bundled) */
80
+ zkeyDir?: string;
81
+ }
82
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,0BAA0B;AAC1B,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,SAAS,EAAE;QAAE,EAAE,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,4CAA4C;AAC5C,oBAAY,UAAU;IACpB,SAAS,IAAI;IACb,UAAU,IAAI;IACd,eAAe,IAAI,CAAM,SAAS;IAClC,gBAAgB,IAAI,CAAK,4BAA4B;IACrD,mBAAmB,IAAI,CAAE,qCAAqC;IAC9D,cAAc,IAAI;IAClB,YAAY,IAAI;IAChB,UAAU,IAAI;CACf;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,yBAAyB;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,6BAA6B;AAC7B,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gEAAgE;AAChE,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,GAAG,CAAC;IACX,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,gCAAgC;AAChC,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Permission = void 0;
4
+ /** Permission bits (cumulative encoding) */
5
+ var Permission;
6
+ (function (Permission) {
7
+ Permission[Permission["READ_DATA"] = 0] = "READ_DATA";
8
+ Permission[Permission["WRITE_DATA"] = 1] = "WRITE_DATA";
9
+ Permission[Permission["FINANCIAL_SMALL"] = 2] = "FINANCIAL_SMALL";
10
+ Permission[Permission["FINANCIAL_MEDIUM"] = 3] = "FINANCIAL_MEDIUM";
11
+ Permission[Permission["FINANCIAL_UNLIMITED"] = 4] = "FINANCIAL_UNLIMITED";
12
+ Permission[Permission["SIGN_ON_BEHALF"] = 5] = "SIGN_ON_BEHALF";
13
+ Permission[Permission["SUB_DELEGATE"] = 6] = "SUB_DELEGATE";
14
+ Permission[Permission["ACCESS_PII"] = 7] = "ACCESS_PII";
15
+ })(Permission || (exports.Permission = Permission = {}));
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAsBA,4CAA4C;AAC5C,IAAY,UASX;AATD,WAAY,UAAU;IACpB,qDAAa,CAAA;IACb,uDAAc,CAAA;IACd,iEAAmB,CAAA;IACnB,mEAAoB,CAAA;IACpB,yEAAuB,CAAA;IACvB,+DAAkB,CAAA;IAClB,2DAAgB,CAAA;IAChB,uDAAc,CAAA;AAChB,CAAC,EATW,UAAU,0BAAV,UAAU,QASrB"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Lazy-initialized crypto primitives.
3
+ * circomlibjs requires async factory calls; we cache them on first use.
4
+ */
5
+ /** Poseidon hash with 2 inputs. Returns a bigint. */
6
+ export declare function poseidon2(a: bigint, b: bigint): Promise<bigint>;
7
+ /** Poseidon hash with 5 inputs. Returns a bigint. */
8
+ export declare function poseidon5(a: bigint, b: bigint, c: bigint, d: bigint, e: bigint): Promise<bigint>;
9
+ /**
10
+ * Derive EdDSA public key from a private key buffer (Baby Jubjub).
11
+ * Uses eddsa.prv2pub which matches what EdDSAPoseidonVerifier expects:
12
+ * hash the key, clamp bits per RFC 8032, then multiply base point.
13
+ *
14
+ * IMPORTANT: This is NOT the same as babyJub.mulPointEscalar(Base8, scalar).
15
+ * The HumanUniqueness circuit uses BabyPbk (direct scalar multiply) for
16
+ * the human identity. The AgentPolicy circuit uses EdDSAPoseidonVerifier
17
+ * which expects prv2pub-derived keys. Use the right function for each.
18
+ */
19
+ export declare function derivePublicKey(secret: bigint | Buffer): Promise<{
20
+ x: bigint;
21
+ y: bigint;
22
+ }>;
23
+ /**
24
+ * Derive public key via direct scalar multiplication (Baby Jubjub).
25
+ * Used by HumanUniqueness circuit's BabyPbk component.
26
+ */
27
+ export declare function derivePublicKeyScalar(secret: bigint): Promise<{
28
+ x: bigint;
29
+ y: bigint;
30
+ }>;
31
+ /** Sign a message (field element) with EdDSA. */
32
+ export declare function eddsaSign(privateKey: bigint | Buffer, message: bigint): Promise<{
33
+ R8: {
34
+ x: bigint;
35
+ y: bigint;
36
+ };
37
+ S: bigint;
38
+ }>;
39
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,qDAAqD;AACrD,wBAAsB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIrE;AAED,qDAAqD;AACrD,wBAAsB,SAAS,CAC7B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,OAAO,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYnC;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAOnC;AAED,iDAAiD;AACjD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,EAAE,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAYtD"}
package/dist/utils.js ADDED
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Lazy-initialized crypto primitives.
4
+ * circomlibjs requires async factory calls; we cache them on first use.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.poseidon2 = poseidon2;
41
+ exports.poseidon5 = poseidon5;
42
+ exports.derivePublicKey = derivePublicKey;
43
+ exports.derivePublicKeyScalar = derivePublicKeyScalar;
44
+ exports.eddsaSign = eddsaSign;
45
+ let _poseidon = null;
46
+ let _eddsa = null;
47
+ let _babyJub = null;
48
+ let _F = null;
49
+ async function ensureCrypto() {
50
+ if (_poseidon)
51
+ return;
52
+ const circomlibjs = await Promise.resolve().then(() => __importStar(require('circomlibjs')));
53
+ _poseidon = await circomlibjs.buildPoseidon();
54
+ _eddsa = await circomlibjs.buildEddsa();
55
+ _babyJub = await circomlibjs.buildBabyjub();
56
+ _F = _poseidon.F;
57
+ }
58
+ /** Poseidon hash with 2 inputs. Returns a bigint. */
59
+ async function poseidon2(a, b) {
60
+ await ensureCrypto();
61
+ const hash = _poseidon([a, b]);
62
+ return _F.toObject(hash);
63
+ }
64
+ /** Poseidon hash with 5 inputs. Returns a bigint. */
65
+ async function poseidon5(a, b, c, d, e) {
66
+ await ensureCrypto();
67
+ const hash = _poseidon([a, b, c, d, e]);
68
+ return _F.toObject(hash);
69
+ }
70
+ /**
71
+ * Derive EdDSA public key from a private key buffer (Baby Jubjub).
72
+ * Uses eddsa.prv2pub which matches what EdDSAPoseidonVerifier expects:
73
+ * hash the key, clamp bits per RFC 8032, then multiply base point.
74
+ *
75
+ * IMPORTANT: This is NOT the same as babyJub.mulPointEscalar(Base8, scalar).
76
+ * The HumanUniqueness circuit uses BabyPbk (direct scalar multiply) for
77
+ * the human identity. The AgentPolicy circuit uses EdDSAPoseidonVerifier
78
+ * which expects prv2pub-derived keys. Use the right function for each.
79
+ */
80
+ async function derivePublicKey(secret) {
81
+ await ensureCrypto();
82
+ const key = typeof secret === 'bigint'
83
+ ? Buffer.from(secret.toString(16).padStart(64, '0'), 'hex')
84
+ : secret;
85
+ // Use eddsa.prv2pub which matches EdDSAPoseidonVerifier's key derivation
86
+ const pubKey = _eddsa.prv2pub(key);
87
+ return {
88
+ x: _F.toObject(pubKey[0]),
89
+ y: _F.toObject(pubKey[1]),
90
+ };
91
+ }
92
+ /**
93
+ * Derive public key via direct scalar multiplication (Baby Jubjub).
94
+ * Used by HumanUniqueness circuit's BabyPbk component.
95
+ */
96
+ async function derivePublicKeyScalar(secret) {
97
+ await ensureCrypto();
98
+ const pubKey = _babyJub.mulPointEscalar(_babyJub.Base8, secret);
99
+ return {
100
+ x: _F.toObject(pubKey[0]),
101
+ y: _F.toObject(pubKey[1]),
102
+ };
103
+ }
104
+ /** Sign a message (field element) with EdDSA. */
105
+ async function eddsaSign(privateKey, message) {
106
+ await ensureCrypto();
107
+ const key = typeof privateKey === 'bigint'
108
+ ? Buffer.from(privateKey.toString(16).padStart(64, '0'), 'hex')
109
+ : privateKey;
110
+ const msgFe = _F.e(message);
111
+ const sig = _eddsa.signPoseidon(key, msgFe);
112
+ return {
113
+ R8: { x: _F.toObject(sig.R8[0]), y: _F.toObject(sig.R8[1]) },
114
+ S: sig.S,
115
+ };
116
+ }
117
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@bolyra/sdk",
3
+ "version": "0.2.0",
4
+ "description": "TypeScript SDK for Bolyra — mutual ZKP authentication for humans and AI agents",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "test": "jest --passWithNoTests",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@semaphore-protocol/core": "^4.14.0",
14
+ "snarkjs": "^0.7.4",
15
+ "circomlibjs": "^0.1.7",
16
+ "ethers": "^6.13.0"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.5.0",
20
+ "@types/node": "^22.0.0",
21
+ "jest": "^29.7.0",
22
+ "ts-jest": "^29.2.0",
23
+ "@types/jest": "^29.5.0"
24
+ },
25
+ "files": [
26
+ "dist/",
27
+ "src/"
28
+ ],
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/bolyra/bolyra"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "license": "MIT"
37
+ }
@@ -0,0 +1,5 @@
1
+ declare module 'circomlibjs' {
2
+ export function buildPoseidon(): Promise<any>;
3
+ export function buildEddsa(): Promise<any>;
4
+ export function buildBabyjub(): Promise<any>;
5
+ }
@@ -0,0 +1,45 @@
1
+ import { BolyraError } from './errors';
2
+ import { DelegationResult, Proof, BolyraConfig, AgentCredential } from './types';
3
+
4
+ /**
5
+ * Delegate scoped permissions to another agent.
6
+ * Currently a stub -- full implementation requires the delegation circuit zkey.
7
+ *
8
+ * @param delegator - The delegating agent's credential
9
+ * @param delegatee - The receiving agent's credential
10
+ * @param parentScopeCommitment - Scope commitment from the parent handshake or delegation
11
+ * @param hopIndex - Current hop index in the delegation chain (0-indexed)
12
+ * @param config - SDK configuration
13
+ * @returns Delegation proof ready for on-chain verification
14
+ */
15
+ export async function delegate(
16
+ _delegator: AgentCredential,
17
+ _delegatee: AgentCredential,
18
+ _parentScopeCommitment: bigint,
19
+ _hopIndex: number,
20
+ _config?: BolyraConfig,
21
+ ): Promise<{ proof: Proof; result: DelegationResult }> {
22
+ throw new BolyraError(
23
+ 'delegate() coming in @bolyra/sdk v0.3 — delegation circuit integration.',
24
+ 'NOT_IMPLEMENTED',
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Verify a delegation proof on-chain.
30
+ *
31
+ * @param proof - The delegation ZK proof
32
+ * @param parentScopeCommitment - Expected parent scope commitment
33
+ * @param config - SDK configuration
34
+ * @returns DelegationResult with new scope commitment and hop index
35
+ */
36
+ export async function verifyDelegation(
37
+ _proof: Proof,
38
+ _parentScopeCommitment: bigint,
39
+ _config?: BolyraConfig,
40
+ ): Promise<DelegationResult> {
41
+ throw new BolyraError(
42
+ 'verifyDelegation() coming in @bolyra/sdk v0.3.',
43
+ 'NOT_IMPLEMENTED',
44
+ );
45
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,69 @@
1
+ export class BolyraError extends Error {
2
+ constructor(
3
+ message: string,
4
+ public code: string,
5
+ public details?: Record<string, unknown>
6
+ ) {
7
+ super(message);
8
+ this.name = 'BolyraError';
9
+ }
10
+ }
11
+
12
+ export class ProofGenerationError extends BolyraError {
13
+ constructor(circuit: string, reason: string) {
14
+ super(
15
+ `Failed to generate ${circuit} proof: ${reason}`,
16
+ 'PROOF_GENERATION_FAILED',
17
+ { circuit, reason }
18
+ );
19
+ }
20
+ }
21
+
22
+ export class VerificationError extends BolyraError {
23
+ constructor(reason: string) {
24
+ super(
25
+ `On-chain verification failed: ${reason}`,
26
+ 'VERIFICATION_FAILED',
27
+ { reason }
28
+ );
29
+ }
30
+ }
31
+
32
+ export class InvalidPermissionError extends BolyraError {
33
+ constructor(message: string) {
34
+ super(message, 'INVALID_PERMISSION');
35
+ }
36
+ }
37
+
38
+ export class ExpiredCredentialError extends BolyraError {
39
+ constructor(expiryTimestamp: bigint) {
40
+ super(
41
+ `Agent credential expired at ${expiryTimestamp}`,
42
+ 'CREDENTIAL_EXPIRED',
43
+ { expiryTimestamp: expiryTimestamp.toString() }
44
+ );
45
+ }
46
+ }
47
+
48
+ export class ScopeEscalationError extends BolyraError {
49
+ constructor(delegatorScope: bigint, requestedScope: bigint) {
50
+ super(
51
+ `Delegation scope escalation: delegatee scope (${requestedScope}) is not a subset of delegator scope (${delegatorScope})`,
52
+ 'SCOPE_ESCALATION',
53
+ {
54
+ delegatorScope: delegatorScope.toString(),
55
+ requestedScope: requestedScope.toString(),
56
+ }
57
+ );
58
+ }
59
+ }
60
+
61
+ export class StaleProofError extends BolyraError {
62
+ constructor(rootType: 'human' | 'agent') {
63
+ super(
64
+ `${rootType} Merkle root is stale — the tree was updated after proof generation. Regenerate the proof.`,
65
+ 'STALE_MERKLE_ROOT',
66
+ { rootType }
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,186 @@
1
+ import * as snarkjs from 'snarkjs';
2
+ import * as path from 'path';
3
+ import {
4
+ HumanIdentity,
5
+ AgentCredential,
6
+ HandshakeResult,
7
+ Proof,
8
+ BolyraConfig,
9
+ } from './types';
10
+ import { ProofGenerationError } from './errors';
11
+
12
+ // Default paths to circuit artifacts (relative to package root)
13
+ const DEFAULT_CIRCUIT_DIR = path.join(__dirname, '../../circuits/build');
14
+
15
+ /**
16
+ * Generate a mutual handshake proof (human + agent).
17
+ * Both proofs can be generated in parallel for wall-clock optimization.
18
+ *
19
+ * @param human - The human's identity (secret + publicKey + commitment)
20
+ * @param agent - The agent's credential (signed by operator)
21
+ * @param options - Optional scope, nonce override, and SDK config
22
+ * @returns Both proofs and the session nonce
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const { humanProof, agentProof, nonce } = await proveHandshake(
27
+ * humanIdentity,
28
+ * agentCredential,
29
+ * { scope: 1n }
30
+ * );
31
+ * // Submit both proofs to IdentityRegistry.verifyHandshake()
32
+ * ```
33
+ */
34
+ export async function proveHandshake(
35
+ human: HumanIdentity,
36
+ agent: AgentCredential,
37
+ options?: {
38
+ scope?: bigint;
39
+ nonce?: bigint;
40
+ config?: BolyraConfig;
41
+ },
42
+ ): Promise<{ humanProof: Proof; agentProof: Proof; nonce: bigint }> {
43
+ const scope = options?.scope ?? 1n;
44
+ const nonce = options?.nonce ?? BigInt(Date.now());
45
+ const circuitDir = options?.config?.circuitDir ?? DEFAULT_CIRCUIT_DIR;
46
+
47
+ // Generate both proofs in parallel
48
+ const [humanProof, agentProof] = await Promise.all([
49
+ generateHumanProof(human, scope, nonce, circuitDir),
50
+ generateAgentProof(agent, nonce, circuitDir),
51
+ ]);
52
+
53
+ return { humanProof, agentProof, nonce };
54
+ }
55
+
56
+ async function generateHumanProof(
57
+ human: HumanIdentity,
58
+ scope: bigint,
59
+ nonce: bigint,
60
+ circuitDir: string,
61
+ ): Promise<Proof> {
62
+ const wasmPath = path.join(
63
+ circuitDir,
64
+ 'HumanUniqueness_js/HumanUniqueness.wasm',
65
+ );
66
+ const zkeyPath = path.join(circuitDir, 'HumanUniqueness_final.zkey');
67
+
68
+ // Build Merkle proof inputs (single leaf: depth 0, padded to 20)
69
+ const siblings = new Array(20).fill('0');
70
+
71
+ const input = {
72
+ secret: human.secret.toString(),
73
+ merkleProofLength: '0', // depth 0 for single-leaf tree
74
+ merkleProofIndex: '0',
75
+ merkleProofSiblings: siblings,
76
+ scope: scope.toString(),
77
+ sessionNonce: nonce.toString(),
78
+ };
79
+
80
+ try {
81
+ const { proof, publicSignals } = await snarkjs.groth16.fullProve(
82
+ input,
83
+ wasmPath,
84
+ zkeyPath,
85
+ );
86
+ return { proof, publicSignals };
87
+ } catch (err: any) {
88
+ throw new ProofGenerationError(
89
+ 'HumanUniqueness',
90
+ err.message ?? String(err),
91
+ );
92
+ }
93
+ }
94
+
95
+ async function generateAgentProof(
96
+ agent: AgentCredential,
97
+ nonce: bigint,
98
+ circuitDir: string,
99
+ ): Promise<Proof> {
100
+ const wasmPath = path.join(
101
+ circuitDir,
102
+ 'AgentPolicy_js/AgentPolicy.wasm',
103
+ );
104
+ const zkeyPath = path.join(circuitDir, 'AgentPolicy_plonk.zkey');
105
+
106
+ const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
107
+ const requiredScopeMask = 0n; // no required scope for basic handshake
108
+
109
+ const siblings = new Array(20).fill('0');
110
+
111
+ const input = {
112
+ modelHash: agent.modelHash.toString(),
113
+ operatorPubkeyAx: agent.operatorPublicKey.x.toString(),
114
+ operatorPubkeyAy: agent.operatorPublicKey.y.toString(),
115
+ permissionBitmask: agent.permissionBitmask.toString(),
116
+ expiryTimestamp: agent.expiryTimestamp.toString(),
117
+ sigR8x: agent.signature.R8.x.toString(),
118
+ sigR8y: agent.signature.R8.y.toString(),
119
+ sigS: agent.signature.S.toString(),
120
+ merkleProofLength: '0',
121
+ merkleProofIndex: '0',
122
+ merkleProofSiblings: siblings,
123
+ requiredScopeMask: requiredScopeMask.toString(),
124
+ currentTimestamp: currentTimestamp.toString(),
125
+ sessionNonce: nonce.toString(),
126
+ };
127
+
128
+ try {
129
+ const { proof, publicSignals } = await snarkjs.plonk.fullProve(
130
+ input,
131
+ wasmPath,
132
+ zkeyPath,
133
+ );
134
+ return { proof, publicSignals };
135
+ } catch (err: any) {
136
+ throw new ProofGenerationError(
137
+ 'AgentPolicy',
138
+ err.message ?? String(err),
139
+ );
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Verify a handshake result (check proof validity without on-chain submission).
145
+ * For on-chain verification, submit proofs to IdentityRegistry.verifyHandshake().
146
+ *
147
+ * @param humanProof - The human's ZK proof
148
+ * @param agentProof - The agent's ZK proof
149
+ * @param nonce - The session nonce used during proof generation
150
+ * @param config - SDK configuration (circuitDir for vkey paths)
151
+ * @returns HandshakeResult with nullifiers and verification status
152
+ */
153
+ export async function verifyHandshake(
154
+ humanProof: Proof,
155
+ agentProof: Proof,
156
+ nonce: bigint,
157
+ config?: BolyraConfig,
158
+ ): Promise<HandshakeResult> {
159
+ const circuitDir = config?.circuitDir ?? DEFAULT_CIRCUIT_DIR;
160
+
161
+ // Verify human proof (Groth16)
162
+ const humanVkeyPath = path.join(circuitDir, 'HumanUniqueness_vkey.json');
163
+ const humanVkey = require(humanVkeyPath);
164
+ const humanValid = await snarkjs.groth16.verify(
165
+ humanVkey,
166
+ humanProof.publicSignals,
167
+ humanProof.proof,
168
+ );
169
+
170
+ // Verify agent proof (PLONK)
171
+ const agentVkeyPath = path.join(circuitDir, 'AgentPolicy_vkey.json');
172
+ const agentVkey = require(agentVkeyPath);
173
+ const agentValid = await snarkjs.plonk.verify(
174
+ agentVkey,
175
+ agentProof.publicSignals,
176
+ agentProof.proof,
177
+ );
178
+
179
+ return {
180
+ humanNullifier: BigInt(humanProof.publicSignals[1]),
181
+ agentNullifier: BigInt(agentProof.publicSignals[1]),
182
+ sessionNonce: nonce,
183
+ scopeCommitment: BigInt(agentProof.publicSignals[2]),
184
+ verified: humanValid && agentValid,
185
+ };
186
+ }