fix(helia): Manually porting @achingbrian PR to v5 branch

This commit is contained in:
Chris Troutner
2025-02-20 20:51:09 -07:00
parent e5cdf28e34
commit 4d9e948e30
5 changed files with 471 additions and 832 deletions
+1
View File
@@ -131,6 +131,7 @@ export default {
// IPFS Ports
ipfsTcpPort: process.env.IPFS_TCP_PORT ? process.env.IPFS_TCP_PORT : 4001,
ipfsWsPort: process.env.IPFS_WS_PORT ? process.env.IPFS_WS_PORT : 4003,
ipfsWebRtcPort: process.env.IPFS_WEB_RTC_PORT ? process.env.IPFS_WEB_RTC_PORT : 4005,
// Settings for production, using external go-ipfs node.
isProduction: process.env.SVC_ENV === 'prod' ? true : false,
+356 -759
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -28,14 +28,15 @@
"@chainsafe/libp2p-noise": "16.0.1",
"@chainsafe/libp2p-yamux": "7.0.1",
"@helia/unixfs": "4.0.2",
"@libp2p/bootstrap": "11.0.22",
"@libp2p/circuit-relay-v2": "3.1.12",
"@libp2p/identify": "3.0.18",
"@libp2p/bootstrap": "11.0.23",
"@libp2p/circuit-relay-v2": "3.1.13",
"@libp2p/config": "1.1.0",
"@libp2p/identify": "3.0.19",
"@libp2p/keychain": "5.0.14",
"@libp2p/logger": "5.1.8",
"@libp2p/ping": "2.0.18",
"@libp2p/tcp": "10.0.19",
"@libp2p/webrtc": "5.1.0",
"@libp2p/tcp": "10.0.20",
"@libp2p/webrtc": "5.1.1",
"@libp2p/websockets": "9.1.5",
"@multiformats/multiaddr": "12.3.5",
"axios": "0.27.2",
@@ -59,7 +60,7 @@
"koa-router": "10.0.0",
"koa-static": "5.0.0",
"koa2-ratelimit": "0.9.1",
"libp2p": "2.6.2",
"libp2p": "2.6.3",
"line-reader": "0.4.0",
"minimal-slp-wallet": "5.13.2",
"mongoose": "5.13.14",
+77 -37
View File
@@ -19,19 +19,20 @@ import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
// import { bootstrap } from '@libp2p/bootstrap'
// import { identifyService } from 'libp2p/identify'
import { identify } from '@libp2p/identify'
import { identify, identifyPush } from '@libp2p/identify'
import { circuitRelayServer, circuitRelayTransport } from '@libp2p/circuit-relay-v2'
// import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
import { webSockets } from '@libp2p/websockets'
import { publicIpv4 } from 'public-ip'
import { multiaddr } from '@multiformats/multiaddr'
import { webRTC } from '@libp2p/webrtc'
import { webRTC, webRTCDirect } from '@libp2p/webrtc'
import { keychain } from '@libp2p/keychain'
import { unixfs } from '@helia/unixfs'
import { generateKeyPairFromSeed } from '@libp2p/crypto/keys'
import crypto from 'crypto'
// import { generateKeyPairFromSeed } from '@libp2p/crypto/keys'
// import crypto from 'crypto'
import { ping } from '@libp2p/ping'
import { loadOrCreateSelfKey } from '@libp2p/config'
// Local libraries
import config from '../../../config/index.js'
@@ -66,7 +67,8 @@ class IpfsAdapter {
this.createNode = this.createNode.bind(this)
this.stop = this.stop.bind(this)
this.ensureBlocksDir = this.ensureBlocksDir.bind(this)
this.getPrivateKey = this.getPrivateKey.bind(this)
// this.getPrivateKey = this.getPrivateKey.bind(this)
this.getSeed = this.getSeed.bind(this)
}
// Start an IPFS node.
@@ -121,14 +123,23 @@ class IpfsAdapter {
const datastore = new FsDatastore(`${IPFS_DIR}/datastore`)
// Get the private key.
const privateKey = await this.getPrivateKey()
// const privateKey = await this.getPrivateKey()
// console.log('privateKey: ', privateKey)
// Create an identity
const keychainInit = {
selfKey: 'myKey',
pass: await this.getSeed()
}
const privateKey = await loadOrCreateSelfKey(datastore, keychainInit)
// Configure services
const services = {
identify: identify(),
identifyPush: identifyPush(),
pubsub: gossipsub({ allowPublishToZeroTopicPeers: true }),
ping: ping()
ping: ping(),
keychain: keychain(keychainInit)
}
if (this.config.isCircuitRelay) {
console.log('Helia (IPFS) node IS configured as Circuit Relay')
@@ -140,10 +151,10 @@ class IpfsAdapter {
reservationClearInterval: 300 * 1000, // how often to reclaim stale reservations
applyDefaultLimit: true, // whether to apply default data/duration limits to each relayed connection
defaultDurationLimit: 2 * 60 * 1000, // the default maximum amount of time a relayed connection can be open for
defaultDataLimit: BigInt(2 << 7), // the default maximum number of bytes that can be transferred over a relayed connection
defaultDataLimit: BigInt(2 << 7) // the default maximum number of bytes that can be transferred over a relayed connection
},
maxInboundHopStreams: 32, // how many inbound HOP streams are allow simultaneously
maxOutboundHopStreams: 64 // how many outbound HOP streams are allow simultaneously
}
})
} else {
console.log('Helia (IPFS) node IS NOT configured as Circuit Relay')
@@ -156,7 +167,8 @@ class IpfsAdapter {
discoverRelays: 3,
reservationConcurrency: 3
}),
webRTC()
webRTC(),
webRTCDirect()
]
// libp2p is the networking layer that underpins Helia
@@ -231,47 +243,75 @@ class IpfsAdapter {
}
}
// Get the private key from disk, or generate a new one and save it,
// if it doesn't exist.
async getPrivateKey () {
// This function opens the seed used to generate the key for this IPFS peer.
// The seed is stored in a JSON file. If it doesn't exist, a new one is created.
async getSeed () {
try {
const filename = `${IPFS_DIR}/privkey.json`
let seed
const filename = `${IPFS_DIR}/seed.json`
let privKeyHex
try {
// Try to read the JSON file containing the seed.
privKeyHex = await this.jsonFiles.readJSON(filename)
// console.log('saved privKeyHex: ', privKeyHex)
seed = await this.jsonFiles.readJSON(filename)
} catch (err) {
// Generate a new private key and save it to disk.
// Generate a new private key and save it to disk.
const randomBuffer = crypto.randomBytes(32)
// console.log('randomBuffer: ', randomBuffer)
privKeyHex = randomBuffer.toString('hex')
// console.log('new privKeyHex: ', privKeyHex)
const seedNum = Math.floor(Math.random() * 1000000000000000000000)
seed = seedNum.toString()
// Save the newly generated seed
await this.jsonFiles.writeJSON(privKeyHex, filename)
await this.jsonFiles.writeJSON(seed, filename)
}
// Convert the saved hex string to a buffer.
const privKeyBuf = Buffer.from(privKeyHex, 'hex')
// console.log('getSeed() seed: ', seed)
// Convert the buffer to a Uint8Array 'seed'
const seed = new Uint8Array(privKeyBuf.buffer, privKeyBuf.byteOffset, privKeyBuf.byteLength)
// console.log('seed: ', seed)
// Generate a ED25519 key pair.
const privKey = await generateKeyPairFromSeed('Ed25519', seed)
return privKey
return seed
} catch (err) {
console.error('Error in adapters/ipfs/ipfs.js/getPrivateKey(): ', err)
console.error('Error in adapters/ipfs/ipfs.js/getSeed()')
throw err
}
}
// Get the private key from disk, or generate a new one and save it,
// if it doesn't exist.
// async getPrivateKey () {
// try {
// const filename = `${IPFS_DIR}/privkey.json`
// let privKeyHex
// try {
// // Try to read the JSON file containing the seed.
// privKeyHex = await this.jsonFiles.readJSON(filename)
// // console.log('saved privKeyHex: ', privKeyHex)
// } catch (err) {
// // Generate a new private key and save it to disk.
// // Generate a new private key and save it to disk.
// const randomBuffer = crypto.randomBytes(32)
// // console.log('randomBuffer: ', randomBuffer)
// privKeyHex = randomBuffer.toString('hex')
// // console.log('new privKeyHex: ', privKeyHex)
// // Save the newly generated seed
// await this.jsonFiles.writeJSON(privKeyHex, filename)
// }
// // Convert the saved hex string to a buffer.
// const privKeyBuf = Buffer.from(privKeyHex, 'hex')
// // Convert the buffer to a Uint8Array 'seed'
// const seed = new Uint8Array(privKeyBuf.buffer, privKeyBuf.byteOffset, privKeyBuf.byteLength)
// // console.log('seed: ', seed)
// // Generate a ED25519 key pair.
// const privKey = await generateKeyPairFromSeed('Ed25519', seed)
// return privKey
// } catch (err) {
// console.error('Error in adapters/ipfs/ipfs.js/getPrivateKey(): ', err)
// throw err
// }
// }
}
export default IpfsAdapter
+28 -28
View File
@@ -203,40 +203,40 @@ describe('#IPFS-adapter', () => {
})
})
// describe('#getSeed', () => {
// it('should read the seed from the JSON file', async () => {
// // Mock dependencies and force desired code path
// sandbox.stub(uut.jsonFiles, 'readJSON').resolves('12345678')
describe('#getSeed', () => {
it('should read the seed from the JSON file', async () => {
// Mock dependencies and force desired code path
sandbox.stub(uut.jsonFiles, 'readJSON').resolves('12345678')
// const result = await uut.getSeed()
// // console.log('result: ', result)
const result = await uut.getSeed()
// console.log('result: ', result)
// assert.isString(result)
// })
assert.isString(result)
})
// it('should generate a new seed if the JSON file is not found', async () => {
// // Mock dependencies and force desired code path
// sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
// sandbox.stub(uut.jsonFiles, 'writeJSON').resolves()
it('should generate a new seed if the JSON file is not found', async () => {
// Mock dependencies and force desired code path
sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
sandbox.stub(uut.jsonFiles, 'writeJSON').resolves()
// const result = await uut.getSeed()
// // console.log('result: ', result)
const result = await uut.getSeed()
// console.log('result: ', result)
// assert.isString(result)
// })
assert.isString(result)
})
// it('should catch, report, and throw errors', async () => {
// try {
// // Force an error
// sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
// sandbox.stub(uut.jsonFiles, 'writeJSON').rejects(new Error('test error'))
it('should catch, report, and throw errors', async () => {
try {
// Force an error
sandbox.stub(uut.jsonFiles, 'readJSON').rejects(new Error('test error'))
sandbox.stub(uut.jsonFiles, 'writeJSON').rejects(new Error('test error'))
// await uut.getSeed()
await uut.getSeed()
// assert.fail('Unexpected code path')
// } catch (err) {
// assert.include(err.message, 'test error')
// }
// })
// })
assert.fail('Unexpected code path')
} catch (err) {
assert.include(err.message, 'test error')
}
})
})
})