@@ -12,38 +12,35 @@ const uint8ArrayToString = require('uint8arrays/to-string')
12
12
const uint8ArrayConcat = require ( 'uint8arrays/concat' )
13
13
14
14
const debug = require ( 'debug' )
15
- const log = debug ( 'jsipns' )
16
- log . error = debug ( 'jsipns:error' )
15
+ const log = Object . assign ( debug ( 'jsipns' ) , {
16
+ error : debug ( 'jsipns:error' )
17
+ } )
17
18
18
- const ipnsEntryProto = require ( './pb/ipns.proto' )
19
+ const {
20
+ IpnsEntry : ipnsEntryProto
21
+ } = require ( './pb/ipns.js' )
19
22
const { parseRFC3339 } = require ( './utils' )
20
23
const ERRORS = require ( './errors' )
21
24
22
- const ID_MULTIHASH_CODE = multihash . names . id
25
+ const ID_MULTIHASH_CODE = multihash . names . identity
23
26
24
27
const namespace = '/ipns/'
25
28
26
29
/**
27
- * IPNS entry
28
- *
29
- * @typedef {Object } IpnsEntry
30
- * @property {string } value - value to be stored in the record
31
- * @property {Uint8Array } signature - signature of the record
32
- * @property {number } validityType - Type of validation being used
33
- * @property {string } validity - expiration datetime for the record in RFC3339 format
34
- * @property {number } sequence - number representing the version of the record
30
+ * @typedef {import('./types').IPNSEntry } IPNSEntry
31
+ * @typedef {import('libp2p-crypto').PublicKey } PublicKey
32
+ * @typedef {import('libp2p-crypto').PrivateKey } PrivateKey
35
33
*/
36
34
37
35
/**
38
36
* Creates a new ipns entry and signs it with the given private key.
39
37
* The ipns entry validity should follow the [RFC3339]{@link https://www.ietf.org/rfc/rfc3339.txt} with nanoseconds precision.
40
38
* Note: This function does not embed the public key. If you want to do that, use `EmbedPublicKey`.
41
39
*
42
- * @param {Object } privateKey - private key for signing the record.
40
+ * @param {PrivateKey } privateKey - private key for signing the record.
43
41
* @param {string } value - value to be stored in the record.
44
42
* @param {number } seq - number representing the current version of the record.
45
43
* @param {number|string } lifetime - lifetime of the record (in milliseconds).
46
- * @returns {Promise<IpnsEntry> } entry
47
44
*/
48
45
const create = ( privateKey , value , seq , lifetime ) => {
49
46
// Validity in ISOString with nanoseconds precision and validity type EOL
@@ -56,17 +53,23 @@ const create = (privateKey, value, seq, lifetime) => {
56
53
* Same as create(), but instead of generating a new Date, it receives the intended expiration time
57
54
* WARNING: nano precision is not standard, make sure the value in seconds is 9 orders of magnitude lesser than the one provided.
58
55
*
59
- * @param {Object } privateKey - private key for signing the record.
56
+ * @param {PrivateKey } privateKey - private key for signing the record.
60
57
* @param {string } value - value to be stored in the record.
61
58
* @param {number } seq - number representing the current version of the record.
62
59
* @param {string } expiration - expiration datetime for record in the [RFC3339]{@link https://www.ietf.org/rfc/rfc3339.txt} with nanoseconds precision.
63
- * @returns {Promise<IpnsEntry> } entry
64
60
*/
65
61
const createWithExpiration = ( privateKey , value , seq , expiration ) => {
66
62
const validityType = ipnsEntryProto . ValidityType . EOL
67
63
return _create ( privateKey , value , seq , expiration , validityType )
68
64
}
69
65
66
+ /**
67
+ * @param {PrivateKey } privateKey
68
+ * @param {string } value
69
+ * @param {number } seq
70
+ * @param {string } isoValidity
71
+ * @param {number } validityType
72
+ */
70
73
const _create = async ( privateKey , value , seq , isoValidity , validityType ) => {
71
74
const signature = await sign ( privateKey , value , validityType , isoValidity )
72
75
@@ -85,9 +88,8 @@ const _create = async (privateKey, value, seq, isoValidity, validityType) => {
85
88
/**
86
89
* Validates the given ipns entry against the given public key.
87
90
*
88
- * @param {Object } publicKey - public key for validating the record.
89
- * @param {IpnsEntry } entry - ipns entry record.
90
- * @returns {Promise }
91
+ * @param {PublicKey } publicKey - public key for validating the record.
92
+ * @param {IPNSEntry } entry - ipns entry record.
91
93
*/
92
94
const validate = async ( publicKey , entry ) => {
93
95
const { value, validityType, validity } = entry
@@ -116,7 +118,7 @@ const validate = async (publicKey, entry) => {
116
118
throw errCode ( new Error ( 'unrecognized validity format (not an rfc3339 format)' ) , ERRORS . ERR_UNRECOGNIZED_FORMAT )
117
119
}
118
120
119
- if ( validityDate < Date . now ( ) ) {
121
+ if ( validityDate . getTime ( ) < Date . now ( ) ) {
120
122
log . error ( 'record has expired' )
121
123
throw errCode ( new Error ( 'record has expired' ) , ERRORS . ERR_IPNS_EXPIRED_RECORD )
122
124
}
@@ -137,9 +139,8 @@ const validate = async (publicKey, entry) => {
137
139
* send this as part of the record itself. For newer ed25519 keys, the public key
138
140
* can be embedded in the peerId.
139
141
*
140
- * @param {Object } publicKey - public key to embed.
141
- * @param {Object } entry - ipns entry record.
142
- * @returns {IpnsEntry } entry with public key embedded
142
+ * @param {PublicKey } publicKey - public key to embed.
143
+ * @param {IPNSEntry } entry - ipns entry record.
143
144
*/
144
145
const embedPublicKey = async ( publicKey , entry ) => {
145
146
if ( ! publicKey || ! publicKey . bytes || ! entry ) {
@@ -182,9 +183,8 @@ const embedPublicKey = async (publicKey, entry) => {
182
183
/**
183
184
* Extracts a public key matching `pid` from the ipns record.
184
185
*
185
- * @param {Object } peerId - peer identifier object.
186
- * @param {IpnsEntry } entry - ipns entry record.
187
- * @returns {Object } the public key
186
+ * @param {PeerId } peerId - peer identifier object.
187
+ * @param {IPNSEntry } entry - ipns entry record.
188
188
*/
189
189
const extractPublicKey = ( peerId , entry ) => {
190
190
if ( ! entry || ! peerId ) {
@@ -211,15 +211,18 @@ const extractPublicKey = (peerId, entry) => {
211
211
throw Object . assign ( new Error ( 'no public key is available' ) , { code : ERRORS . ERR_UNDEFINED_PARAMETER } )
212
212
}
213
213
214
- // rawStdEncoding with RFC4648
214
+ /**
215
+ * rawStdEncoding with RFC4648
216
+ *
217
+ * @param {Uint8Array } key
218
+ */
215
219
const rawStdEncoding = ( key ) => multibase . encode ( 'base32' , key ) . toString ( ) . slice ( 1 ) . toUpperCase ( )
216
220
217
221
/**
218
222
* Get key for storing the record locally.
219
223
* Format: /ipns/${base32(<HASH>)}
220
224
*
221
225
* @param {Uint8Array } key - peer identifier object.
222
- * @returns {string }
223
226
*/
224
227
const getLocalKey = ( key ) => new Key ( `/ipns/${ rawStdEncoding ( key ) } ` )
225
228
@@ -228,7 +231,6 @@ const getLocalKey = (key) => new Key(`/ipns/${rawStdEncoding(key)}`)
228
231
* Format: ${base32(/ipns/<HASH>)}, ${base32(/pk/<HASH>)}
229
232
*
230
233
* @param {Uint8Array } pid - peer identifier represented by the multihash of the public key as Uint8Array.
231
- * @returns {Object } containing the `nameKey` and the `ipnsKey`.
232
234
*/
233
235
const getIdKeys = ( pid ) => {
234
236
const pkBuffer = uint8ArrayFromString ( '/pk/' )
@@ -242,7 +244,14 @@ const getIdKeys = (pid) => {
242
244
}
243
245
}
244
246
245
- // Sign ipns record data
247
+ /**
248
+ * Sign ipns record data
249
+ *
250
+ * @param {PrivateKey } privateKey
251
+ * @param {string } value
252
+ * @param {number } validityType
253
+ * @param {Uint8Array | string } validity
254
+ */
246
255
const sign = ( privateKey , value , validityType , validity ) => {
247
256
try {
248
257
const dataForSignature = ipnsEntryDataForSig ( value , validityType , validity )
@@ -254,7 +263,11 @@ const sign = (privateKey, value, validityType, validity) => {
254
263
}
255
264
}
256
265
257
- // Utility for getting the validity type code name of a validity
266
+ /**
267
+ * Utility for getting the validity type code name of a validity
268
+ *
269
+ * @param {number } validityType
270
+ */
258
271
const getValidityType = ( validityType ) => {
259
272
if ( validityType . toString ( ) === '0' ) {
260
273
return 'EOL'
@@ -265,7 +278,13 @@ const getValidityType = (validityType) => {
265
278
throw errCode ( error , ERRORS . ERR_UNRECOGNIZED_VALIDITY )
266
279
}
267
280
268
- // Utility for creating the record data for being signed
281
+ /**
282
+ * Utility for creating the record data for being signed
283
+ *
284
+ * @param {string | Uint8Array } value
285
+ * @param {number } validityType
286
+ * @param {string | Uint8Array } validity
287
+ */
269
288
const ipnsEntryDataForSig = ( value , validityType , validity ) => {
270
289
if ( ! ( value instanceof Uint8Array ) ) {
271
290
value = uint8ArrayFromString ( value )
@@ -280,7 +299,11 @@ const ipnsEntryDataForSig = (value, validityType, validity) => {
280
299
return uint8ArrayConcat ( [ value , validity , validityTypeBuffer ] )
281
300
}
282
301
283
- // Utility for extracting the public key from a peer-id
302
+ /**
303
+ * Utility for extracting the public key from a peer-id
304
+ *
305
+ * @param {PeerId } peerId
306
+ */
284
307
const extractPublicKeyFromId = ( peerId ) => {
285
308
const decodedId = multihash . decode ( peerId . id )
286
309
@@ -291,11 +314,34 @@ const extractPublicKeyFromId = (peerId) => {
291
314
return crypto . keys . unmarshalPublicKey ( decodedId . digest )
292
315
}
293
316
294
- const marshal = ipnsEntryProto . encode
317
+ /**
318
+ * @param {IPNSEntry } obj
319
+ */
320
+ const marshal = ( obj ) => {
321
+ return ipnsEntryProto . encode ( obj ) . finish ( )
322
+ }
295
323
296
- const unmarshal = ipnsEntryProto . decode
324
+ /**
325
+ * @param {Uint8Array } buf
326
+ * @returns {IPNSEntry }
327
+ */
328
+ const unmarshal = ( buf ) => {
329
+ const message = ipnsEntryProto . decode ( buf )
330
+
331
+ // @ts -ignore
332
+ return ipnsEntryProto . toObject ( message , {
333
+ defaults : false ,
334
+ arrays : true ,
335
+ longs : Number ,
336
+ objects : false
337
+ } )
338
+ }
297
339
298
340
const validator = {
341
+ /**
342
+ * @param {Uint8Array } marshalledData
343
+ * @param {Uint8Array } key
344
+ */
299
345
validate : async ( marshalledData , key ) => {
300
346
const receivedEntry = unmarshal ( marshalledData )
301
347
const bufferId = key . slice ( '/ipns/' . length )
@@ -308,6 +354,10 @@ const validator = {
308
354
await validate ( pubKey , receivedEntry )
309
355
return true
310
356
} ,
357
+ /**
358
+ * @param {Uint8Array } dataA
359
+ * @param {Uint8Array } dataB
360
+ */
311
361
select : ( dataA , dataB ) => {
312
362
const entryA = unmarshal ( dataA )
313
363
const entryB = unmarshal ( dataB )
0 commit comments