@algovoi/substrate 0.3.1 → 0.4.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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/settlement-binding.d.ts +61 -0
- package/dist/settlement-binding.d.ts.map +1 -0
- package/dist/settlement-binding.js +79 -0
- package/dist/settlement-binding.js.map +1 -0
- package/package.json +2 -2
- package/src/index.ts +7 -0
- package/src/settlement-binding.ts +110 -0
package/dist/index.d.ts
CHANGED
|
@@ -22,4 +22,5 @@ export { CompositeTrustQueryError, type EmitterRow, compositeTrustQueryHash, } f
|
|
|
22
22
|
export { SCREEN_RESULTS, type ScreenResult, ComplianceReceiptError, type ComplianceReceipt, type BuildComplianceReceiptInput, buildComplianceReceipt, } from './compliance-receipt.js';
|
|
23
23
|
export { AuditChainError, type AuditChainRow, appendToChain, verifyAuditChain, } from './audit-chain.js';
|
|
24
24
|
export { TransactionalError, type TransitionPreimage, type TransitionInput, type TransitionRecord, type TransactionalChain, type TransactionalChainInput, transitionPreimage, transitionHash, buildTransactionalActionChain, } from './transactional.js';
|
|
25
|
+
export { SettlementBindingError, type SettlementBindingPreimage, settlementBindingPreimage, settlementActionBinding, } from './settlement-binding.js';
|
|
25
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,wBAAwB,EACxB,KAAK,UAAU,EACf,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,kBAAkB,EAClB,cAAc,EACd,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,wBAAwB,EACxB,KAAK,UAAU,EACf,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,sBAAsB,EACtB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EACf,KAAK,aAAa,EAClB,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,kBAAkB,EAClB,cAAc,EACd,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,sBAAsB,EACtB,KAAK,yBAAyB,EAC9B,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -22,4 +22,5 @@ export { CompositeTrustQueryError, compositeTrustQueryHash, } from './composite-
|
|
|
22
22
|
export { SCREEN_RESULTS, ComplianceReceiptError, buildComplianceReceipt, } from './compliance-receipt.js';
|
|
23
23
|
export { AuditChainError, appendToChain, verifyAuditChain, } from './audit-chain.js';
|
|
24
24
|
export { TransactionalError, transitionPreimage, transitionHash, buildTransactionalActionChain, } from './transactional.js';
|
|
25
|
+
export { SettlementBindingError, settlementBindingPreimage, settlementActionBinding, } from './settlement-binding.js';
|
|
25
26
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EAGd,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,wBAAwB,EAExB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,cAAc,EAEd,sBAAsB,EAGtB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EAEf,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAMlB,kBAAkB,EAClB,cAAc,EACd,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,iBAAiB,EACjB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EAGd,SAAS,EACT,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,wBAAwB,EAExB,uBAAuB,GACxB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,cAAc,EAEd,sBAAsB,EAGtB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,eAAe,EAEf,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,kBAAkB,EAMlB,kBAAkB,EAClB,cAAc,EACd,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,sBAAsB,EAEtB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settlement-action binding (non-normative substrate extension).
|
|
3
|
+
*
|
|
4
|
+
* An x402/AP2/A2A settlement attestation proves a *payment* occurred. It does
|
|
5
|
+
* not, on its own, prove *which verified agent action* the payment corresponds
|
|
6
|
+
* to, nor that the correspondence is recorded in a tamper-evident chain. This
|
|
7
|
+
* module closes that post-settlement accountability gap with a single canonical
|
|
8
|
+
* reference binding four already-published substrate artifacts into one record:
|
|
9
|
+
*
|
|
10
|
+
* binding_ref = "sha256:" + SHA-256(JCS({
|
|
11
|
+
* action_ref, // the verified agent-action identity
|
|
12
|
+
* transition_hash, // the COMMITTED lifecycle transition (the "once")
|
|
13
|
+
* settlement_ref, // the settlement attestation content_hash
|
|
14
|
+
* retention_chain_ref, // the tamper-evident chain position recording it
|
|
15
|
+
* }))
|
|
16
|
+
*
|
|
17
|
+
* No new hashing primitive is introduced: the binding is the substrate's
|
|
18
|
+
* existing JCS + SHA-256 over the four references. Because action_ref and
|
|
19
|
+
* transition_hash are themselves computed from epoch-millisecond-integer
|
|
20
|
+
* preimages (Substrate Rule 2), any upstream RFC 3339 string timestamp produces
|
|
21
|
+
* a different action_ref, hence a different binding -- a non-conformant lineage
|
|
22
|
+
* cannot reproduce the binding bytes.
|
|
23
|
+
*
|
|
24
|
+
* The output carries the "sha256:" algorithm prefix, consistent with
|
|
25
|
+
* retention_chain_ref, signalling a content-addressed reference.
|
|
26
|
+
*/
|
|
27
|
+
export declare class SettlementBindingError extends Error {
|
|
28
|
+
constructor(message: string);
|
|
29
|
+
}
|
|
30
|
+
export interface SettlementBindingPreimage {
|
|
31
|
+
action_ref: string;
|
|
32
|
+
transition_hash: string;
|
|
33
|
+
settlement_ref: string;
|
|
34
|
+
retention_chain_ref: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Return the validated four-field binding preimage object.
|
|
38
|
+
*
|
|
39
|
+
* The shape is fixed at the substrate layer; each field cryptographically
|
|
40
|
+
* contributes to the binding so that no one component can be substituted
|
|
41
|
+
* without changing the binding_ref.
|
|
42
|
+
*/
|
|
43
|
+
export declare function settlementBindingPreimage(input: {
|
|
44
|
+
action_ref: string;
|
|
45
|
+
transition_hash: string;
|
|
46
|
+
settlement_ref: string;
|
|
47
|
+
retention_chain_ref: string;
|
|
48
|
+
}): SettlementBindingPreimage;
|
|
49
|
+
/**
|
|
50
|
+
* Return the binding_ref as a "sha256:"-prefixed content-addressed reference.
|
|
51
|
+
*
|
|
52
|
+
* binding_ref = "sha256:" + SHA-256(JCS({action_ref, transition_hash,
|
|
53
|
+
* settlement_ref, retention_chain_ref}))
|
|
54
|
+
*/
|
|
55
|
+
export declare function settlementActionBinding(input: {
|
|
56
|
+
action_ref: string;
|
|
57
|
+
transition_hash: string;
|
|
58
|
+
settlement_ref: string;
|
|
59
|
+
retention_chain_ref: string;
|
|
60
|
+
}): string;
|
|
61
|
+
//# sourceMappingURL=settlement-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlement-binding.d.ts","sourceRoot":"","sources":["../src/settlement-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAOH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AA8BD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,yBAAyB,CAO5B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,MAAM,CAGT"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settlement-action binding (non-normative substrate extension).
|
|
3
|
+
*
|
|
4
|
+
* An x402/AP2/A2A settlement attestation proves a *payment* occurred. It does
|
|
5
|
+
* not, on its own, prove *which verified agent action* the payment corresponds
|
|
6
|
+
* to, nor that the correspondence is recorded in a tamper-evident chain. This
|
|
7
|
+
* module closes that post-settlement accountability gap with a single canonical
|
|
8
|
+
* reference binding four already-published substrate artifacts into one record:
|
|
9
|
+
*
|
|
10
|
+
* binding_ref = "sha256:" + SHA-256(JCS({
|
|
11
|
+
* action_ref, // the verified agent-action identity
|
|
12
|
+
* transition_hash, // the COMMITTED lifecycle transition (the "once")
|
|
13
|
+
* settlement_ref, // the settlement attestation content_hash
|
|
14
|
+
* retention_chain_ref, // the tamper-evident chain position recording it
|
|
15
|
+
* }))
|
|
16
|
+
*
|
|
17
|
+
* No new hashing primitive is introduced: the binding is the substrate's
|
|
18
|
+
* existing JCS + SHA-256 over the four references. Because action_ref and
|
|
19
|
+
* transition_hash are themselves computed from epoch-millisecond-integer
|
|
20
|
+
* preimages (Substrate Rule 2), any upstream RFC 3339 string timestamp produces
|
|
21
|
+
* a different action_ref, hence a different binding -- a non-conformant lineage
|
|
22
|
+
* cannot reproduce the binding bytes.
|
|
23
|
+
*
|
|
24
|
+
* The output carries the "sha256:" algorithm prefix, consistent with
|
|
25
|
+
* retention_chain_ref, signalling a content-addressed reference.
|
|
26
|
+
*/
|
|
27
|
+
import { sha256Jcs } from './canonicalize.js';
|
|
28
|
+
const HEX64_RE = /^[0-9a-f]{64}$/;
|
|
29
|
+
const SHA256_REF_RE = /^sha256:[0-9a-f]{64}$/;
|
|
30
|
+
export class SettlementBindingError extends Error {
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = 'SettlementBindingError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function requireHex64(field, value) {
|
|
37
|
+
if (typeof value !== 'string') {
|
|
38
|
+
throw new SettlementBindingError(`${field} must be string, got ${typeof value}`);
|
|
39
|
+
}
|
|
40
|
+
if (!HEX64_RE.test(value)) {
|
|
41
|
+
throw new SettlementBindingError(`${field} must be a lowercase 64-character SHA-256 hex string`);
|
|
42
|
+
}
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
function requireChainRef(value) {
|
|
46
|
+
if (typeof value !== 'string') {
|
|
47
|
+
throw new SettlementBindingError(`retention_chain_ref must be string, got ${typeof value}`);
|
|
48
|
+
}
|
|
49
|
+
if (!SHA256_REF_RE.test(value)) {
|
|
50
|
+
throw new SettlementBindingError("retention_chain_ref must be of the form 'sha256:<lowercase 64-char hex>'");
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Return the validated four-field binding preimage object.
|
|
56
|
+
*
|
|
57
|
+
* The shape is fixed at the substrate layer; each field cryptographically
|
|
58
|
+
* contributes to the binding so that no one component can be substituted
|
|
59
|
+
* without changing the binding_ref.
|
|
60
|
+
*/
|
|
61
|
+
export function settlementBindingPreimage(input) {
|
|
62
|
+
return {
|
|
63
|
+
action_ref: requireHex64('action_ref', input.action_ref),
|
|
64
|
+
transition_hash: requireHex64('transition_hash', input.transition_hash),
|
|
65
|
+
settlement_ref: requireHex64('settlement_ref', input.settlement_ref),
|
|
66
|
+
retention_chain_ref: requireChainRef(input.retention_chain_ref),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Return the binding_ref as a "sha256:"-prefixed content-addressed reference.
|
|
71
|
+
*
|
|
72
|
+
* binding_ref = "sha256:" + SHA-256(JCS({action_ref, transition_hash,
|
|
73
|
+
* settlement_ref, retention_chain_ref}))
|
|
74
|
+
*/
|
|
75
|
+
export function settlementActionBinding(input) {
|
|
76
|
+
const obj = settlementBindingPreimage(input);
|
|
77
|
+
return `sha256:${sha256Jcs(obj)}`;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=settlement-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settlement-binding.js","sourceRoot":"","sources":["../src/settlement-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,QAAQ,GAAG,gBAAgB,CAAC;AAClC,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAE9C,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AASD,SAAS,YAAY,CAAC,KAAa,EAAE,KAAc;IACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,sBAAsB,CAC9B,GAAG,KAAK,wBAAwB,OAAO,KAAK,EAAE,CAC/C,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,sBAAsB,CAC9B,GAAG,KAAK,sDAAsD,CAC/D,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,sBAAsB,CAC9B,2CAA2C,OAAO,KAAK,EAAE,CAC1D,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,sBAAsB,CAC9B,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAKzC;IACC,OAAO;QACL,UAAU,EAAE,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,CAAC;QACxD,eAAe,EAAE,YAAY,CAAC,iBAAiB,EAAE,KAAK,CAAC,eAAe,CAAC;QACvE,cAAc,EAAE,YAAY,CAAC,gBAAgB,EAAE,KAAK,CAAC,cAAc,CAAC;QACpE,mBAAmB,EAAE,eAAe,CAAC,KAAK,CAAC,mBAAmB,CAAC;KAChE,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAKvC;IACC,MAAM,GAAG,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;IAC7C,OAAO,UAAU,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;AACpC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algovoi/substrate",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "AlgoVoi agentic-payments substrate -- JCS canonicalisation, action_ref, composite trust-query, compliance receipts, audit chain",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "AlgoVoi agentic-payments substrate -- JCS canonicalisation, action_ref, composite trust-query, compliance receipts, audit chain, settlement-action binding",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"x402",
|
|
7
7
|
"ap2",
|
package/src/index.ts
CHANGED
|
@@ -66,3 +66,10 @@ export {
|
|
|
66
66
|
transitionHash,
|
|
67
67
|
buildTransactionalActionChain,
|
|
68
68
|
} from './transactional.js';
|
|
69
|
+
|
|
70
|
+
export {
|
|
71
|
+
SettlementBindingError,
|
|
72
|
+
type SettlementBindingPreimage,
|
|
73
|
+
settlementBindingPreimage,
|
|
74
|
+
settlementActionBinding,
|
|
75
|
+
} from './settlement-binding.js';
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settlement-action binding (non-normative substrate extension).
|
|
3
|
+
*
|
|
4
|
+
* An x402/AP2/A2A settlement attestation proves a *payment* occurred. It does
|
|
5
|
+
* not, on its own, prove *which verified agent action* the payment corresponds
|
|
6
|
+
* to, nor that the correspondence is recorded in a tamper-evident chain. This
|
|
7
|
+
* module closes that post-settlement accountability gap with a single canonical
|
|
8
|
+
* reference binding four already-published substrate artifacts into one record:
|
|
9
|
+
*
|
|
10
|
+
* binding_ref = "sha256:" + SHA-256(JCS({
|
|
11
|
+
* action_ref, // the verified agent-action identity
|
|
12
|
+
* transition_hash, // the COMMITTED lifecycle transition (the "once")
|
|
13
|
+
* settlement_ref, // the settlement attestation content_hash
|
|
14
|
+
* retention_chain_ref, // the tamper-evident chain position recording it
|
|
15
|
+
* }))
|
|
16
|
+
*
|
|
17
|
+
* No new hashing primitive is introduced: the binding is the substrate's
|
|
18
|
+
* existing JCS + SHA-256 over the four references. Because action_ref and
|
|
19
|
+
* transition_hash are themselves computed from epoch-millisecond-integer
|
|
20
|
+
* preimages (Substrate Rule 2), any upstream RFC 3339 string timestamp produces
|
|
21
|
+
* a different action_ref, hence a different binding -- a non-conformant lineage
|
|
22
|
+
* cannot reproduce the binding bytes.
|
|
23
|
+
*
|
|
24
|
+
* The output carries the "sha256:" algorithm prefix, consistent with
|
|
25
|
+
* retention_chain_ref, signalling a content-addressed reference.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import { sha256Jcs } from './canonicalize.js';
|
|
29
|
+
|
|
30
|
+
const HEX64_RE = /^[0-9a-f]{64}$/;
|
|
31
|
+
const SHA256_REF_RE = /^sha256:[0-9a-f]{64}$/;
|
|
32
|
+
|
|
33
|
+
export class SettlementBindingError extends Error {
|
|
34
|
+
constructor(message: string) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'SettlementBindingError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SettlementBindingPreimage {
|
|
41
|
+
action_ref: string;
|
|
42
|
+
transition_hash: string;
|
|
43
|
+
settlement_ref: string;
|
|
44
|
+
retention_chain_ref: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function requireHex64(field: string, value: unknown): string {
|
|
48
|
+
if (typeof value !== 'string') {
|
|
49
|
+
throw new SettlementBindingError(
|
|
50
|
+
`${field} must be string, got ${typeof value}`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
if (!HEX64_RE.test(value)) {
|
|
54
|
+
throw new SettlementBindingError(
|
|
55
|
+
`${field} must be a lowercase 64-character SHA-256 hex string`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function requireChainRef(value: unknown): string {
|
|
62
|
+
if (typeof value !== 'string') {
|
|
63
|
+
throw new SettlementBindingError(
|
|
64
|
+
`retention_chain_ref must be string, got ${typeof value}`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (!SHA256_REF_RE.test(value)) {
|
|
68
|
+
throw new SettlementBindingError(
|
|
69
|
+
"retention_chain_ref must be of the form 'sha256:<lowercase 64-char hex>'",
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Return the validated four-field binding preimage object.
|
|
77
|
+
*
|
|
78
|
+
* The shape is fixed at the substrate layer; each field cryptographically
|
|
79
|
+
* contributes to the binding so that no one component can be substituted
|
|
80
|
+
* without changing the binding_ref.
|
|
81
|
+
*/
|
|
82
|
+
export function settlementBindingPreimage(input: {
|
|
83
|
+
action_ref: string;
|
|
84
|
+
transition_hash: string;
|
|
85
|
+
settlement_ref: string;
|
|
86
|
+
retention_chain_ref: string;
|
|
87
|
+
}): SettlementBindingPreimage {
|
|
88
|
+
return {
|
|
89
|
+
action_ref: requireHex64('action_ref', input.action_ref),
|
|
90
|
+
transition_hash: requireHex64('transition_hash', input.transition_hash),
|
|
91
|
+
settlement_ref: requireHex64('settlement_ref', input.settlement_ref),
|
|
92
|
+
retention_chain_ref: requireChainRef(input.retention_chain_ref),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Return the binding_ref as a "sha256:"-prefixed content-addressed reference.
|
|
98
|
+
*
|
|
99
|
+
* binding_ref = "sha256:" + SHA-256(JCS({action_ref, transition_hash,
|
|
100
|
+
* settlement_ref, retention_chain_ref}))
|
|
101
|
+
*/
|
|
102
|
+
export function settlementActionBinding(input: {
|
|
103
|
+
action_ref: string;
|
|
104
|
+
transition_hash: string;
|
|
105
|
+
settlement_ref: string;
|
|
106
|
+
retention_chain_ref: string;
|
|
107
|
+
}): string {
|
|
108
|
+
const obj = settlementBindingPreimage(input);
|
|
109
|
+
return `sha256:${sha256Jcs(obj)}`;
|
|
110
|
+
}
|