@bsv/dpp-overlay-topics 0.4.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 (87) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +169 -0
  3. package/dist/anchorStorage.d.ts +58 -0
  4. package/dist/anchorStorage.d.ts.map +1 -0
  5. package/dist/anchorStorage.js +72 -0
  6. package/dist/anchorStorage.js.map +1 -0
  7. package/dist/attestationAnchor.d.ts +10 -0
  8. package/dist/attestationAnchor.d.ts.map +1 -0
  9. package/dist/attestationAnchor.js +10 -0
  10. package/dist/attestationAnchor.js.map +1 -0
  11. package/dist/attestationStorage.d.ts +49 -0
  12. package/dist/attestationStorage.d.ts.map +1 -0
  13. package/dist/attestationStorage.js +78 -0
  14. package/dist/attestationStorage.js.map +1 -0
  15. package/dist/capabilities.d.ts +127 -0
  16. package/dist/capabilities.d.ts.map +1 -0
  17. package/dist/capabilities.js +210 -0
  18. package/dist/capabilities.js.map +1 -0
  19. package/dist/engineStorage.d.ts +106 -0
  20. package/dist/engineStorage.d.ts.map +1 -0
  21. package/dist/engineStorage.js +253 -0
  22. package/dist/engineStorage.js.map +1 -0
  23. package/dist/evidenceExport.d.ts +189 -0
  24. package/dist/evidenceExport.d.ts.map +1 -0
  25. package/dist/evidenceExport.js +517 -0
  26. package/dist/evidenceExport.js.map +1 -0
  27. package/dist/history.d.ts +114 -0
  28. package/dist/history.d.ts.map +1 -0
  29. package/dist/history.js +215 -0
  30. package/dist/history.js.map +1 -0
  31. package/dist/index.d.ts +269 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +1223 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/lib.d.ts +31 -0
  36. package/dist/lib.d.ts.map +1 -0
  37. package/dist/lib.js +31 -0
  38. package/dist/lib.js.map +1 -0
  39. package/dist/limits.d.ts +44 -0
  40. package/dist/limits.d.ts.map +1 -0
  41. package/dist/limits.js +44 -0
  42. package/dist/limits.js.map +1 -0
  43. package/dist/lsAttestation.d.ts +21 -0
  44. package/dist/lsAttestation.d.ts.map +1 -0
  45. package/dist/lsAttestation.js +45 -0
  46. package/dist/lsAttestation.js.map +1 -0
  47. package/dist/lsDpp.d.ts +53 -0
  48. package/dist/lsDpp.d.ts.map +1 -0
  49. package/dist/lsDpp.js +148 -0
  50. package/dist/lsDpp.js.map +1 -0
  51. package/dist/lsUoraDpp.d.ts +55 -0
  52. package/dist/lsUoraDpp.d.ts.map +1 -0
  53. package/dist/lsUoraDpp.js +152 -0
  54. package/dist/lsUoraDpp.js.map +1 -0
  55. package/dist/policyConfig.d.ts +31 -0
  56. package/dist/policyConfig.d.ts.map +1 -0
  57. package/dist/policyConfig.js +112 -0
  58. package/dist/policyConfig.js.map +1 -0
  59. package/dist/retraction.d.ts +41 -0
  60. package/dist/retraction.d.ts.map +1 -0
  61. package/dist/retraction.js +147 -0
  62. package/dist/retraction.js.map +1 -0
  63. package/dist/storage.d.ts +117 -0
  64. package/dist/storage.d.ts.map +1 -0
  65. package/dist/storage.js +158 -0
  66. package/dist/storage.js.map +1 -0
  67. package/dist/sync.d.ts +75 -0
  68. package/dist/sync.d.ts.map +1 -0
  69. package/dist/sync.js +118 -0
  70. package/dist/sync.js.map +1 -0
  71. package/dist/tmAttestation.d.ts +36 -0
  72. package/dist/tmAttestation.d.ts.map +1 -0
  73. package/dist/tmAttestation.js +50 -0
  74. package/dist/tmAttestation.js.map +1 -0
  75. package/dist/tmDpp.d.ts +154 -0
  76. package/dist/tmDpp.d.ts.map +1 -0
  77. package/dist/tmDpp.js +397 -0
  78. package/dist/tmDpp.js.map +1 -0
  79. package/dist/tmUoraDpp.d.ts +73 -0
  80. package/dist/tmUoraDpp.d.ts.map +1 -0
  81. package/dist/tmUoraDpp.js +150 -0
  82. package/dist/tmUoraDpp.js.map +1 -0
  83. package/dist/uoraAnchor.d.ts +209 -0
  84. package/dist/uoraAnchor.d.ts.map +1 -0
  85. package/dist/uoraAnchor.js +433 -0
  86. package/dist/uoraAnchor.js.map +1 -0
  87. package/package.json +51 -0
