@libp2p/pubsub 1.2.3 → 1.2.7
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/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +8 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +33 -30
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +192 -128
- package/dist/src/index.js.map +1 -1
- package/dist/src/message/rpc.d.ts +586 -175
- package/dist/src/message/rpc.js +1238 -67
- package/dist/src/message/sign.d.ts +1 -1
- package/dist/src/message/sign.d.ts.map +1 -1
- package/dist/src/message/sign.js +8 -14
- package/dist/src/message/sign.js.map +1 -1
- package/dist/src/peer-streams.d.ts +5 -5
- package/dist/src/peer-streams.d.ts.map +1 -1
- package/dist/src/peer-streams.js +1 -0
- package/dist/src/peer-streams.js.map +1 -1
- package/dist/src/utils.d.ts +6 -9
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +36 -35
- package/dist/src/utils.js.map +1 -1
- package/package.json +7 -10
- package/src/errors.ts +8 -0
- package/src/index.ts +236 -140
- package/src/message/rpc.d.ts +586 -175
- package/src/message/rpc.js +1238 -67
- package/src/message/rpc.proto +38 -4
- package/src/message/sign.ts +10 -16
- package/src/peer-streams.ts +6 -4
- package/src/utils.ts +35 -34
package/src/message/rpc.proto
CHANGED
@@ -2,19 +2,53 @@ syntax = "proto3";
|
|
2
2
|
|
3
3
|
message RPC {
|
4
4
|
repeated SubOpts subscriptions = 1;
|
5
|
-
repeated Message
|
5
|
+
repeated Message messages = 2;
|
6
|
+
optional ControlMessage control = 3;
|
6
7
|
|
7
8
|
message SubOpts {
|
8
9
|
optional bool subscribe = 1; // subscribe or unsubcribe
|
9
|
-
optional string
|
10
|
+
optional string topic = 2;
|
10
11
|
}
|
11
12
|
|
12
13
|
message Message {
|
13
14
|
optional bytes from = 1;
|
14
15
|
optional bytes data = 2;
|
15
16
|
optional bytes seqno = 3;
|
16
|
-
|
17
|
+
optional string topic = 4;
|
17
18
|
optional bytes signature = 5;
|
18
19
|
optional bytes key = 6;
|
19
20
|
}
|
20
|
-
}
|
21
|
+
}
|
22
|
+
|
23
|
+
message ControlMessage {
|
24
|
+
repeated ControlIHave ihave = 1;
|
25
|
+
repeated ControlIWant iwant = 2;
|
26
|
+
repeated ControlGraft graft = 3;
|
27
|
+
repeated ControlPrune prune = 4;
|
28
|
+
}
|
29
|
+
|
30
|
+
message ControlIHave {
|
31
|
+
optional string topicID = 1;
|
32
|
+
// implementors from other languages should use bytes here - go protobuf emits invalid utf8 strings
|
33
|
+
repeated string messageIDs = 2;
|
34
|
+
}
|
35
|
+
|
36
|
+
message ControlIWant {
|
37
|
+
// implementors from other languages should use bytes here - go protobuf emits invalid utf8 strings
|
38
|
+
repeated string messageIDs = 1;
|
39
|
+
}
|
40
|
+
|
41
|
+
message ControlGraft {
|
42
|
+
optional string topicID = 1;
|
43
|
+
}
|
44
|
+
|
45
|
+
message ControlPrune {
|
46
|
+
optional string topicID = 1;
|
47
|
+
repeated PeerInfo peers = 2;
|
48
|
+
optional uint64 backoff = 3;
|
49
|
+
}
|
50
|
+
|
51
|
+
message PeerInfo {
|
52
|
+
optional bytes peerID = 1;
|
53
|
+
optional bytes signedPeerRecord = 2;
|
54
|
+
}
|
package/src/message/sign.ts
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
import * as PeerIdFactory from '@libp2p/peer-id-factory'
|
2
1
|
import { RPC } from './rpc.js'
|
3
2
|
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
|
4
3
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
5
|
-
import {
|
4
|
+
import { toRpcMessage } from '../utils.js'
|
6
5
|
import type { PeerId } from '@libp2p/interfaces/peer-id'
|
7
6
|
import { keys } from '@libp2p/crypto'
|
8
|
-
import { PeerId as PeerIdImpl } from '@libp2p/peer-id'
|
9
7
|
import type { Message } from '@libp2p/interfaces/pubsub'
|
8
|
+
import { peerIdFromKeys } from '@libp2p/peer-id'
|
10
9
|
|
11
10
|
export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:')
|
12
11
|
|
@@ -17,7 +16,7 @@ export async function signMessage (peerId: PeerId, message: Message) {
|
|
17
16
|
// Get the message in bytes, and prepend with the pubsub prefix
|
18
17
|
const bytes = uint8ArrayConcat([
|
19
18
|
SignPrefix,
|
20
|
-
RPC.Message.encode(
|
19
|
+
RPC.Message.encode(toRpcMessage(message)).finish()
|
21
20
|
])
|
22
21
|
|
23
22
|
if (peerId.privateKey == null) {
|
@@ -56,7 +55,7 @@ export async function verifySignature (message: Message) {
|
|
56
55
|
const bytes = uint8ArrayConcat([
|
57
56
|
SignPrefix,
|
58
57
|
RPC.Message.encode({
|
59
|
-
...message,
|
58
|
+
...toRpcMessage(message),
|
60
59
|
signature: undefined,
|
61
60
|
key: undefined
|
62
61
|
}).finish()
|
@@ -72,7 +71,7 @@ export async function verifySignature (message: Message) {
|
|
72
71
|
|
73
72
|
/**
|
74
73
|
* Returns the PublicKey associated with the given message.
|
75
|
-
* If no
|
74
|
+
* If no valid PublicKey can be retrieved an error will be returned.
|
76
75
|
*/
|
77
76
|
export async function messagePublicKey (message: Message) {
|
78
77
|
// should be available in the from property of the message (peer id)
|
@@ -80,21 +79,16 @@ export async function messagePublicKey (message: Message) {
|
|
80
79
|
throw new Error('Could not get the public key from the originator id')
|
81
80
|
}
|
82
81
|
|
83
|
-
const from = PeerIdImpl.fromBytes(message.from)
|
84
|
-
|
85
82
|
if (message.key != null) {
|
86
|
-
const keyPeerId = await
|
87
|
-
|
88
|
-
// the key belongs to the sender, return the key
|
89
|
-
if (!keyPeerId.equals(from)) {
|
90
|
-
throw new Error('Public Key does not match the originator')
|
91
|
-
}
|
83
|
+
const keyPeerId = await peerIdFromKeys(message.key)
|
92
84
|
|
93
85
|
if (keyPeerId.publicKey != null) {
|
94
86
|
return keyPeerId.publicKey
|
95
87
|
}
|
96
|
-
}
|
97
|
-
|
88
|
+
}
|
89
|
+
|
90
|
+
if (message.from.publicKey != null) {
|
91
|
+
return message.from.publicKey
|
98
92
|
}
|
99
93
|
|
100
94
|
// We couldn't validate pubkey is from the originator, error
|
package/src/peer-streams.ts
CHANGED
@@ -25,19 +25,19 @@ export class PeerStreams extends EventEmitter<PeerStreamEvents> {
|
|
25
25
|
/**
|
26
26
|
* Write stream - it's preferable to use the write method
|
27
27
|
*/
|
28
|
-
public outboundStream
|
28
|
+
public outboundStream?: Pushable<Uint8Array>
|
29
29
|
/**
|
30
30
|
* Read stream
|
31
31
|
*/
|
32
|
-
public inboundStream
|
32
|
+
public inboundStream?: AsyncIterable<Uint8Array>
|
33
33
|
/**
|
34
34
|
* The raw outbound stream, as retrieved from conn.newStream
|
35
35
|
*/
|
36
|
-
private _rawOutboundStream
|
36
|
+
private _rawOutboundStream?: Stream
|
37
37
|
/**
|
38
38
|
* The raw inbound stream, as retrieved from the callback from libp2p.handle
|
39
39
|
*/
|
40
|
-
private _rawInboundStream
|
40
|
+
private _rawInboundStream?: Stream
|
41
41
|
/**
|
42
42
|
* An AbortController for controlled shutdown of the inbound stream
|
43
43
|
*/
|
@@ -142,6 +142,8 @@ export class PeerStreams extends EventEmitter<PeerStreamEvents> {
|
|
142
142
|
if (_prevStream == null) {
|
143
143
|
this.dispatchEvent(new CustomEvent('stream:outbound'))
|
144
144
|
}
|
145
|
+
|
146
|
+
return this.outboundStream
|
145
147
|
}
|
146
148
|
|
147
149
|
/**
|
package/src/utils.ts
CHANGED
@@ -1,39 +1,39 @@
|
|
1
1
|
import { randomBytes } from 'iso-random-stream'
|
2
2
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
3
|
-
import {
|
3
|
+
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
4
4
|
import { sha256 } from 'multiformats/hashes/sha2'
|
5
5
|
import type * as RPC from './message/rpc.js'
|
6
|
-
import type { Message } from '@libp2p/interfaces/pubsub'
|
6
|
+
import type { Message, RPCMessage } from '@libp2p/interfaces/pubsub'
|
7
|
+
import { peerIdFromBytes } from '@libp2p/peer-id'
|
8
|
+
import { codes } from './errors.js'
|
9
|
+
import errcode from 'err-code'
|
7
10
|
|
8
11
|
/**
|
9
12
|
* Generate a random sequence number
|
10
13
|
*/
|
11
|
-
export
|
12
|
-
return randomBytes(8)
|
14
|
+
export function randomSeqno (): BigInt {
|
15
|
+
return BigInt(`0x${uint8ArrayToString(randomBytes(8), 'base16')}`)
|
13
16
|
}
|
14
17
|
|
15
18
|
/**
|
16
|
-
* Generate a message id, based on the `
|
19
|
+
* Generate a message id, based on the `key` and `seqno`
|
17
20
|
*/
|
18
|
-
export const msgId = (
|
19
|
-
|
21
|
+
export const msgId = (key: Uint8Array, seqno: BigInt) => {
|
22
|
+
const seqnoBytes = uint8ArrayFromString(seqno.toString(16).padStart(16, '0'), 'base16')
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
fromBytes = PeerId.fromString(from).multihash.digest
|
25
|
-
}
|
24
|
+
const msgId = new Uint8Array(key.length + seqnoBytes.length)
|
25
|
+
msgId.set(key, 0)
|
26
|
+
msgId.set(seqnoBytes, key.length)
|
26
27
|
|
27
|
-
const msgId = new Uint8Array(fromBytes.length + seqno.length)
|
28
|
-
msgId.set(fromBytes, 0)
|
29
|
-
msgId.set(seqno, fromBytes.length)
|
30
28
|
return msgId
|
31
29
|
}
|
32
30
|
|
33
31
|
/**
|
34
32
|
* Generate a message id, based on message `data`
|
35
33
|
*/
|
36
|
-
export const noSignMsgId = (data: Uint8Array) =>
|
34
|
+
export const noSignMsgId = (data: Uint8Array) => {
|
35
|
+
return sha256.encode(data)
|
36
|
+
}
|
37
37
|
|
38
38
|
/**
|
39
39
|
* Check if any member of the first set is also a member
|
@@ -67,27 +67,28 @@ export const ensureArray = function <T> (maybeArray: T | T[]) {
|
|
67
67
|
return maybeArray
|
68
68
|
}
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
export const normalizeInRpcMessage = (message: RPC.RPC.IMessage, peerId?: string) => {
|
74
|
-
// @ts-expect-error receivedFrom not yet defined
|
75
|
-
const m: NormalizedIMessage = Object.assign({}, message)
|
76
|
-
|
77
|
-
if (peerId != null) {
|
78
|
-
m.receivedFrom = peerId
|
70
|
+
export const toMessage = (message: RPC.RPC.IMessage): Message => {
|
71
|
+
if (message.from == null) {
|
72
|
+
throw errcode(new Error('RPC message was missing from'), codes.ERR_MISSING_FROM)
|
79
73
|
}
|
80
74
|
|
81
|
-
return
|
75
|
+
return {
|
76
|
+
from: peerIdFromBytes(message.from),
|
77
|
+
topic: message.topic ?? '',
|
78
|
+
seqno: message.seqno == null ? undefined : BigInt(`0x${uint8ArrayToString(message.seqno, 'base16')}`),
|
79
|
+
data: message.data ?? new Uint8Array(0),
|
80
|
+
signature: message.signature ?? undefined,
|
81
|
+
key: message.key ?? undefined
|
82
|
+
}
|
82
83
|
}
|
83
84
|
|
84
|
-
export const
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
export const toRpcMessage = (message: Message): RPCMessage => {
|
86
|
+
return {
|
87
|
+
from: message.from.multihash.bytes,
|
88
|
+
data: message.data,
|
89
|
+
seqno: message.seqno == null ? undefined : uint8ArrayFromString(message.seqno.toString(16).padStart(16, '0'), 'base16'),
|
90
|
+
topic: message.topic,
|
91
|
+
signature: message.signature,
|
92
|
+
key: message.key
|
91
93
|
}
|
92
|
-
return m
|
93
94
|
}
|