@libp2p/interop 5.0.0 → 6.0.1

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.
Files changed (38) hide show
  1. package/dist/index.min.js +5 -5
  2. package/dist/src/connect.js +2 -2
  3. package/dist/src/connect.js.map +1 -1
  4. package/dist/src/index.d.ts +4 -1
  5. package/dist/src/index.d.ts.map +1 -1
  6. package/dist/src/index.js +3 -1
  7. package/dist/src/index.js.map +1 -1
  8. package/dist/src/pubsub/floodsub.d.ts.map +1 -1
  9. package/dist/src/pubsub/floodsub.js +12 -5
  10. package/dist/src/pubsub/floodsub.js.map +1 -1
  11. package/dist/src/pubsub/gossipsub.d.ts.map +1 -1
  12. package/dist/src/pubsub/gossipsub.js +7 -2
  13. package/dist/src/pubsub/gossipsub.js.map +1 -1
  14. package/dist/src/pubsub/hybrid.d.ts.map +1 -1
  15. package/dist/src/pubsub/hybrid.js +7 -2
  16. package/dist/src/pubsub/hybrid.js.map +1 -1
  17. package/dist/src/relay/index.d.ts +3 -0
  18. package/dist/src/relay/index.d.ts.map +1 -0
  19. package/dist/src/relay/index.js +62 -0
  20. package/dist/src/relay/index.js.map +1 -0
  21. package/dist/src/relay/pb/index.d.ts +93 -0
  22. package/dist/src/relay/pb/index.d.ts.map +1 -0
  23. package/dist/src/relay/pb/index.js +435 -0
  24. package/dist/src/relay/pb/index.js.map +1 -0
  25. package/dist/src/relay/util.d.ts +11 -0
  26. package/dist/src/relay/util.d.ts.map +1 -0
  27. package/dist/src/relay/util.js +24 -0
  28. package/dist/src/relay/util.js.map +1 -0
  29. package/package.json +16 -5
  30. package/src/connect.ts +2 -2
  31. package/src/index.ts +8 -1
  32. package/src/pubsub/floodsub.ts +14 -5
  33. package/src/pubsub/gossipsub.ts +10 -3
  34. package/src/pubsub/hybrid.ts +8 -2
  35. package/src/relay/index.ts +76 -0
  36. package/src/relay/pb/index.proto +67 -0
  37. package/src/relay/pb/index.ts +549 -0
  38. package/src/relay/util.ts +35 -0
@@ -4,6 +4,8 @@ import { expect } from 'aegir/chai'
4
4
  import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
6
  import first from 'it-first'
7
+ import pWaitFor from 'p-wait-for'
8
+ import type { IdentifyResult } from '@libp2p/daemon-client'
7
9
 
