@libp2p/peer-record 6.0.6-f9d1c072 → 6.0.7-346ff5a2
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 +38 -57
- package/dist/src/index.d.ts +134 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +134 -0
- package/dist/src/index.js.map +1 -1
- package/package.json +6 -6
- package/src/index.ts +135 -0
package/README.md
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# @libp2p/peer-record <!-- omit in toc -->
|
|
2
|
-
|
|
3
1
|
[](http://libp2p.io/)
|
|
4
2
|
[](https://discuss.libp2p.io)
|
|
5
3
|
[](https://codecov.io/gh/libp2p/js-libp2p)
|
|
@@ -7,44 +5,11 @@
|
|
|
7
5
|
|
|
8
6
|
> Used to transfer signed peer data across the network
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- [Install](#install)
|
|
13
|
-
- [Browser `<script>` tag](#browser-script-tag)
|
|
14
|
-
- [Description](#description)
|
|
15
|
-
- [Envelope](#envelope)
|
|
16
|
-
- [Usage](#usage)
|
|
17
|
-
- [Peer Record](#peer-record)
|
|
18
|
-
- [Usage](#usage-1)
|
|
19
|
-
- [Libp2p Flows](#libp2p-flows)
|
|
20
|
-
- [Self Record](#self-record)
|
|
21
|
-
- [Self record Updates](#self-record-updates)
|
|
22
|
-
- [Subsystem receiving a record](#subsystem-receiving-a-record)
|
|
23
|
-
- [Subsystem providing a record](#subsystem-providing-a-record)
|
|
24
|
-
- [Future Work](#future-work)
|
|
25
|
-
- [API Docs](#api-docs)
|
|
26
|
-
- [License](#license)
|
|
27
|
-
- [Contribution](#contribution)
|
|
28
|
-
|
|
29
|
-
## Install
|
|
30
|
-
|
|
31
|
-
```console
|
|
32
|
-
$ npm i @libp2p/peer-record
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Browser `<script>` tag
|
|
36
|
-
|
|
37
|
-
Loading this module through a script tag will make it's exports available as `Libp2pPeerRecord` in the global namespace.
|
|
38
|
-
|
|
39
|
-
```html
|
|
40
|
-
<script src="https://unpkg.com/@libp2p/peer-record/dist/index.min.js"></script>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Description
|
|
8
|
+
# About
|
|
44
9
|
|
|
45
10
|
Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with.
|
|
46
11
|
|
|
47
|
-
|
|
12
|
+
## Envelope
|
|
48
13
|
|
|
49
14
|
Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified.
|
|
50
15
|
|
|
@@ -52,9 +17,9 @@ This envelope stores a marshaled record implementing the [interface-record](http
|
|
|
52
17
|
|
|
53
18
|
You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
54
19
|
|
|
55
|
-
##
|
|
20
|
+
## Example
|
|
56
21
|
|
|
57
|
-
|
|
22
|
+
Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged:
|
|
58
23
|
|
|
59
24
|
```js
|
|
60
25
|
// interface-record implementation example with the "libp2p-example" namespace
|
|
@@ -83,7 +48,9 @@ const e = await PeerEnvelope.seal(rec, peerId)
|
|
|
83
48
|
const wireData = e.marshal()
|
|
84
49
|
```
|
|
85
50
|
|
|
86
|
-
|
|
51
|
+
## Example
|
|
52
|
+
|
|
53
|
+
Consume a received envelope (`wireData`) and transform it back to a record:
|
|
87
54
|
|
|
88
55
|
```js
|
|
89
56
|
import { PeerEnvelope } from '@libp2p/peer-record'
|
|
@@ -109,9 +76,9 @@ A peer record contains the peers' publicly reachable listen addresses, and may b
|
|
|
109
76
|
|
|
110
77
|
You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
111
78
|
|
|
112
|
-
|
|
79
|
+
## Example
|
|
113
80
|
|
|
114
|
-
|
|
81
|
+
Create a new Peer Record
|
|
115
82
|
|
|
116
83
|
```js
|
|
117
84
|
import { PeerRecord } from '@libp2p/peer-record'
|
|
@@ -122,7 +89,9 @@ const pr = new PeerRecord({
|
|
|
122
89
|
})
|
|
123
90
|
```
|
|
124
91
|
|
|
125
|
-
|
|
92
|
+
## Example
|
|
93
|
+
|
|
94
|
+
Create a Peer Record from a protobuf
|
|
126
95
|
|
|
127
96
|
```js
|
|
128
97
|
import { PeerRecord } from '@libp2p/peer-record'
|
|
@@ -130,23 +99,21 @@ import { PeerRecord } from '@libp2p/peer-record'
|
|
|
130
99
|
const pr = PeerRecord.createFromProtobuf(data)
|
|
131
100
|
```
|
|
132
101
|
|
|
133
|
-
|
|
102
|
+
## Libp2p Flows
|
|
134
103
|
|
|
135
|
-
|
|
104
|
+
### Self Record
|
|
136
105
|
|
|
137
106
|
Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created.
|
|
138
107
|
|
|
139
108
|
The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers.
|
|
140
109
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
***NOT\_YET\_IMPLEMENTED***
|
|
110
|
+
### Self record Updates
|
|
144
111
|
|
|
145
112
|
While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT.
|
|
146
113
|
|
|
147
114
|
When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers.
|
|
148
115
|
|
|
149
|
-
|
|
116
|
+
### Subsystem receiving a record
|
|
150
117
|
|
|
151
118
|
Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record.
|
|
152
119
|
|
|
@@ -154,34 +121,48 @@ Once a record is received and its signature properly validated, its envelope is
|
|
|
154
121
|
|
|
155
122
|
The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer.
|
|
156
123
|
|
|
157
|
-
|
|
124
|
+
### Subsystem providing a record
|
|
158
125
|
|
|
159
126
|
Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer.
|
|
160
127
|
|
|
161
128
|
When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook.
|
|
162
129
|
|
|
163
|
-
|
|
130
|
+
## Future Work
|
|
164
131
|
|
|
165
132
|
- Persistence only considering certified addresses?
|
|
166
133
|
- Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses.
|
|
167
134
|
- A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid.
|
|
168
135
|
- Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet.
|
|
169
136
|
- Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
137
|
+
- Modular dialer? (taken from go PR notes)
|
|
138
|
+
- With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline.
|
|
139
|
+
- Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials.
|
|
140
|
+
|
|
141
|
+
# Install
|
|
142
|
+
|
|
143
|
+
```console
|
|
144
|
+
$ npm i @libp2p/peer-record
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Browser `<script>` tag
|
|
148
|
+
|
|
149
|
+
Loading this module through a script tag will make it's exports available as `Libp2pPeerRecord` in the global namespace.
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<script src="https://unpkg.com/@libp2p/peer-record/dist/index.min.js"></script>
|
|
153
|
+
```
|
|
173
154
|
|
|
174
|
-
|
|
155
|
+
# API Docs
|
|
175
156
|
|
|
176
157
|
- <https://libp2p.github.io/js-libp2p/modules/_libp2p_peer_record.html>
|
|
177
158
|
|
|
178
|
-
|
|
159
|
+
# License
|
|
179
160
|
|
|
180
161
|
Licensed under either of
|
|
181
162
|
|
|
182
163
|
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
|
|
183
164
|
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
|
|
184
165
|
|
|
185
|
-
|
|
166
|
+
# Contribution
|
|
186
167
|
|
|
187
168
|
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with.
|
|
5
|
+
*
|
|
6
|
+
* ## Envelope
|
|
7
|
+
*
|
|
8
|
+
* Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified.
|
|
9
|
+
*
|
|
10
|
+
* This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers.
|
|
11
|
+
*
|
|
12
|
+
* You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
*
|
|
16
|
+
* Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged:
|
|
17
|
+
*
|
|
18
|
+
* ```js
|
|
19
|
+
* // interface-record implementation example with the "libp2p-example" namespace
|
|
20
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
21
|
+
* import { fromString } from 'uint8arrays/from-string'
|
|
22
|
+
*
|
|
23
|
+
* class ExampleRecord extends PeerRecord {
|
|
24
|
+
* constructor () {
|
|
25
|
+
* super ('libp2p-example', fromString('0302', 'hex'))
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* marshal () {}
|
|
29
|
+
*
|
|
30
|
+
* equals (other) {}
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* ExampleRecord.createFromProtobuf = () => {}
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ```js
|
|
37
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
38
|
+
* import { ExampleRecord } from './example-record.js'
|
|
39
|
+
*
|
|
40
|
+
* const rec = new ExampleRecord()
|
|
41
|
+
* const e = await PeerEnvelope.seal(rec, peerId)
|
|
42
|
+
* const wireData = e.marshal()
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
*
|
|
47
|
+
* Consume a received envelope (`wireData`) and transform it back to a record:
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
51
|
+
* import { ExampleRecord } from './example-record.js'
|
|
52
|
+
*
|
|
53
|
+
* const domain = 'libp2p-example'
|
|
54
|
+
* let e
|
|
55
|
+
*
|
|
56
|
+
* try {
|
|
57
|
+
* e = await PeerEnvelope.openAndCertify(wireData, domain)
|
|
58
|
+
* } catch (err) {}
|
|
59
|
+
*
|
|
60
|
+
* const rec = ExampleRecord.createFromProtobuf(e.payload)
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## Peer Record
|
|
64
|
+
*
|
|
65
|
+
* All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources.
|
|
66
|
+
*
|
|
67
|
+
* Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing).
|
|
68
|
+
*
|
|
69
|
+
* A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record.
|
|
70
|
+
*
|
|
71
|
+
* You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
*
|
|
75
|
+
* Create a new Peer Record
|
|
76
|
+
*
|
|
77
|
+
* ```js
|
|
78
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
79
|
+
*
|
|
80
|
+
* const pr = new PeerRecord({
|
|
81
|
+
* peerId: node.peerId,
|
|
82
|
+
* multiaddrs: node.multiaddrs
|
|
83
|
+
* })
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
*
|
|
88
|
+
* Create a Peer Record from a protobuf
|
|
89
|
+
*
|
|
90
|
+
* ```js
|
|
91
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
92
|
+
*
|
|
93
|
+
* const pr = PeerRecord.createFromProtobuf(data)
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* ## Libp2p Flows
|
|
97
|
+
*
|
|
98
|
+
* ### Self Record
|
|
99
|
+
*
|
|
100
|
+
* Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created.
|
|
101
|
+
*
|
|
102
|
+
* The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers.
|
|
103
|
+
*
|
|
104
|
+
* ### Self record Updates
|
|
105
|
+
*
|
|
106
|
+
* While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT.
|
|
107
|
+
*
|
|
108
|
+
* When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers.
|
|
109
|
+
*
|
|
110
|
+
* ### Subsystem receiving a record
|
|
111
|
+
*
|
|
112
|
+
* Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record.
|
|
113
|
+
*
|
|
114
|
+
* Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record.
|
|
115
|
+
*
|
|
116
|
+
* The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer.
|
|
117
|
+
*
|
|
118
|
+
* ### Subsystem providing a record
|
|
119
|
+
*
|
|
120
|
+
* Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer.
|
|
121
|
+
*
|
|
122
|
+
* When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook.
|
|
123
|
+
*
|
|
124
|
+
* ## Future Work
|
|
125
|
+
*
|
|
126
|
+
* - Persistence only considering certified addresses?
|
|
127
|
+
* - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses.
|
|
128
|
+
* - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid.
|
|
129
|
+
* - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet.
|
|
130
|
+
* - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin.
|
|
131
|
+
* - Modular dialer? (taken from go PR notes)
|
|
132
|
+
* - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline.
|
|
133
|
+
* - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials.
|
|
134
|
+
*/
|
|
1
135
|
export { RecordEnvelope } from './envelope/index.js';
|
|
2
136
|
export type { RecordEnvelopeInit } from './envelope/index.js';
|
|
3
137
|
export { PeerRecord } from './peer-record/index.js';
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with.
|
|
5
|
+
*
|
|
6
|
+
* ## Envelope
|
|
7
|
+
*
|
|
8
|
+
* Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified.
|
|
9
|
+
*
|
|
10
|
+
* This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers.
|
|
11
|
+
*
|
|
12
|
+
* You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
*
|
|
16
|
+
* Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged:
|
|
17
|
+
*
|
|
18
|
+
* ```js
|
|
19
|
+
* // interface-record implementation example with the "libp2p-example" namespace
|
|
20
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
21
|
+
* import { fromString } from 'uint8arrays/from-string'
|
|
22
|
+
*
|
|
23
|
+
* class ExampleRecord extends PeerRecord {
|
|
24
|
+
* constructor () {
|
|
25
|
+
* super ('libp2p-example', fromString('0302', 'hex'))
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* marshal () {}
|
|
29
|
+
*
|
|
30
|
+
* equals (other) {}
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* ExampleRecord.createFromProtobuf = () => {}
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ```js
|
|
37
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
38
|
+
* import { ExampleRecord } from './example-record.js'
|
|
39
|
+
*
|
|
40
|
+
* const rec = new ExampleRecord()
|
|
41
|
+
* const e = await PeerEnvelope.seal(rec, peerId)
|
|
42
|
+
* const wireData = e.marshal()
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
*
|
|
47
|
+
* Consume a received envelope (`wireData`) and transform it back to a record:
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
51
|
+
* import { ExampleRecord } from './example-record.js'
|
|
52
|
+
*
|
|
53
|
+
* const domain = 'libp2p-example'
|
|
54
|
+
* let e
|
|
55
|
+
*
|
|
56
|
+
* try {
|
|
57
|
+
* e = await PeerEnvelope.openAndCertify(wireData, domain)
|
|
58
|
+
* } catch (err) {}
|
|
59
|
+
*
|
|
60
|
+
* const rec = ExampleRecord.createFromProtobuf(e.payload)
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## Peer Record
|
|
64
|
+
*
|
|
65
|
+
* All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources.
|
|
66
|
+
*
|
|
67
|
+
* Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing).
|
|
68
|
+
*
|
|
69
|
+
* A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record.
|
|
70
|
+
*
|
|
71
|
+
* You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
*
|
|
75
|
+
* Create a new Peer Record
|
|
76
|
+
*
|
|
77
|
+
* ```js
|
|
78
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
79
|
+
*
|
|
80
|
+
* const pr = new PeerRecord({
|
|
81
|
+
* peerId: node.peerId,
|
|
82
|
+
* multiaddrs: node.multiaddrs
|
|
83
|
+
* })
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
*
|
|
88
|
+
* Create a Peer Record from a protobuf
|
|
89
|
+
*
|
|
90
|
+
* ```js
|
|
91
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
92
|
+
*
|
|
93
|
+
* const pr = PeerRecord.createFromProtobuf(data)
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* ## Libp2p Flows
|
|
97
|
+
*
|
|
98
|
+
* ### Self Record
|
|
99
|
+
*
|
|
100
|
+
* Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created.
|
|
101
|
+
*
|
|
102
|
+
* The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers.
|
|
103
|
+
*
|
|
104
|
+
* ### Self record Updates
|
|
105
|
+
*
|
|
106
|
+
* While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT.
|
|
107
|
+
*
|
|
108
|
+
* When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers.
|
|
109
|
+
*
|
|
110
|
+
* ### Subsystem receiving a record
|
|
111
|
+
*
|
|
112
|
+
* Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record.
|
|
113
|
+
*
|
|
114
|
+
* Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record.
|
|
115
|
+
*
|
|
116
|
+
* The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer.
|
|
117
|
+
*
|
|
118
|
+
* ### Subsystem providing a record
|
|
119
|
+
*
|
|
120
|
+
* Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer.
|
|
121
|
+
*
|
|
122
|
+
* When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook.
|
|
123
|
+
*
|
|
124
|
+
* ## Future Work
|
|
125
|
+
*
|
|
126
|
+
* - Persistence only considering certified addresses?
|
|
127
|
+
* - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses.
|
|
128
|
+
* - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid.
|
|
129
|
+
* - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet.
|
|
130
|
+
* - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin.
|
|
131
|
+
* - Modular dialer? (taken from go PR notes)
|
|
132
|
+
* - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline.
|
|
133
|
+
* - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials.
|
|
134
|
+
*/
|
|
1
135
|
export { RecordEnvelope } from './envelope/index.js';
|
|
2
136
|
export { PeerRecord } from './peer-record/index.js';
|
|
3
137
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/peer-record",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.7-346ff5a2",
|
|
4
4
|
"description": "Used to transfer signed peer data across the network",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/peer-record#readme",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"test:electron-main": "aegir test -t electron-main"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@libp2p/crypto": "2.0.
|
|
60
|
-
"@libp2p/interface": "0.1.
|
|
61
|
-
"@libp2p/peer-id": "3.0.
|
|
62
|
-
"@libp2p/utils": "4.0.
|
|
59
|
+
"@libp2p/crypto": "2.0.6-346ff5a2",
|
|
60
|
+
"@libp2p/interface": "0.1.4-346ff5a2",
|
|
61
|
+
"@libp2p/peer-id": "3.0.4-346ff5a2",
|
|
62
|
+
"@libp2p/utils": "4.0.5-346ff5a2",
|
|
63
63
|
"@multiformats/multiaddr": "^12.1.5",
|
|
64
64
|
"protons-runtime": "^5.0.0",
|
|
65
65
|
"uint8-varint": "^2.0.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"uint8arrays": "^4.0.6"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@libp2p/peer-id-factory": "3.0.
|
|
70
|
+
"@libp2p/peer-id-factory": "3.0.6-346ff5a2",
|
|
71
71
|
"aegir": "^41.0.2",
|
|
72
72
|
"protons": "^7.0.2"
|
|
73
73
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,3 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
*
|
|
4
|
+
* Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with.
|
|
5
|
+
*
|
|
6
|
+
* ## Envelope
|
|
7
|
+
*
|
|
8
|
+
* Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified.
|
|
9
|
+
*
|
|
10
|
+
* This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers.
|
|
11
|
+
*
|
|
12
|
+
* You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
*
|
|
16
|
+
* Create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged:
|
|
17
|
+
*
|
|
18
|
+
* ```js
|
|
19
|
+
* // interface-record implementation example with the "libp2p-example" namespace
|
|
20
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
21
|
+
* import { fromString } from 'uint8arrays/from-string'
|
|
22
|
+
*
|
|
23
|
+
* class ExampleRecord extends PeerRecord {
|
|
24
|
+
* constructor () {
|
|
25
|
+
* super ('libp2p-example', fromString('0302', 'hex'))
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* marshal () {}
|
|
29
|
+
*
|
|
30
|
+
* equals (other) {}
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* ExampleRecord.createFromProtobuf = () => {}
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* ```js
|
|
37
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
38
|
+
* import { ExampleRecord } from './example-record.js'
|
|
39
|
+
*
|
|
40
|
+
* const rec = new ExampleRecord()
|
|
41
|
+
* const e = await PeerEnvelope.seal(rec, peerId)
|
|
42
|
+
* const wireData = e.marshal()
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
*
|
|
47
|
+
* Consume a received envelope (`wireData`) and transform it back to a record:
|
|
48
|
+
*
|
|
49
|
+
* ```js
|
|
50
|
+
* import { PeerEnvelope } from '@libp2p/peer-record'
|
|
51
|
+
* import { ExampleRecord } from './example-record.js'
|
|
52
|
+
*
|
|
53
|
+
* const domain = 'libp2p-example'
|
|
54
|
+
* let e
|
|
55
|
+
*
|
|
56
|
+
* try {
|
|
57
|
+
* e = await PeerEnvelope.openAndCertify(wireData, domain)
|
|
58
|
+
* } catch (err) {}
|
|
59
|
+
*
|
|
60
|
+
* const rec = ExampleRecord.createFromProtobuf(e.payload)
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* ## Peer Record
|
|
64
|
+
*
|
|
65
|
+
* All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources.
|
|
66
|
+
*
|
|
67
|
+
* Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing).
|
|
68
|
+
*
|
|
69
|
+
* A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record.
|
|
70
|
+
*
|
|
71
|
+
* You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217).
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
*
|
|
75
|
+
* Create a new Peer Record
|
|
76
|
+
*
|
|
77
|
+
* ```js
|
|
78
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
79
|
+
*
|
|
80
|
+
* const pr = new PeerRecord({
|
|
81
|
+
* peerId: node.peerId,
|
|
82
|
+
* multiaddrs: node.multiaddrs
|
|
83
|
+
* })
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
*
|
|
88
|
+
* Create a Peer Record from a protobuf
|
|
89
|
+
*
|
|
90
|
+
* ```js
|
|
91
|
+
* import { PeerRecord } from '@libp2p/peer-record'
|
|
92
|
+
*
|
|
93
|
+
* const pr = PeerRecord.createFromProtobuf(data)
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* ## Libp2p Flows
|
|
97
|
+
*
|
|
98
|
+
* ### Self Record
|
|
99
|
+
*
|
|
100
|
+
* Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created.
|
|
101
|
+
*
|
|
102
|
+
* The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers.
|
|
103
|
+
*
|
|
104
|
+
* ### Self record Updates
|
|
105
|
+
*
|
|
106
|
+
* While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT.
|
|
107
|
+
*
|
|
108
|
+
* When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers.
|
|
109
|
+
*
|
|
110
|
+
* ### Subsystem receiving a record
|
|
111
|
+
*
|
|
112
|
+
* Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record.
|
|
113
|
+
*
|
|
114
|
+
* Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record.
|
|
115
|
+
*
|
|
116
|
+
* The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer.
|
|
117
|
+
*
|
|
118
|
+
* ### Subsystem providing a record
|
|
119
|
+
*
|
|
120
|
+
* Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer.
|
|
121
|
+
*
|
|
122
|
+
* When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook.
|
|
123
|
+
*
|
|
124
|
+
* ## Future Work
|
|
125
|
+
*
|
|
126
|
+
* - Persistence only considering certified addresses?
|
|
127
|
+
* - Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses.
|
|
128
|
+
* - A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid.
|
|
129
|
+
* - Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet.
|
|
130
|
+
* - Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin.
|
|
131
|
+
* - Modular dialer? (taken from go PR notes)
|
|
132
|
+
* - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline.
|
|
133
|
+
* - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials.
|
|
134
|
+
*/
|
|
135
|
+
|
|
1
136
|
export { RecordEnvelope } from './envelope/index.js'
|
|
2
137
|
export type { RecordEnvelopeInit } from './envelope/index.js'
|
|
3
138
|
export { PeerRecord } from './peer-record/index.js'
|