reputrans 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +114 -0
- package/circuits/composite/target/composite.json +1 -0
- package/circuits/field_disclosure/target/field_disclosure.json +1 -0
- package/circuits/map_to_curve/target/map_to_curve.json +1 -0
- package/circuits/poseidon_compat/target/poseidon_compat.json +1 -0
- package/circuits/range_proof/target/range_proof.json +1 -0
- package/circuits/set_membership/target/set_membership.json +1 -0
- package/circuits/signature_verify/target/signature_verify.json +1 -0
- package/dist/cli/src/auto-detect.d.ts +9 -0
- package/dist/cli/src/auto-detect.d.ts.map +1 -0
- package/dist/cli/src/auto-detect.js +21 -0
- package/dist/cli/src/auto-detect.js.map +1 -0
- package/dist/cli/src/commands/inspect.d.ts +6 -0
- package/dist/cli/src/commands/inspect.d.ts.map +1 -0
- package/dist/cli/src/commands/inspect.js +43 -0
- package/dist/cli/src/commands/inspect.js.map +1 -0
- package/dist/cli/src/commands/issue.d.ts +8 -0
- package/dist/cli/src/commands/issue.d.ts.map +1 -0
- package/dist/cli/src/commands/issue.js +107 -0
- package/dist/cli/src/commands/issue.js.map +1 -0
- package/dist/cli/src/commands/keygen.d.ts +7 -0
- package/dist/cli/src/commands/keygen.d.ts.map +1 -0
- package/dist/cli/src/commands/keygen.js +39 -0
- package/dist/cli/src/commands/keygen.js.map +1 -0
- package/dist/cli/src/commands/prove.d.ts +9 -0
- package/dist/cli/src/commands/prove.d.ts.map +1 -0
- package/dist/cli/src/commands/prove.js +139 -0
- package/dist/cli/src/commands/prove.js.map +1 -0
- package/dist/cli/src/commands/verify.d.ts +6 -0
- package/dist/cli/src/commands/verify.d.ts.map +1 -0
- package/dist/cli/src/commands/verify.js +63 -0
- package/dist/cli/src/commands/verify.js.map +1 -0
- package/dist/cli/src/index.d.ts +3 -0
- package/dist/cli/src/index.d.ts.map +1 -0
- package/dist/cli/src/index.js +45 -0
- package/dist/cli/src/index.js.map +1 -0
- package/dist/sdk/src/circuit-loader.d.ts +19 -0
- package/dist/sdk/src/circuit-loader.d.ts.map +1 -0
- package/dist/sdk/src/circuit-loader.js +65 -0
- package/dist/sdk/src/circuit-loader.js.map +1 -0
- package/dist/sdk/src/eddsa.d.ts +63 -0
- package/dist/sdk/src/eddsa.d.ts.map +1 -0
- package/dist/sdk/src/eddsa.js +177 -0
- package/dist/sdk/src/eddsa.js.map +1 -0
- package/dist/sdk/src/encoder.d.ts +49 -0
- package/dist/sdk/src/encoder.d.ts.map +1 -0
- package/dist/sdk/src/encoder.js +117 -0
- package/dist/sdk/src/encoder.js.map +1 -0
- package/dist/sdk/src/identity.d.ts +69 -0
- package/dist/sdk/src/identity.d.ts.map +1 -0
- package/dist/sdk/src/identity.js +110 -0
- package/dist/sdk/src/identity.js.map +1 -0
- package/dist/sdk/src/index.d.ts +18 -0
- package/dist/sdk/src/index.d.ts.map +1 -0
- package/dist/sdk/src/index.js +18 -0
- package/dist/sdk/src/index.js.map +1 -0
- package/dist/sdk/src/poseidon.d.ts +33 -0
- package/dist/sdk/src/poseidon.d.ts.map +1 -0
- package/dist/sdk/src/poseidon.js +59 -0
- package/dist/sdk/src/poseidon.js.map +1 -0
- package/dist/sdk/src/proof-request.d.ts +58 -0
- package/dist/sdk/src/proof-request.d.ts.map +1 -0
- package/dist/sdk/src/proof-request.js +68 -0
- package/dist/sdk/src/proof-request.js.map +1 -0
- package/dist/sdk/src/prover.d.ts +38 -0
- package/dist/sdk/src/prover.d.ts.map +1 -0
- package/dist/sdk/src/prover.js +108 -0
- package/dist/sdk/src/prover.js.map +1 -0
- package/dist/sdk/src/vc-parser.d.ts +50 -0
- package/dist/sdk/src/vc-parser.d.ts.map +1 -0
- package/dist/sdk/src/vc-parser.js +96 -0
- package/dist/sdk/src/vc-parser.js.map +1 -0
- package/dist/sdk/src/verifier.d.ts +19 -0
- package/dist/sdk/src/verifier.d.ts.map +1 -0
- package/dist/sdk/src/verifier.js +31 -0
- package/dist/sdk/src/verifier.js.map +1 -0
- package/dist/verifier/src/did-resolver.d.ts +36 -0
- package/dist/verifier/src/did-resolver.d.ts.map +1 -0
- package/dist/verifier/src/did-resolver.js +179 -0
- package/dist/verifier/src/did-resolver.js.map +1 -0
- package/dist/verifier/src/index.d.ts +2 -0
- package/dist/verifier/src/index.d.ts.map +1 -0
- package/dist/verifier/src/index.js +9 -0
- package/dist/verifier/src/index.js.map +1 -0
- package/dist/verifier/src/server.d.ts +6 -0
- package/dist/verifier/src/server.d.ts.map +1 -0
- package/dist/verifier/src/server.js +75 -0
- package/dist/verifier/src/server.js.map +1 -0
- package/dist/verifier/src/verify.d.ts +20 -0
- package/dist/verifier/src/verify.d.ts.map +1 -0
- package/dist/verifier/src/verify.js +97 -0
- package/dist/verifier/src/verify.js.map +1 -0
- package/package.json +41 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* W3C Verifiable Credential parser for REPUTRANS.
|
|
3
|
+
*
|
|
4
|
+
* Parses W3C VC JSON-LD into typed objects, validates required fields,
|
|
5
|
+
* and extracts credentialSubject for downstream encoding.
|
|
6
|
+
*/
|
|
7
|
+
const REQUIRED_FIELDS = ['@context', 'type', 'issuer', 'credentialSubject', 'proof'];
|
|
8
|
+
export class VCParseError extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'VCParseError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse a W3C Verifiable Credential from a JSON string or object.
|
|
16
|
+
* Validates all required fields are present.
|
|
17
|
+
*/
|
|
18
|
+
export function parseVC(input) {
|
|
19
|
+
let obj;
|
|
20
|
+
if (typeof input === 'string') {
|
|
21
|
+
try {
|
|
22
|
+
obj = JSON.parse(input);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new VCParseError('Invalid JSON');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
obj = input;
|
|
30
|
+
}
|
|
31
|
+
if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
|
|
32
|
+
throw new VCParseError('VC must be a JSON object');
|
|
33
|
+
}
|
|
34
|
+
// Validate required fields
|
|
35
|
+
for (const field of REQUIRED_FIELDS) {
|
|
36
|
+
if (!(field in obj) || obj[field] === undefined || obj[field] === null) {
|
|
37
|
+
throw new VCParseError(`Missing required field: ${field}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Validate @context
|
|
41
|
+
const context = obj['@context'];
|
|
42
|
+
if (typeof context !== 'string' && !Array.isArray(context)) {
|
|
43
|
+
throw new VCParseError('@context must be a string or array');
|
|
44
|
+
}
|
|
45
|
+
// Validate type
|
|
46
|
+
const type = obj['type'];
|
|
47
|
+
if (typeof type !== 'string' && !Array.isArray(type)) {
|
|
48
|
+
throw new VCParseError('type must be a string or array');
|
|
49
|
+
}
|
|
50
|
+
// Validate issuer
|
|
51
|
+
const issuer = obj['issuer'];
|
|
52
|
+
if (typeof issuer !== 'string' && (typeof issuer !== 'object' || issuer === null)) {
|
|
53
|
+
throw new VCParseError('issuer must be a string or object with id');
|
|
54
|
+
}
|
|
55
|
+
// Validate credentialSubject
|
|
56
|
+
const subject = obj['credentialSubject'];
|
|
57
|
+
if (typeof subject !== 'object' || subject === null || Array.isArray(subject)) {
|
|
58
|
+
throw new VCParseError('credentialSubject must be a JSON object');
|
|
59
|
+
}
|
|
60
|
+
// Validate proof
|
|
61
|
+
const proof = obj['proof'];
|
|
62
|
+
if (typeof proof !== 'object' || proof === null || Array.isArray(proof)) {
|
|
63
|
+
throw new VCParseError('proof must be a JSON object');
|
|
64
|
+
}
|
|
65
|
+
if (typeof proof['type'] !== 'string') {
|
|
66
|
+
throw new VCParseError('proof.type is required and must be a string');
|
|
67
|
+
}
|
|
68
|
+
return obj;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Extract credentialSubject fields as a flat key-value map.
|
|
72
|
+
* Nested objects are JSON-stringified.
|
|
73
|
+
*/
|
|
74
|
+
export function extractSubjectFields(vc) {
|
|
75
|
+
const result = {};
|
|
76
|
+
for (const [key, value] of Object.entries(vc.credentialSubject)) {
|
|
77
|
+
if (key === 'id')
|
|
78
|
+
continue; // skip subject id
|
|
79
|
+
if (typeof value === 'object' && value !== null) {
|
|
80
|
+
result[key] = JSON.stringify(value);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
result[key] = String(value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get the issuer ID string regardless of issuer format.
|
|
90
|
+
*/
|
|
91
|
+
export function getIssuerId(vc) {
|
|
92
|
+
if (typeof vc.issuer === 'string')
|
|
93
|
+
return vc.issuer;
|
|
94
|
+
return vc.issuer.id;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=vc-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vc-parser.js","sourceRoot":"","sources":["../../../sdk/src/vc-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side proof verification for REPUTRANS Arbiters.
|
|
3
|
+
*
|
|
4
|
+
* Uses @noir-lang/backend_barretenberg to verify proofs locally
|
|
5
|
+
* (useful for testing/development and off-chain verification).
|
|
6
|
+
*/
|
|
7
|
+
import type { CompiledCircuit } from './prover.js';
|
|
8
|
+
import type { ProofResponse } from './proof-request.js';
|
|
9
|
+
export interface Verifier {
|
|
10
|
+
/** Verify a proof response. Returns true if valid. */
|
|
11
|
+
verifyProof(response: ProofResponse): Promise<boolean>;
|
|
12
|
+
/** Destroy the verifier and free WASM resources. */
|
|
13
|
+
destroy(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a verifier instance from a compiled circuit JSON.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createVerifier(circuit: CompiledCircuit): Promise<Verifier>;
|
|
19
|
+
//# sourceMappingURL=verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../../sdk/src/verifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvD,oDAAoD;IACpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,CAqBhF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side proof verification for REPUTRANS Arbiters.
|
|
3
|
+
*
|
|
4
|
+
* Uses @noir-lang/backend_barretenberg to verify proofs locally
|
|
5
|
+
* (useful for testing/development and off-chain verification).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Create a verifier instance from a compiled circuit JSON.
|
|
9
|
+
*/
|
|
10
|
+
export async function createVerifier(circuit) {
|
|
11
|
+
const { BarretenbergBackend } = await import('@noir-lang/backend_barretenberg');
|
|
12
|
+
const backend = new BarretenbergBackend(circuit);
|
|
13
|
+
return {
|
|
14
|
+
async verifyProof(response) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await backend.verifyProof({
|
|
17
|
+
proof: response.proof,
|
|
18
|
+
publicInputs: response.publicInputs,
|
|
19
|
+
});
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
async destroy() {
|
|
27
|
+
await backend.destroy?.();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../../sdk/src/verifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB;IAC3D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,iCAAiC,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,IAAI,mBAAmB,CAAC,OAAc,CAAC,CAAC;IAExD,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,QAAuB;YACvC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC;oBACvC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,YAAY,EAAE,QAAQ,CAAC,YAAY;iBACpC,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAO,OAAe,CAAC,OAAO,EAAE,EAAE,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DID resolver for Arbiter use - resolves DIDs to EdDSA public keys.
|
|
3
|
+
* Supports did:key and did:web methods.
|
|
4
|
+
*/
|
|
5
|
+
export interface EdDSAPublicKey {
|
|
6
|
+
ax: bigint;
|
|
7
|
+
ay: bigint;
|
|
8
|
+
}
|
|
9
|
+
export interface DIDDocument {
|
|
10
|
+
id: string;
|
|
11
|
+
verificationMethod?: VerificationMethod[];
|
|
12
|
+
}
|
|
13
|
+
export interface VerificationMethod {
|
|
14
|
+
id: string;
|
|
15
|
+
type: string;
|
|
16
|
+
controller: string;
|
|
17
|
+
publicKeyMultibase?: string;
|
|
18
|
+
publicKeyJwk?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
export declare class DIDResolver {
|
|
21
|
+
private cache;
|
|
22
|
+
private ttlMs;
|
|
23
|
+
constructor(ttlMs?: number);
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a DID to its document.
|
|
26
|
+
*/
|
|
27
|
+
resolve(did: string): Promise<DIDDocument>;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a DID and extract the EdDSA Baby Jubjub public key (Ax, Ay).
|
|
30
|
+
* Looks for a verification method with type BabyJubJubKey2021 or EdDSABabyJubJubVerificationKey.
|
|
31
|
+
*/
|
|
32
|
+
getEdDSAPublicKey(did: string): Promise<EdDSAPublicKey>;
|
|
33
|
+
clearCache(): void;
|
|
34
|
+
}
|
|
35
|
+
export declare const defaultResolver: DIDResolver;
|
|
36
|
+
//# sourceMappingURL=did-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did-resolver.d.ts","sourceRoot":"","sources":["../../../verifier/src/did-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,kBAAkB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AASD,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,SAAiB;IAIlC;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAmBhD;;;OAGG;IACG,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAuB7D,UAAU,IAAI,IAAI;CAGnB;AA0ID,eAAO,MAAM,eAAe,aAAoB,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DID resolver for Arbiter use - resolves DIDs to EdDSA public keys.
|
|
3
|
+
* Supports did:key and did:web methods.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
6
|
+
export class DIDResolver {
|
|
7
|
+
cache = new Map();
|
|
8
|
+
ttlMs;
|
|
9
|
+
constructor(ttlMs = DEFAULT_TTL_MS) {
|
|
10
|
+
this.ttlMs = ttlMs;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a DID to its document.
|
|
14
|
+
*/
|
|
15
|
+
async resolve(did) {
|
|
16
|
+
const cached = this.cache.get(did);
|
|
17
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
18
|
+
return cached.doc;
|
|
19
|
+
}
|
|
20
|
+
let doc;
|
|
21
|
+
if (did.startsWith('did:key:')) {
|
|
22
|
+
doc = resolveDIDKey(did);
|
|
23
|
+
}
|
|
24
|
+
else if (did.startsWith('did:web:')) {
|
|
25
|
+
doc = await resolveDIDWeb(did);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw new Error(`Unsupported DID method: ${did}`);
|
|
29
|
+
}
|
|
30
|
+
this.cache.set(did, { doc, expiresAt: Date.now() + this.ttlMs });
|
|
31
|
+
return doc;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a DID and extract the EdDSA Baby Jubjub public key (Ax, Ay).
|
|
35
|
+
* Looks for a verification method with type BabyJubJubKey2021 or EdDSABabyJubJubVerificationKey.
|
|
36
|
+
*/
|
|
37
|
+
async getEdDSAPublicKey(did) {
|
|
38
|
+
const doc = await this.resolve(did);
|
|
39
|
+
const methods = doc.verificationMethod ?? [];
|
|
40
|
+
for (const method of methods) {
|
|
41
|
+
if (method.type === 'BabyJubJubKey2021' ||
|
|
42
|
+
method.type === 'EdDSABabyJubJubVerificationKey') {
|
|
43
|
+
return extractBabyJubJubKey(method);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Fall back: look for any key with JWK crv=BabyJubJub
|
|
47
|
+
for (const method of methods) {
|
|
48
|
+
if (method.publicKeyJwk?.crv === 'BabyJubJub') {
|
|
49
|
+
return extractBabyJubJubKey(method);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`No BabyJubJub verification key found in DID document: ${did}`);
|
|
53
|
+
}
|
|
54
|
+
clearCache() {
|
|
55
|
+
this.cache.clear();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// -- did:key resolution --
|
|
59
|
+
/**
|
|
60
|
+
* Resolve a did:key DID.
|
|
61
|
+
* For BabyJubJub keys the multibase identifier uses the 0xed01 multicodec prefix (draft).
|
|
62
|
+
* This constructs a minimal DID document; callers embed Ax/Ay in publicKeyMultibase.
|
|
63
|
+
*/
|
|
64
|
+
function resolveDIDKey(did) {
|
|
65
|
+
const id = did;
|
|
66
|
+
const keyId = `${did}#${did.slice('did:key:'.length)}`;
|
|
67
|
+
return {
|
|
68
|
+
id,
|
|
69
|
+
verificationMethod: [
|
|
70
|
+
{
|
|
71
|
+
id: keyId,
|
|
72
|
+
type: 'BabyJubJubKey2021',
|
|
73
|
+
controller: id,
|
|
74
|
+
publicKeyMultibase: did.slice('did:key:'.length),
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// -- did:web resolution --
|
|
80
|
+
async function resolveDIDWeb(did) {
|
|
81
|
+
// did:web:example.com -> https://example.com/.well-known/did.json
|
|
82
|
+
// did:web:example.com:path:sub -> https://example.com/path/sub/did.json
|
|
83
|
+
const withoutPrefix = did.slice('did:web:'.length);
|
|
84
|
+
const parts = withoutPrefix.split(':');
|
|
85
|
+
const host = decodeURIComponent(parts[0]);
|
|
86
|
+
let urlPath;
|
|
87
|
+
if (parts.length === 1) {
|
|
88
|
+
urlPath = '/.well-known/did.json';
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
urlPath = '/' + parts.slice(1).map(decodeURIComponent).join('/') + '/did.json';
|
|
92
|
+
}
|
|
93
|
+
const url = `https://${host}${urlPath}`;
|
|
94
|
+
const response = await fetch(url, {
|
|
95
|
+
headers: { Accept: 'application/json' },
|
|
96
|
+
signal: AbortSignal.timeout(10_000),
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw new Error(`did:web fetch failed for ${url}: HTTP ${response.status}`);
|
|
100
|
+
}
|
|
101
|
+
const doc = (await response.json());
|
|
102
|
+
if (doc.id !== did) {
|
|
103
|
+
throw new Error(`did:web document id mismatch: got ${doc.id}, expected ${did}`);
|
|
104
|
+
}
|
|
105
|
+
return doc;
|
|
106
|
+
}
|
|
107
|
+
// -- Key extraction --
|
|
108
|
+
/**
|
|
109
|
+
* Extract Ax, Ay from a verification method.
|
|
110
|
+
* Expects publicKeyMultibase as "z" + base58(concat(Ax_le_32bytes, Ay_le_32bytes))
|
|
111
|
+
* OR publicKeyJwk with x and y as base64url-encoded 32-byte little-endian values.
|
|
112
|
+
*/
|
|
113
|
+
function extractBabyJubJubKey(method) {
|
|
114
|
+
if (method.publicKeyJwk) {
|
|
115
|
+
const { x, y } = method.publicKeyJwk;
|
|
116
|
+
if (!x || !y)
|
|
117
|
+
throw new Error('JWK missing x or y');
|
|
118
|
+
return {
|
|
119
|
+
ax: base64urlToBigintLE(x),
|
|
120
|
+
ay: base64urlToBigintLE(y),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
if (method.publicKeyMultibase) {
|
|
124
|
+
const mb = method.publicKeyMultibase;
|
|
125
|
+
if (!mb.startsWith('z')) {
|
|
126
|
+
throw new Error('Only base58btc (z prefix) multibase supported for BabyJubJub keys');
|
|
127
|
+
}
|
|
128
|
+
const bytes = base58Decode(mb.slice(1));
|
|
129
|
+
// Strip 2-byte multicodec prefix if present
|
|
130
|
+
const keyBytes = bytes.length === 66 ? bytes.slice(2) : bytes;
|
|
131
|
+
if (keyBytes.length !== 64) {
|
|
132
|
+
throw new Error(`Expected 64 key bytes, got ${keyBytes.length}`);
|
|
133
|
+
}
|
|
134
|
+
const ax = bytesToBigintLE(keyBytes.slice(0, 32));
|
|
135
|
+
const ay = bytesToBigintLE(keyBytes.slice(32, 64));
|
|
136
|
+
return { ax, ay };
|
|
137
|
+
}
|
|
138
|
+
throw new Error('No supported key encoding in verification method');
|
|
139
|
+
}
|
|
140
|
+
// -- Encoding helpers --
|
|
141
|
+
function base64urlToBigintLE(b64url) {
|
|
142
|
+
const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
|
|
143
|
+
const binary = atob(b64);
|
|
144
|
+
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
145
|
+
return bytesToBigintLE(bytes);
|
|
146
|
+
}
|
|
147
|
+
function bytesToBigintLE(bytes) {
|
|
148
|
+
let result = 0n;
|
|
149
|
+
for (let i = bytes.length - 1; i >= 0; i--) {
|
|
150
|
+
result = (result << 8n) | BigInt(bytes[i]);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
155
|
+
function base58Decode(input) {
|
|
156
|
+
let num = 0n;
|
|
157
|
+
for (const char of input) {
|
|
158
|
+
const idx = BASE58_ALPHABET.indexOf(char);
|
|
159
|
+
if (idx === -1)
|
|
160
|
+
throw new Error(`Invalid base58 character: ${char}`);
|
|
161
|
+
num = num * 58n + BigInt(idx);
|
|
162
|
+
}
|
|
163
|
+
const bytes = [];
|
|
164
|
+
while (num > 0n) {
|
|
165
|
+
bytes.unshift(Number(num & 0xffn));
|
|
166
|
+
num >>= 8n;
|
|
167
|
+
}
|
|
168
|
+
// Leading zeros
|
|
169
|
+
for (const char of input) {
|
|
170
|
+
if (char === '1')
|
|
171
|
+
bytes.unshift(0);
|
|
172
|
+
else
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
return Uint8Array.from(bytes);
|
|
176
|
+
}
|
|
177
|
+
// Default singleton resolver
|
|
178
|
+
export const defaultResolver = new DIDResolver();
|
|
179
|
+
//# sourceMappingURL=did-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did-resolver.js","sourceRoot":"","sources":["../../../verifier/src/did-resolver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;AAElD,MAAM,OAAO,WAAW;IACd,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IACtC,KAAK,CAAS;IAEtB,YAAY,KAAK,GAAG,cAAc;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5C,OAAO,MAAM,CAAC,GAAG,CAAC;QACpB,CAAC;QAED,IAAI,GAAgB,CAAC;QACrB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,GAAG,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACjE,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,iBAAiB,CAAC,GAAW;QACjC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAE7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IACE,MAAM,CAAC,IAAI,KAAK,mBAAmB;gBACnC,MAAM,CAAC,IAAI,KAAK,gCAAgC,EAChD,CAAC;gBACD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,MAAM,CAAC,YAAY,EAAE,GAAG,KAAK,YAAY,EAAE,CAAC;gBAC9C,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,yDAAyD,GAAG,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAED,2BAA2B;AAE3B;;;;GAIG;AACH,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,EAAE,GAAG,GAAG,CAAC;IACf,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IAEvD,OAAO;QACL,EAAE;QACF,kBAAkB,EAAE;YAClB;gBACE,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,mBAAmB;gBACzB,UAAU,EAAE,EAAE;gBACd,kBAAkB,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;aACjD;SACF;KACF,CAAC;AACJ,CAAC;AAED,2BAA2B;AAE3B,KAAK,UAAU,aAAa,CAAC,GAAW;IACtC,kEAAkE;IAClE,wEAAwE;IACxE,MAAM,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE1C,IAAI,OAAe,CAAC;IACpB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,uBAAuB,CAAC;IACpC,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;IACjF,CAAC;IAED,MAAM,GAAG,GAAG,WAAW,IAAI,GAAG,OAAO,EAAE,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;QACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;KACpC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,GAAG,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAgB,CAAC;IAEnD,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,EAAE,cAAc,GAAG,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,uBAAuB;AAEvB;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,MAA0B;IACtD,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;QACrC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACpD,OAAO;YACL,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;YAC1B,EAAE,EAAE,mBAAmB,CAAC,CAAC,CAAC;SAC3B,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,EAAE,GAAG,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACnD,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IACpB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACtE,CAAC;AAED,yBAAyB;AAEzB,SAAS,mBAAmB,CAAC,MAAc;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,eAAe,CAAC,KAAiB;IACxC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,eAAe,GAAG,4DAA4D,CAAC;AAErF,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;QACrE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,OAAO,GAAG,GAAG,EAAE,EAAE,CAAC;QAChB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC;QACnC,GAAG,KAAK,EAAE,CAAC;IACb,CAAC;IACD,gBAAgB;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;;YAC9B,MAAM;IACb,CAAC;IACD,OAAO,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,6BAA6B;AAC7B,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../verifier/src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createServer } from './server.js';
|
|
2
|
+
const PORT = parseInt(process.env.PORT ?? '3000', 10);
|
|
3
|
+
const LOG_LEVEL = process.env.LOG_LEVEL ?? 'info';
|
|
4
|
+
const CIRCUIT_PATH = process.env.CIRCUIT_PATH ?? '../circuits';
|
|
5
|
+
const app = createServer({ logLevel: LOG_LEVEL, circuitPath: CIRCUIT_PATH });
|
|
6
|
+
app.listen(PORT, () => {
|
|
7
|
+
console.log(`[reputrans-verifier] listening on port ${PORT}`);
|
|
8
|
+
});
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../verifier/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AACtD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC;AAClD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,aAAa,CAAC;AAE/D,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,CAAC;AAE7E,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../verifier/src/server.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,+CAgFhD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import rateLimit from 'express-rate-limit';
|
|
4
|
+
import { verifyProof, listCircuits } from './verify.js';
|
|
5
|
+
const START_TIME = Date.now();
|
|
6
|
+
export function createServer(config) {
|
|
7
|
+
const app = express();
|
|
8
|
+
const corsOrigins = process.env.CORS_ORIGINS?.split(',') || false;
|
|
9
|
+
app.use(cors({ origin: corsOrigins }));
|
|
10
|
+
app.use(express.json());
|
|
11
|
+
const verifyLimiter = rateLimit({
|
|
12
|
+
windowMs: 60 * 1000,
|
|
13
|
+
max: 20,
|
|
14
|
+
standardHeaders: true,
|
|
15
|
+
legacyHeaders: false,
|
|
16
|
+
message: { valid: false, error: 'Too many verification requests, try again later' },
|
|
17
|
+
});
|
|
18
|
+
// Minimal request logging
|
|
19
|
+
app.use((req, _res, next) => {
|
|
20
|
+
if (config.logLevel !== 'silent') {
|
|
21
|
+
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
|
|
22
|
+
}
|
|
23
|
+
next();
|
|
24
|
+
});
|
|
25
|
+
// GET /status - health check
|
|
26
|
+
app.get('/status', (_req, res) => {
|
|
27
|
+
res.json({
|
|
28
|
+
status: 'ok',
|
|
29
|
+
version: '0.1.0',
|
|
30
|
+
uptime: Math.floor((Date.now() - START_TIME) / 1000),
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
// GET /circuits - list available circuits and their verification keys
|
|
34
|
+
app.get('/circuits', async (_req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const circuits = await listCircuits(config.circuitPath);
|
|
37
|
+
res.json({ circuits });
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
res.status(500).json({ error: 'Failed to list circuits' });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// POST /verify - verify a Barretenberg proof
|
|
44
|
+
app.post('/verify', verifyLimiter, async (req, res) => {
|
|
45
|
+
const { proof, publicInputs, circuitType } = req.body;
|
|
46
|
+
if (!proof || typeof proof !== 'string') {
|
|
47
|
+
res.status(400).json({ valid: false, error: 'proof is required (hex string)' });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!Array.isArray(publicInputs)) {
|
|
51
|
+
res.status(400).json({ valid: false, error: 'publicInputs is required (string[])' });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const valid = await verifyProof({
|
|
56
|
+
proof,
|
|
57
|
+
publicInputs,
|
|
58
|
+
circuitType,
|
|
59
|
+
circuitPath: config.circuitPath,
|
|
60
|
+
});
|
|
61
|
+
res.json({ valid });
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const message = err instanceof Error ? err.message : 'verification failed';
|
|
65
|
+
res.status(400).json({ valid: false, error: message });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// Error handling middleware
|
|
69
|
+
app.use((err, _req, res, _next) => {
|
|
70
|
+
console.error('[reputrans-verifier] unhandled error:', err);
|
|
71
|
+
res.status(500).json({ error: 'internal server error' });
|
|
72
|
+
});
|
|
73
|
+
return app;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../verifier/src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface VerifyRequest {
|
|
2
|
+
proof: string;
|
|
3
|
+
publicInputs: string[];
|
|
4
|
+
circuitType?: string;
|
|
5
|
+
circuitPath: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CircuitInfo {
|
|
8
|
+
name: string;
|
|
9
|
+
hasVerificationKey: boolean;
|
|
10
|
+
expectedPublicInputs: number | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Verify a Barretenberg (UltraHonk) proof against the named circuit.
|
|
14
|
+
*/
|
|
15
|
+
export declare function verifyProof(req: VerifyRequest): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* List available circuits and whether their compiled artifacts exist.
|
|
18
|
+
*/
|
|
19
|
+
export declare function listCircuits(circuitPath: string): Promise<CircuitInfo[]>;
|
|
20
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../verifier/src/verify.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,EAAE,OAAO,CAAC;IAC5B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAqBD;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAwCtE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CA0B9E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { readFile, readdir } from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { UltraHonkBackend } from '@noir-lang/backend_barretenberg';
|
|
4
|
+
// Circuit types and the number of public inputs each expects (used for inference)
|
|
5
|
+
const CIRCUIT_PUBLIC_INPUT_COUNTS = {
|
|
6
|
+
composite: 8,
|
|
7
|
+
signature_verify: 5,
|
|
8
|
+
field_disclosure: 3,
|
|
9
|
+
range_proof: 2,
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Infer circuit type from public input count when not explicitly provided.
|
|
13
|
+
*/
|
|
14
|
+
function inferCircuitType(publicInputCount) {
|
|
15
|
+
for (const [name, count] of Object.entries(CIRCUIT_PUBLIC_INPUT_COUNTS)) {
|
|
16
|
+
if (count === publicInputCount)
|
|
17
|
+
return name;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load the compiled circuit artifact (circuit.json) for a given circuit type.
|
|
23
|
+
*/
|
|
24
|
+
async function loadCircuit(circuitPath, circuitType) {
|
|
25
|
+
const artifactPath = path.resolve(circuitPath, circuitType, 'target', `${circuitType}.json`);
|
|
26
|
+
const raw = await readFile(artifactPath, 'utf-8');
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Verify a Barretenberg (UltraHonk) proof against the named circuit.
|
|
31
|
+
*/
|
|
32
|
+
export async function verifyProof(req) {
|
|
33
|
+
const { proof, publicInputs, circuitPath } = req;
|
|
34
|
+
// Determine and sanitize circuit type
|
|
35
|
+
let circuitType = req.circuitType;
|
|
36
|
+
if (circuitType && !/^[a-z_]+$/.test(circuitType)) {
|
|
37
|
+
throw new Error('Invalid circuitType: must match /^[a-z_]+$/');
|
|
38
|
+
}
|
|
39
|
+
if (!circuitType) {
|
|
40
|
+
const inferred = inferCircuitType(publicInputs.length);
|
|
41
|
+
if (!inferred) {
|
|
42
|
+
throw new Error(`Cannot infer circuit type from ${publicInputs.length} public inputs. ` +
|
|
43
|
+
`Provide circuitType explicitly. Known counts: ${JSON.stringify(CIRCUIT_PUBLIC_INPUT_COUNTS)}`);
|
|
44
|
+
}
|
|
45
|
+
circuitType = inferred;
|
|
46
|
+
}
|
|
47
|
+
const artifact = await loadCircuit(circuitPath, circuitType);
|
|
48
|
+
// Decode hex proof to Uint8Array
|
|
49
|
+
const proofHex = proof.startsWith('0x') ? proof.slice(2) : proof;
|
|
50
|
+
if (proofHex.length % 2 !== 0) {
|
|
51
|
+
throw new Error('proof hex string has odd length');
|
|
52
|
+
}
|
|
53
|
+
const proofBytes = Uint8Array.from(proofHex.match(/.{2}/g).map((b) => parseInt(b, 16)));
|
|
54
|
+
const backend = new UltraHonkBackend(artifact);
|
|
55
|
+
try {
|
|
56
|
+
const valid = await backend.verifyProof({
|
|
57
|
+
proof: proofBytes,
|
|
58
|
+
publicInputs,
|
|
59
|
+
});
|
|
60
|
+
return valid;
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
await backend.destroy();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* List available circuits and whether their compiled artifacts exist.
|
|
68
|
+
*/
|
|
69
|
+
export async function listCircuits(circuitPath) {
|
|
70
|
+
const resolved = path.resolve(circuitPath);
|
|
71
|
+
let entries;
|
|
72
|
+
try {
|
|
73
|
+
entries = await readdir(resolved);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
const results = [];
|
|
79
|
+
for (const entry of entries) {
|
|
80
|
+
const artifactPath = path.join(resolved, entry, 'target', `${entry}.json`);
|
|
81
|
+
let hasVk = false;
|
|
82
|
+
try {
|
|
83
|
+
await readFile(artifactPath);
|
|
84
|
+
hasVk = true;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// artifact not compiled yet
|
|
88
|
+
}
|
|
89
|
+
results.push({
|
|
90
|
+
name: entry,
|
|
91
|
+
hasVerificationKey: hasVk,
|
|
92
|
+
expectedPublicInputs: CIRCUIT_PUBLIC_INPUT_COUNTS[entry] ?? null,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../../verifier/src/verify.ts"],"names":[],"mappings":"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"}
|