8
10
  export function gossipsubTests (factory: DaemonFactory): void {
9
11
  const nodeTypes: NodeType[] = ['js', 'go']
@@ -22,6 +24,7 @@ export function gossipsubTests (factory: DaemonFactory): void {
22
24
  function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
23
25
  describe('pubsub.gossipsub', () => {
24
26
  let daemons: Daemon[]
27
+ let identify1: IdentifyResult
25
28
 
26
29
  // Start Daemons
27
30
  before(async function () {
@@ -32,7 +35,7 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
32
35
  factory.spawn(optionsB)
33
36
  ])
34
37
 
35
- const identify1 = await daemons[1].client.identify()
38
+ identify1 = await daemons[1].client.identify()
36
39
  await daemons[0].client.connect(identify1.peerId, identify1.addrs)
37
40
  })
38
41
 
@@ -40,7 +43,7 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
40
43
  after(async function () {
41
44
  if (daemons != null) {
42
45
  await Promise.all(
43
- daemons.map(async (daemon) => { await daemon.stop() })
46
+ daemons.map(async daemon => { await daemon.stop() })
44
47
  )
45
48
  }
46
49
  })
@@ -59,7 +62,11 @@ function runGossipsubTests (factory: DaemonFactory, optionsA: SpawnOptions, opti
59
62
 
60
63
  const publisher = async (): Promise<void> => {
61
64
  // wait for subscription stream
62
- await new Promise(resolve => setTimeout(resolve, 800))
65
+ await pWaitFor(async () => {
66
+ const peers = await daemons[0].client.pubsub.getSubscribers(topic)
67
+ return peers.map(p => p.toString()).includes(identify1.peerId.toString())
68
+ })
69
+
63
70
  await daemons[0].client.pubsub.publish(topic, data)
64
71
  }
65
72
 
@@ -4,6 +4,8 @@ import { expect } from 'aegir/chai'
4
4
  import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
5
5
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
6
  import first from 'it-first'
7
+ import pWaitFor from 'p-wait-for'
8
+ import type { IdentifyResult } from '@libp2p/daemon-client'
7
9
 
8
10
  export function hybridTests (factory: DaemonFactory): void {
9
11
  const nodeTypes: NodeType[] = ['js', 'go']
@@ -22,6 +24,7 @@ export function hybridTests (factory: DaemonFactory): void {
22
24
  function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions): void {
23
25
  describe('pubsub.hybrid', () => {
24
26
  let daemons: Daemon[]
27
+ let identify1: IdentifyResult
25
28
 
26
29
  // Start Daemons
27
30
  before(async function () {
@@ -32,7 +35,7 @@ function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, options
32
35
  factory.spawn(optionsB)
33
36
  ])
34
37
 
35
- const identify1 = await daemons[1].client.identify()
38
+ identify1 = await daemons[1].client.identify()
36
39
  await daemons[0].client.connect(identify1.peerId, identify1.addrs)
37
40
  })
38
41
 
@@ -59,7 +62,10 @@ function runHybridTests (factory: DaemonFactory, optionsA: SpawnOptions, options
59
62
 
60
63
  const publisher = async (): Promise<void> => {
61
64
  // wait for subscription stream
62
- await new Promise(resolve => setTimeout(resolve, 800))
65
+ await pWaitFor(async () => {
66
+ const peers = await daemons[0].client.pubsub.getSubscribers(topic)
67
+ return peers.map(p => p.toString()).includes(identify1.peerId.toString())
68
+ })
63
69
  await daemons[0].client.pubsub.publish(topic, data)
64
70
  }
65
71
 
@@ -0,0 +1,76 @@
1
+ import { Multiaddr, multiaddr } from '@multiformats/multiaddr'
2
+ import { expect } from 'aegir/chai'
3
+ import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
4
+ import { Status } from './pb/index.js'
5
+ import { echoHandler, reserve } from './util.js'
6
+ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
7
+ import type { IdentifyResult } from '@libp2p/daemon-client'
8
+ import { handshake } from 'it-handshake'
9
+
10
+ export function relayTests (factory: DaemonFactory): void {
11
+ const t: NodeType[] = ['go', 'js']
12
+ t.forEach(a => { t.forEach(b => { t.forEach(r => { relayTest(factory, a, b, r) }) }) })
13
+ }
14
+
15
+ function relayTest (factory: DaemonFactory, aType: NodeType, bType: NodeType, relayType: NodeType): void {
16
+ describe(`${aType} to ${bType} over relay ${relayType}`, () => {
17
+ const opts: SpawnOptions[] = [
18
+ { type: aType, noise: true, noListen: true },
19
+ { type: bType, noise: true, noListen: true },
20
+ { type: relayType, noise: true, relay: true }
21
+ ]
22
+
23
+ let aNode: Daemon
24
+ let bNode: Daemon
25
+ let relay: Daemon
26
+ let bId: IdentifyResult
27
+ let relayId: IdentifyResult
28
+ let bAddrViaRelay: Multiaddr
29
+
30
+ beforeEach(async function () {
31
+ this.timeout(20 * 1000)
32
+ ;[aNode, bNode, relay] = await Promise.all(opts.map(async o => await factory.spawn(o)))
33
+ ;[bId, relayId] = await Promise.all([bNode, relay].map(async d => await d.client.identify()))
34
+
35
+ // construct a relay address
36
+ bAddrViaRelay = multiaddr(`${relayId.addrs[0].toString()}/p2p/${relayId.peerId.toString()}/p2p-circuit/p2p/${bId.peerId.toString()}`)
37
+
38
+ // connect b to the relay
39
+ await bNode.client.connect(relayId.peerId, relayId.addrs)
40
+ })
41
+
42
+ afterEach(async function () {
43
+ await Promise.all([aNode, bNode, relay].map(async d => { await d.stop() }))
44
+ })
45
+
46
+ it('connects', async () => {
47
+ // b makes reservation on relay
48
+ const reserveResponse = await reserve(bNode, relayId.peerId)
49
+ expect(reserveResponse.status).to.eq(Status.OK)
50
+
51
+ // a dials b through relay
52
+ await aNode.client.connect(bId.peerId, [bAddrViaRelay])
53
+ await new Promise(resolve => setTimeout(resolve, 500))
54
+ const connectedPeers = await aNode.client.listPeers()
55
+ expect(connectedPeers.filter(p => p.equals(bId.peerId))).to.have.length(1)
56
+
57
+ // run an echo test
58
+ await bNode.client.registerStreamHandler(echoHandler.protocol, echoHandler.handler)
59
+ const stream = await aNode.client.openStream(bId.peerId, echoHandler.protocol)
60
+
61
+ // send some data, read the response
62
+ const input = uint8ArrayFromString('test')
63
+ const shake = handshake(stream)
64
+ shake.write(input)
65
+ const output = await shake.read()
66
+
67
+ expect(output?.subarray()).to.deep.equal(input)
68
+ })
69
+
70
+ it('fails to connect without a reservation', async () => {
71
+ // a dials b through relay
72
+ await expect(aNode.client.connect(bId.peerId, [bAddrViaRelay])).to.eventually.be.rejected
73
+ .with.property('message').that.matches(/NO_RESERVATION/)
74
+ })
75
+ })
76
+ }
@@ -0,0 +1,67 @@
1
+ syntax = "proto3";
2
+
3
+ message HopMessage {
4
+ enum Type {
5
+ RESERVE = 0;
6
+ CONNECT = 1;
7
+ STATUS = 2;
8
+ }
9
+
10
+ // the presence of this field is enforced at application level
11
+ optional Type type = 1;
12
+
13
+ optional Peer peer = 2;
14
+ optional Reservation reservation = 3;
15
+ optional Limit limit = 4;
16
+
17
+ optional Status status = 5;
18
+ }
19
+
20
+ message StopMessage {
21
+ enum Type {
22
+ CONNECT = 0;
23
+ STATUS = 1;
24
+ }
25
+
26
+ // the presence of this field is enforced at application level
27
+ optional Type type = 1;
28
+
29
+ optional Peer peer = 2;
30
+ optional Limit limit = 3;
31
+
32
+ optional Status status = 4;
33
+ }
34
+
35
+ message Peer {
36
+ bytes id = 1;
37
+ repeated bytes addrs = 2;
38
+ }
39
+
40
+ message Reservation {
41
+ uint64 expire = 1; // Unix expiration time (UTC)
42
+ repeated bytes addrs = 2; // relay addrs for reserving peer
43
+ optional bytes voucher = 3; // reservation voucher
44
+ }
45
+
46
+ message Limit {
47
+ optional uint32 duration = 1; // seconds
48
+ optional uint64 data = 2; // bytes
49
+ }
50
+
51
+ enum Status {
52
+ UNUSED = 0;
53
+ OK = 100;
54
+ RESERVATION_REFUSED = 200;
55
+ RESOURCE_LIMIT_EXCEEDED = 201;
56
+ PERMISSION_DENIED = 202;
57
+ CONNECTION_FAILED = 203;
58
+ NO_RESERVATION = 204;
59
+ MALFORMED_MESSAGE = 400;
60
+ UNEXPECTED_MESSAGE = 401;
61
+ }
62
+
63
+ message ReservationVoucher {
64
+ bytes relay = 1;
65
+ bytes peer = 2;
66
+ uint64 expiration = 3;
67
+ }