helia-coord 1.5.7 → 1.5.9
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/examples/create-helia-node.js +3 -1
- package/examples/memory-usage/README.md +12 -0
- package/examples/memory-usage/create-helia-node.js +154 -0
- package/examples/memory-usage/json-to-csv.js +28 -0
- package/examples/memory-usage/memory-log-example.json +3 -0
- package/examples/memory-usage/memory-log.json +3 -0
- package/examples/memory-usage/start-node.js +57 -0
- package/index.js +1 -1
- package/lib/adapters/ipfs-adapter.js +3 -3
- package/lib/controllers/timer-controller.js +3 -3
- package/lib/use-cases/pubsub-use-cases.js +2 -2
- package/lib/use-cases/this-node-use-cases.js +1 -0
- package/mem-test/README.md +12 -0
- package/mem-test/create-helia-node.js +154 -0
- package/mem-test/json-to-csv.js +28 -0
- package/mem-test/memory-log.json +3 -0
- package/mem-test/snapshots/v1.5.8/00-v1.5.8/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/01-baseline/01-baseline.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/02-pubsub/02-pubsub.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/02-pubsub/memory-log.json +324 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-1/memory-log.csv +61 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-1/memory-log.json +604 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-1/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-2/README.md +8 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-2/memory-log.csv +55 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-2/memory-log.json +544 -0
- package/mem-test/snapshots/v1.5.8/03-init-connections-2/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-1/README.md +4 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-1/memory-log.csv +77 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-1/memory-log.json +764 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-1/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-2/README.md +4 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-2/memory-log.csv +61 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-2/memory-log.json +604 -0
- package/mem-test/snapshots/v1.5.8/04-relay-reconnect-2/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-1/README.md +5 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-1/memory-log.csv +493 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-1/memory-log.json +4924 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-1/memory-log.xlsx +0 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-2/README.md +5 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-2/memory-log.csv +64 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-2/memory-log.json +634 -0
- package/mem-test/snapshots/v1.5.8/05-peer-reconnect-2/memory-log.xlsx +0 -0
- package/mem-test/start-node.js +57 -0
- package/package.json +12 -12
|
@@ -81,7 +81,7 @@ class CreateHeliaNode {
|
|
|
81
81
|
// Configure services
|
|
82
82
|
const services = {
|
|
83
83
|
identify: identify(),
|
|
84
|
-
pubsub: gossipsub({
|
|
84
|
+
pubsub: gossipsub({ allowPublishToZeroTopicPeers: true })
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// libp2p is the networking layer that underpins Helia
|
|
@@ -143,6 +143,8 @@ class CreateHeliaNode {
|
|
|
143
143
|
|
|
144
144
|
!fs.existsSync(`${IPFS_DIR}/datastore`) && fs.mkdirSync(`${IPFS_DIR}/datastore`)
|
|
145
145
|
|
|
146
|
+
// !fs.existsSync(`${IPFS_DIR}/datastore/peers`) && fs.mkdirSync(`${IPFS_DIR}/datastore/peers`)
|
|
147
|
+
|
|
146
148
|
return true
|
|
147
149
|
} catch (err) {
|
|
148
150
|
console.error('Error in ensureBlocksDir(): ', err)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Memory Usage
|
|
2
|
+
|
|
3
|
+
This is the same example app as the directory above, but it's been modified to take
|
|
4
|
+
periodic memory snapshots and write the memory usage to a JSON file. This is useful
|
|
5
|
+
for tracking potential memory leaks by monitoring memory usage over time.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Copy the `memory-log-example.json` to a new file called `memory-log.json`
|
|
10
|
+
|
|
11
|
+
Run this program with:
|
|
12
|
+
- `node start-node.js`
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This library creates a Helia IPFS node. This is done prior to attaching
|
|
3
|
+
helia-coord to the node.
|
|
4
|
+
This library is called by start-node.js.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import { createHelia } from 'helia'
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
import { FsBlockstore } from 'blockstore-fs'
|
|
11
|
+
import { FsDatastore } from 'datastore-fs'
|
|
12
|
+
import { createLibp2p } from 'libp2p'
|
|
13
|
+
import { tcp } from '@libp2p/tcp'
|
|
14
|
+
import { noise } from '@chainsafe/libp2p-noise'
|
|
15
|
+
import { yamux } from '@chainsafe/libp2p-yamux'
|
|
16
|
+
// import { bootstrap } from '@libp2p/bootstrap'
|
|
17
|
+
// import { identifyService } from 'libp2p/identify'
|
|
18
|
+
import { identify } from '@libp2p/identify'
|
|
19
|
+
// import { circuitRelayTransport } from 'libp2p/circuit-relay'
|
|
20
|
+
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
21
|
+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
|
|
22
|
+
import { webSockets } from '@libp2p/websockets'
|
|
23
|
+
import { publicIpv4 } from 'public-ip'
|
|
24
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
25
|
+
import { webRTC } from '@libp2p/webrtc'
|
|
26
|
+
|
|
27
|
+
const ROOT_DIR = './'
|
|
28
|
+
const IPFS_DIR = './.ipfsdata/ipfs'
|
|
29
|
+
|
|
30
|
+
class CreateHeliaNode {
|
|
31
|
+
constructor () {
|
|
32
|
+
this.publicIp = publicIpv4
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Start an IPFS node.
|
|
36
|
+
async start () {
|
|
37
|
+
try {
|
|
38
|
+
// Ensure the directory structure exists that is needed by the IPFS node to store data.
|
|
39
|
+
this.ensureBlocksDir()
|
|
40
|
+
|
|
41
|
+
// Create an IPFS node
|
|
42
|
+
const ipfs = await this.createNode()
|
|
43
|
+
// console.log('ipfs: ', ipfs)
|
|
44
|
+
|
|
45
|
+
this.id = ipfs.libp2p.peerId.toString()
|
|
46
|
+
console.log('IPFS ID: ', this.id)
|
|
47
|
+
|
|
48
|
+
// Attempt to guess our ip4 IP address.
|
|
49
|
+
const ip4 = await this.publicIp()
|
|
50
|
+
let detectedMultiaddr = `/ip4/${ip4}/tcp/4001/p2p/${this.id}`
|
|
51
|
+
detectedMultiaddr = multiaddr(detectedMultiaddr)
|
|
52
|
+
|
|
53
|
+
// Get the multiaddrs for the node.
|
|
54
|
+
const multiaddrs = ipfs.libp2p.getMultiaddrs()
|
|
55
|
+
multiaddrs.push(detectedMultiaddr)
|
|
56
|
+
console.log('Multiaddrs: ', multiaddrs)
|
|
57
|
+
|
|
58
|
+
this.multiaddrs = multiaddrs
|
|
59
|
+
|
|
60
|
+
// Signal that this adapter is ready.
|
|
61
|
+
this.isReady = true
|
|
62
|
+
|
|
63
|
+
this.ipfs = ipfs
|
|
64
|
+
|
|
65
|
+
return this.ipfs
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error('Error in start()')
|
|
68
|
+
|
|
69
|
+
throw err
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// This function creates an IPFS node using Helia.
|
|
74
|
+
// It returns the node as an object.
|
|
75
|
+
async createNode () {
|
|
76
|
+
try {
|
|
77
|
+
// Create block and data stores.
|
|
78
|
+
const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`)
|
|
79
|
+
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
|
|
80
|
+
|
|
81
|
+
// Configure services
|
|
82
|
+
const services = {
|
|
83
|
+
identify: identify(),
|
|
84
|
+
pubsub: gossipsub({ allowPublishToZeroPeers: true })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// libp2p is the networking layer that underpins Helia
|
|
88
|
+
const libp2p = await createLibp2p({
|
|
89
|
+
datastore,
|
|
90
|
+
addresses: {
|
|
91
|
+
listen: [
|
|
92
|
+
'/ip4/127.0.0.1/tcp/0',
|
|
93
|
+
'/ip4/0.0.0.0/tcp/4001',
|
|
94
|
+
'/ip4/0.0.0.0/tcp/4003/ws',
|
|
95
|
+
'/webrtc'
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
transports: [
|
|
99
|
+
tcp(),
|
|
100
|
+
webSockets(),
|
|
101
|
+
circuitRelayTransport({ discoverRelays: 3 }),
|
|
102
|
+
webRTC()
|
|
103
|
+
],
|
|
104
|
+
connectionEncryption: [
|
|
105
|
+
noise()
|
|
106
|
+
],
|
|
107
|
+
streamMuxers: [
|
|
108
|
+
yamux()
|
|
109
|
+
],
|
|
110
|
+
services
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// create a Helia node
|
|
114
|
+
const helia = await createHelia({
|
|
115
|
+
blockstore,
|
|
116
|
+
datastore,
|
|
117
|
+
libp2p
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return helia
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.error('Error creating Helia node: ', err)
|
|
123
|
+
|
|
124
|
+
throw err
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async stop () {
|
|
129
|
+
await this.ipfs.stop()
|
|
130
|
+
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Ensure that the directories exist to store blocks from the IPFS network.
|
|
135
|
+
// This function is called at startup, before the IPFS node is started.
|
|
136
|
+
ensureBlocksDir () {
|
|
137
|
+
try {
|
|
138
|
+
!fs.existsSync(`${ROOT_DIR}.ipfsdata`) && fs.mkdirSync(`${ROOT_DIR}.ipfsdata`)
|
|
139
|
+
|
|
140
|
+
!fs.existsSync(`${IPFS_DIR}`) && fs.mkdirSync(`${IPFS_DIR}`)
|
|
141
|
+
|
|
142
|
+
!fs.existsSync(`${IPFS_DIR}/blockstore`) && fs.mkdirSync(`${IPFS_DIR}/blockstore`)
|
|
143
|
+
|
|
144
|
+
!fs.existsSync(`${IPFS_DIR}/datastore`) && fs.mkdirSync(`${IPFS_DIR}/datastore`)
|
|
145
|
+
|
|
146
|
+
return true
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error('Error in ensureBlocksDir(): ', err)
|
|
149
|
+
throw err
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default CreateHeliaNode
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This app converts the memory-log.json file to a CSV file that can be imported
|
|
3
|
+
into a spreadsheet for further analysis.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
|
|
8
|
+
async function jsonToCsv () {
|
|
9
|
+
try {
|
|
10
|
+
const log = JSON.parse(fs.readFileSync('./memory-log.json'))
|
|
11
|
+
const memoryLogs = log.memoryLogs
|
|
12
|
+
|
|
13
|
+
let outStr = 'timestampIso,timestampJs,heapTotal (MB),heapUsed (MB),external (MB),arrayBuffers (MB),rss (MB)\n'
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < memoryLogs.length; i++) {
|
|
16
|
+
const thisLog = memoryLogs[i]
|
|
17
|
+
|
|
18
|
+
outStr += `${thisLog.timestampIso},${thisLog.timestampJs},${thisLog.heapTotal / 1000000},${thisLog.heapUsed / 1000000},${thisLog.external / 1000000},${thisLog.arrayBuffers / 1000000},${thisLog.rss / 1000000}\n`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await fs.writeFileSync('./memory-log.csv', outStr)
|
|
22
|
+
console.log('JSON memory log converted to CSV file.')
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.error('Error in jsonToCsv(): ', err)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
jsonToCsv()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This is an example of how to start a Helia IPFS node with node.js and attach
|
|
3
|
+
the helia-coord library to it.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Global npm libraries
|
|
7
|
+
import SlpWallet from 'minimal-slp-wallet'
|
|
8
|
+
import { memoryUsage } from 'node:process'
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
|
|
11
|
+
// Local libraries
|
|
12
|
+
import IpfsCoord from '../../index.js'
|
|
13
|
+
import CreateHeliaNode from './create-helia-node.js'
|
|
14
|
+
|
|
15
|
+
async function start () {
|
|
16
|
+
// Create an instance of bch-js and IPFS.
|
|
17
|
+
const wallet = new SlpWallet()
|
|
18
|
+
await wallet.walletInfoPromise
|
|
19
|
+
|
|
20
|
+
const createHeliaNode = new CreateHeliaNode()
|
|
21
|
+
const ipfs = await createHeliaNode.start()
|
|
22
|
+
|
|
23
|
+
// Pass bch-js and IPFS to ipfs-coord when instantiating it.
|
|
24
|
+
const ipfsCoord = new IpfsCoord({
|
|
25
|
+
ipfs,
|
|
26
|
+
wallet,
|
|
27
|
+
type: 'node.js',
|
|
28
|
+
// type: 'browser'
|
|
29
|
+
nodeType: 'external',
|
|
30
|
+
debugLevel: 2
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
await ipfsCoord.start()
|
|
34
|
+
console.log('IPFS and the coordination library is ready.')
|
|
35
|
+
|
|
36
|
+
setInterval(async function () {
|
|
37
|
+
try {
|
|
38
|
+
const memoryLog = JSON.parse(fs.readFileSync('./memory-log.json'))
|
|
39
|
+
// console.log('memoryLog: ', memoryLog)
|
|
40
|
+
|
|
41
|
+
const memory = memoryUsage()
|
|
42
|
+
|
|
43
|
+
const now = new Date()
|
|
44
|
+
memory.timestampIso = now.toISOString()
|
|
45
|
+
memory.timestampLocal = now.toLocaleString()
|
|
46
|
+
memory.timestampJs = now.getTime()
|
|
47
|
+
|
|
48
|
+
memoryLog.memoryLogs.push(memory)
|
|
49
|
+
|
|
50
|
+
await fs.writeFileSync('./memory-log.json', JSON.stringify(memoryLog, null, 2))
|
|
51
|
+
console.log(`Memory logged at ${now.toLocaleString()}`)
|
|
52
|
+
} catch (err) {
|
|
53
|
+
console.error('Error trying to measure memory: ', err)
|
|
54
|
+
}
|
|
55
|
+
}, 60000)
|
|
56
|
+
}
|
|
57
|
+
start()
|
package/index.js
CHANGED
|
@@ -90,7 +90,7 @@ class IpfsCoord {
|
|
|
90
90
|
this.useCases.pubsub.updateThisNode(this.thisNode)
|
|
91
91
|
|
|
92
92
|
// Subscribe to Pubsub Channels
|
|
93
|
-
//
|
|
93
|
+
// feature commented out
|
|
94
94
|
await this.useCases.pubsub.initializePubsub({ controllers: this.controllers })
|
|
95
95
|
|
|
96
96
|
// Start timer-based controllers.
|
|
@@ -76,14 +76,14 @@ class IpfsAdapter {
|
|
|
76
76
|
// Attempts to connect to an IPFS peer, given its IPFS multiaddr.
|
|
77
77
|
// Returns true if the connection succeeded. Otherwise returns false.
|
|
78
78
|
async connectToPeer (inObj = {}) {
|
|
79
|
+
const { multiaddr } = inObj
|
|
80
|
+
|
|
79
81
|
try {
|
|
80
82
|
// console.log('connectToPeer() inObj: ', inObj)
|
|
81
83
|
|
|
82
84
|
// TODO: Throw error if ipfs ID is passed, instead of a multiaddr.
|
|
83
85
|
// console.log('ipfsAddr: ', ipfsAddr)
|
|
84
86
|
|
|
85
|
-
const { multiaddr } = inObj
|
|
86
|
-
|
|
87
87
|
// await this.ipfs.swarm.connect(ipfsAddr, { timeout: CONNECTION_TIMEOUT })
|
|
88
88
|
await this.ipfs.libp2p.dial(this.multiaddr(multiaddr))
|
|
89
89
|
// console.log('connectToPeer() result: ', result)
|
|
@@ -97,7 +97,7 @@ class IpfsAdapter {
|
|
|
97
97
|
} catch (err) {
|
|
98
98
|
/* exit quietly */
|
|
99
99
|
// console.log('connectToPeer() Error connecting to peer: ', err)
|
|
100
|
-
this.log.statusLog(2,
|
|
100
|
+
this.log.statusLog(2, `Error trying to connect to peer node ${multiaddr}: `, err.message)
|
|
101
101
|
|
|
102
102
|
return {
|
|
103
103
|
success: false,
|
|
@@ -81,9 +81,9 @@ class TimerControllers {
|
|
|
81
81
|
|
|
82
82
|
// Periodically try to connect to problematic peers that advertise as
|
|
83
83
|
// potential circuit relays.
|
|
84
|
-
this.relaySearchHandle = setInterval(async function () {
|
|
85
|
-
|
|
86
|
-
}, this.relaySearchInterval)
|
|
84
|
+
// this.relaySearchHandle = setInterval(async function () {
|
|
85
|
+
// await _this.searchForRelays(thisNode, useCases)
|
|
86
|
+
// }, this.relaySearchInterval)
|
|
87
87
|
|
|
88
88
|
this.listPubsubChannelsHandle = setInterval(async function () {
|
|
89
89
|
await _this.listPubsubChannels()
|
|
@@ -151,7 +151,7 @@ class PubsubUseCase {
|
|
|
151
151
|
// Skip any repeated messages
|
|
152
152
|
const shouldProcess = this.checkForDuplicateMsg(msg)
|
|
153
153
|
if (!shouldProcess) {
|
|
154
|
-
console.log('parseCoordPubsub() duplicate message.')
|
|
154
|
+
// console.log('parseCoordPubsub() duplicate message.')
|
|
155
155
|
return false
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -162,7 +162,7 @@ class PubsubUseCase {
|
|
|
162
162
|
// Ignore this message if it originated from this IPFS node.
|
|
163
163
|
const thisNodeId = this.adapters.ipfs.ipfsPeerId
|
|
164
164
|
if (from === thisNodeId) {
|
|
165
|
-
console.log('parseCoordPubsub() message came from this node.')
|
|
165
|
+
// console.log('parseCoordPubsub() message came from this node.')
|
|
166
166
|
return false
|
|
167
167
|
}
|
|
168
168
|
|
|
@@ -97,6 +97,7 @@ class ThisNodeUseCases {
|
|
|
97
97
|
|
|
98
98
|
// Subscribe to my own pubsub channel, for receiving info from other peers.
|
|
99
99
|
this.tempHandler = () => {} // This handler will be overwritten by handleNewMessage()
|
|
100
|
+
|
|
100
101
|
selfData.pubsub = await this.adapters.pubsub.subscribeToPubsubChannel(
|
|
101
102
|
selfData.ipfsId,
|
|
102
103
|
this.tempHandler,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Memory Usage
|
|
2
|
+
|
|
3
|
+
This is the same example app as the directory above, but it's been modified to take
|
|
4
|
+
periodic memory snapshots and write the memory usage to a JSON file. This is useful
|
|
5
|
+
for tracking potential memory leaks by monitoring memory usage over time.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Copy the `memory-log-example.json` to a new file called `memory-log.json`
|
|
10
|
+
|
|
11
|
+
Run this program with:
|
|
12
|
+
- `node start-node.js`
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This library creates a Helia IPFS node. This is done prior to attaching
|
|
3
|
+
helia-coord to the node.
|
|
4
|
+
This library is called by start-node.js.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Global npm libraries
|
|
8
|
+
import { createHelia } from 'helia'
|
|
9
|
+
import fs from 'fs'
|
|
10
|
+
import { FsBlockstore } from 'blockstore-fs'
|
|
11
|
+
import { FsDatastore } from 'datastore-fs'
|
|
12
|
+
import { createLibp2p } from 'libp2p'
|
|
13
|
+
import { tcp } from '@libp2p/tcp'
|
|
14
|
+
import { noise } from '@chainsafe/libp2p-noise'
|
|
15
|
+
import { yamux } from '@chainsafe/libp2p-yamux'
|
|
16
|
+
// import { bootstrap } from '@libp2p/bootstrap'
|
|
17
|
+
// import { identifyService } from 'libp2p/identify'
|
|
18
|
+
import { identify } from '@libp2p/identify'
|
|
19
|
+
// import { circuitRelayTransport } from 'libp2p/circuit-relay'
|
|
20
|
+
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
21
|
+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
|
|
22
|
+
import { webSockets } from '@libp2p/websockets'
|
|
23
|
+
import { publicIpv4 } from 'public-ip'
|
|
24
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
25
|
+
import { webRTC } from '@libp2p/webrtc'
|
|
26
|
+
|
|
27
|
+
const ROOT_DIR = './'
|
|
28
|
+
const IPFS_DIR = './.ipfsdata/ipfs'
|
|
29
|
+
|
|
30
|
+
class CreateHeliaNode {
|
|
31
|
+
constructor () {
|
|
32
|
+
this.publicIp = publicIpv4
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Start an IPFS node.
|
|
36
|
+
async start () {
|
|
37
|
+
try {
|
|
38
|
+
// Ensure the directory structure exists that is needed by the IPFS node to store data.
|
|
39
|
+
this.ensureBlocksDir()
|
|
40
|
+
|
|
41
|
+
// Create an IPFS node
|
|
42
|
+
const ipfs = await this.createNode()
|
|
43
|
+
// console.log('ipfs: ', ipfs)
|
|
44
|
+
|
|
45
|
+
this.id = ipfs.libp2p.peerId.toString()
|
|
46
|
+
console.log('IPFS ID: ', this.id)
|
|
47
|
+
|
|
48
|
+
// Attempt to guess our ip4 IP address.
|
|
49
|
+
const ip4 = await this.publicIp()
|
|
50
|
+
let detectedMultiaddr = `/ip4/${ip4}/tcp/4001/p2p/${this.id}`
|
|
51
|
+
detectedMultiaddr = multiaddr(detectedMultiaddr)
|
|
52
|
+
|
|
53
|
+
// Get the multiaddrs for the node.
|
|
54
|
+
const multiaddrs = ipfs.libp2p.getMultiaddrs()
|
|
55
|
+
multiaddrs.push(detectedMultiaddr)
|
|
56
|
+
console.log('Multiaddrs: ', multiaddrs)
|
|
57
|
+
|
|
58
|
+
this.multiaddrs = multiaddrs
|
|
59
|
+
|
|
60
|
+
// Signal that this adapter is ready.
|
|
61
|
+
this.isReady = true
|
|
62
|
+
|
|
63
|
+
this.ipfs = ipfs
|
|
64
|
+
|
|
65
|
+
return this.ipfs
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error('Error in start()')
|
|
68
|
+
|
|
69
|
+
throw err
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// This function creates an IPFS node using Helia.
|
|
74
|
+
// It returns the node as an object.
|
|
75
|
+
async createNode () {
|
|
76
|
+
try {
|
|
77
|
+
// Create block and data stores.
|
|
78
|
+
const blockstore = new FsBlockstore(`${IPFS_DIR}/blockstore`)
|
|
79
|
+
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
|
|
80
|
+
|
|
81
|
+
// Configure services
|
|
82
|
+
const services = {
|
|
83
|
+
identify: identify(),
|
|
84
|
+
pubsub: gossipsub({ allowPublishToZeroPeers: true })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// libp2p is the networking layer that underpins Helia
|
|
88
|
+
const libp2p = await createLibp2p({
|
|
89
|
+
datastore,
|
|
90
|
+
addresses: {
|
|
91
|
+
listen: [
|
|
92
|
+
'/ip4/127.0.0.1/tcp/0',
|
|
93
|
+
'/ip4/0.0.0.0/tcp/4001',
|
|
94
|
+
'/ip4/0.0.0.0/tcp/4003/ws',
|
|
95
|
+
'/webrtc'
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
transports: [
|
|
99
|
+
tcp(),
|
|
100
|
+
webSockets(),
|
|
101
|
+
circuitRelayTransport({ discoverRelays: 3 }),
|
|
102
|
+
webRTC()
|
|
103
|
+
],
|
|
104
|
+
connectionEncryption: [
|
|
105
|
+
noise()
|
|
106
|
+
],
|
|
107
|
+
streamMuxers: [
|
|
108
|
+
yamux()
|
|
109
|
+
],
|
|
110
|
+
services
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// create a Helia node
|
|
114
|
+
const helia = await createHelia({
|
|
115
|
+
blockstore,
|
|
116
|
+
datastore,
|
|
117
|
+
libp2p
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
return helia
|
|
121
|
+
} catch (err) {
|
|
122
|
+
console.error('Error creating Helia node: ', err)
|
|
123
|
+
|
|
124
|
+
throw err
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async stop () {
|
|
129
|
+
await this.ipfs.stop()
|
|
130
|
+
|
|
131
|
+
return true
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Ensure that the directories exist to store blocks from the IPFS network.
|
|
135
|
+
// This function is called at startup, before the IPFS node is started.
|
|
136
|
+
ensureBlocksDir () {
|
|
137
|
+
try {
|
|
138
|
+
!fs.existsSync(`${ROOT_DIR}.ipfsdata`) && fs.mkdirSync(`${ROOT_DIR}.ipfsdata`)
|
|
139
|
+
|
|
140
|
+
!fs.existsSync(`${IPFS_DIR}`) && fs.mkdirSync(`${IPFS_DIR}`)
|
|
141
|
+
|
|
142
|
+
!fs.existsSync(`${IPFS_DIR}/blockstore`) && fs.mkdirSync(`${IPFS_DIR}/blockstore`)
|
|
143
|
+
|
|
144
|
+
!fs.existsSync(`${IPFS_DIR}/datastore`) && fs.mkdirSync(`${IPFS_DIR}/datastore`)
|
|
145
|
+
|
|
146
|
+
return true
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.error('Error in ensureBlocksDir(): ', err)
|
|
149
|
+
throw err
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export default CreateHeliaNode
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/*
|
|
2
|
+
This app converts the memory-log.json file to a CSV file that can be imported
|
|
3
|
+
into a spreadsheet for further analysis.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
|
|
8
|
+
async function jsonToCsv () {
|
|
9
|
+
try {
|
|
10
|
+
const log = JSON.parse(fs.readFileSync('./memory-log.json'))
|
|
11
|
+
const memoryLogs = log.memoryLogs
|
|
12
|
+
|
|
13
|
+
let outStr = 'timestampIso,timestampJs,heapTotal (MB),heapUsed (MB),external (MB),arrayBuffers (MB),rss (MB)\n'
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < memoryLogs.length; i++) {
|
|
16
|
+
const thisLog = memoryLogs[i]
|
|
17
|
+
|
|
18
|
+
outStr += `${thisLog.timestampIso},${thisLog.timestampJs},${thisLog.heapTotal / 1000000},${thisLog.heapUsed / 1000000},${thisLog.external / 1000000},${thisLog.arrayBuffers / 1000000},${thisLog.rss / 1000000}\n`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await fs.writeFileSync('./memory-log.csv', outStr)
|
|
22
|
+
console.log('JSON memory log converted to CSV file.')
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.error('Error in jsonToCsv(): ', err)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
jsonToCsv()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|