@@ -0,0 +1,209 @@
1
+ import type { LockingScript, WalletProtocol } from '@bsv/sdk';
2
+ /**
3
+ * `uora-anchor-v3`: the attestation anchor output, as this overlay reads it.
4
+ *
5
+ * ## Why the format is not v1
6
+ *
7
+ * v1, the anchoring service's original format, is three fields: a prefix, a
8
+ * digest and the attestation id. It proves an attestation existed at a point
9
+ * in the chain's order and nothing else; its own specification recorded both
10
+ * gaps, and this format closes them:
11
+ *
12
+ * 1. **Nothing in a v1 anchor says who claimed anything.** The digest covers an
13
+ * attestation the chain never sees, so an indexer holding only the output
14
+ * cannot answer "what has this party attested", which is the whole of a
15
+ * DID-keyed lookup. This format carries the issuer's `did:key`, the subject
16
+ * and the UORA type in the clear, because those three are the query.
17
+ * 2. **Nothing in a v1 anchor says who anchored it, either.** v1 locks with
18
+ * counterparty `self`, whose BRC-42 derivation needs the treasury's root
19
+ * *private* key, so a third party cannot reproduce the locking key and
20
+ * cannot tie the output to anyone. That is not a small gap: the anchoring
21
+ * service established that more than one treasury has already anchored
22
+ * under the v1 prefix and the format cannot distinguish them. This format
23
+ * locks with counterparty `'anyone'`, which a stranger *can* reproduce from
24
+ * a published identity key, so `expectedLockingKey` below is checkable by
25
+ * anybody and is what this topic's admission rule turns on.
26
+ *
27
+ * v1 is untouched. Every anchor already broadcast keeps verifying under its
28
+ * own rules, exactly as its specification promises, and the prefixes are
29
+ * distinguishable by reading field 0. This is a new format beside it, not an
30
+ * edit to it.
31
+ *
32
+ * ## Why v3 and not v2
33
+ *
34
+ * v2 had these same seven fields, in this order, with this derivation. What it
35
+ * got wrong was the signature. `PushDrop.lock` appends one over `fields.flat()`,
36
+ * the field bytes run together with no delimiters and no lengths, which
37
+ * authenticates the total byte string and says nothing about where one field
38
+ * ends and the next begins.
39
+ *
40
+ * Four of the seven have their boundaries pinned by other checks anyway: the
41
+ * prefix is a fixed literal, the digest is exactly 64 hex characters, and the
42
+ * attestation id and the anchoring key are both fixed by the derivation of the
43
+ * locking key. The subject and the type are neither, and they are adjacent. So
44
+ * anyone holding a v2 anchor could re-cut that one boundary into a different
45
+ * subject and a different type, copy the signature bytes across verbatim, and
46
+ * still pass every check this reader made. The single v2 anchor on mainnet
47
+ * admits 63 such variants, and this reader would have indexed any of them under
48
+ * a subject nobody had signed.
49
+ *
50
+ * v3 signs `uoraAnchorSigningPreimage` instead: each field behind its own
51
+ * length, so any other split of the same bytes is a different preimage and the
52
+ * signature stops verifying. The prefix moves with it because a reader has no
53
+ * other way to know which preimage to rebuild, and because the format's own
54
+ * rule is that a change of layout is a change of prefix. Nothing repairs the
55
+ * outputs already written, so **v2 is superseded and this reader refuses it**
56
+ * rather than reading it leniently.
57
+ *
58
+ * ## Why this file imports nothing of ours
59
+ *
60
+ * `tm_dpp` reads the token standard, so it depends on `@bsv/dpp-core` and can never
61
+ * be published as part of a shared overlay package. `tm_uora_dpp` is meant to
62
+ * be PR'd into the shared mainnet overlay instances, so it deliberately depends
63
+ * on `@bsv/sdk` and `@bsv/overlay` alone. The fifteen lines of `did:key`
64
+ * decoding below are the same fifteen in `@bsv/dpp-core/did.ts`, duplicated on
65
+ * purpose against the repository's own rule about one implementation per
66
+ * concept: the alternative is that a shared overlay instance takes a dependency
67
+ * on this programme's token core, which is a worse trade. The two are pinned
68
+ * together by a shared fixture rather than by an import
69
+ * (`test/anchor-v3-fixture.ts`), which is the same discipline the
70
+ * canonical-bytes digest is held to across the two repositories.
71
+ */
72
+ /** Marks the output as ours and versions the field layout. */
73
+ export declare const UORA_ANCHOR_PREFIX = "uora-anchor-v3";
74
+ /**
75
+ * The superseded layout, named so it can be refused deliberately rather than
76
+ * by falling off the end of a string comparison. It is the one near miss worth
77
+ * spelling out: same seven fields, same order, same derivation, often the same
78
+ * treasury, and a signature that does not commit to where the subject stops.
79
+ */
80
+ export declare const UORA_ANCHOR_PREFIX_V2 = "uora-anchor-v2";
81
+ /**
82
+ * The anchoring service's original three-field format, described above. Never
83
+ * read by this index; named so the capability document can list it as
84
+ * historical rather than leave a reader guessing why v1 anchors are not
85
+ * answered.
86
+ */
87
+ export declare const UORA_ANCHOR_PREFIX_V1 = "uora-anchor-v1";
88
+ /**
89
+ * BRC-42 child the anchor is locked under. A distinct string from v2's
90
+ * `[1, 'uora anchor v2']` and v1's `[1, 'uora anchor v1']`, because two
91
+ * incompatible formats sharing one protocol name would be two keys wearing one
92
+ * label.
93
+ */
94
+ export declare const UORA_ANCHOR_PROTOCOL: WalletProtocol;
95
+ /**
96
+ * Basket the outputs land in, unchanged from v1 on purpose: the treasury's
97
+ * balance and its anchor count should keep seeing one population, and the
98
+ * version is legible in field 0 for anything that needs to tell them apart.
99
+ */
100
+ export declare const UORA_ANCHOR_BASKET = "uora-anchor";
101
+ /** Fields before the appended signature. */
102
+ export declare const UORA_ANCHOR_FIELD_COUNT = 7;
103
+ /**
104
+ * The bytes a v3 signature covers: every field preceded by its own length, so
105
+ * the boundaries between the fields are part of what is signed.
106
+ *
107
+ * Byte-identical in behaviour to `anchorSigningPreimage` in the resolver's
108
+ * `src/anchoring/anchor.ts`, and it has to stay that way. The resolver signs
109
+ * this preimage and appends the result as the eighth field, locking with
110
+ * `includeSignature: false`; this package rebuilds it from the output and
111
+ * checks it. Neither repository can import the other, so the shared fixture in
112
+ * `test/anchor-v3-fixture.ts` is what catches a drift.
113
+ *
114
+ * `PushDrop.lock`'s own signature is not used and cannot be made to serve here:
115
+ * it has no option to commit to boundaries, which is the whole of what went
116
+ * wrong with v2.
117
+ */
118
+ export declare function uoraAnchorSigningPreimage(fields: number[][]): number[];
119
+ /**
120
+ * One anchor, as read off the chain. Every field validated, nothing inferred.
121
+ *
122
+ * **Two parties appear here and they are not the same one.** `issuer` is who
123
+ * made the claim, and the anchor carries it without checking it. `anchoredBy`
124
+ * is who wrote this output, and the anchor proves it. Conflating them is the
125
+ * one misreading this format invites, which is why they are named apart.
126
+ */
127
+ export interface UoraAnchor {
128
+ /** Lower-case hex SHA-256 over the attestation's canonical form. */
129
+ digest: string;
130
+ /** The resolver's id for the attestation this digest covers. */
131
+ attestationId: string;
132
+ /** The party that made the claim, as a `did:key`. Carried, not proved. */
133
+ issuer: string;
134
+ /** The issuer's compressed secp256k1 key, hex, decoded from the DID. */
135
+ issuerKey: string;
136
+ /** What the claim is about: a passport id. */
137
+ subject: string;
138
+ /** The UORA attestation type, verbatim and unvalidated against any list. */
139
+ uoraType: string;
140
+ /**
141
+ * The anchoring service's published identity key, hex.
142
+ *
143
+ * Named by the output itself rather than configured into the reader, so this
144
+ * topic needs no per-deployment key list to attribute an anchor: the locking
145
+ * key must be the BRC-42 child of this one, and producing that needs its
146
+ * private half. A shared overlay can therefore carry anchors from a
147
+ * deployment it has never been told about, and still say whose each one is.
148
+ */
149
+ anchoredBy: string;
150
+ /** The key locking the output: the BRC-42 child of `anchoredBy`. */
151
+ lockingKey: string;
152
+ }
153
+ /**
154
+ * The seven fields, in order, for whoever writes one.
155
+ *
156
+ * The eighth field a written anchor carries is the signature over
157
+ * `uoraAnchorSigningPreimage(theseSeven)`, appended by the writer. It is not
158
+ * the signature `PushDrop.lock` appends, and a writer that leaves
159
+ * `includeSignature` at its default produces an output this reader refuses.
160
+ */
161
+ export declare function uoraAnchorFields(anchor: Pick<UoraAnchor, 'digest' | 'attestationId' | 'issuer' | 'subject' | 'uoraType' | 'anchoredBy'>): number[][];
162
+ /**
163
+ * The compressed key inside a `did:key`, or null.
164
+ *
165
+ * Refuses another curve rather than returning bytes that would fail later: an
166
+ * Ed25519 DID is a well-formed `did:key` and a meaningless secp256k1 key, and
167
+ * the difference is the two bytes at the front. Also refuses a non-canonical
168
+ * encoding, because the SDK reduces `x >= p` mod p and would hand back a key
169
+ * that indexes under a DID nobody else computes.
170
+ */
171
+ export declare function identityKeyFromDidKey(did: string): string | null;
172
+ /** The inverse, so a writer and a reader cannot drift on the encoding. */
173
+ export declare function didKeyFromIdentityKey(identityKeyHex: string): string;
174
+ /**
175
+ * The key an anchor for this attestation id must be locked to, given the
176
+ * anchoring service's published identity key.
177
+ *
178
+ * Half the reason this format exists at all. Counterparty `'anyone'` means this
179
+ * runs with no secret, so the admission rule below is one a stranger can also
180
+ * apply, and a verifier can say "this anchor is that service's" rather than
181
+ * "this anchor is somebody's".
182
+ */
183
+ export declare function expectedLockingKey(serviceIdentityKey: string, attestationId: string): string;
184
+ /**
185
+ * The version prefix in field 0, or null when the output is not a PushDrop with
186
+ * a readable text field there.
187
+ *
188
+ * Says nothing about whether the rest of the output is valid, and is not a
189
+ * shortcut past `tryParseUoraAnchor`. It exists so a reader can *name* what it
190
+ * is refusing: an anchor turned away for being v2 is a different event from a
191
+ * stranger's output that was never an anchor, and only one of the two is worth
192
+ * telling an operator about.
193
+ */
194
+ export declare function uoraAnchorPrefix(script: LockingScript): string | null;
195
+ /**
196
+ * Parse and fully validate one output. Null for anything that is not a
197
+ * well-formed v3 anchor, including a v1 or a v2 one, neither of which this
198
+ * topic indexes.
199
+ *
200
+ * Nothing is returned unless the signature verifies, which is not a detail. A
201
+ * caller that got the carried fields back beside a failed signature would be
202
+ * holding an issuer, a subject and a type that nothing vouches for, and would
203
+ * have no way to tell them from ones that do.
204
+ *
205
+ * Total: no throw on any input, because it runs against whatever an overlay is
206
+ * handed. A malformed output is not an error, it is an output that is not ours.
207
+ */
208
+ export declare function tryParseUoraAnchor(script: LockingScript): UoraAnchor | null;
209
+ //# sourceMappingURL=uoraAnchor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uoraAnchor.d.ts","sourceRoot":"","sources":["../src/uoraAnchor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AAEH,8DAA8D;AAC9D,eAAO,MAAM,kBAAkB,mBAAmB,CAAA;AAElD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,mBAAmB,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,mBAAmB,CAAA;AAErD;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAAsC,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAA;AAE/C,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAOtE;AA0BD;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAA;IACd,gEAAgE;IAChE,aAAa,EAAE,MAAM,CAAA;IACrB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAA;IACjB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAA;IACf,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,CACV,UAAU,EACV,QAAQ,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,YAAY,CAC9E,GACA,MAAM,EAAE,EAAE,CAUZ;AAiBD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAmBhE;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAOpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,kBAAkB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAE5F;AA0GD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAIrE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,GAAG,IAAI,CAwD3E"}
@@ -0,0 +1,433 @@
1
+ import { BigNumber, CachedKeyDeriver, ECDSA, Hash, PublicKey, Signature, Utils } from '@bsv/sdk';
2
+ /**
3
+ * `uora-anchor-v3`: the attestation anchor output, as this overlay reads it.
4
+ *
5
+ * ## Why the format is not v1
6
+ *
7
+ * v1, the anchoring service's original format, is three fields: a prefix, a
8
+ * digest and the attestation id. It proves an attestation existed at a point
9
+ * in the chain's order and nothing else; its own specification recorded both
10
+ * gaps, and this format closes them:
11
+ *
12
+ * 1. **Nothing in a v1 anchor says who claimed anything.** The digest covers an
13
+ * attestation the chain never sees, so an indexer holding only the output
14
+ * cannot answer "what has this party attested", which is the whole of a
15
+ * DID-keyed lookup. This format carries the issuer's `did:key`, the subject
16
+ * and the UORA type in the clear, because those three are the query.
17
+ * 2. **Nothing in a v1 anchor says who anchored it, either.** v1 locks with
18
+ * counterparty `self`, whose BRC-42 derivation needs the treasury's root
19
+ * *private* key, so a third party cannot reproduce the locking key and
20
+ * cannot tie the output to anyone. That is not a small gap: the anchoring
21
+ * service established that more than one treasury has already anchored
22
+ * under the v1 prefix and the format cannot distinguish them. This format
23
+ * locks with counterparty `'anyone'`, which a stranger *can* reproduce from
24
+ * a published identity key, so `expectedLockingKey` below is checkable by
25
+ * anybody and is what this topic's admission rule turns on.
26
+ *
27
+ * v1 is untouched. Every anchor already broadcast keeps verifying under its
28
+ * own rules, exactly as its specification promises, and the prefixes are
29
+ * distinguishable by reading field 0. This is a new format beside it, not an
30
+ * edit to it.
31
+ *
32
+ * ## Why v3 and not v2
33
+ *
34
+ * v2 had these same seven fields, in this order, with this derivation. What it
35
+ * got wrong was the signature. `PushDrop.lock` appends one over `fields.flat()`,
36
+ * the field bytes run together with no delimiters and no lengths, which
37
+ * authenticates the total byte string and says nothing about where one field
38
+ * ends and the next begins.
39
+ *
40
+ * Four of the seven have their boundaries pinned by other checks anyway: the
41
+ * prefix is a fixed literal, the digest is exactly 64 hex characters, and the
42
+ * attestation id and the anchoring key are both fixed by the derivation of the
43
+ * locking key. The subject and the type are neither, and they are adjacent. So
44
+ * anyone holding a v2 anchor could re-cut that one boundary into a different
45
+ * subject and a different type, copy the signature bytes across verbatim, and
46
+ * still pass every check this reader made. The single v2 anchor on mainnet
47
+ * admits 63 such variants, and this reader would have indexed any of them under
48
+ * a subject nobody had signed.
49
+ *
50
+ * v3 signs `uoraAnchorSigningPreimage` instead: each field behind its own
51
+ * length, so any other split of the same bytes is a different preimage and the
52
+ * signature stops verifying. The prefix moves with it because a reader has no
53
+ * other way to know which preimage to rebuild, and because the format's own
54
+ * rule is that a change of layout is a change of prefix. Nothing repairs the
55
+ * outputs already written, so **v2 is superseded and this reader refuses it**
56
+ * rather than reading it leniently.
57
+ *
58
+ * ## Why this file imports nothing of ours
59
+ *
60
+ * `tm_dpp` reads the token standard, so it depends on `@bsv/dpp-core` and can never
61
+ * be published as part of a shared overlay package. `tm_uora_dpp` is meant to
62
+ * be PR'd into the shared mainnet overlay instances, so it deliberately depends
63
+ * on `@bsv/sdk` and `@bsv/overlay` alone. The fifteen lines of `did:key`
64
+ * decoding below are the same fifteen in `@bsv/dpp-core/did.ts`, duplicated on
65
+ * purpose against the repository's own rule about one implementation per
66
+ * concept: the alternative is that a shared overlay instance takes a dependency
67
+ * on this programme's token core, which is a worse trade. The two are pinned
68
+ * together by a shared fixture rather than by an import
69
+ * (`test/anchor-v3-fixture.ts`), which is the same discipline the
70
+ * canonical-bytes digest is held to across the two repositories.
71
+ */
72
+ /** Marks the output as ours and versions the field layout. */
73
+ export const UORA_ANCHOR_PREFIX = 'uora-anchor-v3';
74
+ /**
75
+ * The superseded layout, named so it can be refused deliberately rather than
76
+ * by falling off the end of a string comparison. It is the one near miss worth
77
+ * spelling out: same seven fields, same order, same derivation, often the same
78
+ * treasury, and a signature that does not commit to where the subject stops.
79
+ */
80
+ export const UORA_ANCHOR_PREFIX_V2 = 'uora-anchor-v2';
81
+ /**
82
+ * The anchoring service's original three-field format, described above. Never
83
+ * read by this index; named so the capability document can list it as
84
+ * historical rather than leave a reader guessing why v1 anchors are not
85
+ * answered.
86
+ */
87
+ export const UORA_ANCHOR_PREFIX_V1 = 'uora-anchor-v1';
88
+ /**
89
+ * BRC-42 child the anchor is locked under. A distinct string from v2's
90
+ * `[1, 'uora anchor v2']` and v1's `[1, 'uora anchor v1']`, because two
91
+ * incompatible formats sharing one protocol name would be two keys wearing one
92
+ * label.
93
+ */
94
+ export const UORA_ANCHOR_PROTOCOL = [1, 'uora anchor v3'];
95
+ /**
96
+ * Basket the outputs land in, unchanged from v1 on purpose: the treasury's
97
+ * balance and its anchor count should keep seeing one population, and the
98
+ * version is legible in field 0 for anything that needs to tell them apart.
99
+ */
100
+ export const UORA_ANCHOR_BASKET = 'uora-anchor';
101
+ /** Fields before the appended signature. */
102
+ export const UORA_ANCHOR_FIELD_COUNT = 7;
103
+ /**
104
+ * The bytes a v3 signature covers: every field preceded by its own length, so
105
+ * the boundaries between the fields are part of what is signed.
106
+ *
107
+ * Byte-identical in behaviour to `anchorSigningPreimage` in the resolver's
108
+ * `src/anchoring/anchor.ts`, and it has to stay that way. The resolver signs
109
+ * this preimage and appends the result as the eighth field, locking with
110
+ * `includeSignature: false`; this package rebuilds it from the output and
111
+ * checks it. Neither repository can import the other, so the shared fixture in
112
+ * `test/anchor-v3-fixture.ts` is what catches a drift.
113
+ *
114
+ * `PushDrop.lock`'s own signature is not used and cannot be made to serve here:
115
+ * it has no option to commit to boundaries, which is the whole of what went
116
+ * wrong with v2.
117
+ */
118
+ export function uoraAnchorSigningPreimage(fields) {
119
+ const writer = new Utils.Writer();
120
+ for (const field of fields) {
121
+ writer.writeVarIntNum(field.length);
122
+ writer.write(field);
123
+ }
124
+ return writer.toArray();
125
+ }
126
+ /**
127
+ * Bounds on the free-text fields. An overlay admits from whoever can reach it,
128
+ * and an index keyed on a field a stranger controls is a field a stranger can
129
+ * make expensive. Generous enough that no honest value is near them: a GS1
130
+ * Digital Link with a long serial is under 200 characters.
131
+ */
132
+ const MAX_ATTESTATION_ID = 256;
133
+ const MAX_SUBJECT = 512;
134
+ const MAX_TYPE = 64;
135
+ const HEX_64 = /^[0-9a-f]{64}$/;
136
+ /** Rules out control characters and the stray replacement char a bad decode leaves. */
137
+ const PRINTABLE = /^[ -~ -￿]+$/;
138
+ const OP_CHECKSIG = 0xac;
139
+ const OP_DROP = 0x75;
140
+ const OP_2DROP = 0x6d;
141
+ const SECP256K1_PUB_MULTICODEC = [0xe7, 0x01];
142
+ const BASE58BTC = 'z';
143
+ const DID_KEY_PREFIX = `did:key:${BASE58BTC}`;
144
+ const anyone = new CachedKeyDeriver('anyone');
145
+ /**
146
+ * The seven fields, in order, for whoever writes one.
147
+ *
148
+ * The eighth field a written anchor carries is the signature over
149
+ * `uoraAnchorSigningPreimage(theseSeven)`, appended by the writer. It is not
150
+ * the signature `PushDrop.lock` appends, and a writer that leaves
151
+ * `includeSignature` at its default produces an output this reader refuses.
152
+ */
153
+ export function uoraAnchorFields(anchor) {
154
+ return [
155
+ Utils.toArray(UORA_ANCHOR_PREFIX, 'utf8'),
156
+ Utils.toArray(anchor.digest, 'utf8'),
157
+ Utils.toArray(anchor.attestationId, 'utf8'),
158
+ Utils.toArray(anchor.issuer, 'utf8'),
159
+ Utils.toArray(anchor.subject, 'utf8'),
160
+ Utils.toArray(anchor.uoraType, 'utf8'),
161
+ Utils.toArray(anchor.anchoredBy, 'utf8'),
162
+ ];
163
+ }
164
+ /**
165
+ * A 33-byte compressed key in its one canonical spelling, or false.
166
+ *
167
+ * The SDK reduces `x >= p` rather than refusing, so an unchecked encoding would
168
+ * be accepted here and index under a key nobody else computes.
169
+ */
170
+ function canonicalCompressedKey(hex) {
171
+ if (!/^0[23][0-9a-f]{64}$/.test(hex))
172
+ return false;
173
+ try {
174
+ return PublicKey.fromString(hex).toString() === hex;
175
+ }
176
+ catch {
177
+ return false;
178
+ }
179
+ }
180
+ /**
181
+ * The compressed key inside a `did:key`, or null.
182
+ *
183
+ * Refuses another curve rather than returning bytes that would fail later: an
184
+ * Ed25519 DID is a well-formed `did:key` and a meaningless secp256k1 key, and
185
+ * the difference is the two bytes at the front. Also refuses a non-canonical
186
+ * encoding, because the SDK reduces `x >= p` mod p and would hand back a key
187
+ * that indexes under a DID nobody else computes.
188
+ */
189
+ export function identityKeyFromDidKey(did) {
190
+ if (!did.startsWith(DID_KEY_PREFIX))
191
+ return null;
192
+ let bytes;
193
+ try {
194
+ bytes = Utils.fromBase58(did.slice(DID_KEY_PREFIX.length));
195
+ }
196
+ catch {
197
+ return null;
198
+ }
199
+ if (bytes[0] !== SECP256K1_PUB_MULTICODEC[0] || bytes[1] !== SECP256K1_PUB_MULTICODEC[1]) {
200
+ return null;
201
+ }
202
+ const key = bytes.slice(2);
203
+ if (key.length !== 33)
204
+ return null;
205
+ const hex = Utils.toHex(key);
206
+ try {
207
+ return PublicKey.fromString(hex).toString() === hex ? hex : null;
208
+ }
209
+ catch {
210
+ return null;
211
+ }
212
+ }
213
+ /** The inverse, so a writer and a reader cannot drift on the encoding. */
214
+ export function didKeyFromIdentityKey(identityKeyHex) {
215
+ const key = PublicKey.fromString(identityKeyHex);
216
+ if (key.toString() !== identityKeyHex) {
217
+ throw new Error('not a canonical compressed public key');
218
+ }
219
+ const bytes = [...SECP256K1_PUB_MULTICODEC, ...key.encode(true)];
220
+ return `${DID_KEY_PREFIX}${Utils.toBase58(bytes)}`;
221
+ }
222
+ /**
223
+ * The key an anchor for this attestation id must be locked to, given the
224
+ * anchoring service's published identity key.
225
+ *
226
+ * Half the reason this format exists at all. Counterparty `'anyone'` means this
227
+ * runs with no secret, so the admission rule below is one a stranger can also
228
+ * apply, and a verifier can say "this anchor is that service's" rather than
229
+ * "this anchor is somebody's".
230
+ */
231
+ export function expectedLockingKey(serviceIdentityKey, attestationId) {
232
+ return anyone.derivePublicKey(UORA_ANCHOR_PROTOCOL, attestationId, serviceIdentityKey).toString();
233
+ }
234
+ /**
235
+ * Read a PushDrop locking script into its key and its fields.
236
+ *
237
+ * Written over the chunks rather than `PushDrop.decode` for the reason
238
+ * `/spec` spends four lines on: the decoder renders an empty field as a single
239
+ * zero byte, so a preimage built from its output is one byte too long per empty
240
+ * field and the signature check fails for a reason that has nothing to do with
241
+ * the signature. No v3 field may be empty, so an empty one is rejected either
242
+ * way; reading it exactly means it is rejected for the right reason. It matters
243
+ * more under v3 than it did under v2, because the preimage now carries each
244
+ * field's length and a length read one byte out is a different preimage.
245
+ */
246
+ function readPushDrop(script) {
247
+ const chunks = script.chunks;
248
+ if (chunks.length < 3)
249
+ return null;
250
+ const keyData = chunks[0]?.data;
251
+ /*
252
+ * Exactly 33 bytes, the compressed encoding a conforming writer emits. A
253
+ * 65-byte uncompressed push used to parse here and then pass attribution,
254
+ * because `PublicKey.toString()` re-compresses before the comparison, which
255
+ * made the acceptance invisible: an anchor in a spelling nobody writes was
256
+ * admitted as though it were canonical. The record rail's reader was always
257
+ * exact about the same push; this one now matches it, and the fixture's
258
+ * `uncompressedKey` vector is what keeps it matched.
259
+ */
260
+ if (keyData == null || keyData.length !== 33)
261
+ return null;
262
+ if (chunks[1]?.op !== OP_CHECKSIG)
263
+ return null;
264
+ let lockingKey;
265
+ try {
266
+ lockingKey = PublicKey.fromString(Utils.toHex(keyData));
267
+ }
268
+ catch {
269
+ return null;
270
+ }
271
+ const fields = [];
272
+ for (const chunk of chunks.slice(2)) {
273
+ if (chunk.op === OP_DROP || chunk.op === OP_2DROP)
274
+ break;
275
+ if (chunk.data != null && chunk.data.length > 0)
276
+ fields.push(chunk.data);
277
+ else if (chunk.op === 0)
278
+ fields.push([]);
279
+ else if (chunk.op >= 0x51 && chunk.op <= 0x60)
280
+ fields.push([chunk.op - 0x50]);
281
+ else
282
+ return null;
283
+ }
284
+ /*
285
+ * The drop tail, validated exactly the way the record rail's codec validates
286
+ * its own: floor(n/2) OP_2DROPs, one OP_DROP when n is odd, and nothing at
287
+ * all after them. This reader used to stop at the first drop and never look
288
+ * back, so an anchor with a short tail, a wrong mix, or trailing chunks was
289
+ * parsed and admitted; the fixture's `malformedTail` vectors pin the refusal.
290
+ */
291
+ const tail = chunks.slice(2 + fields.length);
292
+ const twoDrops = Math.floor(fields.length / 2);
293
+ const oneDrop = fields.length % 2;
294
+ const tailValid = tail.length === twoDrops + oneDrop &&
295
+ tail.slice(0, twoDrops).every((chunk) => chunk.op === OP_2DROP) &&
296
+ (oneDrop === 0 || tail[twoDrops]?.op === OP_DROP);
297
+ if (!tailValid)
298
+ return null;
299
+ return { lockingKey, fields };
300
+ }
301
+ /** UTF-8 that round-trips. A field that does not is not a field we wrote. */
302
+ function text(bytes) {
303
+ let decoded;
304
+ try {
305
+ decoded = Utils.toUTF8(bytes);
306
+ }
307
+ catch {
308
+ return null;
309
+ }
310
+ if (decoded === '' || !PRINTABLE.test(decoded))
311
+ return null;
312
+ return Utils.toHex(Utils.toArray(decoded, 'utf8')) === Utils.toHex(bytes) ? decoded : null;
313
+ }
314
+ /**
315
+ * The appended signature, checked.
316
+ *
317
+ * It proves the seven fields were sealed **together, at these boundaries**, by
318
+ * whoever holds the key in the script. An output whose digest or issuer was
319
+ * edited after signing fails here; so does one assembled by copying another
320
+ * anchor's signature; and so, now, does one that moves the boundary between the
321
+ * subject and the type without altering a single byte, which is the forgery v2
322
+ * could not see and the reason the preimage is length-prefixed.
323
+ *
324
+ * On its own that is tamper-evidence over the anchor's structure and not
325
+ * attribution. Attribution is `expectedLockingKey`, and the topic manager wants
326
+ * both.
327
+ */
328
+ function sealedByLockingKey(fields, lockingKey) {
329
+ const signature = fields[UORA_ANCHOR_FIELD_COUNT];
330
+ if (signature == null || signature.length === 0)
331
+ return false;
332
+ const signed = uoraAnchorSigningPreimage(fields.slice(0, UORA_ANCHOR_FIELD_COUNT));
333
+ try {
334
+ return ECDSA.verify(new BigNumber(Hash.sha256(signed)), Signature.fromDER(signature), lockingKey);
335
+ }
336
+ catch {
337
+ return false;
338
+ }
339
+ }
340
+ /**
341
+ * The version prefix in field 0, or null when the output is not a PushDrop with
342
+ * a readable text field there.
343
+ *
344
+ * Says nothing about whether the rest of the output is valid, and is not a
345
+ * shortcut past `tryParseUoraAnchor`. It exists so a reader can *name* what it
346
+ * is refusing: an anchor turned away for being v2 is a different event from a
347
+ * stranger's output that was never an anchor, and only one of the two is worth
348
+ * telling an operator about.
349
+ */
350
+ export function uoraAnchorPrefix(script) {
351
+ const decoded = readPushDrop(script);
352
+ const first = decoded?.fields[0];
353
+ return first == null ? null : text(first);
354
+ }
355
+ /**
356
+ * Parse and fully validate one output. Null for anything that is not a
357
+ * well-formed v3 anchor, including a v1 or a v2 one, neither of which this
358
+ * topic indexes.
359
+ *
360
+ * Nothing is returned unless the signature verifies, which is not a detail. A
361
+ * caller that got the carried fields back beside a failed signature would be
362
+ * holding an issuer, a subject and a type that nothing vouches for, and would
363
+ * have no way to tell them from ones that do.
364
+ *
365
+ * Total: no throw on any input, because it runs against whatever an overlay is
366
+ * handed. A malformed output is not an error, it is an output that is not ours.
367
+ */
368
+ export function tryParseUoraAnchor(script) {
369
+ const decoded = readPushDrop(script);
370
+ if (decoded == null)
371
+ return null;
372
+ const { fields, lockingKey } = decoded;
373
+ if (fields.length !== UORA_ANCHOR_FIELD_COUNT + 1)
374
+ return null;
375
+ const parts = fields.slice(0, UORA_ANCHOR_FIELD_COUNT).map(text);
376
+ if (parts.some((part) => part == null))
377
+ return null;
378
+ const [prefix, digest, attestationId, issuer, subject, uoraType, anchoredBy] = parts;
379
+ /*
380
+ * v2 is refused by name, ahead of the general prefix check, because it is the
381
+ * one near miss somebody maintaining this later might be tempted to wave
382
+ * through: the fields are right, the derivation is right, and the treasury is
383
+ * often ours. Waving it through would index a subject and a type its own
384
+ * signature does not cover. The refusal is a decision, and this is where it
385
+ * is written down rather than left to fall out of a string comparison.
386
+ */
387
+ if (prefix === UORA_ANCHOR_PREFIX_V2)
388
+ return null;
389
+ if (prefix !== UORA_ANCHOR_PREFIX)
390
+ return null;
391
+ if (!HEX_64.test(digest))
392
+ return null;
393
+ if (attestationId.length > MAX_ATTESTATION_ID)
394
+ return null;
395
+ if (subject.length > MAX_SUBJECT)
396
+ return null;
397
+ if (uoraType.length > MAX_TYPE)
398
+ return null;
399
+ const issuerKey = identityKeyFromDidKey(issuer);
400
+ if (issuerKey == null)
401
+ return null;
402
+ if (!sealedByLockingKey(fields, lockingKey))
403
+ return null;
404
+ /*
405
+ * The attribution check, and it is part of being well-formed rather than a
406
+ * policy on top. An output that names an anchoring service its locking key
407
+ * does not derive from is claiming something untrue about itself, so it is
408
+ * malformed, not merely unwanted. Producing one that passes needs the private
409
+ * half of the key in field 6, which is the whole proof.
410
+ */
411
+ if (!canonicalCompressedKey(anchoredBy))
412
+ return null;
413
+ let derived;
414
+ try {
415
+ derived = expectedLockingKey(anchoredBy, attestationId);
416
+ }
417
+ catch {
418
+ return null;
419
+ }
420
+ if (derived !== lockingKey.toString())
421
+ return null;
422
+ return {
423
+ digest,
424
+ attestationId,
425
+ issuer,
426
+ issuerKey,
427
+ subject,
428
+ uoraType,
429
+ anchoredBy,
430
+ lockingKey: lockingKey.toString(),
431
+ };
432
+ }
433
+ //# sourceMappingURL=uoraAnchor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uoraAnchor.js","sourceRoot":"","sources":["../src/uoraAnchor.ts"],"names":[],"mappings":"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"}