@bsv/dpp-core 0.3.0-beta.1

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.
Files changed (86) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +95 -0
  3. package/dist/acceptance.d.ts +100 -0
  4. package/dist/acceptance.d.ts.map +1 -0
  5. package/dist/acceptance.js +202 -0
  6. package/dist/acceptance.js.map +1 -0
  7. package/dist/anchor.d.ts +66 -0
  8. package/dist/anchor.d.ts.map +1 -0
  9. package/dist/anchor.js +145 -0
  10. package/dist/anchor.js.map +1 -0
  11. package/dist/attestation.d.ts +40 -0
  12. package/dist/attestation.d.ts.map +1 -0
  13. package/dist/attestation.js +111 -0
  14. package/dist/attestation.js.map +1 -0
  15. package/dist/blob.d.ts +11 -0
  16. package/dist/blob.d.ts.map +1 -0
  17. package/dist/blob.js +16 -0
  18. package/dist/blob.js.map +1 -0
  19. package/dist/canonical.d.ts +32 -0
  20. package/dist/canonical.d.ts.map +1 -0
  21. package/dist/canonical.js +54 -0
  22. package/dist/canonical.js.map +1 -0
  23. package/dist/canonicalJson.d.ts +22 -0
  24. package/dist/canonicalJson.d.ts.map +1 -0
  25. package/dist/canonicalJson.js +60 -0
  26. package/dist/canonicalJson.js.map +1 -0
  27. package/dist/codec.d.ts +45 -0
  28. package/dist/codec.d.ts.map +1 -0
  29. package/dist/codec.js +459 -0
  30. package/dist/codec.js.map +1 -0
  31. package/dist/constants.d.ts +150 -0
  32. package/dist/constants.d.ts.map +1 -0
  33. package/dist/constants.js +179 -0
  34. package/dist/constants.js.map +1 -0
  35. package/dist/did.d.ts +37 -0
  36. package/dist/did.d.ts.map +1 -0
  37. package/dist/did.js +129 -0
  38. package/dist/did.js.map +1 -0
  39. package/dist/evidence.d.ts +224 -0
  40. package/dist/evidence.d.ts.map +1 -0
  41. package/dist/evidence.js +716 -0
  42. package/dist/evidence.js.map +1 -0
  43. package/dist/evidencePackage.d.ts +114 -0
  44. package/dist/evidencePackage.d.ts.map +1 -0
  45. package/dist/evidencePackage.js +164 -0
  46. package/dist/evidencePackage.js.map +1 -0
  47. package/dist/index.d.ts +31 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +31 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/owner.d.ts +135 -0
  52. package/dist/owner.d.ts.map +1 -0
  53. package/dist/owner.js +181 -0
  54. package/dist/owner.js.map +1 -0
  55. package/dist/publisherPolicy.d.ts +70 -0
  56. package/dist/publisherPolicy.d.ts.map +1 -0
  57. package/dist/publisherPolicy.js +186 -0
  58. package/dist/publisherPolicy.js.map +1 -0
  59. package/dist/signatures.d.ts +84 -0
  60. package/dist/signatures.d.ts.map +1 -0
  61. package/dist/signatures.js +137 -0
  62. package/dist/signatures.js.map +1 -0
  63. package/dist/transition.d.ts +29 -0
  64. package/dist/transition.d.ts.map +1 -0
  65. package/dist/transition.js +117 -0
  66. package/dist/transition.js.map +1 -0
  67. package/dist/types.d.ts +135 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +2 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/verifyChain.d.ts +152 -0
  72. package/dist/verifyChain.d.ts.map +1 -0
  73. package/dist/verifyChain.js +314 -0
  74. package/dist/verifyChain.js.map +1 -0
  75. package/package.json +46 -0
  76. package/schemas/capabilities.schema.json +129 -0
  77. package/schemas/epcis-import.schema.json +212 -0
  78. package/schemas/evidence-export.schema.json +67 -0
  79. package/schemas/evidence-package.schema.json +307 -0
  80. package/schemas/native-evidence-extension.schema.json +66 -0
  81. package/schemas/paginated-history.schema.json +32 -0
  82. package/schemas/passport-projection.schema.json +151 -0
  83. package/schemas/passport-source.schema.json +370 -0
  84. package/schemas/profile-evidence.schema.json +706 -0
  85. package/schemas/publisher-policy.schema.json +173 -0
  86. package/schemas/verification-report.schema.json +397 -0
