Skip to content

Commit 51089d0

Browse files
committed
Explicit versioning for audit record/anchor
1 parent 49c1b3f commit 51089d0

File tree

3 files changed

+32
-27
lines changed

3 files changed

+32
-27
lines changed

packages/sdk/src/wasm/VerifiablePresentationV1/audit-record.ts

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { VerifiablePresentationRequestV1, VerifiablePresentationV1 } from './ind
1717

1818
const JSONBig = _JB({ alwaysParseAsBig: true, useNativeBigInt: true });
1919

20+
const VERSION = 1;
21+
2022
/**
2123
* A verification audit record that contains the complete verifiable presentation
2224
* request and response data. This record maintains the full audit trail of a verification
@@ -26,23 +28,18 @@ const JSONBig = _JB({ alwaysParseAsBig: true, useNativeBigInt: true });
2628
* of verification interactions, while only publishing hash-based public records on-chain
2729
* to preserve privacy.
2830
*/
29-
class VerificationAuditRecord {
30-
/** The type identifier for this audit record */
31-
public readonly type = 'ConcordiumVerificationAuditRecord';
32-
31+
class VerificationAuditRecordV1 {
3332
/**
3433
* Creates a new verification audit record.
3534
*
3635
* @param request - The verifiable presentation request that was made
3736
* @param presentation - The verifiable presentation that was provided in response
3837
* @param id - Unique identifier for this audit record
39-
* @param version - The version of the audit record format
4038
*/
4139
constructor(
4240
public readonly request: VerifiablePresentationRequestV1.Type,
4341
public readonly presentation: VerifiablePresentationV1.Type,
44-
public readonly id: string,
45-
public readonly version: number = 1
42+
public readonly id: string
4643
) {}
4744

4845
/**
@@ -51,7 +48,13 @@ class VerificationAuditRecord {
5148
* @returns The JSON representation of this audit record
5249
*/
5350
public toJSON(): JSON {
54-
return { ...this, request: this.request.toJSON(), presentation: this.presentation.toJSON() };
51+
return {
52+
request: this.request.toJSON(),
53+
presentation: this.presentation.toJSON(),
54+
id: this.id,
55+
version: VERSION,
56+
type: 'ConcordiumVerificationAuditRecord',
57+
};
5558
}
5659
}
5760

@@ -64,13 +67,17 @@ class VerificationAuditRecord {
6467
* of verification interactions, while only publishing hash-based public records on-chain
6568
* to preserve privacy.
6669
*/
67-
export type Type = VerificationAuditRecord;
70+
export type Type = VerificationAuditRecordV1;
6871

6972
/**
7073
* JSON representation of a verification audit record.
7174
* Contains the serialized forms of the request and presentation data.
7275
*/
73-
export type JSON = Pick<Type, 'id' | 'type' | 'version'> & {
76+
export type JSON = Pick<Type, 'id'> & {
77+
/** The type identifier for the audit record */
78+
type: 'ConcordiumVerificationAuditRecord';
79+
/** The audit record version */
80+
version: 1;
7481
/** The serialized verifiable presentation request */
7582
request: VerifiablePresentationRequestV1.JSON;
7683
/** The serialized verifiable presentation */
@@ -90,8 +97,8 @@ export function create(
9097
id: string,
9198
request: VerifiablePresentationRequestV1.Type,
9299
presentation: VerifiablePresentationV1.Type
93-
): VerificationAuditRecord {
94-
return new VerificationAuditRecord(request, presentation, id);
100+
): VerificationAuditRecordV1 {
101+
return new VerificationAuditRecordV1(request, presentation, id);
95102
}
96103

97104
/**
@@ -100,12 +107,11 @@ export function create(
100107
* @param json - The JSON representation to deserialize
101108
* @returns The deserialized verification audit record
102109
*/
103-
export function fromJSON(json: JSON): VerificationAuditRecord {
104-
return new VerificationAuditRecord(
110+
export function fromJSON(json: JSON): VerificationAuditRecordV1 {
111+
return new VerificationAuditRecordV1(
105112
VerifiablePresentationRequestV1.fromJSON(json.request),
106113
VerifiablePresentationV1.fromJSON(json.presentation),
107-
json.id,
108-
Number(json.version)
114+
json.id
109115
);
110116
}
111117

@@ -135,10 +141,10 @@ export type AnchorData = {
135141
*
136142
* @returns The anchor encoding corresponding to the audit record
137143
*/
138-
export function createAnchor(record: VerificationAuditRecord, info?: Record<string, any>): Uint8Array {
144+
export function createAnchor(record: VerificationAuditRecordV1, info?: Record<string, any>): Uint8Array {
139145
const message = Buffer.from(JSONBig.stringify(record)); // TODO: replace this with proper hashing.. properly from @concordium/rust-bindings
140146
const hash = Uint8Array.from(sha256([message]));
141-
let anchor: AnchorData = { hash: hash, version: record.version, type: 'CCDVAA', public: info };
147+
let anchor: AnchorData = { hash: hash, version: VERSION, type: 'CCDVAA', public: info };
142148
return cborEncode(anchor);
143149
}
144150

@@ -158,8 +164,7 @@ export function decodeAnchor(cbor: Uint8Array): AnchorData {
158164
if (typeof value !== 'object' || value === null) throw new Error('Expected a cbor encoded object');
159165
// required fields
160166
if (!('type' in value) || value.type !== 'CCDVAA') throw new Error('Expected "type" to be "CCDVAA"');
161-
if (!('version' in value) || typeof value.version !== 'number')
162-
throw new Error('Expected "version" to be a number');
167+
if (!('version' in value) || value.version !== VERSION) throw new Error('Expected "version" to be 1');
163168
if (!('hash' in value) || !(value.hash instanceof Uint8Array))
164169
throw new Error('Expected "hash" to be a Uint8Array');
165170
// optional fields
@@ -184,7 +189,7 @@ export function decodeAnchor(cbor: Uint8Array): AnchorData {
184189
* @throws Error if the transaction fails or network issues occur
185190
*/
186191
export async function registerAnchor(
187-
record: VerificationAuditRecord,
192+
record: VerificationAuditRecordV1,
188193
grpc: ConcordiumGRPCClient,
189194
sender: AccountAddress.Type,
190195
signer: AccountSigner,

packages/sdk/src/wasm/VerifiablePresentationV1/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* - VerificationAuditRecord: For public audit trails of verification events
1212
* - PrivateVerificationAuditRecord: For private audit records with full data
1313
*/
14-
import * as VerificationAuditRecord from './audit-record.js';
14+
import * as VerificationAuditRecordV1 from './audit-record.js';
1515
import * as VerifiablePresentationV1 from './proof.js';
1616
import * as VerifiablePresentationRequestV1 from './request.js';
1717

@@ -21,7 +21,7 @@ export {
2121
/** Namespace for verifiable presentation proof operations */
2222
VerifiablePresentationV1,
2323
/** Namespace for verification audit record operations */
24-
VerificationAuditRecord,
24+
VerificationAuditRecordV1,
2525
};
2626

2727
/** Export all common types used across the verifiable presentation system */

packages/sdk/test/ci/wasm/VerificationAuditRecord.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import _JB from 'json-bigint';
33
import {
44
VerifiablePresentationRequestV1,
55
VerifiablePresentationV1,
6-
VerificationAuditRecord,
6+
VerificationAuditRecordV1,
77
} from '../../../src/index.ts';
88

99
const JSONBig = _JB({ alwaysParseAsBig: true, useNativeBigInt: true });
@@ -75,17 +75,17 @@ const PRESENTATION = VerifiablePresentationV1.fromJSON({
7575
proof: { created: '2025-10-17T13:14:14.290Z', proofValue: [], type: 'ConcordiumWeakLinkingProofV1' },
7676
});
7777

78-
const PRIVATE_RECORD = VerificationAuditRecord.create('VERY unique ID', PRESENTATION_REQUEST, PRESENTATION);
78+
const PRIVATE_RECORD = VerificationAuditRecordV1.create('VERY unique ID', PRESENTATION_REQUEST, PRESENTATION);
7979

8080
describe('VerificationAuditRecord', () => {
8181
it('completes JSON roundtrip', () => {
8282
const json = JSONBig.stringify(PRIVATE_RECORD);
83-
const roundtrip = VerificationAuditRecord.fromJSON(JSONBig.parse(json));
83+
const roundtrip = VerificationAuditRecordV1.fromJSON(JSONBig.parse(json));
8484
expect(roundtrip).toEqual(PRIVATE_RECORD);
8585
});
8686

8787
it('creates expected anchor', () => {
88-
const anchor = VerificationAuditRecord.createAnchor(PRIVATE_RECORD, { info: 'some public info?' });
88+
const anchor = VerificationAuditRecordV1.createAnchor(PRIVATE_RECORD, { info: 'some public info?' });
8989
const expected =
9090
'a464686173685820df6c87461f549ac8d734c42f65b5355e745aa8444ce83907ba1a3ab9f5a0898f647479706566434344564141667075626c6963a164696e666f71736f6d65207075626c696320696e666f3f6776657273696f6e01';
9191
expect(Buffer.from(anchor).toString('hex')).toEqual(expected);

0 commit comments

Comments
 (0)