@uvrn/adapter 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +3 -2
- package/dist/src/validator.d.ts +21 -4
- package/dist/src/validator.js +40 -4
- package/dist/src/wrapper.d.ts +3 -2
- package/dist/src/wrapper.js +13 -6
- package/dist/tests/wrapper.test.js +16 -20
- package/package.json +9 -2
- package/jest.config.js +0 -12
- package/schemas/drvc3.schema.json +0 -115
- package/src/index.ts +0 -16
- package/src/signer.ts +0 -47
- package/src/types.ts +0 -102
- package/src/validator.ts +0 -53
- package/src/wrapper.ts +0 -103
- package/tests/integration.test.ts +0 -123
- package/tests/wrapper.test.ts +0 -115
- package/tsconfig.json +0 -21
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
UVRN DRVC3 envelope adapter — wraps Delta Engine receipts in DRVC3 envelopes with EIP-191 signatures. Use this when you need to attach issuer identity and signing to core receipts without changing their deterministic hash.
|
|
4
4
|
|
|
5
|
+
**Disclaimer:** UVRN is in Alpha testing. The engine measures whether your sources agree with each other — not whether they’re correct. Final trust of output rests with the user. Use at your own risk. Have fun.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
package/dist/src/index.d.ts
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
export * from './types';
|
|
6
6
|
export { wrapInDRVC3, extractDeltaReceipt } from './wrapper';
|
|
7
7
|
export { signHash, recoverSigner, verifySignature } from './signer';
|
|
8
|
-
export { validateDRVC3, isDRVC3Receipt } from './validator';
|
|
8
|
+
export { validateDRVC3, isDRVC3Receipt, verifyDRVC3Integrity } from './validator';
|
package/dist/src/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.isDRVC3Receipt = exports.validateDRVC3 = exports.verifySignature = exports.recoverSigner = exports.signHash = exports.extractDeltaReceipt = exports.wrapInDRVC3 = void 0;
|
|
21
|
+
exports.verifyDRVC3Integrity = exports.isDRVC3Receipt = exports.validateDRVC3 = exports.verifySignature = exports.recoverSigner = exports.signHash = exports.extractDeltaReceipt = exports.wrapInDRVC3 = void 0;
|
|
22
22
|
// Types
|
|
23
23
|
__exportStar(require("./types"), exports);
|
|
24
24
|
// Core wrapper
|
|
@@ -30,7 +30,8 @@ var signer_1 = require("./signer");
|
|
|
30
30
|
Object.defineProperty(exports, "signHash", { enumerable: true, get: function () { return signer_1.signHash; } });
|
|
31
31
|
Object.defineProperty(exports, "recoverSigner", { enumerable: true, get: function () { return signer_1.recoverSigner; } });
|
|
32
32
|
Object.defineProperty(exports, "verifySignature", { enumerable: true, get: function () { return signer_1.verifySignature; } });
|
|
33
|
-
// Validation
|
|
33
|
+
// Validation (validateDRVC3 is schema-only; use verifyDRVC3Integrity for full integrity)
|
|
34
34
|
var validator_1 = require("./validator");
|
|
35
35
|
Object.defineProperty(exports, "validateDRVC3", { enumerable: true, get: function () { return validator_1.validateDRVC3; } });
|
|
36
36
|
Object.defineProperty(exports, "isDRVC3Receipt", { enumerable: true, get: function () { return validator_1.isDRVC3Receipt; } });
|
|
37
|
+
Object.defineProperty(exports, "verifyDRVC3Integrity", { enumerable: true, get: function () { return validator_1.verifyDRVC3Integrity; } });
|
package/dist/src/validator.d.ts
CHANGED
|
@@ -1,17 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DRVC3 Schema Validator
|
|
3
|
-
*
|
|
2
|
+
* DRVC3 Schema Validator and Integrity Verification
|
|
3
|
+
* - validateDRVC3: schema-only (structure); does not verify signatures or embedded receipt hash.
|
|
4
|
+
* - verifyDRVC3Integrity: full integrity check (schema + signature + core receipt hash).
|
|
4
5
|
*/
|
|
5
6
|
import { DRVC3ValidationResult } from './types';
|
|
6
7
|
/**
|
|
7
|
-
* Validates a DRVC3 receipt against the official schema
|
|
8
|
+
* Validates a DRVC3 receipt against the official schema only.
|
|
9
|
+
* Does not verify cryptographic signature or embedded receipt hash.
|
|
10
|
+
* For full integrity check, use verifyDRVC3Integrity().
|
|
11
|
+
*
|
|
8
12
|
* @param receipt - The receipt object to validate
|
|
9
13
|
* @returns Validation result with errors if invalid
|
|
10
14
|
*/
|
|
11
15
|
export declare function validateDRVC3(receipt: unknown): DRVC3ValidationResult;
|
|
12
16
|
/**
|
|
13
|
-
* Type guard to check if an object is a valid DRVC3 receipt
|
|
17
|
+
* Type guard to check if an object is a valid DRVC3 receipt (schema-only).
|
|
14
18
|
* @param obj - Object to check
|
|
15
19
|
* @returns True if the object is a valid DRVC3 receipt
|
|
16
20
|
*/
|
|
17
21
|
export declare function isDRVC3Receipt(obj: unknown): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Full integrity verification: schema, EIP-191 signature, and embedded receipt hash.
|
|
24
|
+
* Use this before trusting envelope contents; extractDeltaReceipt is safe after this passes.
|
|
25
|
+
*
|
|
26
|
+
* @param drvc3 - DRVC3 envelope to verify
|
|
27
|
+
* @returns Object with verified: true, or verified: false and error message
|
|
28
|
+
*/
|
|
29
|
+
export declare function verifyDRVC3Integrity(drvc3: unknown): {
|
|
30
|
+
verified: true;
|
|
31
|
+
} | {
|
|
32
|
+
verified: false;
|
|
33
|
+
error: string;
|
|
34
|
+
};
|
package/dist/src/validator.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* DRVC3 Schema Validator
|
|
4
|
-
*
|
|
3
|
+
* DRVC3 Schema Validator and Integrity Verification
|
|
4
|
+
* - validateDRVC3: schema-only (structure); does not verify signatures or embedded receipt hash.
|
|
5
|
+
* - verifyDRVC3Integrity: full integrity check (schema + signature + core receipt hash).
|
|
5
6
|
*/
|
|
6
7
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
8
|
if (k2 === undefined) k2 = k;
|
|
@@ -42,9 +43,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
42
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
44
|
exports.validateDRVC3 = validateDRVC3;
|
|
44
45
|
exports.isDRVC3Receipt = isDRVC3Receipt;
|
|
46
|
+
exports.verifyDRVC3Integrity = verifyDRVC3Integrity;
|
|
47
|
+
const core_1 = require("@uvrn/core");
|
|
45
48
|
const ajv_1 = __importDefault(require("ajv"));
|
|
46
49
|
const path = __importStar(require("path"));
|
|
47
50
|
const fs = __importStar(require("fs"));
|
|
51
|
+
const signer_1 = require("./signer");
|
|
52
|
+
const wrapper_1 = require("./wrapper");
|
|
48
53
|
// Load schema from file
|
|
49
54
|
const schemaPath = path.join(__dirname, '../schemas/drvc3.schema.json');
|
|
50
55
|
const drvc3Schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
|
|
@@ -57,7 +62,10 @@ addFormats(ajv);
|
|
|
57
62
|
// Compile the schema once
|
|
58
63
|
const validateSchema = ajv.compile(drvc3Schema);
|
|
59
64
|
/**
|
|
60
|
-
* Validates a DRVC3 receipt against the official schema
|
|
65
|
+
* Validates a DRVC3 receipt against the official schema only.
|
|
66
|
+
* Does not verify cryptographic signature or embedded receipt hash.
|
|
67
|
+
* For full integrity check, use verifyDRVC3Integrity().
|
|
68
|
+
*
|
|
61
69
|
* @param receipt - The receipt object to validate
|
|
62
70
|
* @returns Validation result with errors if invalid
|
|
63
71
|
*/
|
|
@@ -73,10 +81,38 @@ function validateDRVC3(receipt) {
|
|
|
73
81
|
return { valid: false, errors };
|
|
74
82
|
}
|
|
75
83
|
/**
|
|
76
|
-
* Type guard to check if an object is a valid DRVC3 receipt
|
|
84
|
+
* Type guard to check if an object is a valid DRVC3 receipt (schema-only).
|
|
77
85
|
* @param obj - Object to check
|
|
78
86
|
* @returns True if the object is a valid DRVC3 receipt
|
|
79
87
|
*/
|
|
80
88
|
function isDRVC3Receipt(obj) {
|
|
81
89
|
return validateDRVC3(obj).valid;
|
|
82
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Full integrity verification: schema, EIP-191 signature, and embedded receipt hash.
|
|
93
|
+
* Use this before trusting envelope contents; extractDeltaReceipt is safe after this passes.
|
|
94
|
+
*
|
|
95
|
+
* @param drvc3 - DRVC3 envelope to verify
|
|
96
|
+
* @returns Object with verified: true, or verified: false and error message
|
|
97
|
+
*/
|
|
98
|
+
function verifyDRVC3Integrity(drvc3) {
|
|
99
|
+
const schemaResult = validateDRVC3(drvc3);
|
|
100
|
+
if (!schemaResult.valid) {
|
|
101
|
+
return { verified: false, error: schemaResult.errors?.join('; ') ?? 'Schema validation failed' };
|
|
102
|
+
}
|
|
103
|
+
const envelope = drvc3;
|
|
104
|
+
const { integrity, validation } = envelope;
|
|
105
|
+
if (!validation?.checks?.delta_receipt) {
|
|
106
|
+
return { verified: false, error: 'Missing validation.checks.delta_receipt' };
|
|
107
|
+
}
|
|
108
|
+
const receipt = (0, wrapper_1.extractDeltaReceipt)(envelope);
|
|
109
|
+
const coreResult = (0, core_1.verifyReceipt)(receipt);
|
|
110
|
+
if (!coreResult.verified) {
|
|
111
|
+
return { verified: false, error: `Embedded receipt: ${coreResult.error}` };
|
|
112
|
+
}
|
|
113
|
+
const sigOk = (0, signer_1.verifySignature)(integrity.hash, integrity.signature, integrity.signer_address);
|
|
114
|
+
if (!sigOk) {
|
|
115
|
+
return { verified: false, error: 'Signature verification failed' };
|
|
116
|
+
}
|
|
117
|
+
return { verified: true };
|
|
118
|
+
}
|
package/dist/src/wrapper.d.ts
CHANGED
|
@@ -33,9 +33,10 @@ import { DRVC3Receipt, WrapOptions } from './types';
|
|
|
33
33
|
*/
|
|
34
34
|
export declare function wrapInDRVC3(deltaReceipt: DeltaReceipt, signer: Wallet | HDNodeWallet, options: WrapOptions): Promise<DRVC3Receipt>;
|
|
35
35
|
/**
|
|
36
|
-
* Extracts the original DeltaReceipt from a DRVC3 envelope
|
|
36
|
+
* Extracts the original DeltaReceipt from a DRVC3 envelope.
|
|
37
|
+
* Does not verify signature or receipt hash; for untrusted input use verifyDRVC3Integrity() first, then extract.
|
|
37
38
|
*
|
|
38
|
-
* @param drvc3 - DRVC3 receipt envelope
|
|
39
|
+
* @param drvc3 - DRVC3 receipt envelope (must have validation.checks.delta_receipt)
|
|
39
40
|
* @returns The embedded DeltaReceipt
|
|
40
41
|
*/
|
|
41
42
|
export declare function extractDeltaReceipt(drvc3: DRVC3Receipt): DeltaReceipt;
|
package/dist/src/wrapper.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.wrapInDRVC3 = wrapInDRVC3;
|
|
12
12
|
exports.extractDeltaReceipt = extractDeltaReceipt;
|
|
13
|
+
const core_1 = require("@uvrn/core");
|
|
13
14
|
const signer_1 = require("./signer");
|
|
14
15
|
/**
|
|
15
16
|
* Wraps a DeltaReceipt in a DRVC3 envelope
|
|
@@ -34,14 +35,19 @@ const signer_1 = require("./signer");
|
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
36
37
|
async function wrapInDRVC3(deltaReceipt, signer, options) {
|
|
37
|
-
// 1.
|
|
38
|
+
// 1. Verify receipt integrity before attesting (do not sign tampered payloads)
|
|
39
|
+
const coreVerify = (0, core_1.verifyReceipt)(deltaReceipt);
|
|
40
|
+
if (!coreVerify.verified) {
|
|
41
|
+
throw new Error(`Cannot wrap invalid receipt: ${coreVerify.error}`);
|
|
42
|
+
}
|
|
43
|
+
// 2. Generate receipt_id (ENVELOPE METADATA - non-deterministic, intentional)
|
|
38
44
|
const timestamp = new Date().toISOString();
|
|
39
45
|
const receipt_id = `drvc3-${deltaReceipt.bundleId}-${Date.now()}`;
|
|
40
|
-
//
|
|
46
|
+
// 3. Read hash from DeltaReceipt (HASH DOMAIN - read-only from Layer 1)
|
|
41
47
|
const hash = deltaReceipt.hash;
|
|
42
|
-
//
|
|
48
|
+
// 4. Sign hash with EIP-191 (ENVELOPE METADATA - certifies "who" and "when")
|
|
43
49
|
const signature = await (0, signer_1.signHash)(hash, signer);
|
|
44
|
-
//
|
|
50
|
+
// 5. Construct DRVC3 envelope
|
|
45
51
|
const drvc3 = {
|
|
46
52
|
receipt_id,
|
|
47
53
|
issuer: options.issuer,
|
|
@@ -82,9 +88,10 @@ async function wrapInDRVC3(deltaReceipt, signer, options) {
|
|
|
82
88
|
return drvc3;
|
|
83
89
|
}
|
|
84
90
|
/**
|
|
85
|
-
* Extracts the original DeltaReceipt from a DRVC3 envelope
|
|
91
|
+
* Extracts the original DeltaReceipt from a DRVC3 envelope.
|
|
92
|
+
* Does not verify signature or receipt hash; for untrusted input use verifyDRVC3Integrity() first, then extract.
|
|
86
93
|
*
|
|
87
|
-
* @param drvc3 - DRVC3 receipt envelope
|
|
94
|
+
* @param drvc3 - DRVC3 receipt envelope (must have validation.checks.delta_receipt)
|
|
88
95
|
* @returns The embedded DeltaReceipt
|
|
89
96
|
*/
|
|
90
97
|
function extractDeltaReceipt(drvc3) {
|
|
@@ -5,31 +5,25 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const ethers_1 = require("ethers");
|
|
8
|
+
const core_1 = require("@uvrn/core");
|
|
8
9
|
const wrapper_1 = require("../src/wrapper");
|
|
9
10
|
const validator_1 = require("../src/validator");
|
|
10
11
|
const signer_1 = require("../src/signer");
|
|
11
12
|
describe('DRVC3 Wrapper', () => {
|
|
12
|
-
|
|
13
|
-
const mockDeltaReceipt = {
|
|
14
|
-
bundleId: 'test-bundle-001',
|
|
15
|
-
deltaFinal: 0.05,
|
|
16
|
-
sources: ['Source A', 'Source B'],
|
|
17
|
-
rounds: [
|
|
18
|
-
{
|
|
19
|
-
round: 1,
|
|
20
|
-
deltasByMetric: { revenue: 0.05, users: 0.0 },
|
|
21
|
-
withinThreshold: true,
|
|
22
|
-
witnessRequired: false
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
suggestedFixes: [],
|
|
26
|
-
outcome: 'consensus',
|
|
27
|
-
hash: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'
|
|
28
|
-
};
|
|
13
|
+
let mockDeltaReceipt;
|
|
29
14
|
let testWallet;
|
|
30
15
|
beforeAll(() => {
|
|
31
|
-
// Create a deterministic wallet for testing
|
|
32
16
|
testWallet = ethers_1.Wallet.createRandom();
|
|
17
|
+
const bundle = {
|
|
18
|
+
bundleId: 'test-bundle-001',
|
|
19
|
+
claim: 'Test claim',
|
|
20
|
+
dataSpecs: [
|
|
21
|
+
{ id: 's1', label: 'Source A', sourceKind: 'report', originDocIds: [], metrics: [{ key: 'k', value: 10 }] },
|
|
22
|
+
{ id: 's2', label: 'Source B', sourceKind: 'report', originDocIds: [], metrics: [{ key: 'k', value: 10.5 }] }
|
|
23
|
+
],
|
|
24
|
+
thresholdPct: 0.1
|
|
25
|
+
};
|
|
26
|
+
mockDeltaReceipt = (0, core_1.runDeltaEngine)(bundle);
|
|
33
27
|
});
|
|
34
28
|
it('should wrap DeltaReceipt in valid DRVC3 envelope', async () => {
|
|
35
29
|
const drvc3 = await (0, wrapper_1.wrapInDRVC3)(mockDeltaReceipt, testWallet, {
|
|
@@ -42,7 +36,7 @@ describe('DRVC3 Wrapper', () => {
|
|
|
42
36
|
expect(drvc3.event).toBe('delta-reconciliation');
|
|
43
37
|
expect(drvc3.timestamp).toBeDefined();
|
|
44
38
|
expect(drvc3.block_state).toBe('loose');
|
|
45
|
-
expect(drvc3.certificate).toBe('DRVC3 v1.
|
|
39
|
+
expect(drvc3.certificate).toBe('DRVC3 v1.01');
|
|
46
40
|
// Check integrity block
|
|
47
41
|
expect(drvc3.integrity.hash_algorithm).toBe('sha256');
|
|
48
42
|
expect(drvc3.integrity.hash).toBe(mockDeltaReceipt.hash);
|
|
@@ -91,6 +85,8 @@ describe('DRVC3 Wrapper', () => {
|
|
|
91
85
|
event: 'test'
|
|
92
86
|
});
|
|
93
87
|
const extracted = (0, wrapper_1.extractDeltaReceipt)(drvc3);
|
|
94
|
-
expect(extracted).
|
|
88
|
+
expect(extracted.bundleId).toBe(mockDeltaReceipt.bundleId);
|
|
89
|
+
expect(extracted.hash).toBe(mockDeltaReceipt.hash);
|
|
90
|
+
expect(extracted.outcome).toBe(mockDeltaReceipt.outcome);
|
|
95
91
|
});
|
|
96
92
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uvrn/adapter",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
4
7
|
"description": "UVRN DRVC3 envelope adapter — wraps core receipts with EIP-191 signatures",
|
|
5
8
|
"main": "dist/index.js",
|
|
6
9
|
"types": "dist/index.d.ts",
|
|
@@ -21,7 +24,7 @@
|
|
|
21
24
|
"ethers": "^6.0.0",
|
|
22
25
|
"ajv": "^8.12.0",
|
|
23
26
|
"ajv-formats": "^2.1.1",
|
|
24
|
-
"@uvrn/core": "1.0.
|
|
27
|
+
"@uvrn/core": "^1.0.3"
|
|
25
28
|
},
|
|
26
29
|
"devDependencies": {
|
|
27
30
|
"@types/jest": "^29.5.0",
|
|
@@ -33,6 +36,10 @@
|
|
|
33
36
|
"engines": {
|
|
34
37
|
"node": ">=18.0.0"
|
|
35
38
|
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
36
43
|
"scripts": {
|
|
37
44
|
"build": "tsc",
|
|
38
45
|
"test": "jest",
|
package/jest.config.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
2
|
-
module.exports = {
|
|
3
|
-
preset: 'ts-jest',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
testMatch: ['**/tests/**/*.test.ts'],
|
|
6
|
-
moduleFileExtensions: ['ts', 'js', 'json'],
|
|
7
|
-
collectCoverageFrom: ['src/**/*.ts'],
|
|
8
|
-
moduleNameMapper: {
|
|
9
|
-
'^@uvrn/core$': '<rootDir>/../uvrn-core/src'
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"$id": "https://uvrn.org/schemas/drvc3.v1.01.json",
|
|
4
|
-
"title": "DRVC3 Receipt v1.01",
|
|
5
|
-
"description": "DRVC3 envelope with Layer 2 extensions support. Backward-compatible with v1.0.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"required": [
|
|
8
|
-
"receipt_id",
|
|
9
|
-
"issuer",
|
|
10
|
-
"event",
|
|
11
|
-
"timestamp",
|
|
12
|
-
"integrity",
|
|
13
|
-
"block_state",
|
|
14
|
-
"certificate"
|
|
15
|
-
],
|
|
16
|
-
"properties": {
|
|
17
|
-
"receipt_id": {
|
|
18
|
-
"type": "string"
|
|
19
|
-
},
|
|
20
|
-
"issuer": {
|
|
21
|
-
"type": "string"
|
|
22
|
-
},
|
|
23
|
-
"event": {
|
|
24
|
-
"type": "string"
|
|
25
|
-
},
|
|
26
|
-
"timestamp": {
|
|
27
|
-
"type": "string",
|
|
28
|
-
"format": "date-time"
|
|
29
|
-
},
|
|
30
|
-
"description": {
|
|
31
|
-
"type": "string"
|
|
32
|
-
},
|
|
33
|
-
"resource": {
|
|
34
|
-
"type": "object",
|
|
35
|
-
"properties": {
|
|
36
|
-
"type": {
|
|
37
|
-
"type": "string"
|
|
38
|
-
},
|
|
39
|
-
"url": {
|
|
40
|
-
"type": "string"
|
|
41
|
-
},
|
|
42
|
-
"branch": {
|
|
43
|
-
"type": "string"
|
|
44
|
-
},
|
|
45
|
-
"commit_hash": {
|
|
46
|
-
"type": "string"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"integrity": {
|
|
51
|
-
"type": "object",
|
|
52
|
-
"required": [
|
|
53
|
-
"hash_algorithm",
|
|
54
|
-
"hash",
|
|
55
|
-
"signature_method",
|
|
56
|
-
"signature",
|
|
57
|
-
"signer_address"
|
|
58
|
-
],
|
|
59
|
-
"properties": {
|
|
60
|
-
"hash_algorithm": {
|
|
61
|
-
"enum": [
|
|
62
|
-
"sha256"
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
"hash": {
|
|
66
|
-
"type": "string"
|
|
67
|
-
},
|
|
68
|
-
"signature_method": {
|
|
69
|
-
"enum": [
|
|
70
|
-
"eip191"
|
|
71
|
-
]
|
|
72
|
-
},
|
|
73
|
-
"signature": {
|
|
74
|
-
"type": "string"
|
|
75
|
-
},
|
|
76
|
-
"signer_address": {
|
|
77
|
-
"type": "string"
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
"validation": {
|
|
82
|
-
"type": "object",
|
|
83
|
-
"properties": {
|
|
84
|
-
"v_score": {
|
|
85
|
-
"type": "number"
|
|
86
|
-
},
|
|
87
|
-
"checks": {
|
|
88
|
-
"type": "object"
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
"block_state": {
|
|
93
|
-
"enum": [
|
|
94
|
-
"loose",
|
|
95
|
-
"blocked"
|
|
96
|
-
]
|
|
97
|
-
},
|
|
98
|
-
"certificate": {
|
|
99
|
-
"type": "string"
|
|
100
|
-
},
|
|
101
|
-
"replay_instructions": {
|
|
102
|
-
"type": "object"
|
|
103
|
-
},
|
|
104
|
-
"tags": {
|
|
105
|
-
"type": "array",
|
|
106
|
-
"items": {
|
|
107
|
-
"type": "string"
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
"extensions": {
|
|
111
|
-
"type": "object",
|
|
112
|
-
"description": "Layer 2 provenance data — source URLs, timestamps, evidence links, domain metadata. Not covered by L1 integrity hash."
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Loosechain UVRN Adapter
|
|
3
|
-
* Layer 2 - Wraps Delta Engine Core receipts in DRVC3 envelopes
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Types
|
|
7
|
-
export * from './types';
|
|
8
|
-
|
|
9
|
-
// Core wrapper
|
|
10
|
-
export { wrapInDRVC3, extractDeltaReceipt } from './wrapper';
|
|
11
|
-
|
|
12
|
-
// Signing utilities
|
|
13
|
-
export { signHash, recoverSigner, verifySignature } from './signer';
|
|
14
|
-
|
|
15
|
-
// Validation
|
|
16
|
-
export { validateDRVC3, isDRVC3Receipt } from './validator';
|
package/src/signer.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EIP-191 Signing Utilities
|
|
3
|
-
* Provides Ethereum personal message signing for DRVC3 receipts
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Wallet, HDNodeWallet, verifyMessage } from 'ethers';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Signs a hash using EIP-191 (Ethereum Signed Message)
|
|
10
|
-
* @param hash - The hex string hash to sign
|
|
11
|
-
* @param wallet - ethers Wallet instance with private key
|
|
12
|
-
* @returns Promise resolving to the signature hex string
|
|
13
|
-
*/
|
|
14
|
-
export async function signHash(hash: string, wallet: Wallet | HDNodeWallet): Promise<string> {
|
|
15
|
-
// signMessage automatically prefixes with "\x19Ethereum Signed Message:\n" + message length
|
|
16
|
-
return wallet.signMessage(hash);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Recovers the signer address from a hash and signature
|
|
21
|
-
* @param hash - The original hash that was signed
|
|
22
|
-
* @param signature - The EIP-191 signature
|
|
23
|
-
* @returns The signer's Ethereum address
|
|
24
|
-
*/
|
|
25
|
-
export function recoverSigner(hash: string, signature: string): string {
|
|
26
|
-
return verifyMessage(hash, signature);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Verifies that a signature was created by the expected signer
|
|
31
|
-
* @param hash - The original hash that was signed
|
|
32
|
-
* @param signature - The EIP-191 signature
|
|
33
|
-
* @param expectedAddress - The expected signer address
|
|
34
|
-
* @returns True if the signature is valid and matches the expected address
|
|
35
|
-
*/
|
|
36
|
-
export function verifySignature(
|
|
37
|
-
hash: string,
|
|
38
|
-
signature: string,
|
|
39
|
-
expectedAddress: string
|
|
40
|
-
): boolean {
|
|
41
|
-
try {
|
|
42
|
-
const recoveredAddress = recoverSigner(hash, signature);
|
|
43
|
-
return recoveredAddress.toLowerCase() === expectedAddress.toLowerCase();
|
|
44
|
-
} catch {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DRVC3 Types for UVRN Adapter (v1.01)
|
|
3
|
-
* Layer 2 envelope types that wrap Layer 1 DeltaReceipt
|
|
4
|
-
*
|
|
5
|
-
* v1.01 adds the `extensions` field for Layer 2 provenance data.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { DeltaReceipt } from '@uvrn/core';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* DRVC3 Integrity block - contains hash and signature data
|
|
12
|
-
*/
|
|
13
|
-
export interface DRVC3Integrity {
|
|
14
|
-
hash_algorithm: 'sha256';
|
|
15
|
-
hash: string;
|
|
16
|
-
signature_method: 'eip191';
|
|
17
|
-
signature: string;
|
|
18
|
-
signer_address: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* DRVC3 Validation block - contains score and embedded checks
|
|
23
|
-
*/
|
|
24
|
-
export interface DRVC3Validation {
|
|
25
|
-
v_score: number;
|
|
26
|
-
checks: {
|
|
27
|
-
delta_receipt: DeltaReceipt;
|
|
28
|
-
[key: string]: unknown;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* DRVC3 Resource block (optional) - describes the verified resource
|
|
34
|
-
*/
|
|
35
|
-
export interface DRVC3Resource {
|
|
36
|
-
type?: string;
|
|
37
|
-
url?: string;
|
|
38
|
-
branch?: string;
|
|
39
|
-
commit_hash?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Block state - "loose" means mutable/portable, "blocked" means canonized/permanent
|
|
44
|
-
*/
|
|
45
|
-
export type BlockState = 'loose' | 'blocked';
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Full DRVC3 Receipt Envelope
|
|
49
|
-
* Wraps Layer 1 DeltaReceipt with protocol metadata and signatures
|
|
50
|
-
*/
|
|
51
|
-
export interface DRVC3Receipt {
|
|
52
|
-
receipt_id: string;
|
|
53
|
-
issuer: string;
|
|
54
|
-
event: string;
|
|
55
|
-
timestamp: string;
|
|
56
|
-
description?: string;
|
|
57
|
-
resource?: DRVC3Resource;
|
|
58
|
-
integrity: DRVC3Integrity;
|
|
59
|
-
validation: DRVC3Validation;
|
|
60
|
-
block_state: BlockState;
|
|
61
|
-
certificate: string;
|
|
62
|
-
replay_instructions?: Record<string, unknown>;
|
|
63
|
-
tags?: string[];
|
|
64
|
-
/**
|
|
65
|
-
* Layer 2 extension data — provenance, evidence, domain-specific metadata.
|
|
66
|
-
* This field is NOT covered by the L1 integrity hash. It is envelope metadata
|
|
67
|
-
* owned by the consumer chain (e.g., MarketChain source URLs, evidence links).
|
|
68
|
-
*/
|
|
69
|
-
extensions?: Record<string, unknown>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Options for wrapping a DeltaReceipt in DRVC3 envelope
|
|
74
|
-
*/
|
|
75
|
-
export interface WrapOptions {
|
|
76
|
-
/** Issuer identifier (e.g., "uvrn", "app.example.com") */
|
|
77
|
-
issuer: string;
|
|
78
|
-
/** Event type (e.g., "delta-reconciliation") */
|
|
79
|
-
event: string;
|
|
80
|
-
/** Block state - defaults to "loose" */
|
|
81
|
-
blockState?: BlockState;
|
|
82
|
-
/** DRVC3 certificate version - defaults to "DRVC3 v1.0" */
|
|
83
|
-
certificate?: string;
|
|
84
|
-
/** Optional description */
|
|
85
|
-
description?: string;
|
|
86
|
-
/** Optional resource metadata */
|
|
87
|
-
resource?: DRVC3Resource;
|
|
88
|
-
/** Optional replay instructions */
|
|
89
|
-
replayInstructions?: Record<string, unknown>;
|
|
90
|
-
/** Optional tags (e.g., ["#uvrn", "#receipt"]) */
|
|
91
|
-
tags?: string[];
|
|
92
|
-
/** Optional Layer 2 extension data (provenance, evidence, domain metadata) */
|
|
93
|
-
extensions?: Record<string, unknown>;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Validation result from schema validation
|
|
98
|
-
*/
|
|
99
|
-
export interface DRVC3ValidationResult {
|
|
100
|
-
valid: boolean;
|
|
101
|
-
errors?: string[];
|
|
102
|
-
}
|
package/src/validator.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DRVC3 Schema Validator
|
|
3
|
-
* Uses ajv to validate DRVC3 receipts against the official schema
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import Ajv from 'ajv';
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
import * as fs from 'fs';
|
|
9
|
-
import { DRVC3ValidationResult } from './types';
|
|
10
|
-
|
|
11
|
-
// Load schema from file
|
|
12
|
-
const schemaPath = path.join(__dirname, '../schemas/drvc3.schema.json');
|
|
13
|
-
const drvc3Schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
|
|
14
|
-
|
|
15
|
-
// Initialize Ajv with JSON Schema 2020-12 support
|
|
16
|
-
const ajv = new Ajv({ strict: false });
|
|
17
|
-
|
|
18
|
-
// Add formats support (date-time, etc.)
|
|
19
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
20
|
-
const addFormats = require('ajv-formats');
|
|
21
|
-
addFormats(ajv);
|
|
22
|
-
|
|
23
|
-
// Compile the schema once
|
|
24
|
-
const validateSchema = ajv.compile(drvc3Schema);
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Validates a DRVC3 receipt against the official schema
|
|
28
|
-
* @param receipt - The receipt object to validate
|
|
29
|
-
* @returns Validation result with errors if invalid
|
|
30
|
-
*/
|
|
31
|
-
export function validateDRVC3(receipt: unknown): DRVC3ValidationResult {
|
|
32
|
-
const valid = validateSchema(receipt);
|
|
33
|
-
|
|
34
|
-
if (valid) {
|
|
35
|
-
return { valid: true };
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const errors = validateSchema.errors?.map(err => {
|
|
39
|
-
const path = err.instancePath || '/';
|
|
40
|
-
return `${path}: ${err.message}`;
|
|
41
|
-
}) || ['Unknown validation error'];
|
|
42
|
-
|
|
43
|
-
return { valid: false, errors };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Type guard to check if an object is a valid DRVC3 receipt
|
|
48
|
-
* @param obj - Object to check
|
|
49
|
-
* @returns True if the object is a valid DRVC3 receipt
|
|
50
|
-
*/
|
|
51
|
-
export function isDRVC3Receipt(obj: unknown): boolean {
|
|
52
|
-
return validateDRVC3(obj).valid;
|
|
53
|
-
}
|
package/src/wrapper.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DRVC3 Wrapper
|
|
3
|
-
* Wraps Layer 1 DeltaReceipt in a DRVC3 envelope with EIP-191 signatures
|
|
4
|
-
*
|
|
5
|
-
* Key Principle: The DeltaReceipt hash is READ-ONLY from Layer 1.
|
|
6
|
-
* DRVC3 envelope fields (receipt_id, timestamp, signature) are envelope metadata
|
|
7
|
-
* and do NOT affect determinism or replay.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { DeltaReceipt } from '@uvrn/core';
|
|
11
|
-
import { Wallet, HDNodeWallet, Signer } from 'ethers';
|
|
12
|
-
import { DRVC3Receipt, WrapOptions } from './types';
|
|
13
|
-
import { signHash } from './signer';
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Wraps a DeltaReceipt in a DRVC3 envelope
|
|
17
|
-
*
|
|
18
|
-
* @param deltaReceipt - Layer 1 DeltaReceipt (deterministic, hash-covered)
|
|
19
|
-
* @param signer - ethers Wallet for EIP-191 signing
|
|
20
|
-
* @param options - Envelope options (issuer, event, etc.)
|
|
21
|
-
* @returns Promise resolving to complete DRVC3 receipt
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```typescript
|
|
25
|
-
* import { runDeltaEngine } from '@uvrn/core';
|
|
26
|
-
* import { wrapInDRVC3 } from '@uvrn/adapter';
|
|
27
|
-
* import { Wallet } from 'ethers';
|
|
28
|
-
*
|
|
29
|
-
* const deltaReceipt = runDeltaEngine(bundle);
|
|
30
|
-
* const wallet = new Wallet(privateKey);
|
|
31
|
-
* const drvc3 = await wrapInDRVC3(deltaReceipt, wallet, {
|
|
32
|
-
* issuer: 'uvrn',
|
|
33
|
-
* event: 'delta-reconciliation'
|
|
34
|
-
* });
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export async function wrapInDRVC3(
|
|
38
|
-
deltaReceipt: DeltaReceipt,
|
|
39
|
-
signer: Wallet | HDNodeWallet,
|
|
40
|
-
options: WrapOptions
|
|
41
|
-
): Promise<DRVC3Receipt> {
|
|
42
|
-
// 1. Generate receipt_id (ENVELOPE METADATA - non-deterministic, intentional)
|
|
43
|
-
const timestamp = new Date().toISOString();
|
|
44
|
-
const receipt_id = `drvc3-${deltaReceipt.bundleId}-${Date.now()}`;
|
|
45
|
-
|
|
46
|
-
// 2. Read hash from DeltaReceipt (HASH DOMAIN - read-only from Layer 1)
|
|
47
|
-
const hash = deltaReceipt.hash;
|
|
48
|
-
|
|
49
|
-
// 3. Sign hash with EIP-191 (ENVELOPE METADATA - certifies "who" and "when")
|
|
50
|
-
const signature = await signHash(hash, signer);
|
|
51
|
-
|
|
52
|
-
// 4. Construct DRVC3 envelope
|
|
53
|
-
const drvc3: DRVC3Receipt = {
|
|
54
|
-
receipt_id,
|
|
55
|
-
issuer: options.issuer,
|
|
56
|
-
event: options.event,
|
|
57
|
-
timestamp,
|
|
58
|
-
integrity: {
|
|
59
|
-
hash_algorithm: 'sha256',
|
|
60
|
-
hash,
|
|
61
|
-
signature_method: 'eip191',
|
|
62
|
-
signature,
|
|
63
|
-
signer_address: signer.address
|
|
64
|
-
},
|
|
65
|
-
validation: {
|
|
66
|
-
v_score: deltaReceipt.deltaFinal,
|
|
67
|
-
checks: {
|
|
68
|
-
delta_receipt: deltaReceipt
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
block_state: options.blockState || 'loose',
|
|
72
|
-
certificate: options.certificate || 'DRVC3 v1.01'
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Add optional fields if provided
|
|
76
|
-
if (options.description) {
|
|
77
|
-
drvc3.description = options.description;
|
|
78
|
-
}
|
|
79
|
-
if (options.resource) {
|
|
80
|
-
drvc3.resource = options.resource;
|
|
81
|
-
}
|
|
82
|
-
if (options.replayInstructions) {
|
|
83
|
-
drvc3.replay_instructions = options.replayInstructions;
|
|
84
|
-
}
|
|
85
|
-
if (options.extensions) {
|
|
86
|
-
drvc3.extensions = options.extensions;
|
|
87
|
-
}
|
|
88
|
-
if (options.tags) {
|
|
89
|
-
drvc3.tags = options.tags;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return drvc3;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Extracts the original DeltaReceipt from a DRVC3 envelope
|
|
97
|
-
*
|
|
98
|
-
* @param drvc3 - DRVC3 receipt envelope
|
|
99
|
-
* @returns The embedded DeltaReceipt
|
|
100
|
-
*/
|
|
101
|
-
export function extractDeltaReceipt(drvc3: DRVC3Receipt): DeltaReceipt {
|
|
102
|
-
return drvc3.validation.checks.delta_receipt;
|
|
103
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration Tests
|
|
3
|
-
* Tests the full flow from DeltaBundle → DeltaReceipt → DRVC3Receipt
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Wallet, HDNodeWallet } from 'ethers';
|
|
7
|
-
import {
|
|
8
|
-
runDeltaEngine,
|
|
9
|
-
verifyReceipt,
|
|
10
|
-
DeltaBundle
|
|
11
|
-
} from '@uvrn/core';
|
|
12
|
-
import { wrapInDRVC3, extractDeltaReceipt, validateDRVC3 } from '../src';
|
|
13
|
-
|
|
14
|
-
describe('Integration: Layer 1 → Layer 2', () => {
|
|
15
|
-
let testWallet: HDNodeWallet;
|
|
16
|
-
|
|
17
|
-
beforeAll(() => {
|
|
18
|
-
testWallet = Wallet.createRandom();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('should complete full flow: bundle → receipt → DRVC3', async () => {
|
|
22
|
-
// 1. Create a DeltaBundle (input to Layer 1)
|
|
23
|
-
const bundle: DeltaBundle = {
|
|
24
|
-
bundleId: 'integration-test-001',
|
|
25
|
-
claim: 'Integration Test',
|
|
26
|
-
thresholdPct: 0.1,
|
|
27
|
-
dataSpecs: [
|
|
28
|
-
{
|
|
29
|
-
id: 'source-1',
|
|
30
|
-
label: 'Source 1',
|
|
31
|
-
sourceKind: 'metric',
|
|
32
|
-
originDocIds: ['doc-1'],
|
|
33
|
-
metrics: [
|
|
34
|
-
{ key: 'revenue', value: 1000 },
|
|
35
|
-
{ key: 'users', value: 500 }
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: 'source-2',
|
|
40
|
-
label: 'Source 2',
|
|
41
|
-
sourceKind: 'metric',
|
|
42
|
-
originDocIds: ['doc-2'],
|
|
43
|
-
metrics: [
|
|
44
|
-
{ key: 'revenue', value: 1050 },
|
|
45
|
-
{ key: 'users', value: 510 }
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
// 2. Run Layer 1 Engine
|
|
52
|
-
const deltaReceipt = runDeltaEngine(bundle);
|
|
53
|
-
|
|
54
|
-
// Verify Layer 1 receipt
|
|
55
|
-
const verifyResult = verifyReceipt(deltaReceipt);
|
|
56
|
-
expect(verifyResult.verified).toBe(true);
|
|
57
|
-
|
|
58
|
-
// 3. Wrap in DRVC3 (Layer 2)
|
|
59
|
-
const drvc3 = await wrapInDRVC3(deltaReceipt, testWallet, {
|
|
60
|
-
issuer: 'uvrn-integration',
|
|
61
|
-
event: 'delta-reconciliation',
|
|
62
|
-
tags: ['#uvrn', '#integration-test']
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// 4. Validate DRVC3 schema
|
|
66
|
-
const schemaResult = validateDRVC3(drvc3);
|
|
67
|
-
expect(schemaResult.valid).toBe(true);
|
|
68
|
-
|
|
69
|
-
// 5. Verify hash chain integrity
|
|
70
|
-
expect(drvc3.integrity.hash).toBe(deltaReceipt.hash);
|
|
71
|
-
|
|
72
|
-
// 6. Extract and verify embedded receipt
|
|
73
|
-
const extracted = extractDeltaReceipt(drvc3);
|
|
74
|
-
expect(extracted.hash).toBe(deltaReceipt.hash);
|
|
75
|
-
expect(verifyReceipt(extracted).verified).toBe(true);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should maintain hash integrity through Layer 2 wrapping', async () => {
|
|
79
|
-
const bundle: DeltaBundle = {
|
|
80
|
-
bundleId: 'hash-integrity-test',
|
|
81
|
-
claim: 'Hash Test',
|
|
82
|
-
thresholdPct: 0.05,
|
|
83
|
-
dataSpecs: [
|
|
84
|
-
{
|
|
85
|
-
id: 'a',
|
|
86
|
-
label: 'A',
|
|
87
|
-
sourceKind: 'metric',
|
|
88
|
-
originDocIds: [],
|
|
89
|
-
metrics: [{ key: 'val', value: 100 }]
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
id: 'b',
|
|
93
|
-
label: 'B',
|
|
94
|
-
sourceKind: 'metric',
|
|
95
|
-
originDocIds: [],
|
|
96
|
-
metrics: [{ key: 'val', value: 100 }]
|
|
97
|
-
}
|
|
98
|
-
]
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const receipt = runDeltaEngine(bundle);
|
|
102
|
-
const originalHash = receipt.hash;
|
|
103
|
-
|
|
104
|
-
// Wrap multiple times - hash should always match
|
|
105
|
-
const drvc3_1 = await wrapInDRVC3(receipt, testWallet, {
|
|
106
|
-
issuer: 'test',
|
|
107
|
-
event: 'test'
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
const drvc3_2 = await wrapInDRVC3(receipt, testWallet, {
|
|
111
|
-
issuer: 'test',
|
|
112
|
-
event: 'test'
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Envelope metadata differs (receipt_id, timestamp)
|
|
116
|
-
expect(drvc3_1.receipt_id).not.toBe(drvc3_2.receipt_id);
|
|
117
|
-
expect(drvc3_1.timestamp).not.toBe(drvc3_2.timestamp);
|
|
118
|
-
|
|
119
|
-
// But hash domain remains identical
|
|
120
|
-
expect(drvc3_1.integrity.hash).toBe(originalHash);
|
|
121
|
-
expect(drvc3_2.integrity.hash).toBe(originalHash);
|
|
122
|
-
});
|
|
123
|
-
});
|
package/tests/wrapper.test.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DRVC3 Wrapper Tests
|
|
3
|
-
* Tests the wrapInDRVC3 function and schema validation
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Wallet, HDNodeWallet } from 'ethers';
|
|
7
|
-
import { wrapInDRVC3, extractDeltaReceipt } from '../src/wrapper';
|
|
8
|
-
import { validateDRVC3 } from '../src/validator';
|
|
9
|
-
import { recoverSigner } from '../src/signer';
|
|
10
|
-
import { DeltaReceipt } from '@uvrn/core';
|
|
11
|
-
|
|
12
|
-
describe('DRVC3 Wrapper', () => {
|
|
13
|
-
// Mock DeltaReceipt (as would come from Layer 1)
|
|
14
|
-
const mockDeltaReceipt: DeltaReceipt = {
|
|
15
|
-
bundleId: 'test-bundle-001',
|
|
16
|
-
deltaFinal: 0.05,
|
|
17
|
-
sources: ['Source A', 'Source B'],
|
|
18
|
-
rounds: [
|
|
19
|
-
{
|
|
20
|
-
round: 1,
|
|
21
|
-
deltasByMetric: { revenue: 0.05, users: 0.0 },
|
|
22
|
-
withinThreshold: true,
|
|
23
|
-
witnessRequired: false
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
suggestedFixes: [],
|
|
27
|
-
outcome: 'consensus',
|
|
28
|
-
hash: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2'
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
let testWallet: HDNodeWallet;
|
|
32
|
-
|
|
33
|
-
beforeAll(() => {
|
|
34
|
-
// Create a deterministic wallet for testing
|
|
35
|
-
testWallet = Wallet.createRandom();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should wrap DeltaReceipt in valid DRVC3 envelope', async () => {
|
|
39
|
-
const drvc3 = await wrapInDRVC3(mockDeltaReceipt, testWallet, {
|
|
40
|
-
issuer: 'uvrn-test',
|
|
41
|
-
event: 'delta-reconciliation'
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Check required fields
|
|
45
|
-
expect(drvc3.receipt_id).toMatch(/^drvc3-test-bundle-001-\d+$/);
|
|
46
|
-
expect(drvc3.issuer).toBe('uvrn-test');
|
|
47
|
-
expect(drvc3.event).toBe('delta-reconciliation');
|
|
48
|
-
expect(drvc3.timestamp).toBeDefined();
|
|
49
|
-
expect(drvc3.block_state).toBe('loose');
|
|
50
|
-
expect(drvc3.certificate).toBe('DRVC3 v1.0');
|
|
51
|
-
|
|
52
|
-
// Check integrity block
|
|
53
|
-
expect(drvc3.integrity.hash_algorithm).toBe('sha256');
|
|
54
|
-
expect(drvc3.integrity.hash).toBe(mockDeltaReceipt.hash);
|
|
55
|
-
expect(drvc3.integrity.signature_method).toBe('eip191');
|
|
56
|
-
expect(drvc3.integrity.signature).toBeDefined();
|
|
57
|
-
expect(drvc3.integrity.signer_address).toBe(testWallet.address);
|
|
58
|
-
|
|
59
|
-
// Check validation block
|
|
60
|
-
expect(drvc3.validation.v_score).toBe(mockDeltaReceipt.deltaFinal);
|
|
61
|
-
expect(drvc3.validation.checks.delta_receipt).toEqual(mockDeltaReceipt);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should produce schema-valid DRVC3 receipt', async () => {
|
|
65
|
-
const drvc3 = await wrapInDRVC3(mockDeltaReceipt, testWallet, {
|
|
66
|
-
issuer: 'uvrn',
|
|
67
|
-
event: 'test'
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const result = validateDRVC3(drvc3);
|
|
71
|
-
expect(result.valid).toBe(true);
|
|
72
|
-
expect(result.errors).toBeUndefined();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should include optional fields when provided', async () => {
|
|
76
|
-
const drvc3 = await wrapInDRVC3(mockDeltaReceipt, testWallet, {
|
|
77
|
-
issuer: 'uvrn',
|
|
78
|
-
event: 'delta-reconciliation',
|
|
79
|
-
blockState: 'blocked',
|
|
80
|
-
certificate: 'DRVC3 v1.1',
|
|
81
|
-
description: 'Test receipt',
|
|
82
|
-
tags: ['#uvrn', '#receipt', '#test']
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
expect(drvc3.block_state).toBe('blocked');
|
|
86
|
-
expect(drvc3.certificate).toBe('DRVC3 v1.1');
|
|
87
|
-
expect(drvc3.description).toBe('Test receipt');
|
|
88
|
-
expect(drvc3.tags).toEqual(['#uvrn', '#receipt', '#test']);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should create verifiable signature', async () => {
|
|
92
|
-
const drvc3 = await wrapInDRVC3(mockDeltaReceipt, testWallet, {
|
|
93
|
-
issuer: 'uvrn',
|
|
94
|
-
event: 'test'
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Recover signer from signature
|
|
98
|
-
const recoveredAddress = recoverSigner(
|
|
99
|
-
drvc3.integrity.hash,
|
|
100
|
-
drvc3.integrity.signature
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
expect(recoveredAddress.toLowerCase()).toBe(testWallet.address.toLowerCase());
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should extract original DeltaReceipt from envelope', async () => {
|
|
107
|
-
const drvc3 = await wrapInDRVC3(mockDeltaReceipt, testWallet, {
|
|
108
|
-
issuer: 'uvrn',
|
|
109
|
-
event: 'test'
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const extracted = extractDeltaReceipt(drvc3);
|
|
113
|
-
expect(extracted).toEqual(mockDeltaReceipt);
|
|
114
|
-
});
|
|
115
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"lib": ["ES2020"],
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noImplicitAny": true,
|
|
9
|
-
"strictNullChecks": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"moduleResolution": "node",
|
|
14
|
-
"resolveJsonModule": true,
|
|
15
|
-
"outDir": "./dist",
|
|
16
|
-
"rootDir": ".",
|
|
17
|
-
"baseUrl": "."
|
|
18
|
-
},
|
|
19
|
-
"include": ["src/**/*", "tests/**/*"],
|
|
20
|
-
"exclude": ["node_modules", "dist"]
|
|
21
|
-
}
|