@libp2p/interop 0.0.0
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/LICENSE +4 -0
- package/README.md +60 -0
- package/dist/src/connect.d.ts +3 -0
- package/dist/src/connect.d.ts.map +1 -0
- package/dist/src/connect.js +54 -0
- package/dist/src/connect.js.map +1 -0
- package/dist/src/dht/content-fetching.d.ts +3 -0
- package/dist/src/dht/content-fetching.d.ts.map +1 -0
- package/dist/src/dht/content-fetching.js +50 -0
- package/dist/src/dht/content-fetching.js.map +1 -0
- package/dist/src/dht/content-routing.d.ts +3 -0
- package/dist/src/dht/content-routing.d.ts.map +1 -0
- package/dist/src/dht/content-routing.js +50 -0
- package/dist/src/dht/content-routing.js.map +1 -0
- package/dist/src/dht/index.d.ts +3 -0
- package/dist/src/dht/index.d.ts.map +1 -0
- package/dist/src/dht/index.js +9 -0
- package/dist/src/dht/index.js.map +1 -0
- package/dist/src/dht/peer-routing.d.ts +3 -0
- package/dist/src/dht/peer-routing.d.ts.map +1 -0
- package/dist/src/dht/peer-routing.js +44 -0
- package/dist/src/dht/peer-routing.js.map +1 -0
- package/dist/src/index.d.ts +20 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/pubsub/floodsub.d.ts +3 -0
- package/dist/src/pubsub/floodsub.d.ts.map +1 -0
- package/dist/src/pubsub/floodsub.js +52 -0
- package/dist/src/pubsub/floodsub.js.map +1 -0
- package/dist/src/pubsub/gossipsub.d.ts +3 -0
- package/dist/src/pubsub/gossipsub.d.ts.map +1 -0
- package/dist/src/pubsub/gossipsub.js +52 -0
- package/dist/src/pubsub/gossipsub.js.map +1 -0
- package/dist/src/pubsub/hybrid.d.ts +3 -0
- package/dist/src/pubsub/hybrid.d.ts.map +1 -0
- package/dist/src/pubsub/hybrid.js +52 -0
- package/dist/src/pubsub/hybrid.js.map +1 -0
- package/dist/src/pubsub/index.d.ts +3 -0
- package/dist/src/pubsub/index.d.ts.map +1 -0
- package/dist/src/pubsub/index.js +9 -0
- package/dist/src/pubsub/index.js.map +1 -0
- package/dist/src/resources/keys/go.ed25519.key +1 -0
- package/dist/src/resources/keys/go.rsa.key +0 -0
- package/dist/src/resources/keys/go.secp256k1.key +1 -0
- package/dist/src/resources/keys/index.d.ts +5 -0
- package/dist/src/resources/keys/index.d.ts.map +1 -0
- package/dist/src/resources/keys/index.js +18 -0
- package/dist/src/resources/keys/index.js.map +1 -0
- package/dist/src/resources/keys/js.ed25519.key +1 -0
- package/dist/src/resources/keys/js.rsa.key +0 -0
- package/dist/src/resources/keys/js.secp256k1.key +1 -0
- package/dist/src/utils/dht-record.d.ts +6 -0
- package/dist/src/utils/dht-record.d.ts.map +1 -0
- package/dist/src/utils/dht-record.js +10 -0
- package/dist/src/utils/dht-record.js.map +1 -0
- package/package.json +151 -0
- package/src/connect.ts +75 -0
- package/src/dht/content-fetching.ts +70 -0
- package/src/dht/content-routing.ts +74 -0
- package/src/dht/index.ts +10 -0
- package/src/dht/peer-routing.ts +63 -0
- package/src/index.ts +31 -0
- package/src/pubsub/floodsub.ts +70 -0
- package/src/pubsub/gossipsub.ts +70 -0
- package/src/pubsub/hybrid.ts +70 -0
- package/src/pubsub/index.ts +10 -0
- package/src/resources/keys/go.ed25519.key +1 -0
- package/src/resources/keys/go.rsa.key +0 -0
- package/src/resources/keys/go.secp256k1.key +1 -0
- package/src/resources/keys/index.ts +24 -0
- package/src/resources/keys/js.ed25519.key +1 -0
- package/src/resources/keys/js.rsa.key +0 -0
- package/src/resources/keys/js.secp256k1.key +1 -0
- package/src/utils/dht-record.ts +10 -0
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{��ܥg�oT+.�\�L�Y��Jb���G�q7�
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/resources/keys/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAIjD,aAAK,aAAa,GAAG,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;AAc/C,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,CAGhD,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url)); // eslint-disable-line @typescript-eslint/naming-convention
|
|
4
|
+
const goKeys = {
|
|
5
|
+
ed25519: path.join(__dirname, 'go.ed25519.key'),
|
|
6
|
+
rsa: path.join(__dirname, 'go.rsa.key'),
|
|
7
|
+
secp256k1: path.join(__dirname, 'go.secp256k1.key')
|
|
8
|
+
};
|
|
9
|
+
const jsKeys = {
|
|
10
|
+
ed25519: path.join(__dirname, 'js.ed25519.key'),
|
|
11
|
+
rsa: path.join(__dirname, 'js.rsa.key'),
|
|
12
|
+
secp256k1: path.join(__dirname, 'js.secp256k1.key')
|
|
13
|
+
};
|
|
14
|
+
export const keys = {
|
|
15
|
+
go: goKeys,
|
|
16
|
+
js: jsKeys
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/resources/keys/index.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAGnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA,CAAC,2DAA2D;AAI1H,MAAM,MAAM,GAAkB;IAC5B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;IAC/C,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;IACvC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;CACpD,CAAA;AAED,MAAM,MAAM,GAAkB;IAC5B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC;IAC/C,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;IACvC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC;CACpD,CAAA;AAED,MAAM,CAAC,MAAM,IAAI,GAAoC;IACnD,EAAE,EAAE,MAAM;IACV,EAAE,EAAE,MAAM;CACX,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
`F́o��.ux��7f�v71��{�z���9*x7Ӟ�g��Q�g,�FhŒ�0������]3�7Ӟ�g��Q�g,�FhŒ�0������]3�
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
�z�m�/�kPa�ࡓ$�Z���p"�>v��
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dht-record.d.ts","sourceRoot":"","sources":["../../../src/utils/dht-record.ts"],"names":[],"mappings":";;;;AAGA,wBAMC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
|
|
2
|
+
import { concat as uint8ArrayConcat } from 'uint8arrays/concat';
|
|
3
|
+
export default {
|
|
4
|
+
key: uint8ArrayConcat([
|
|
5
|
+
uint8ArrayFromString('/pk/'),
|
|
6
|
+
uint8ArrayFromString('muft89xjpybos8eas1vaq2xrbsx2vkll7is4ocy7pia5fsjlt3c2', 'base36')
|
|
7
|
+
]),
|
|
8
|
+
value: uint8ArrayFromString('080012a60230820122300d06092a864886f70d01010105000382010f003082010a0282010100c2588f998971dac9e3eef76a311bf9159505aff69ea3b664c55a36aa28ee08de1127228a4d431bb9c0840240c75f6e98a0843a78d945491a3ea5e1f7cee2bc71383510db5290702383975b7bffae9fb40c84cc1220fb4a7db862fffb0de42f8fd8fb33a17deb20f30e2d0f194791fe69355a392f77df35f101e08a2fc95b2c018768938814fcb52482f899f5e90a1905e8abbcdbb1647ad80a5b0417e1ce8320d64197a6ba3848926375c63adebabdf6eb82109bcadfee13b62bf922bbb6f74c1a26c9bc6122d1436787e0e6de3c152b1959701092abef84599f73eaedb2fcef9f87293e1bbe8e0fef3f1a7fd2e8b94c7e633f88473644a63cb948e4d25c54490203010001', 'hex')
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=dht-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dht-record.js","sourceRoot":"","sources":["../../../src/utils/dht-record.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,EAAE,MAAM,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE/D,eAAe;IACb,GAAG,EAAE,gBAAgB,CAAC;QACpB,oBAAoB,CAAC,MAAM,CAAC;QAC5B,oBAAoB,CAAC,sDAAsD,EAAE,QAAQ,CAAC;KACvF,CAAC;IACF,KAAK,EAAE,oBAAoB,CAAC,wlBAAwlB,EAAE,KAAK,CAAC;CAC7nB,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libp2p/interop",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Interoperability Tests for libp2p",
|
|
5
|
+
"license": "Apache-2.0 OR MIT",
|
|
6
|
+
"homepage": "https://github.com/libp2p/interop#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/libp2p/interop.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/libp2p/interop/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"libp2p"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=16.0.0",
|
|
19
|
+
"npm": ">=7.0.0"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"types": "./dist/src/index.d.ts",
|
|
23
|
+
"files": [
|
|
24
|
+
"src",
|
|
25
|
+
"dist/src",
|
|
26
|
+
"!dist/test",
|
|
27
|
+
"!**/*.tsbuildinfo"
|
|
28
|
+
],
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"import": "./dist/src/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"eslintConfig": {
|
|
35
|
+
"extends": "ipfs",
|
|
36
|
+
"parserOptions": {
|
|
37
|
+
"sourceType": "module"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"release": {
|
|
41
|
+
"branches": [
|
|
42
|
+
"master"
|
|
43
|
+
],
|
|
44
|
+
"plugins": [
|
|
45
|
+
[
|
|
46
|
+
"@semantic-release/commit-analyzer",
|
|
47
|
+
{
|
|
48
|
+
"preset": "conventionalcommits",
|
|
49
|
+
"releaseRules": [
|
|
50
|
+
{
|
|
51
|
+
"breaking": true,
|
|
52
|
+
"release": "major"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"revert": true,
|
|
56
|
+
"release": "patch"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"type": "feat",
|
|
60
|
+
"release": "minor"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "fix",
|
|
64
|
+
"release": "patch"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": "chore",
|
|
68
|
+
"release": "patch"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"type": "docs",
|
|
72
|
+
"release": "patch"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "test",
|
|
76
|
+
"release": "patch"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"scope": "no-release",
|
|
80
|
+
"release": false
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
[
|
|
86
|
+
"@semantic-release/release-notes-generator",
|
|
87
|
+
{
|
|
88
|
+
"preset": "conventionalcommits",
|
|
89
|
+
"presetConfig": {
|
|
90
|
+
"types": [
|
|
91
|
+
{
|
|
92
|
+
"type": "feat",
|
|
93
|
+
"section": "Features"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"type": "fix",
|
|
97
|
+
"section": "Bug Fixes"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"type": "chore",
|
|
101
|
+
"section": "Trivial Changes"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"type": "docs",
|
|
105
|
+
"section": "Trivial Changes"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"type": "test",
|
|
109
|
+
"section": "Tests"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"@semantic-release/changelog",
|
|
116
|
+
"@semantic-release/npm",
|
|
117
|
+
"@semantic-release/github",
|
|
118
|
+
"@semantic-release/git"
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"scripts": {
|
|
122
|
+
"lint": "aegir lint",
|
|
123
|
+
"dep-check": "aegir dep-check dist/src/**/*.js dist/test/**/*.js",
|
|
124
|
+
"build": "tsc",
|
|
125
|
+
"postbuild": "cp src/resources/keys/*.key dist/src/resources/keys",
|
|
126
|
+
"pretest": "npm run build",
|
|
127
|
+
"test": "aegir test -f \"./dist/test/**/*.spec.js\"",
|
|
128
|
+
"test:node": "npm run test -- -t node -f ./dist/test/node.js",
|
|
129
|
+
"test:chrome": "npm run test -- -t browser -f ./dist/test/browser.js ",
|
|
130
|
+
"test:firefox": "npm run test -- -t browser -- --browser firefox -f ./dist/test/browser.js",
|
|
131
|
+
"release": "semantic-release"
|
|
132
|
+
},
|
|
133
|
+
"dependencies": {
|
|
134
|
+
"@libp2p/daemon-client": "^0.0.2",
|
|
135
|
+
"@libp2p/interfaces": "^1.3.17",
|
|
136
|
+
"@libp2p/logger": "^1.1.2",
|
|
137
|
+
"@libp2p/peer-id": "^1.1.8",
|
|
138
|
+
"@multiformats/multiaddr": "^10.1.8",
|
|
139
|
+
"it-all": "^1.0.6",
|
|
140
|
+
"it-first": "^1.0.7",
|
|
141
|
+
"multiformats": "^9.4.5",
|
|
142
|
+
"p-retry": "^5.1.0",
|
|
143
|
+
"uint8arrays": "^3.0.0"
|
|
144
|
+
},
|
|
145
|
+
"peerDependencies": {
|
|
146
|
+
"aegir": "^36.0.0"
|
|
147
|
+
},
|
|
148
|
+
"devDependencies": {
|
|
149
|
+
"aegir": "^36.0.0"
|
|
150
|
+
}
|
|
151
|
+
}
|
package/src/connect.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
2
|
+
import type { Daemon, NodeType, SpawnOptions, DaemonFactory, PeerIdType } from './index.js'
|
|
3
|
+
import { keys } from './resources/keys/index.js'
|
|
4
|
+
|
|
5
|
+
export function connectTests (factory: DaemonFactory) {
|
|
6
|
+
const keyTypes: PeerIdType[] = ['ed25519', 'rsa', 'secp256k1']
|
|
7
|
+
const impls: NodeType[] = ['js', 'go']
|
|
8
|
+
|
|
9
|
+
for (const keyType of keyTypes) {
|
|
10
|
+
for (const implA of impls) {
|
|
11
|
+
for (const implB of impls) {
|
|
12
|
+
runConnectTests(
|
|
13
|
+
`noise/${keyType}`,
|
|
14
|
+
factory,
|
|
15
|
+
{ type: implA, noise: true, key: keys.go[keyType] },
|
|
16
|
+
{ type: implB, noise: true, key: keys.js[keyType] }
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function runConnectTests (name: string, factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
24
|
+
describe(`connect using ${name}`, () => {
|
|
25
|
+
let daemons: Daemon[]
|
|
26
|
+
|
|
27
|
+
// Start Daemons
|
|
28
|
+
before(async function () {
|
|
29
|
+
this.timeout(20 * 1000)
|
|
30
|
+
|
|
31
|
+
daemons = await Promise.all([
|
|
32
|
+
factory.spawn(optionsA),
|
|
33
|
+
factory.spawn(optionsB)
|
|
34
|
+
])
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Stop daemons
|
|
38
|
+
after(async function () {
|
|
39
|
+
if (daemons != null) {
|
|
40
|
+
await Promise.all(
|
|
41
|
+
daemons.map(async (daemon) => await daemon.stop())
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
47
|
+
this.timeout(10 * 1000)
|
|
48
|
+
|
|
49
|
+
const identify1 = await daemons[0].client.identify()
|
|
50
|
+
const identify2 = await daemons[1].client.identify()
|
|
51
|
+
|
|
52
|
+
// verify connected peers
|
|
53
|
+
const knownPeersBeforeConnect1 = await daemons[0].client.listPeers()
|
|
54
|
+
expect(knownPeersBeforeConnect1).to.have.lengthOf(0)
|
|
55
|
+
|
|
56
|
+
const knownPeersBeforeConnect2 = await daemons[1].client.listPeers()
|
|
57
|
+
expect(knownPeersBeforeConnect2).to.have.lengthOf(0)
|
|
58
|
+
|
|
59
|
+
// connect peers
|
|
60
|
+
await daemons[0].client.connect(identify2.peerId, identify2.addrs)
|
|
61
|
+
|
|
62
|
+
// daemons[0] will take some time to get the peers
|
|
63
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
64
|
+
|
|
65
|
+
// verify connected peers
|
|
66
|
+
const knownPeersAfterConnect1 = await daemons[0].client.listPeers()
|
|
67
|
+
expect(knownPeersAfterConnect1).to.have.lengthOf(1)
|
|
68
|
+
expect(knownPeersAfterConnect1[0].toString()).to.equal(identify2.peerId.toString())
|
|
69
|
+
|
|
70
|
+
const knownPeersAfterConnect2 = await daemons[1].client.listPeers()
|
|
71
|
+
expect(knownPeersAfterConnect2).to.have.lengthOf(1)
|
|
72
|
+
expect(knownPeersAfterConnect2[0].toString()).to.equal(identify1.peerId.toString())
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
4
|
+
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
5
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
|
+
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
|
|
7
|
+
|
|
8
|
+
const record = {
|
|
9
|
+
key: uint8ArrayConcat([
|
|
10
|
+
uint8ArrayFromString('/pk/'),
|
|
11
|
+
uint8ArrayFromString('muft89xjpybos8eas1vaq2xrbsx2vkll7is4ocy7pia5fsjlt3c2', 'base36')
|
|
12
|
+
]),
|
|
13
|
+
value: uint8ArrayFromString('080012a60230820122300d06092a864886f70d01010105000382010f003082010a0282010100c2588f998971dac9e3eef76a311bf9159505aff69ea3b664c55a36aa28ee08de1127228a4d431bb9c0840240c75f6e98a0843a78d945491a3ea5e1f7cee2bc71383510db5290702383975b7bffae9fb40c84cc1220fb4a7db862fffb0de42f8fd8fb33a17deb20f30e2d0f194791fe69355a392f77df35f101e08a2fc95b2c018768938814fcb52482f899f5e90a1905e8abbcdbb1647ad80a5b0417e1ce8320d64197a6ba3848926375c63adebabdf6eb82109bcadfee13b62bf922bbb6f74c1a26c9bc6122d1436787e0e6de3c152b1959701092abef84599f73eaedb2fcef9f87293e1bbe8e0fef3f1a7fd2e8b94c7e633f88473644a63cb948e4d25c54490203010001', 'hex')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function contentFetchingTests (factory: DaemonFactory) {
|
|
17
|
+
const nodeTypes: NodeType[] = ['js', 'go']
|
|
18
|
+
|
|
19
|
+
for (const typeA of nodeTypes) {
|
|
20
|
+
for (const typeB of nodeTypes) {
|
|
21
|
+
runContentFetchingTests(
|
|
22
|
+
factory,
|
|
23
|
+
{ type: typeA, dht: true },
|
|
24
|
+
{ type: typeB, dht: true }
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function runContentFetchingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
31
|
+
describe('dht.contentFetching', () => {
|
|
32
|
+
let daemons: Daemon[]
|
|
33
|
+
|
|
34
|
+
// Start Daemons
|
|
35
|
+
before(async function () {
|
|
36
|
+
this.timeout(20 * 1000)
|
|
37
|
+
|
|
38
|
+
daemons = await Promise.all([
|
|
39
|
+
factory.spawn(optionsA),
|
|
40
|
+
factory.spawn(optionsB)
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
// connect them
|
|
44
|
+
const identify0 = await daemons[0].client.identify()
|
|
45
|
+
|
|
46
|
+
await daemons[1].client.connect(identify0.peerId, identify0.addrs)
|
|
47
|
+
|
|
48
|
+
// jsDaemon1 will take some time to get the peers
|
|
49
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// Stop daemons
|
|
53
|
+
after(async function () {
|
|
54
|
+
if (daemons != null) {
|
|
55
|
+
await Promise.all(
|
|
56
|
+
daemons.map(async (daemon) => await daemon.stop())
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
62
|
+
this.timeout(10 * 1000)
|
|
63
|
+
|
|
64
|
+
await daemons[0].client.dht.put(record.key, record.value)
|
|
65
|
+
|
|
66
|
+
const data = await daemons[1].client.dht.get(record.key)
|
|
67
|
+
expect(data).to.equalBytes(record.value)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
4
|
+
import { CID } from 'multiformats/cid'
|
|
5
|
+
import all from 'it-all'
|
|
6
|
+
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
7
|
+
import type { IdentifyResult } from '@libp2p/daemon-client'
|
|
8
|
+
|
|
9
|
+
export function contentRoutingTests (factory: DaemonFactory) {
|
|
10
|
+
const nodeTypes: NodeType[] = ['js', 'go']
|
|
11
|
+
|
|
12
|
+
for (const typeA of nodeTypes) {
|
|
13
|
+
for (const typeB of nodeTypes) {
|
|
14
|
+
if (typeA === 'go' && typeB === 'go') {
|
|
15
|
+
// skip go<->go as it never seems to populate the routing tables
|
|
16
|
+
continue
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
runContentRoutingTests(
|
|
20
|
+
factory,
|
|
21
|
+
{ type: typeA, dht: true },
|
|
22
|
+
{ type: typeB, dht: true }
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function runContentRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
29
|
+
describe('dht.contentRouting', () => {
|
|
30
|
+
let daemons: Daemon[]
|
|
31
|
+
let identify: IdentifyResult[]
|
|
32
|
+
|
|
33
|
+
// Start Daemons
|
|
34
|
+
before(async function () {
|
|
35
|
+
this.timeout(20 * 1000)
|
|
36
|
+
|
|
37
|
+
daemons = await Promise.all([
|
|
38
|
+
factory.spawn(optionsA),
|
|
39
|
+
factory.spawn(optionsB),
|
|
40
|
+
factory.spawn(optionsB)
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
identify = await Promise.all(
|
|
44
|
+
daemons.map(async d => await d.client.identify())
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
await daemons[0].client.connect(identify[1].peerId, identify[1].addrs)
|
|
48
|
+
await daemons[0].client.connect(identify[2].peerId, identify[2].addrs)
|
|
49
|
+
|
|
50
|
+
// get the peers in the table
|
|
51
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Stop daemons
|
|
55
|
+
after(async function () {
|
|
56
|
+
if (daemons != null) {
|
|
57
|
+
await Promise.all(
|
|
58
|
+
daemons.map(async (daemon) => await daemon.stop())
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
64
|
+
const cid = CID.parse('QmVzw6MPsF96TyXBSRs1ptLoVMWRv5FCYJZZGJSVB2Hp39')
|
|
65
|
+
|
|
66
|
+
await daemons[0].client.dht.provide(cid)
|
|
67
|
+
|
|
68
|
+
const providers = await all(daemons[1].client.dht.findProviders(cid, 1))
|
|
69
|
+
|
|
70
|
+
expect(providers).to.exist()
|
|
71
|
+
expect(providers.length).to.be.greaterThan(0)
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
}
|
package/src/dht/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DaemonFactory } from '../index.js'
|
|
2
|
+
import { contentFetchingTests } from './content-fetching.js'
|
|
3
|
+
import { contentRoutingTests } from './content-routing.js'
|
|
4
|
+
import { peerRoutingTests } from './peer-routing.js'
|
|
5
|
+
|
|
6
|
+
export async function dhtTests (factory: DaemonFactory) {
|
|
7
|
+
await contentFetchingTests(factory)
|
|
8
|
+
await contentRoutingTests(factory)
|
|
9
|
+
await peerRoutingTests(factory)
|
|
10
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
4
|
+
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
5
|
+
import pRetry from 'p-retry'
|
|
6
|
+
import type { PeerInfo } from '@libp2p/interfaces/peer-info'
|
|
7
|
+
|
|
8
|
+
export function peerRoutingTests (factory: DaemonFactory) {
|
|
9
|
+
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
|
+
|
|
11
|
+
for (const typeA of nodeTypes) {
|
|
12
|
+
for (const typeB of nodeTypes) {
|
|
13
|
+
runPeerRoutingTests(
|
|
14
|
+
factory,
|
|
15
|
+
{ type: typeA, dht: true },
|
|
16
|
+
{ type: typeB, dht: true }
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function runPeerRoutingTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
23
|
+
describe('dht.peerRouting', () => {
|
|
24
|
+
let daemons: Daemon[]
|
|
25
|
+
|
|
26
|
+
// Start Daemons
|
|
27
|
+
before(async function () {
|
|
28
|
+
this.timeout(20 * 1000)
|
|
29
|
+
|
|
30
|
+
daemons = await Promise.all([
|
|
31
|
+
factory.spawn(optionsA),
|
|
32
|
+
factory.spawn(optionsB),
|
|
33
|
+
factory.spawn(optionsB)
|
|
34
|
+
])
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Stop daemons
|
|
38
|
+
after(async function () {
|
|
39
|
+
if (daemons != null) {
|
|
40
|
+
await Promise.all(
|
|
41
|
+
daemons.map(async (daemon) => await daemon.stop())
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
47
|
+
const identify1 = await daemons[1].client.identify()
|
|
48
|
+
const identify2 = await daemons[2].client.identify()
|
|
49
|
+
|
|
50
|
+
// peers need at least one peer in their routing table or they fail with:
|
|
51
|
+
// connect 0 => 1
|
|
52
|
+
await daemons[0].client.connect(identify1.peerId, identify1.addrs)
|
|
53
|
+
|
|
54
|
+
// connect 0 => 2
|
|
55
|
+
await daemons[0].client.connect(identify2.peerId, identify2.addrs)
|
|
56
|
+
|
|
57
|
+
// peer 1 find peer 2, retry up to 10 times to allow the routing table to refresh
|
|
58
|
+
const peerData: PeerInfo = await pRetry(async () => await daemons[1].client.dht.findPeer(identify2.peerId), { retries: 10 })
|
|
59
|
+
|
|
60
|
+
expect(identify2.addrs.map(ma => ma.toString())).to.include.deep.members(peerData.multiaddrs.map(ma => ma.toString()))
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { connectTests } from './connect.js'
|
|
2
|
+
import { dhtTests } from './dht/index.js'
|
|
3
|
+
import { pubsubTests } from './pubsub/index.js'
|
|
4
|
+
import type { DaemonClient } from '@libp2p/daemon-client'
|
|
5
|
+
|
|
6
|
+
export interface Daemon {
|
|
7
|
+
stop: () => Promise<void>
|
|
8
|
+
client: DaemonClient
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type NodeType = 'js' | 'go'
|
|
12
|
+
export type PeerIdType = 'rsa' | 'ed25519' | 'secp256k1'
|
|
13
|
+
|
|
14
|
+
export interface SpawnOptions {
|
|
15
|
+
type: NodeType
|
|
16
|
+
key?: string
|
|
17
|
+
noise?: true
|
|
18
|
+
dht?: boolean
|
|
19
|
+
pubsub?: boolean
|
|
20
|
+
pubsubRouter?: 'gossipsub' | 'floodsub'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface DaemonFactory {
|
|
24
|
+
spawn: (options: SpawnOptions) => Promise<Daemon>
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export default async function interopTests (factory: DaemonFactory) {
|
|
28
|
+
await connectTests(factory)
|
|
29
|
+
await dhtTests(factory)
|
|
30
|
+
await pubsubTests(factory)
|
|
31
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import { expect } from 'aegir/utils/chai.js'
|
|
4
|
+
import type { Daemon, DaemonFactory, NodeType, SpawnOptions } from '../index.js'
|
|
5
|
+
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
6
|
+
import first from 'it-first'
|
|
7
|
+
|
|
8
|
+
export function floodsubTests (factory: DaemonFactory) {
|
|
9
|
+
const nodeTypes: NodeType[] = ['js', 'go']
|
|
10
|
+
|
|
11
|
+
for (const typeA of nodeTypes) {
|
|
12
|
+
for (const typeB of nodeTypes) {
|
|
13
|
+
runFloodsubTests(
|
|
14
|
+
factory,
|
|
15
|
+
{ type: typeA, pubsub: true, pubsubRouter: 'floodsub' },
|
|
16
|
+
{ type: typeB, pubsub: true, pubsubRouter: 'floodsub' }
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function runFloodsubTests (factory: DaemonFactory, optionsA: SpawnOptions, optionsB: SpawnOptions) {
|
|
23
|
+
describe('pubsub.floodSub', () => {
|
|
24
|
+
let daemons: Daemon[]
|
|
25
|
+
|
|
26
|
+
// Start Daemons
|
|
27
|
+
before(async function () {
|
|
28
|
+
this.timeout(20 * 1000)
|
|
29
|
+
|
|
30
|
+
daemons = await Promise.all([
|
|
31
|
+
factory.spawn(optionsA),
|
|
32
|
+
factory.spawn(optionsB),
|
|
33
|
+
factory.spawn(optionsB)
|
|
34
|
+
])
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Stop daemons
|
|
38
|
+
after(async function () {
|
|
39
|
+
if (daemons != null) {
|
|
40
|
+
await Promise.all(
|
|
41
|
+
daemons.map(async (daemon) => await daemon.stop())
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it(`${optionsA.type} peer to ${optionsB.type} peer`, async function () {
|
|
47
|
+
const topic = 'test-topic'
|
|
48
|
+
const data = uint8ArrayFromString('test-data')
|
|
49
|
+
|
|
50
|
+
const subscribeIterator = await daemons[1].client.pubsub.subscribe(topic)
|
|
51
|
+
const subscriber = async () => {
|
|
52
|
+
const message = await first(subscribeIterator)
|
|
53
|
+
|
|
54
|
+
expect(message).to.exist()
|
|
55
|
+
expect(message).to.have.property('data').that.equalBytes(data)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const publisher = async () => {
|
|
59
|
+
// wait for subscription stream
|
|
60
|
+
await new Promise(resolve => setTimeout(resolve, 800))
|
|
61
|
+
await daemons[0].client.pubsub.publish(topic, data)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return await Promise.all([
|
|
65
|
+
subscriber(),
|
|
66
|
+
publisher()
|
|
67
|
+
])
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
}
|