@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.
@@ -2,19 +2,53 @@ syntax = "proto3";
2
2
 
3
3
  message RPC {
4
4
  repeated SubOpts subscriptions = 1;
5
- repeated Message msgs = 2;
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 topicID = 2;
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
- repeated string topicIDs = 4;
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
+ }
@@ -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 { normalizeOutRpcMessage } from '../utils.js'
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(normalizeOutRpcMessage(message)).finish()
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, valid PublicKey can be retrieved an error will be returned.
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 PeerIdFactory.createFromPubKey(keys.unmarshalPublicKey(message.key))
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
- } else if (from.publicKey != null) {
97
- return from.publicKey
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
@@ -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: Pushable<Uint8Array> | undefined
28
+ public outboundStream?: Pushable<Uint8Array>
29
29
  /**
30
30
  * Read stream
31
31
  */
32
- public inboundStream: AsyncIterable<Uint8Array> | undefined
32
+ public inboundStream?: AsyncIterable<Uint8Array>
33
33
  /**
34
34
  * The raw outbound stream, as retrieved from conn.newStream
35
35
  */
36
- private _rawOutboundStream: Stream | undefined
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: Stream | undefined
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 { PeerId } from '@libp2p/peer-id'
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 const randomSeqno = () => {
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 `from` and `seqno`
19
+ * Generate a message id, based on the `key` and `seqno`
17
20
  */
18
- export const msgId = (from: Uint8Array | string, seqno: Uint8Array) => {
19
- let fromBytes
21
+ export const msgId = (key: Uint8Array, seqno: BigInt) => {
22
+ const seqnoBytes = uint8ArrayFromString(seqno.toString(16).padStart(16, '0'), 'base16')
20
23
 
21
- if (from instanceof Uint8Array) {
22
- fromBytes = PeerId.fromBytes(from).multihash.digest
23
- } else {
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) => sha256.encode(data)
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
- * Ensures `message.from` is base58 encoded
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 m
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 normalizeOutRpcMessage = (message: Message) => {
85
- const m: Message = Object.assign({}, message)
86
- if (typeof message.from === 'string') {
87
- m.from = uint8ArrayFromString(message.from, 'base58btc')
88
- }
89
- if (typeof message.data === 'string') {
90
- m.data = uint8ArrayFromString(message.data)
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
  }