@@ -0,0 +1,137 @@
1
+ import { CachedKeyDeriver, Signature, Utils } from '@bsv/sdk';
2
+ import { DPP_PROTOCOL_ID, DPP_PROTOCOL_ID_V2, PROTOCOL_MARKER, RECORD_V2_ACTOR_TAG, RECORD_V2_PUBLISHER_TAG, STANDARD_VERSION, } from './constants.js';
3
+ import { dataFields, dataFieldsV2, isV2Data } from './codec.js';
4
+ /**
5
+ * Canonical version 1 user-signature preimage (`spec/record-model.md` §5): the
6
+ * concatenated raw bytes of fields 1–12 in standard order - never a JSON
7
+ * serialization.
8
+ *
9
+ * Framing note: §5 mandates plain concatenation, so the preimage bytes alone
10
+ * do not bind field boundaries. Boundary uniqueness comes from field
11
+ * validation (op enum, ISO timestamp, fixed-width keys/hashes, JSON rules)
12
+ * plus the chain invariants (genesis must be ACTIVATE, spend linkage,
13
+ * passport_id immutability), which together block re-split states from
14
+ * verifying in any spec-sanctioned consumer. Version 2 replaces this with a
15
+ * framed, domain-tagged preimage (`actorPreimageV2`); version 1 keeps it
16
+ * because a published state keeps the contract it was signed under.
17
+ */
18
+ export function userPreimageV1(d) {
19
+ return dataFields(d).flat();
20
+ }
21
+ /** Canonical version 1 server-signature preimage: fields 1–13 (user preimage + user_signature). */
22
+ export function serverPreimageV1(d, userSignature) {
23
+ return [...userPreimageV1(d), ...userSignature];
24
+ }
25
+ /**
26
+ * Length framing (`spec/record-model-v2.md` §5): each item as its Bitcoin
27
+ * VarInt byte length followed by its bytes, in order. The same framing the
28
+ * anchor rail uses (`spec/rules.md` §5), so one rule serves both.
29
+ */
30
+ export function frameFields(items) {
31
+ const writer = new Utils.Writer();
32
+ for (const item of items) {
33
+ writer.writeVarIntNum(item.length);
34
+ writer.write(item);
35
+ }
36
+ return writer.toArray();
37
+ }
38
+ /**
39
+ * The version 2 actor preimage: the actor tag, then fields 1–15, every item
40
+ * length-framed. Two field tuples that differ anywhere produce different
41
+ * bytes, and the tag keeps a signature made for the publisher role, or for
42
+ * version 1, from verifying here.
43
+ */
44
+ export function actorPreimageV2(d) {
45
+ return frameFields([Utils.toArray(RECORD_V2_ACTOR_TAG, 'utf8'), ...dataFieldsV2(d)]);
46
+ }
47
+ /** The version 2 publisher preimage: the publisher tag, fields 1–15 and the actor signature, every item length-framed. */
48
+ export function publisherPreimageV2(d, actorSignature) {
49
+ return frameFields([Utils.toArray(RECORD_V2_PUBLISHER_TAG, 'utf8'), ...dataFieldsV2(d), actorSignature]);
50
+ }
51
+ /** The actor's preimage under the version the data declares: version 1 unframed, version 2 framed and tagged. */
52
+ export function userPreimage(d) {
53
+ return isV2Data(d) ? actorPreimageV2(d) : userPreimageV1(d);
54
+ }
55
+ /** The publisher's preimage under the version the data declares. */
56
+ export function serverPreimage(d, userSignature) {
57
+ return isV2Data(d) ? publisherPreimageV2(d, userSignature) : serverPreimageV1(d, userSignature);
58
+ }
59
+ /** The BRC-43 protocol both signatures of a state derive under: one per version, so keys never cross. */
60
+ export function protocolIdFor(d) {
61
+ return isV2Data(d) ? DPP_PROTOCOL_ID_V2 : DPP_PROTOCOL_ID;
62
+ }
63
+ /** Deriver for counterparty-'anyone' verification keys (rootKey = 1). */
64
+ const anyone = new CachedKeyDeriver('anyone');
65
+ /**
66
+ * Create the actor signature (field 13 in version 1, field 16 in version 2):
67
+ * the actor signs the version's actor preimage with the child key for
68
+ * (the version's protocol, actor_keyID, counterparty 'anyone').
69
+ */
70
+ export async function createUserSignature(d, actorWallet) {
71
+ const { signature } = await actorWallet.createSignature({
72
+ data: userPreimage(d),
73
+ protocolID: protocolIdFor(d),
74
+ keyID: d.actorKeyId,
75
+ counterparty: 'anyone',
76
+ });
77
+ return signature;
78
+ }
79
+ /**
80
+ * Create the publisher signature (field 14 in version 1, field 17 in version
81
+ * 2): the service signs the version's publisher preimage with the child key
82
+ * for (the version's protocol, keyID = passport_id, counterparty 'anyone').
83
+ * keyID is pinned to passport_id so verifiers can re-derive the service child
84
+ * key from on-chain data plus the published service identity key (§5).
85
+ */
86
+ export async function createServerSignature(d, userSignature, serverWallet) {
87
+ const { signature } = await serverWallet.createSignature({
88
+ data: serverPreimage(d, userSignature),
89
+ protocolID: protocolIdFor(d),
90
+ keyID: d.passportId,
91
+ counterparty: 'anyone',
92
+ });
93
+ return signature;
94
+ }
95
+ /** Sign the actor and publisher preimages and assemble the complete state of the version the data declares. */
96
+ export async function completeState(d, actorWallet, serverWallet) {
97
+ const userSignature = await createUserSignature(d, actorWallet);
98
+ const serverSignature = await createServerSignature(d, userSignature, serverWallet);
99
+ if (isV2Data(d)) {
100
+ return { ...d, protocolMarker: PROTOCOL_MARKER, userSignature, serverSignature };
101
+ }
102
+ return {
103
+ ...d,
104
+ protocolMarker: PROTOCOL_MARKER,
105
+ version: STANDARD_VERSION,
106
+ userSignature,
107
+ serverSignature,
108
+ };
109
+ }
110
+ /**
111
+ * Verify the actor signature against actor_identity_key + actor_keyID (§5;
112
+ * §8 check 1), under the version the state carries. Open verification: the
113
+ * key is derived with counterparty 'anyone', so no wallet or secret is needed.
114
+ */
115
+ export function verifyUserSignature(state) {
116
+ try {
117
+ const pub = anyone.derivePublicKey(protocolIdFor(state), state.actorKeyId, state.actorIdentityKey);
118
+ return pub.verify(userPreimage(state), Signature.fromDER(state.userSignature));
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ /**
125
+ * Verify the publisher signature against a configured service identity key.
126
+ * Admission policy, not token validity (§5).
127
+ */
128
+ export function verifyServerSignature(state, serverIdentityKey) {
129
+ try {
130
+ const pub = anyone.derivePublicKey(protocolIdFor(state), state.passportId, serverIdentityKey);
131
+ return pub.verify(serverPreimage(state, state.userSignature), Signature.fromDER(state.serverSignature));
132
+ }
133
+ catch {
134
+ return false;
135
+ }
136
+ }
137
+ //# sourceMappingURL=signatures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signatures.js","sourceRoot":"","sources":["../src/signatures.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,KAAK,EAAuB,MAAM,UAAU,CAAA;AAClF,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAG/D;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,CAAe;IAC5C,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;AAC7B,CAAC;AAED,mGAAmG;AACnG,MAAM,UAAU,gBAAgB,CAAC,CAAe,EAAE,aAAuB;IACvE,OAAO,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,CAAA;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAiB;IAC3C,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,MAAM,EAAE,CAAA;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,EAAE,CAAA;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,CAAiB;IAC/C,OAAO,WAAW,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC;AAED,0HAA0H;AAC1H,MAAM,UAAU,mBAAmB,CAAC,CAAiB,EAAE,cAAwB;IAC7E,OAAO,WAAW,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,uBAAuB,EAAE,MAAM,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,CAAA;AAC1G,CAAC;AAED,iHAAiH;AACjH,MAAM,UAAU,YAAY,CAAC,CAAkB;IAC7C,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;AAC7D,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,cAAc,CAAC,CAAkB,EAAE,aAAuB;IACxE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,EAAE,aAAa,CAAC,CAAA;AACjG,CAAC;AAED,yGAAyG;AACzG,MAAM,UAAU,aAAa,CAAC,CAAS;IACrC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe,CAAA;AAC3D,CAAC;AAiBD,yEAAyE;AACzE,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAA;AAE7C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,CAAkB,EAClB,WAAuB;IAEvB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC;QACtD,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;QACrB,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;QAC5B,KAAK,EAAE,CAAC,CAAC,UAAU;QACnB,YAAY,EAAE,QAAQ;KACvB,CAAC,CAAA;IACF,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,CAAkB,EAClB,aAAuB,EACvB,YAAwB;IAExB,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC;QACvD,IAAI,EAAE,cAAc,CAAC,CAAC,EAAE,aAAa,CAAC;QACtC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC;QAC5B,KAAK,EAAE,CAAC,CAAC,UAAU;QACnB,YAAY,EAAE,QAAQ;KACvB,CAAC,CAAA;IACF,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,+GAA+G;AAC/G,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,CAAkB,EAClB,WAAuB,EACvB,YAAwB;IAExB,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAAC,CAAC,EAAE,WAAW,CAAC,CAAA;IAC/D,MAAM,eAAe,GAAG,MAAM,qBAAqB,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,CAAC,CAAA;IACnF,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC,EAAE,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,CAAA;IAClF,CAAC;IACD,OAAO;QACL,GAAG,CAAC;QACJ,cAAc,EAAE,eAAe;QAC/B,OAAO,EAAE,gBAAgB;QACzB,aAAa;QACb,eAAe;KAChB,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAe;IACjD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAChC,aAAa,CAAC,KAAK,CAAC,EACpB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,gBAAgB,CACvB,CAAA;QACD,OAAO,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAe,EACf,iBAAyB;IAEzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAChC,aAAa,CAAC,KAAK,CAAC,EACpB,KAAK,CAAC,UAAU,EAChB,iBAAiB,CAClB,CAAA;QACD,OAAO,GAAG,CAAC,MAAM,CACf,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,EAC1C,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CACzC,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { DppState, Outpoint } from './types.js';
2
+ /**
3
+ * Per-link rules from `spec/record-model.md` §4 and §6 (version 1) and
4
+ * `spec/record-model-v2.md` §4 and §6 (version 2). Field-level well-formedness
5
+ * (event_data emptiness, JSON validity, ISO timestamps, field bounds) is
6
+ * enforced by the codec at decode time. These functions check the rules that
7
+ * span states. Returns null when valid, otherwise a human-readable reason; the
8
+ * fixtures pin these strings.
9
+ */
10
+ /** What a link needs beyond the two states: the predecessor's output index, the lineage's genesis, and the profile's authorities. */
11
+ export interface LinkContext {
12
+ /** The output index of the predecessor's DPP output, as spent. Version 2 binds it (field 13). */
13
+ prevOutputIndex?: number;
14
+ /** The genesis outpoint of the chain being verified. Version 2 binds it (field 12). */
15
+ lineageGenesis?: Outpoint;
16
+ /** Identity keys the profile names as authorities, whose version 2 UPDATE, TRANSFER or RETIRE passes without a control proof. */
17
+ authorities?: readonly string[];
18
+ }
19
+ export declare function checkGenesisState(s: DppState): string | null;
20
+ /**
21
+ * The rules one link must satisfy, under the version of the state that
22
+ * extends the chain. A version 1 successor keeps the version 1 rules exactly;
23
+ * a version 2 successor binds the predecessor outpoint and the lineage
24
+ * genesis, refuses to follow a RETIRE, proves control of the predecessor, and
25
+ * may follow a version 1 predecessor only as the UPDATE that upgrades the
26
+ * lineage (`spec/record-model-v2.md` §8).
27
+ */
28
+ export declare function checkTransition(prev: DppState, next: DppState, prevTxid: string, link?: LinkContext): string | null;
29
+ //# sourceMappingURL=transition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transition.d.ts","sourceRoot":"","sources":["../src/transition.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAc,QAAQ,EAAE,MAAM,YAAY,CAAA;AAEhE;;;;;;;GAOG;AAEH,qIAAqI;AACrI,MAAM,WAAW,WAAW;IAC1B,iGAAiG;IACjG,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,uFAAuF;IACvF,cAAc,CAAC,EAAE,QAAQ,CAAA;IACzB,iIAAiI;IACjI,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAW5D;AA+ED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,WAAgB,GACrB,MAAM,GAAG,IAAI,CAGf"}
@@ -0,0 +1,117 @@
1
+ import { NO_EVENT_OPS, PAYLOAD_CHANGE_OPS, PAYLOAD_CHANGE_OPS_V2 } from './constants.js';
2
+ import { checkControl } from './owner.js';
3
+ export function checkGenesisState(s) {
4
+ if (s.version === '2') {
5
+ if (s.op !== 'ISSUE')
6
+ return `genesis op must be ISSUE, got ${s.op}`;
7
+ if (s.previousTxid !== '' || s.previousOutputIndex != null)
8
+ return 'genesis previous_outpoint must be empty';
9
+ if (s.lineageGenesis != null)
10
+ return 'genesis lineage_genesis must be empty';
11
+ if (s.controlLinkage !== '')
12
+ return 'genesis control_linkage must be empty';
13
+ return null;
14
+ }
15
+ if (s.op !== 'ACTIVATE')
16
+ return `genesis op must be ACTIVATE, got ${s.op}`;
17
+ if (s.previousTxid !== '')
18
+ return 'genesis previous_txid must be empty';
19
+ return null;
20
+ }
21
+ const sameOutpoint = (a, b) => a.txid === b.txid && a.outputIndex === b.outputIndex;
22
+ function checkTransitionV1(prev, next, prevTxid) {
23
+ if (prev.version === '2')
24
+ return 'a version 1 state cannot follow a version 2 state';
25
+ if (next.op === 'ACTIVATE')
26
+ return 'ACTIVATE is allowed at genesis only';
27
+ if (next.previousTxid === '')
28
+ return 'non-genesis previous_txid must be set';
29
+ if (next.passportId !== prev.passportId) {
30
+ return 'passport_id is immutable across the chain';
31
+ }
32
+ if (next.previousTxid !== prevTxid) {
33
+ return 'previous_txid must equal the spent tip txid';
34
+ }
35
+ if (next.op !== 'TRANSFER' && next.ownerIdentityKey !== prev.ownerIdentityKey) {
36
+ return 'owner_identity_key changes only on TRANSFER';
37
+ }
38
+ if (!PAYLOAD_CHANGE_OPS.includes(next.op) &&
39
+ (next.payloadPublic !== prev.payloadPublic ||
40
+ next.payloadOwnerHash !== prev.payloadOwnerHash)) {
41
+ return 'payload_public / payload_owner_hash change only on ACTIVATE, EDIT or TRANSFER';
42
+ }
43
+ if (NO_EVENT_OPS.includes(next.op) && next.eventData !== '') {
44
+ return `event_data must be empty on ${next.op}`;
45
+ }
46
+ return null;
47
+ }
48
+ /**
49
+ * The lineage genesis a version 2 state must name, from what the caller
50
+ * knows: the chain's genesis when supplied; otherwise, for a version 2
51
+ * predecessor, what that predecessor names (or the predecessor itself when it
52
+ * is the ISSUE). A version 1 predecessor names no genesis, so the caller must
53
+ * supply one; a reader that cannot is told so rather than left to guess.
54
+ */
55
+ function expectedLineageGenesis(prev, prevTxid, link) {
56
+ if (link.lineageGenesis != null)
57
+ return link.lineageGenesis;
58
+ if (prev.version !== '2')
59
+ return undefined;
60
+ if (prev.lineageGenesis != null)
61
+ return prev.lineageGenesis;
62
+ if (link.prevOutputIndex == null)
63
+ return undefined;
64
+ return { txid: prevTxid, outputIndex: link.prevOutputIndex };
65
+ }
66
+ function checkTransitionV2(prev, next, prevTxid, link) {
67
+ if (next.op === 'ISSUE')
68
+ return 'ISSUE is allowed at genesis only';
69
+ if (prev.version === '2' && prev.op === 'RETIRE')
70
+ return 'the lineage is retired: no state may follow RETIRE';
71
+ if (prev.version === '1' && next.op !== 'UPDATE') {
72
+ return 'a version 1 state is followed only by a version 2 UPDATE, the upgrade transition';
73
+ }
74
+ if (next.previousTxid === '' || next.previousOutputIndex == null)
75
+ return 'non-genesis previous_outpoint must be set';
76
+ if (next.passportId !== prev.passportId)
77
+ return 'passport_id is immutable across the chain';
78
+ if (next.previousTxid !== prevTxid)
79
+ return 'previous_outpoint must name the spent tip';
80
+ if (link.prevOutputIndex != null && next.previousOutputIndex !== link.prevOutputIndex) {
81
+ return 'previous_outpoint must name the spent tip output';
82
+ }
83
+ const genesis = expectedLineageGenesis(prev, prevTxid, link);
84
+ if (genesis == null)
85
+ return 'lineage_genesis cannot be checked without the chain genesis';
86
+ if (next.lineageGenesis == null || !sameOutpoint(next.lineageGenesis, genesis)) {
87
+ return 'lineage_genesis must name the chain genesis';
88
+ }
89
+ if (prev.version === '1' && next.ownerIdentityKey !== prev.ownerIdentityKey) {
90
+ return 'the upgrade transition keeps the controller key';
91
+ }
92
+ if (next.op !== 'TRANSFER' && next.ownerIdentityKey !== prev.ownerIdentityKey) {
93
+ return 'controller_key changes only on TRANSFER';
94
+ }
95
+ if (!PAYLOAD_CHANGE_OPS_V2.includes(next.op) &&
96
+ (next.payloadPublic !== prev.payloadPublic || next.payloadOwnerHash !== prev.payloadOwnerHash)) {
97
+ return 'payload_public / payload_owner_hash do not change on RETIRE';
98
+ }
99
+ const control = checkControl(prev, next, link.authorities ?? []);
100
+ if (control != null)
101
+ return control;
102
+ return null;
103
+ }
104
+ /**
105
+ * The rules one link must satisfy, under the version of the state that
106
+ * extends the chain. A version 1 successor keeps the version 1 rules exactly;
107
+ * a version 2 successor binds the predecessor outpoint and the lineage
108
+ * genesis, refuses to follow a RETIRE, proves control of the predecessor, and
109
+ * may follow a version 1 predecessor only as the UPDATE that upgrades the
110
+ * lineage (`spec/record-model-v2.md` §8).
111
+ */
112
+ export function checkTransition(prev, next, prevTxid, link = {}) {
113
+ if (next.version === '2')
114
+ return checkTransitionV2(prev, next, prevTxid, link);
115
+ return checkTransitionV1(prev, next, prevTxid);
116
+ }
117
+ //# sourceMappingURL=transition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transition.js","sourceRoot":"","sources":["../src/transition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import { DPP_OPS, DPP_OPS_V2 } from './constants.js';
2
+ export type DppOpV1 = (typeof DPP_OPS)[number];
3
+ export type DppOpV2 = (typeof DPP_OPS_V2)[number];
4
+ /** Every operation either record version carries. A version 1 state carries only a `DppOpV1`, a version 2 state only a `DppOpV2`. */
5
+ export type DppOp = DppOpV1 | DppOpV2;
6
+ /** A transaction output by identifier and index; the shape both record versions and the report name outputs by. */
7
+ export interface Outpoint {
8
+ txid: string;
9
+ outputIndex: number;
10
+ }
11
+ /**
12
+ * The signable content of one version 1 passport state - fields 1–12 of the
13
+ * DPP Token Standard v1 layout (`spec/record-model.md` §3), before signatures.
14
+ */
15
+ export interface DppStateData {
16
+ /** Stable GS1-DL-style ID; immutable across the chain; primary lookup key. */
17
+ passportId: string;
18
+ op: DppOpV1;
19
+ /** Actor-asserted ISO 8601; bounded by neighbouring blocks (§3 field 5). */
20
+ timestamp: string;
21
+ /** Current owner's compressed public key, hex; SHOULD be the owner's BRC-42 child under OWNER_PROTOCOL_ID (§3 field 6). */
22
+ ownerIdentityKey: string;
23
+ /** Compressed public key, hex, of who performed this state change. */
24
+ actorIdentityKey: string;
25
+ /** Published keyID for the actor signature; enables open verification. */
26
+ actorKeyId: string;
27
+ /** Clear JSON event metadata; '' on ACTIVATE and EDIT. */
28
+ eventData: string;
29
+ /** Clear JSON, the record's public tier (`spec/record-model.md` §3 field 10). */
30
+ payloadPublic: string;
31
+ /** SHA-256 hex of the off-chain owner-tier ciphertext blob; '' if none. */
32
+ payloadOwnerHash: string;
33
+ /** Prior tip txid, hex; '' at genesis. Must equal the spent outpoint's txid. */
34
+ previousTxid: string;
35
+ }
36
+ /** The version 1 data, under the name the version 2 type sits beside. */
37
+ export type DppStateDataV1 = DppStateData;
38
+ /**
39
+ * The signable content of one version 2 passport state - fields 1–15 of the
40
+ * layout in `spec/record-model-v2.md` §3, before signatures. The property
41
+ * names shared with version 1 keep their meaning; `ownerIdentityKey` is the
42
+ * controller key (field 6) and `previousTxid` the txid half of the predecessor
43
+ * outpoint (field 13).
44
+ */
45
+ export interface DppStateDataV2 {
46
+ version: '2';
47
+ passportId: string;
48
+ op: DppOpV2;
49
+ timestamp: string;
50
+ /** The controller key, field 6: the per-passport key that names who controls the lineage. */
51
+ ownerIdentityKey: string;
52
+ actorIdentityKey: string;
53
+ actorKeyId: string;
54
+ /** Clear JSON or ''; at most MAX_EVENT_DATA_BYTES_V2 bytes. No property is reserved. */
55
+ eventData: string;
56
+ /** Clear JSON, non-empty; at most MAX_PAYLOAD_PUBLIC_BYTES_V2 bytes. */
57
+ payloadPublic: string;
58
+ payloadOwnerHash: string;
59
+ /** The predecessor's txid, hex; '' on ISSUE. With `previousOutputIndex`, field 13. */
60
+ previousTxid: string;
61
+ /** The predecessor's output index; null on ISSUE. */
62
+ previousOutputIndex: number | null;
63
+ /** The genesis outpoint of the lineage, field 12; null on ISSUE, which is the genesis. */
64
+ lineageGenesis: Outpoint | null;
65
+ /** Field 14: '' or 64 lower-case hex, the BRC-69 scalar linking the actor's root to the previous controller key. */
66
+ controlLinkage: string;
67
+ /** Field 15: '' or 64 lower-case hex, the SHA-256 commitment to the off-chain authorisation record the profile names. */
68
+ authorisationCommitment: string;
69
+ }
70
+ /** Either version's signable content. */
71
+ export type AnyDppStateData = DppStateDataV1 | DppStateDataV2;
72
+ interface SignedFields {
73
+ protocolMarker: string;
74
+ /** DER ECDSA, the actor's signature (field 13 in version 1, field 16 in version 2). */
75
+ userSignature: number[];
76
+ /** DER ECDSA, the publisher's countersignature (field 14 in version 1, field 17 in version 2). */
77
+ serverSignature: number[];
78
+ }
79
+ /** A fully signed version 1 state: fields 1–14 decoded from a DPP output. */
80
+ export interface DppStateV1 extends DppStateDataV1, SignedFields {
81
+ version: '1';
82
+ }
83
+ /** A fully signed version 2 state: fields 1–17 decoded from a DPP output. */
84
+ export interface DppStateV2 extends DppStateDataV2, SignedFields {
85
+ }
86
+ /** A fully signed state of either version. Narrow on `version`. */
87
+ export type DppState = DppStateV1 | DppStateV2;
88
+ /** One link of a passport chain as needed for verification. */
89
+ export interface DppChainEntry {
90
+ state: DppState;
91
+ txid: string;
92
+ /** Output index of the DPP output within its transaction. */
93
+ outputIndex: number;
94
+ }
95
+ export type SpvStatus = 'verified' | 'pending';
96
+ export interface StateCheck {
97
+ txid: string;
98
+ op: DppOp;
99
+ userSignatureValid: boolean;
100
+ serverSignatureValid: boolean | null;
101
+ linkageValid: boolean;
102
+ /**
103
+ * The optional owner-signed transfer (`spec/custody.md` §4). null when the
104
+ * invariant was not run: the option is off, or the state is not a version 1
105
+ * TRANSFER. A report says "not applicable" for null rather than a vacuous pass.
106
+ * Version 2 states prove control as part of linkage instead (`controlValid`
107
+ * on the inspection).
108
+ */
109
+ ownerConsentValid: boolean | null;
110
+ spv: SpvStatus | 'failed';
111
+ }
112
+ export interface ChainVerifyResult {
113
+ valid: boolean;
114
+ /**
115
+ * 'verified' only when the chain is valid and every state proved against
116
+ * block headers. 'pending' covers both an unmined state and one that could
117
+ * not be checked, because to a reader those are the same sentence:
118
+ * inclusion is not proved yet. A chain that fails verification also says
119
+ * 'pending', whatever its proofs said, so no consumer can print "inclusion
120
+ * proved" beside "could not verify"; the per-state detail in `states`
121
+ * keeps 'failed' where a proof was refuted.
122
+ */
123
+ spv: SpvStatus;
124
+ states: StateCheck[];
125
+ /** Human-readable reason for the first failure, when valid === false. */
126
+ error?: string;
127
+ /**
128
+ * Set when the chain tracker could not answer at least once, carrying the
129
+ * first such error. Operational signal only: an outage leaves SPV 'pending'
130
+ * rather than 'failed', and this is how a caller can tell the two apart.
131
+ */
132
+ spvUnavailable?: string;
133
+ }
134
+ export {};
135
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ import { Beef, PublicKey, Transaction, type ChainTracker } from '@bsv/sdk';
2
+ import { type PublisherPolicy } from './publisherPolicy.js';
3
+ import type { DppVersion } from './constants.js';
4
+ import type { ChainVerifyResult, DppState, StateCheck } from './types.js';
5
+ export interface VerifyChainOptions {
6
+ /**
7
+ * Tracker for SPV (`spec/record-model.md` §8 check 3). Omit or pass 'scripts only' to skip root
8
+ * checks - every state then reports SPV 'pending'. The demo app always
9
+ * passes a real tracker; 'scripts only' exists for offline use and tests.
10
+ */
11
+ chainTracker?: ChainTracker | 'scripts only';
12
+ /**
13
+ * When set, server_signature is verified against this service identity key
14
+ * (admission policy, §8). Token validity itself never depends on it; the
15
+ * overlay's topic manager passes its configured key, viewers may omit it.
16
+ */
17
+ serverIdentityKey?: string;
18
+ /**
19
+ * The optional owner-signed transfer (`spec/custody.md` §4), selected by a
20
+ * profile for version 1 states. `true` runs the predicate on every version 1
21
+ * TRANSFER; an object also names the transfer authorities, identity keys
22
+ * whose TRANSFER passes without it (recovery). A malformed authority throws
23
+ * before any state is read: a misconfigured authority must be loud, never
24
+ * silently unmatched. Version 2 states prove control on every UPDATE,
25
+ * TRANSFER and RETIRE regardless (`spec/record-model-v2.md` §6); the same
26
+ * authorities serve them unless `controlAuthorities` names others.
27
+ */
28
+ ownerConsent?: boolean | {
29
+ authorities: string[];
30
+ };
31
+ /**
32
+ * Identity keys the profile names as authorities for version 2 states: an
33
+ * UPDATE, TRANSFER or RETIRE by one of them passes without a control proof
34
+ * (recovery, or a scoped authority the profile defines). Defaults to the
35
+ * `ownerConsent` authorities. Malformed keys throw at construction.
36
+ */
37
+ controlAuthorities?: string[];
38
+ /**
39
+ * The managed-custody profile (`spec/managed-custody.md`): when true, every
40
+ * version 2 TRANSFER must carry an `authorisation_commitment`, the
41
+ * commitment to the acceptance record the custodian retains. Off, the
42
+ * record model alone is checked and the commitment is read but not required.
43
+ */
44
+ managedAcceptance?: boolean;
45
+ }
46
+ export interface DppOutputRef {
47
+ state: DppState;
48
+ outputIndex: number;
49
+ lockingPublicKey: PublicKey;
50
+ }
51
+ /** What a reader reports when the managed-custody profile is selected and a version 2 TRANSFER carries no commitment. */
52
+ export declare const ACCEPTANCE_COMMITMENT_REFUSAL = "TRANSFER carries no authorisation_commitment under managed-custody@1";
53
+ /**
54
+ * Locate THE DPP output of a transaction (§6 invariant 1: exactly one).
55
+ * Returns all matches; callers enforce the invariant.
56
+ */
57
+ export declare function findDppOutputs(tx: Transaction): DppOutputRef[];
58
+ /** The options `inspectChain` takes beyond `verifyChain`'s: several publisher keys, any of which may have countersigned. */
59
+ export interface InspectChainOptions extends VerifyChainOptions {
60
+ /**
61
+ * Publisher identity keys, any one of which satisfies the server-signature
62
+ * check (`spec/verification.md` §4, `publisherSignatures`). `serverIdentityKey`
63
+ * is the one-key spelling of the same option; both may be given.
64
+ */
65
+ publisherKeys?: string[];
66
+ /**
67
+ * A publisher key policy chain (`spec/services.md` §1), already verified by
68
+ * the caller with `verifyPolicyChain`. A state is then checked against the
69
+ * state-publisher keys active at its own timestamp, so a retired key still
70
+ * authenticates what it signed while active and a new key authenticates
71
+ * nothing timestamped before its activation. Combined with `publisherKeys`
72
+ * when both are given.
73
+ */
74
+ publisherPolicy?: PublisherPolicy[];
75
+ }
76
+ /** Why one state stopped the inspection, in the vocabulary the report uses. */
77
+ export type ChainFailureKind = 'encoding' | 'userSignature' | 'serverSignature' | 'linkage' | 'consent' | 'inclusion';
78
+ /** One inspected state: the verifier's findings plus what a report needs to name it. */
79
+ export interface StateInspection extends StateCheck {
80
+ index: number;
81
+ outputIndex: number;
82
+ state: DppState;
83
+ /** The record version the state carries. */
84
+ version: DppVersion;
85
+ linkError: string | null;
86
+ consentError: string | null;
87
+ /**
88
+ * The version 2 control proof (`spec/record-model-v2.md` §6): true when
89
+ * the actor proved control of the predecessor, false when it did not, null
90
+ * on a genesis and on every version 1 state, where the rule does not run.
91
+ */
92
+ controlValid: boolean | null;
93
+ /** True when the countersignature verifies under a key the policy names, but one not active at this state's timestamp. */
94
+ publisherOutsideWindow?: boolean;
95
+ /** Why `spv` is 'pending' or 'failed'; absent when 'verified'. */
96
+ spvReason?: 'no-proof' | 'header-check-disabled' | 'header-source-unavailable' | 'proof-does-not-contain-txid' | 'proof-refuted';
97
+ }
98
+ /**
99
+ * Every finding the token rail's verifier makes, state by state, stopping after
100
+ * the first state that fails (§8's rule: a chain fails as a whole at the first
101
+ * failing state, with the reason identified). `verifyChain` reduces this to
102
+ * the `ChainVerifyResult` it has always returned; `verifyPassportEvidence`
103
+ * reports it check by check instead of collapsing it to one Boolean.
104
+ */
105
+ export interface ChainInspection {
106
+ states: StateInspection[];
107
+ /**
108
+ * The first failure, when there was one. An `encoding` failure names a
109
+ * transaction that yielded no state, so `states` carries nothing for it.
110
+ */
111
+ failure?: {
112
+ index: number;
113
+ txid: string;
114
+ kind: ChainFailureKind;
115
+ message: string;
116
+ };
117
+ /** True when the inspection reached the last supplied transaction without a failure. */
118
+ complete: boolean;
119
+ anyPending: boolean;
120
+ spvUnavailable?: string;
121
+ }
122
+ export declare function inspectChain(txs: Transaction[], options?: InspectChainOptions): Promise<ChainInspection>;
123
+ /**
124
+ * Verify a full passport chain, ordered genesis → tip (§6 + §8).
125
+ *
126
+ * What "Authentic ✓" means (§8): (1) the genesis maker signature is valid;
127
+ * (2) every link satisfies invariants 1–5, checked here both structurally
128
+ * (the next state spends the previous DPP output) and on the readable field
129
+ * (previous_txid equality); (3) SPV - each mined transaction's merkle path
130
+ * validates against block headers via the chain tracker. An unmined state
131
+ * passes with SPV 'pending'. Any failure ⇒ valid: false ("Could not verify").
132
+ *
133
+ * Script execution of spends is enforced by the network and is not
134
+ * re-evaluated here; the in-app checks are exactly the three above.
135
+ *
136
+ * This is supplied-history verification and nothing more: it says whether the
137
+ * states handed to it form a valid chain, not that the last one is the current
138
+ * tip, that its genesis was authorised, or that the attestation rail was
139
+ * checked. `verifyPassportEvidence` (evidence.ts) is the report that keeps
140
+ * those findings apart; this function keeps its one Boolean for the callers
141
+ * that mean exactly what it says.
142
+ */
143
+ export declare function verifyChain(txs: Transaction[], options?: VerifyChainOptions): Promise<ChainVerifyResult>;
144
+ /**
145
+ * Reconstruct the ordered passport chain (genesis → tip) from a BEEF, e.g.
146
+ * as returned by the ls_dpp lookup. Transactions come out hydrated: merkle
147
+ * paths attached, input source transactions linked - ready for verifyChain.
148
+ * States of either version link by `previousTxid`; a version 2 state also
149
+ * carries the predecessor's output index, which the verifier checks.
150
+ */
151
+ export declare function chainFromBeef(beef: Beef, passportId?: string): Transaction[];
152
+ //# sourceMappingURL=verifyChain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyChain.d.ts","sourceRoot":"","sources":["../src/verifyChain.ts"],"names":[],"mappings":"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"}