@helia/ipns 10.1.0 → 10.1.1-2ab3bfc6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/index.min.js +5 -5
- package/dist/index.min.js.map +4 -4
- package/dist/src/errors.d.ts +11 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +13 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +136 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +41 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/ipns/publisher.d.ts +3 -3
- package/dist/src/ipns/publisher.d.ts.map +1 -1
- package/dist/src/ipns/publisher.js +17 -18
- package/dist/src/ipns/publisher.js.map +1 -1
- package/dist/src/ipns/republisher.d.ts +6 -1
- package/dist/src/ipns/republisher.d.ts.map +1 -1
- package/dist/src/ipns/republisher.js +157 -24
- package/dist/src/ipns/republisher.js.map +1 -1
- package/dist/src/ipns/resolver.d.ts +13 -1
- package/dist/src/ipns/resolver.d.ts.map +1 -1
- package/dist/src/ipns/resolver.js +40 -31
- package/dist/src/ipns/resolver.js.map +1 -1
- package/dist/src/ipns.d.ts +6 -3
- package/dist/src/ipns.d.ts.map +1 -1
- package/dist/src/ipns.js +12 -3
- package/dist/src/ipns.js.map +1 -1
- package/dist/src/local-store.d.ts +5 -0
- package/dist/src/local-store.d.ts.map +1 -1
- package/dist/src/local-store.js +68 -23
- package/dist/src/local-store.js.map +1 -1
- package/dist/src/pb/ipns.d.ts +9 -9
- package/dist/src/pb/ipns.d.ts.map +1 -1
- package/dist/src/pb/ipns.js +23 -9
- package/dist/src/pb/ipns.js.map +1 -1
- package/dist/src/pb/metadata.d.ts +16 -3
- package/dist/src/pb/metadata.d.ts.map +1 -1
- package/dist/src/pb/metadata.js +51 -4
- package/dist/src/pb/metadata.js.map +1 -1
- package/dist/src/routing/index.d.ts +13 -1
- package/dist/src/routing/index.d.ts.map +1 -1
- package/dist/src/routing/index.js +17 -0
- package/dist/src/routing/index.js.map +1 -1
- package/dist/src/utils.d.ts +5 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +18 -0
- package/dist/src/utils.js.map +1 -1
- package/dist/src/validator.d.ts +6 -0
- package/dist/src/validator.d.ts.map +1 -1
- package/dist/src/validator.js +24 -14
- package/dist/src/validator.js.map +1 -1
- package/package.json +4 -4
- package/src/errors.ts +18 -0
- package/src/index.ts +145 -7
- package/src/ipns/publisher.ts +22 -20
- package/src/ipns/republisher.ts +182 -26
- package/src/ipns/resolver.ts +54 -36
- package/src/ipns.ts +20 -6
- package/src/local-store.ts +77 -22
- package/src/pb/ipns.ts +34 -18
- package/src/pb/metadata.proto +10 -0
- package/src/pb/metadata.ts +64 -7
- package/src/routing/index.ts +30 -1
- package/src/utils.ts +19 -0
- package/src/validator.ts +30 -18
- package/dist/typedoc-urls.json +0 -68
package/src/pb/ipns.ts
CHANGED
|
@@ -142,69 +142,77 @@ export namespace IPNSEntry {
|
|
|
142
142
|
}, function * (reader, length, prefix, opts = {}) {
|
|
143
143
|
const end = length == null ? reader.len : reader.pos + length
|
|
144
144
|
|
|
145
|
+
if (prefix !== '.') {
|
|
146
|
+
yield {
|
|
147
|
+
field: prefix.endsWith('.') ? prefix.substring(0, prefix.length - 1) : prefix,
|
|
148
|
+
type: 'start',
|
|
149
|
+
message: 'IPNSEntry'
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
145
153
|
while (reader.pos < end) {
|
|
146
154
|
const tag = reader.uint32()
|
|
147
155
|
|
|
148
156
|
switch (tag >>> 3) {
|
|
149
157
|
case 1: {
|
|
150
158
|
yield {
|
|
151
|
-
field: `${prefix}
|
|
159
|
+
field: `${prefix}value`,
|
|
152
160
|
value: reader.bytes()
|
|
153
161
|
}
|
|
154
162
|
break
|
|
155
163
|
}
|
|
156
164
|
case 2: {
|
|
157
165
|
yield {
|
|
158
|
-
field: `${prefix}
|
|
166
|
+
field: `${prefix}signatureV1`,
|
|
159
167
|
value: reader.bytes()
|
|
160
168
|
}
|
|
161
169
|
break
|
|
162
170
|
}
|
|
163
171
|
case 3: {
|
|
164
172
|
yield {
|
|
165
|
-
field: `${prefix}
|
|
173
|
+
field: `${prefix}validityType`,
|
|
166
174
|
value: IPNSEntry.ValidityType.codec().decode(reader)
|
|
167
175
|
}
|
|
168
176
|
break
|
|
169
177
|
}
|
|
170
178
|
case 4: {
|
|
171
179
|
yield {
|
|
172
|
-
field: `${prefix}
|
|
180
|
+
field: `${prefix}validity`,
|
|
173
181
|
value: reader.bytes()
|
|
174
182
|
}
|
|
175
183
|
break
|
|
176
184
|
}
|
|
177
185
|
case 5: {
|
|
178
186
|
yield {
|
|
179
|
-
field: `${prefix}
|
|
187
|
+
field: `${prefix}sequence`,
|
|
180
188
|
value: reader.uint64()
|
|
181
189
|
}
|
|
182
190
|
break
|
|
183
191
|
}
|
|
184
192
|
case 6: {
|
|
185
193
|
yield {
|
|
186
|
-
field: `${prefix}
|
|
194
|
+
field: `${prefix}ttl`,
|
|
187
195
|
value: reader.uint64()
|
|
188
196
|
}
|
|
189
197
|
break
|
|
190
198
|
}
|
|
191
199
|
case 7: {
|
|
192
200
|
yield {
|
|
193
|
-
field: `${prefix}
|
|
201
|
+
field: `${prefix}publicKey`,
|
|
194
202
|
value: reader.bytes()
|
|
195
203
|
}
|
|
196
204
|
break
|
|
197
205
|
}
|
|
198
206
|
case 8: {
|
|
199
207
|
yield {
|
|
200
|
-
field: `${prefix}
|
|
208
|
+
field: `${prefix}signatureV2`,
|
|
201
209
|
value: reader.bytes()
|
|
202
210
|
}
|
|
203
211
|
break
|
|
204
212
|
}
|
|
205
213
|
case 9: {
|
|
206
214
|
yield {
|
|
207
|
-
field: `${prefix}
|
|
215
|
+
field: `${prefix}data`,
|
|
208
216
|
value: reader.bytes()
|
|
209
217
|
}
|
|
210
218
|
break
|
|
@@ -215,6 +223,14 @@ export namespace IPNSEntry {
|
|
|
215
223
|
}
|
|
216
224
|
}
|
|
217
225
|
}
|
|
226
|
+
|
|
227
|
+
if (prefix !== '.') {
|
|
228
|
+
yield {
|
|
229
|
+
field: prefix.endsWith('.') ? prefix.substring(0, prefix.length - 1) : prefix,
|
|
230
|
+
type: 'end',
|
|
231
|
+
message: 'IPNSEntry'
|
|
232
|
+
}
|
|
233
|
+
}
|
|
218
234
|
})
|
|
219
235
|
}
|
|
220
236
|
|
|
@@ -222,47 +238,47 @@ export namespace IPNSEntry {
|
|
|
222
238
|
}
|
|
223
239
|
|
|
224
240
|
export interface IPNSEntryValueFieldEvent {
|
|
225
|
-
field: '
|
|
241
|
+
field: '.value'
|
|
226
242
|
value: Uint8Array<ArrayBuffer>
|
|
227
243
|
}
|
|
228
244
|
|
|
229
245
|
export interface IPNSEntrySignatureV1FieldEvent {
|
|
230
|
-
field: '
|
|
246
|
+
field: '.signatureV1'
|
|
231
247
|
value: Uint8Array<ArrayBuffer>
|
|
232
248
|
}
|
|
233
249
|
|
|
234
250
|
export interface IPNSEntryValidityTypeFieldEvent {
|
|
235
|
-
field: '
|
|
251
|
+
field: '.validityType'
|
|
236
252
|
value: IPNSEntry.ValidityType
|
|
237
253
|
}
|
|
238
254
|
|
|
239
255
|
export interface IPNSEntryValidityFieldEvent {
|
|
240
|
-
field: '
|
|
256
|
+
field: '.validity'
|
|
241
257
|
value: Uint8Array<ArrayBuffer>
|
|
242
258
|
}
|
|
243
259
|
|
|
244
260
|
export interface IPNSEntrySequenceFieldEvent {
|
|
245
|
-
field: '
|
|
261
|
+
field: '.sequence'
|
|
246
262
|
value: bigint
|
|
247
263
|
}
|
|
248
264
|
|
|
249
265
|
export interface IPNSEntryTtlFieldEvent {
|
|
250
|
-
field: '
|
|
266
|
+
field: '.ttl'
|
|
251
267
|
value: bigint
|
|
252
268
|
}
|
|
253
269
|
|
|
254
270
|
export interface IPNSEntryPublicKeyFieldEvent {
|
|
255
|
-
field: '
|
|
271
|
+
field: '.publicKey'
|
|
256
272
|
value: Uint8Array<ArrayBuffer>
|
|
257
273
|
}
|
|
258
274
|
|
|
259
275
|
export interface IPNSEntrySignatureV2FieldEvent {
|
|
260
|
-
field: '
|
|
276
|
+
field: '.signatureV2'
|
|
261
277
|
value: Uint8Array<ArrayBuffer>
|
|
262
278
|
}
|
|
263
279
|
|
|
264
280
|
export interface IPNSEntryDataFieldEvent {
|
|
265
|
-
field: '
|
|
281
|
+
field: '.data'
|
|
266
282
|
value: Uint8Array<ArrayBuffer>
|
|
267
283
|
}
|
|
268
284
|
|
package/src/pb/metadata.proto
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
syntax = "proto3";
|
|
2
2
|
|
|
3
|
+
enum Upkeep {
|
|
4
|
+
reissue = 0; // Re-sign the record with a new validity (key must be in keychain)
|
|
5
|
+
rebroadcast = 1; // Re-publish the record as is (while it is still valid)
|
|
6
|
+
none = 2; // Disables automated republishing for the record
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
message IPNSPublishMetadata {
|
|
4
10
|
// The name of the key that was used to publish the record
|
|
5
11
|
string keyName = 1;
|
|
6
12
|
|
|
7
13
|
// Lifetime is the duration of the signature validity in milliseconds
|
|
14
|
+
// Relevant for Upkeep.reissue
|
|
8
15
|
uint32 lifetime = 2;
|
|
16
|
+
|
|
17
|
+
// Republishing policy
|
|
18
|
+
Upkeep upkeep = 3;
|
|
9
19
|
}
|
package/src/pb/metadata.ts
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
import { decodeMessage, encodeMessage, message, streamMessage } from 'protons-runtime'
|
|
1
|
+
import { decodeMessage, encodeMessage, enumeration, message, streamMessage } from 'protons-runtime'
|
|
2
2
|
import type { Codec, DecodeOptions } from 'protons-runtime'
|
|
3
3
|
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
4
4
|
|
|
5
|
+
export enum Upkeep {
|
|
6
|
+
reissue = 'reissue',
|
|
7
|
+
rebroadcast = 'rebroadcast',
|
|
8
|
+
none = 'none'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
enum __UpkeepValues {
|
|
12
|
+
reissue = 0,
|
|
13
|
+
rebroadcast = 1,
|
|
14
|
+
none = 2
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export namespace Upkeep {
|
|
18
|
+
export const codec = (): Codec<Upkeep> => {
|
|
19
|
+
return enumeration<Upkeep>(__UpkeepValues)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
5
23
|
export interface IPNSPublishMetadata {
|
|
6
24
|
keyName: string
|
|
7
25
|
lifetime: number
|
|
26
|
+
upkeep: Upkeep
|
|
8
27
|
}
|
|
9
28
|
|
|
10
29
|
export namespace IPNSPublishMetadata {
|
|
@@ -27,13 +46,19 @@ export namespace IPNSPublishMetadata {
|
|
|
27
46
|
w.uint32(obj.lifetime)
|
|
28
47
|
}
|
|
29
48
|
|
|
49
|
+
if (obj.upkeep != null && __UpkeepValues[obj.upkeep] !== 0) {
|
|
50
|
+
w.uint32(24)
|
|
51
|
+
Upkeep.codec().encode(obj.upkeep, w)
|
|
52
|
+
}
|
|
53
|
+
|
|
30
54
|
if (opts.lengthDelimited !== false) {
|
|
31
55
|
w.ldelim()
|
|
32
56
|
}
|
|
33
57
|
}, (reader, length, opts = {}) => {
|
|
34
58
|
const obj: any = {
|
|
35
59
|
keyName: '',
|
|
36
|
-
lifetime: 0
|
|
60
|
+
lifetime: 0,
|
|
61
|
+
upkeep: Upkeep.reissue
|
|
37
62
|
}
|
|
38
63
|
|
|
39
64
|
const end = length == null ? reader.len : reader.pos + length
|
|
@@ -50,6 +75,10 @@ export namespace IPNSPublishMetadata {
|
|
|
50
75
|
obj.lifetime = reader.uint32()
|
|
51
76
|
break
|
|
52
77
|
}
|
|
78
|
+
case 3: {
|
|
79
|
+
obj.upkeep = Upkeep.codec().decode(reader)
|
|
80
|
+
break
|
|
81
|
+
}
|
|
53
82
|
default: {
|
|
54
83
|
reader.skipType(tag & 7)
|
|
55
84
|
break
|
|
@@ -61,30 +90,53 @@ export namespace IPNSPublishMetadata {
|
|
|
61
90
|
}, function * (reader, length, prefix, opts = {}) {
|
|
62
91
|
const end = length == null ? reader.len : reader.pos + length
|
|
63
92
|
|
|
93
|
+
if (prefix !== '.') {
|
|
94
|
+
yield {
|
|
95
|
+
field: prefix.endsWith('.') ? prefix.substring(0, prefix.length - 1) : prefix,
|
|
96
|
+
type: 'start',
|
|
97
|
+
message: 'IPNSPublishMetadata'
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
64
101
|
while (reader.pos < end) {
|
|
65
102
|
const tag = reader.uint32()
|
|
66
103
|
|
|
67
104
|
switch (tag >>> 3) {
|
|
68
105
|
case 1: {
|
|
69
106
|
yield {
|
|
70
|
-
field: `${prefix}
|
|
107
|
+
field: `${prefix}keyName`,
|
|
71
108
|
value: reader.string()
|
|
72
109
|
}
|
|
73
110
|
break
|
|
74
111
|
}
|
|
75
112
|
case 2: {
|
|
76
113
|
yield {
|
|
77
|
-
field: `${prefix}
|
|
114
|
+
field: `${prefix}lifetime`,
|
|
78
115
|
value: reader.uint32()
|
|
79
116
|
}
|
|
80
117
|
break
|
|
81
118
|
}
|
|
119
|
+
case 3: {
|
|
120
|
+
yield {
|
|
121
|
+
field: `${prefix}upkeep`,
|
|
122
|
+
value: Upkeep.codec().decode(reader)
|
|
123
|
+
}
|
|
124
|
+
break
|
|
125
|
+
}
|
|
82
126
|
default: {
|
|
83
127
|
reader.skipType(tag & 7)
|
|
84
128
|
break
|
|
85
129
|
}
|
|
86
130
|
}
|
|
87
131
|
}
|
|
132
|
+
|
|
133
|
+
if (prefix !== '.') {
|
|
134
|
+
yield {
|
|
135
|
+
field: prefix.endsWith('.') ? prefix.substring(0, prefix.length - 1) : prefix,
|
|
136
|
+
type: 'end',
|
|
137
|
+
message: 'IPNSPublishMetadata'
|
|
138
|
+
}
|
|
139
|
+
}
|
|
88
140
|
})
|
|
89
141
|
}
|
|
90
142
|
|
|
@@ -92,15 +144,20 @@ export namespace IPNSPublishMetadata {
|
|
|
92
144
|
}
|
|
93
145
|
|
|
94
146
|
export interface IPNSPublishMetadataKeyNameFieldEvent {
|
|
95
|
-
field: '
|
|
147
|
+
field: '.keyName'
|
|
96
148
|
value: string
|
|
97
149
|
}
|
|
98
150
|
|
|
99
151
|
export interface IPNSPublishMetadataLifetimeFieldEvent {
|
|
100
|
-
field: '
|
|
152
|
+
field: '.lifetime'
|
|
101
153
|
value: number
|
|
102
154
|
}
|
|
103
155
|
|
|
156
|
+
export interface IPNSPublishMetadataUpkeepFieldEvent {
|
|
157
|
+
field: '.upkeep'
|
|
158
|
+
value: Upkeep
|
|
159
|
+
}
|
|
160
|
+
|
|
104
161
|
export function encode (obj: Partial<IPNSPublishMetadata>): Uint8Array<ArrayBuffer> {
|
|
105
162
|
return encodeMessage(obj, IPNSPublishMetadata.codec())
|
|
106
163
|
}
|
|
@@ -109,7 +166,7 @@ export namespace IPNSPublishMetadata {
|
|
|
109
166
|
return decodeMessage(buf, IPNSPublishMetadata.codec(), opts)
|
|
110
167
|
}
|
|
111
168
|
|
|
112
|
-
export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<IPNSPublishMetadata>): Generator<IPNSPublishMetadataKeyNameFieldEvent | IPNSPublishMetadataLifetimeFieldEvent> {
|
|
169
|
+
export function stream (buf: Uint8Array | Uint8ArrayList, opts?: DecodeOptions<IPNSPublishMetadata>): Generator<IPNSPublishMetadataKeyNameFieldEvent | IPNSPublishMetadataLifetimeFieldEvent | IPNSPublishMetadataUpkeepFieldEvent> {
|
|
113
170
|
return streamMessage(buf, IPNSPublishMetadata.codec(), opts)
|
|
114
171
|
}
|
|
115
172
|
}
|
package/src/routing/index.ts
CHANGED
|
@@ -6,7 +6,14 @@ import type { AbortOptions } from '@libp2p/interface'
|
|
|
6
6
|
import type { ProgressOptions } from 'progress-events'
|
|
7
7
|
|
|
8
8
|
export interface IPNSRoutingPutOptions extends AbortOptions, ProgressOptions {
|
|
9
|
-
metadata?: IPNSPublishMetadata
|
|
9
|
+
metadata?: Partial<IPNSPublishMetadata>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Overwrite an identical stored record instead of keeping the existing one,
|
|
13
|
+
* re-stamping its local timestamp. Passed on republish/rebroadcast so the
|
|
14
|
+
* record is not re-selected for republishing every cycle.
|
|
15
|
+
*/
|
|
16
|
+
overwrite?: boolean
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
export interface IPNSRoutingGetOptions extends AbortOptions, ProgressOptions {
|
|
@@ -23,6 +30,28 @@ export interface IPNSRouting {
|
|
|
23
30
|
get(routingKey: Uint8Array, options?: IPNSRoutingGetOptions): Promise<Uint8Array>
|
|
24
31
|
}
|
|
25
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Return a printable name for a router, falling back to `CustomRouting()` when
|
|
35
|
+
* the router does not set its own `toString`.
|
|
36
|
+
*/
|
|
37
|
+
export function routerName (router: IPNSRouting): string {
|
|
38
|
+
if (router.toString === Object.prototype.toString) {
|
|
39
|
+
return 'CustomRouting()'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const name = router.toString()
|
|
43
|
+
|
|
44
|
+
if (typeof name !== 'string' || name === '') {
|
|
45
|
+
return 'CustomRouting()'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return name
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isLocalStoreRouting (router: IPNSRouting): boolean {
|
|
52
|
+
return String(router) === 'LocalStoreRouting()'
|
|
53
|
+
}
|
|
54
|
+
|
|
26
55
|
export type { DatastoreProgressEvents }
|
|
27
56
|
export type { HeliaRoutingProgressEvents }
|
|
28
57
|
export type { PubSubProgressEvents }
|
package/src/utils.ts
CHANGED
|
@@ -281,6 +281,25 @@ export function normalizeKey (key?: PublicKey | CID | MultihashDigest | string):
|
|
|
281
281
|
throw new InvalidValueError('Value must be a valid IPNS path starting with /')
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
/**
|
|
285
|
+
* Normalize a key identifier for unpublish: CID/PublicKey/multihash become a
|
|
286
|
+
* MultihashDigest, a keychain key name stays a string.
|
|
287
|
+
*/
|
|
288
|
+
export function normalizeKeyName (keyName: CID<unknown, 0x72> | PublicKey | MultihashDigest | string): MultihashDigest | string {
|
|
289
|
+
// a CID/PublicKey/MultihashDigest is always an IPNS name, let it throw if invalid
|
|
290
|
+
if (typeof keyName !== 'string') {
|
|
291
|
+
return normalizeKey(keyName).digest
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
// a string may be an IPNS name...
|
|
296
|
+
return normalizeKey(keyName).digest
|
|
297
|
+
} catch {
|
|
298
|
+
// ...otherwise treat it as a keychain key name
|
|
299
|
+
return keyName
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
284
303
|
export function validateCborDataMatchesPbData (entry: IPNSEntry, data: IPNSRecordData): void {
|
|
285
304
|
if (!uint8ArrayEquals(data.Value, entry.value ?? new Uint8Array(0))) {
|
|
286
305
|
throw new SignatureVerificationError('Field "value" did not match between protobuf and CBOR')
|
package/src/validator.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import NanoDate from 'timestamp-nano'
|
|
2
|
+
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
2
3
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
3
4
|
import { InvalidEmbeddedPublicKeyError, RecordExpiredError, RecordTooLargeError, SignatureVerificationError, UnsupportedValidityError } from './errors.ts'
|
|
4
5
|
import { IPNSEntry } from './pb/ipns.ts'
|
|
@@ -40,24 +41,7 @@ export async function ipnsValidator (routingKey: Uint8Array, marshalledRecord: U
|
|
|
40
41
|
const data = decodeExtensibleData(record.data)
|
|
41
42
|
const validity = uint8ArrayToString(data.Validity)
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// try to extract public key from routing key
|
|
46
|
-
const routingMultihash = multihashFromIPNSRoutingKey(routingKey)
|
|
47
|
-
|
|
48
|
-
// identity hash
|
|
49
|
-
if (isCodec(routingMultihash, 0x0)) {
|
|
50
|
-
publicKey = await keychain.loadPublicKeyFromProtobuf(routingMultihash.digest, options)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// otherwise try to load key from message
|
|
54
|
-
if (publicKey == null && record.publicKey != null) {
|
|
55
|
-
publicKey = await keychain.loadPublicKeyFromProtobuf(record.publicKey, options)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (publicKey == null) {
|
|
59
|
-
throw new InvalidEmbeddedPublicKeyError('Could not extract public key from IPNS record or routing key')
|
|
60
|
-
}
|
|
44
|
+
const publicKey = await extractPublicKey(routingKey, record, keychain, options)
|
|
61
45
|
|
|
62
46
|
// Validate Signature V2
|
|
63
47
|
let isValid
|
|
@@ -95,6 +79,34 @@ export async function ipnsValidator (routingKey: Uint8Array, marshalledRecord: U
|
|
|
95
79
|
return record
|
|
96
80
|
}
|
|
97
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Extract the public key that signed an IPNS record, either from an
|
|
84
|
+
* identity-hashed routing key or from the key embedded in the record.
|
|
85
|
+
*/
|
|
86
|
+
export async function extractPublicKey (routingKey: Uint8Array, record: IPNSEntry, keychain: Keychain, options?: AbortOptions): Promise<PublicKey> {
|
|
87
|
+
const routingMultihash = multihashFromIPNSRoutingKey(routingKey)
|
|
88
|
+
|
|
89
|
+
// identity hash, the routing key is the public key
|
|
90
|
+
if (isCodec(routingMultihash, 0x0)) {
|
|
91
|
+
return keychain.loadPublicKeyFromProtobuf(routingMultihash.digest, options)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// otherwise the record must embed the public key, and that key must correspond
|
|
95
|
+
// to the routing key, otherwise the record was paired with a routing key it was
|
|
96
|
+
// not signed for
|
|
97
|
+
if (record.publicKey != null) {
|
|
98
|
+
const publicKey = await keychain.loadPublicKeyFromProtobuf(record.publicKey, options)
|
|
99
|
+
|
|
100
|
+
if (!uint8ArrayEquals(publicKey.toMultihash().bytes, routingMultihash.bytes)) {
|
|
101
|
+
throw new InvalidEmbeddedPublicKeyError('Embedded public key does not match the routing key')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return publicKey
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new InvalidEmbeddedPublicKeyError('Could not extract public key from IPNS record or routing key')
|
|
108
|
+
}
|
|
109
|
+
|
|
98
110
|
/**
|
|
99
111
|
* Returns the number of milliseconds until the record expires.
|
|
100
112
|
* If the record is already expired, returns 0.
|
package/dist/typedoc-urls.json
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"codec": "https://ipfs.github.io/helia/functions/_helia_ipns.IPNSEntry.ValidityType.codec.html",
|
|
3
|
-
"ValidityType": "https://ipfs.github.io/helia/enums/_helia_ipns.IPNSEntry.ValidityType.html",
|
|
4
|
-
"IPNSEntryDataFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryDataFieldEvent.html",
|
|
5
|
-
"IPNSEntryPublicKeyFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryPublicKeyFieldEvent.html",
|
|
6
|
-
"IPNSEntrySequenceFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntrySequenceFieldEvent.html",
|
|
7
|
-
"IPNSEntrySignatureV1FieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntrySignatureV1FieldEvent.html",
|
|
8
|
-
"IPNSEntrySignatureV2FieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntrySignatureV2FieldEvent.html",
|
|
9
|
-
"IPNSEntryTtlFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryTtlFieldEvent.html",
|
|
10
|
-
"IPNSEntryValidityFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryValidityFieldEvent.html",
|
|
11
|
-
"IPNSEntryValidityTypeFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryValidityTypeFieldEvent.html",
|
|
12
|
-
"IPNSEntryValueFieldEvent": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.IPNSEntryValueFieldEvent.html",
|
|
13
|
-
"decode": "https://ipfs.github.io/helia/functions/_helia_ipns.IPNSEntry.decode.html",
|
|
14
|
-
"encode": "https://ipfs.github.io/helia/functions/_helia_ipns.IPNSEntry.encode.html",
|
|
15
|
-
"stream": "https://ipfs.github.io/helia/functions/_helia_ipns.IPNSEntry.stream.html",
|
|
16
|
-
"CreateIPNSRecordOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.CreateIPNSRecordOptions.html",
|
|
17
|
-
"IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNS.html",
|
|
18
|
-
".:IPNS": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNS.html",
|
|
19
|
-
"IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSComponents.html",
|
|
20
|
-
".:IPNSComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSComponents.html",
|
|
21
|
-
"IPNSEntry": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSEntry.html",
|
|
22
|
-
"IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSOptions.html",
|
|
23
|
-
".:IPNSOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSOptions.html",
|
|
24
|
-
"IPNSPublishResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSPublishResult.html",
|
|
25
|
-
".:IPNSPublishResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSPublishResult.html",
|
|
26
|
-
"IPNSRecordData": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSRecordData.html",
|
|
27
|
-
".:IPNSRecordData": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSRecordData.html",
|
|
28
|
-
"IPNSResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolveOptions.html",
|
|
29
|
-
".:IPNSResolveOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolveOptions.html",
|
|
30
|
-
"IPNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolver.html",
|
|
31
|
-
".:IPNSResolver": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolver.html",
|
|
32
|
-
"IPNSResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolveResult.html",
|
|
33
|
-
".:IPNSResolveResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolveResult.html",
|
|
34
|
-
"IPNSResolverOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolverOptions.html",
|
|
35
|
-
".:IPNSResolverOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSResolverOptions.html",
|
|
36
|
-
"IPNSRouting": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSRouting.html",
|
|
37
|
-
"IPNSRoutingGetOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSRoutingGetOptions.html",
|
|
38
|
-
"IPNSRoutingPutOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.IPNSRoutingPutOptions.html",
|
|
39
|
-
"PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PublishOptions.html",
|
|
40
|
-
".:PublishOptions": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PublishOptions.html",
|
|
41
|
-
"PublishResult": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PublishResult.html",
|
|
42
|
-
"PubSub": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubSub.html",
|
|
43
|
-
"PubSubEvents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubSubEvents.html",
|
|
44
|
-
"PubSubMessage": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubSubMessage.html",
|
|
45
|
-
"PubsubRoutingComponents": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubsubRoutingComponents.html",
|
|
46
|
-
"PubSubSubscription": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubSubSubscription.html",
|
|
47
|
-
"PubSubSubscriptionChangeData": "https://ipfs.github.io/helia/interfaces/_helia_ipns.PubSubSubscriptionChangeData.html",
|
|
48
|
-
"DatastoreProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.DatastoreProgressEvents.html",
|
|
49
|
-
".:DatastoreProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.DatastoreProgressEvents.html",
|
|
50
|
-
"HeliaRoutingProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.HeliaRoutingProgressEvents.html",
|
|
51
|
-
"IPNSRoutingProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.IPNSRoutingProgressEvents.html",
|
|
52
|
-
"PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.PublishProgressEvents.html",
|
|
53
|
-
".:PublishProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.PublishProgressEvents.html",
|
|
54
|
-
"PubSubProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.PubSubProgressEvents.html",
|
|
55
|
-
"ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.ResolveProgressEvents.html",
|
|
56
|
-
".:ResolveProgressEvents": "https://ipfs.github.io/helia/types/_helia_ipns.ResolveProgressEvents.html",
|
|
57
|
-
"createIPNSRecord": "https://ipfs.github.io/helia/functions/_helia_ipns.createIPNSRecord.html",
|
|
58
|
-
"heliaIPNSRouting": "https://ipfs.github.io/helia/functions/_helia_ipns.heliaIPNSRouting.html",
|
|
59
|
-
"ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.ipns.html",
|
|
60
|
-
".:ipns": "https://ipfs.github.io/helia/functions/_helia_ipns.ipns.html",
|
|
61
|
-
"ipnsResolver": "https://ipfs.github.io/helia/functions/_helia_ipns.ipnsResolver.html",
|
|
62
|
-
".:ipnsResolver": "https://ipfs.github.io/helia/functions/_helia_ipns.ipnsResolver.html",
|
|
63
|
-
"ipnsSelector": "https://ipfs.github.io/helia/functions/_helia_ipns.ipnsSelector.html",
|
|
64
|
-
"ipnsValidator": "https://ipfs.github.io/helia/functions/_helia_ipns.ipnsValidator.html",
|
|
65
|
-
"multihashFromIPNSRoutingKey": "https://ipfs.github.io/helia/functions/_helia_ipns.multihashFromIPNSRoutingKey.html",
|
|
66
|
-
"multihashToIPNSRoutingKey": "https://ipfs.github.io/helia/functions/_helia_ipns.multihashToIPNSRoutingKey.html",
|
|
67
|
-
"pubSubIPNSRouting": "https://ipfs.github.io/helia/functions/_helia_ipns.pubSubIPNSRouting.html"
|
|
68
|
-
}
|