mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-10-07 22:57:07 +00:00
Merge remote-tracking branch 'origin' into feat/encryption
This commit is contained in:
commit
5f54993660
4
.github/workflows/api-publish.yml
vendored
4
.github/workflows/api-publish.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
|||||||
registry-url: https://registry.npmjs.org/
|
registry-url: https://registry.npmjs.org/
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build:docs
|
- run: npm run build:docs
|
||||||
- uses: actions/upload-pages-artifact@v2
|
- uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: ./docs/api/
|
path: ./docs/api/
|
||||||
|
|
||||||
@ -37,5 +37,5 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
uses: actions/deploy-pages@v2 # or the latest "vX.X.X" version tag for this action
|
uses: actions/deploy-pages@v4 # or the latest "vX.X.X" version tag for this action
|
||||||
|
|
||||||
1
.well-known/funding-manifest-urls
Normal file
1
.well-known/funding-manifest-urls
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://orbitdb.org/funding.json
|
||||||
@ -2,4 +2,10 @@
|
|||||||
|
|
||||||
For now, please refer to our Git commit history for a list of changes.
|
For now, please refer to our Git commit history for a list of changes.
|
||||||
|
|
||||||
https://github.com/orbitdb/orbitdb/commits/v1.0.2
|
https://github.com/orbitdb/orbitdb/compare/v2.4.3...v2.5.0
|
||||||
|
|
||||||
|
You can also use the following git command to generate a log of changes:
|
||||||
|
|
||||||
|
```
|
||||||
|
git log v2.4.3..v2.5.0 --oneline
|
||||||
|
```
|
||||||
|
|||||||
@ -28,7 +28,7 @@ Install OrbitDB and its dependencies:
|
|||||||
npm install @orbitdb/core helia
|
npm install @orbitdb/core helia
|
||||||
```
|
```
|
||||||
|
|
||||||
### Browser <script> tag
|
### Browser `<script>` tag
|
||||||
|
|
||||||
OrbitDB can be loaded in the browser using the distributed js file with the `<script/>` tag. OrbitDB is the global namespace and all external functions are available via this namespace:
|
OrbitDB can be loaded in the browser using the distributed js file with the `<script/>` tag. OrbitDB is the global namespace and all external functions are available via this namespace:
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ const options = {
|
|||||||
filter: filters.all
|
filter: filters.all
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
services: {
|
services: {
|
||||||
identify: identify(),
|
identify: identify(),
|
||||||
@ -114,7 +114,7 @@ const options = {
|
|||||||
discoverRelays: 1
|
discoverRelays: 1
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionGater: {
|
connectionGater: {
|
||||||
denyDialMultiaddr: () => {
|
denyDialMultiaddr: () => {
|
||||||
@ -180,7 +180,7 @@ const options = {
|
|||||||
discoverRelays: 1
|
discoverRelays: 1
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionGater: {
|
connectionGater: {
|
||||||
denyDialMultiaddr: () => {
|
denyDialMultiaddr: () => {
|
||||||
@ -247,7 +247,7 @@ const options = {
|
|||||||
discoverRelays: 1
|
discoverRelays: 1
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionGater: {
|
connectionGater: {
|
||||||
denyDialMultiaddr: () => {
|
denyDialMultiaddr: () => {
|
||||||
|
|||||||
@ -264,7 +264,7 @@ CustomDB.type = type
|
|||||||
export default CustomDB
|
export default CustomDB
|
||||||
```
|
```
|
||||||
|
|
||||||
[Documents](../src/db/documents.js), [Events](../src/db/events.js) and [KeyValue](../src/db/keyvalue.js) provide good examples of how a database is implemented in OrbitDB and how to add the logic for returning records from the database (the state of the database).
|
[Documents](../src/databases/documents.js), [Events](../src/databases/events.js) and [KeyValue](../src/databases/keyvalue.js) provide good examples of how a database is implemented in OrbitDB and how to add the logic for returning records from the database (the state of the database).
|
||||||
|
|
||||||
To use a custom database, add it to the list of supported database types:
|
To use a custom database, add it to the list of supported database types:
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,7 @@ A simple Node.js example might look something like:
|
|||||||
transports: [
|
transports: [
|
||||||
tcp()
|
tcp()
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
services: {
|
services: {
|
||||||
identify: identify(),
|
identify: identify(),
|
||||||
@ -79,7 +79,7 @@ export const Libp2pOptions = {
|
|||||||
transports: [
|
transports: [
|
||||||
tcp()
|
tcp()
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
services: {
|
services: {
|
||||||
identify: identify(),
|
identify: identify(),
|
||||||
@ -104,7 +104,7 @@ Assuming you have a Node.js development environment installed, create a new proj
|
|||||||
mkdir orbitdb-app
|
mkdir orbitdb-app
|
||||||
cd orbitdb-app
|
cd orbitdb-app
|
||||||
npm init
|
npm init
|
||||||
npm i helia orbitdb/core blockstore-level @chainsafe/libp2p-gossipsub
|
npm i helia @orbitdb/core blockstore-level @chainsafe/libp2p-gossipsub
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a file in your project called index.js and add the following code to it:
|
Create a file in your project called index.js and add the following code to it:
|
||||||
@ -159,7 +159,7 @@ const db = await orbitdb.open('my-db')
|
|||||||
to:
|
to:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const db = await orbitdb.open('my-documents-db', { type: 'documents '})
|
const db = await orbitdb.open('my-documents-db', { type: 'documents' })
|
||||||
```
|
```
|
||||||
|
|
||||||
Also replace:
|
Also replace:
|
||||||
@ -172,8 +172,8 @@ await db.add('hello world 2')
|
|||||||
with:
|
with:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
await db.put('doc1', { hello: "world 1", hits: 5 })
|
await db.put({ _id: "doc1", hello: "world 1", hits: 5 })
|
||||||
await db.put('doc2', { hello: "world 2", hits: 2 })
|
await db.put({ _id: "doc2", hello: "world 2", hits: 2 })
|
||||||
```
|
```
|
||||||
|
|
||||||
Run index.js again:
|
Run index.js again:
|
||||||
@ -195,7 +195,7 @@ To create an OrbitDB database peer, create a new project called `orbitdb-peer`:
|
|||||||
mkdir orbitdb-peer
|
mkdir orbitdb-peer
|
||||||
cd orbitdb-peer
|
cd orbitdb-peer
|
||||||
npm init
|
npm init
|
||||||
npm i helia orbitdb/core blockstore-level @chainsafe/libp2p-gossipsub
|
npm i helia @orbitdb/core blockstore-level @chainsafe/libp2p-gossipsub
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a new file called index.js and paste in the following code:
|
Create a new file called index.js and paste in the following code:
|
||||||
@ -206,6 +206,7 @@ import { createHelia } from 'helia'
|
|||||||
import { createOrbitDB, IPFSAccessController } from '@orbitdb/core'
|
import { createOrbitDB, IPFSAccessController } from '@orbitdb/core'
|
||||||
import { LevelBlockstore } from 'blockstore-level'
|
import { LevelBlockstore } from 'blockstore-level'
|
||||||
import { Libp2pOptions } from './config/libp2p.js'
|
import { Libp2pOptions } from './config/libp2p.js'
|
||||||
|
import { multiaddr } from '@multiformats/multiaddr'
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
// create a random directory to avoid OrbitDB conflicts.
|
// create a random directory to avoid OrbitDB conflicts.
|
||||||
@ -219,7 +220,9 @@ const main = async () => {
|
|||||||
|
|
||||||
let db
|
let db
|
||||||
|
|
||||||
if (process.argv[2]) {
|
if (process.argv[2] && process.argv[3]) {
|
||||||
|
await orbitdb.ipfs.libp2p.dial(multiaddr(process.argv[3]))
|
||||||
|
console.log('opening db', process.argv[2])
|
||||||
db = await orbitdb.open(process.argv[2])
|
db = await orbitdb.open(process.argv[2])
|
||||||
} else {
|
} else {
|
||||||
// When we open a new database, write access is only available to the
|
// When we open a new database, write access is only available to the
|
||||||
@ -230,6 +233,8 @@ const main = async () => {
|
|||||||
// access using grant and revoke.
|
// access using grant and revoke.
|
||||||
db = await orbitdb.open('my-db', { AccessController: IPFSAccessController({ write: ['*']}) })
|
db = await orbitdb.open('my-db', { AccessController: IPFSAccessController({ write: ['*']}) })
|
||||||
|
|
||||||
|
console.log('libp2p address', '(copy one of these addresses then dial into this node from the second node)', orbitdb.ipfs.libp2p.getMultiaddrs())
|
||||||
|
|
||||||
// Copy this output if you want to connect a peer to another.
|
// Copy this output if you want to connect a peer to another.
|
||||||
console.log('my-db address', '(copy my db address and use when launching peer 2)', db.address)
|
console.log('my-db address', '(copy my db address and use when launching peer 2)', db.address)
|
||||||
}
|
}
|
||||||
@ -263,27 +268,33 @@ const main = async () => {
|
|||||||
main()
|
main()
|
||||||
```
|
```
|
||||||
|
|
||||||
Open two consoles in your command line terminal.
|
Launch peer 1 from the terminal:
|
||||||
|
|
||||||
In terminal 1, run the first peer:
|
```bash
|
||||||
|
node test.js
|
||||||
```sh
|
|
||||||
node index.js
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When running, you should see the address of the database, for example:
|
Once launched you will see some output which may look something like this:
|
||||||
|
|
||||||
```sh
|
```
|
||||||
|
libp2p address (copy one of these addresses then dial into this node from the second node) [
|
||||||
|
Multiaddr(/ip4/127.0.0.1/tcp/36161/p2p/12D3KooWKFWB78Hka2uPVNYYoXfucWp6rDLsQzr5CFiP67NAo7YF),
|
||||||
|
Multiaddr(/ip4/192.168.1.22/tcp/36161/p2p/12D3KooWKFWB78Hka2uPVNYYoXfucWp6rDLsQzr5CFiP67NAo7YF),
|
||||||
|
Multiaddr(/ip4/100.64.100.6/tcp/36161/p2p/12D3KooWKFWB78Hka2uPVNYYoXfucWp6rDLsQzr5CFiP67NAo7YF)
|
||||||
|
]
|
||||||
my-db address (copy my db address and use when launching peer 2) /orbitdb/zdpuB2aYUCnZ7YUBrDkCWpRLQ8ieUbqJEVRZEd5aDhJBDpBqj
|
my-db address (copy my db address and use when launching peer 2) /orbitdb/zdpuB2aYUCnZ7YUBrDkCWpRLQ8ieUbqJEVRZEd5aDhJBDpBqj
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy the database's address from terminal 1 and, in terminal 2, run:
|
It contains the libp2p address and db address. You will need both of these when connecting from peer 2.
|
||||||
|
|
||||||
```sh
|
Open another terminal and launch peer 2. The command takes the form `node test.js <orbitdb-address> <libp2p-address>`
|
||||||
node index.js /orbitdb/zdpuB2aYUCnZ7YUBrDkCWpRLQ8ieUbqJEVRZEd5aDhJBDpBqj
|
|
||||||
|
```bash
|
||||||
|
node test.js /orbitdb/zdpuB2aYUCnZ7YUBrDkCWpRLQ8ieUbqJEVRZEd5aDhJBDpBqj /ip4/127.0.0.1/tcp/36161/p2p/12D3KooWKFWB78Hka2uPVNYYoXfucWp6rDLsQzr5CFiP67NAo7YF
|
||||||
```
|
```
|
||||||
|
|
||||||
Both peers will print new records to the terminal as the log is updated. When you stop each peer using ctrl+c, the final state of the database will be printed to the terminal. They should match.
|
What is happening is the second peer is dialing the first peer on the /ip4/ address then opens the database.
|
||||||
|
|
||||||
|
|
||||||
**PLEASE NOTE:**
|
**PLEASE NOTE:**
|
||||||
|
|
||||||
|
|||||||
@ -109,7 +109,7 @@ const identity = await identities.createIdentity({ id: 'me' })
|
|||||||
const cid = CID.parse(identity.hash, base58btc)
|
const cid = CID.parse(identity.hash, base58btc)
|
||||||
|
|
||||||
// Extract the hash from the full db path.
|
// Extract the hash from the full db path.
|
||||||
const bytes = await ipfs.block.get(cid)
|
const bytes = await ipfs.blockstore.get(cid)
|
||||||
|
|
||||||
// Defines how we serialize/hash the data.
|
// Defines how we serialize/hash the data.
|
||||||
const codec = dagCbor
|
const codec = dagCbor
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
## OrbitDB API - v2.2
|
## OrbitDB API - v2.5
|
||||||
|
|
||||||
OrbitDB is a serverless, distributed, peer-to-peer database. OrbitDB uses IPFS
|
OrbitDB is a serverless, distributed, peer-to-peer database. OrbitDB uses IPFS
|
||||||
as its data storage and Libp2p Pubsub to automatically sync databases with peers. It's an eventually consistent database that uses Merkle-CRDTs for conflict-free database writes and merges making OrbitDB an excellent choice for p2p and decentralized apps, blockchain applications and local first web applications.
|
as its data storage and Libp2p Pubsub to automatically sync databases with peers. It's an eventually consistent database that uses Merkle-CRDTs for conflict-free database writes and merges making OrbitDB an excellent choice for p2p and decentralized apps, blockchain applications and local first web applications.
|
||||||
|
|||||||
9963
package-lock.json
generated
9963
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@orbitdb/core",
|
"name": "@orbitdb/core",
|
||||||
"version": "2.2.0",
|
"version": "2.5.0",
|
||||||
"description": "Distributed p2p database on IPFS",
|
"description": "Distributed p2p database on IPFS",
|
||||||
"author": "Haad",
|
"author": "Haad",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@ -19,8 +19,7 @@
|
|||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ipld/dag-cbor": "^9.0.6",
|
"@ipld/dag-cbor": "^9.0.6",
|
||||||
"@libp2p/crypto": "^3.0.2",
|
"@libp2p/crypto": "^5.0.5",
|
||||||
"eth-crypto": "^2.6.0",
|
|
||||||
"it-pipe": "^3.0.1",
|
"it-pipe": "^3.0.1",
|
||||||
"level": "^8.0.0",
|
"level": "^8.0.0",
|
||||||
"lru": "^3.1.0",
|
"lru": "^3.1.0",
|
||||||
@ -30,23 +29,20 @@
|
|||||||
"uint8arrays": "^5.0.0"
|
"uint8arrays": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@chainsafe/libp2p-gossipsub": "^13.0.0",
|
"@chainsafe/libp2p-gossipsub": "^14.1.0",
|
||||||
"@chainsafe/libp2p-yamux": "^6.0.1",
|
"@libp2p/circuit-relay-v2": "^3.1.0",
|
||||||
"@helia/block-brokers": "^1.0.0",
|
"blockstore-level": "^2.0.1",
|
||||||
"@libp2p/circuit-relay-v2": "^1.0.10",
|
|
||||||
"blockstore-level": "^1.1.7",
|
|
||||||
"c8": "^8.0.1",
|
"c8": "^8.0.1",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"helia": "^4.0.1",
|
"helia": "^5.1.0",
|
||||||
"it-all": "^3.0.4",
|
"it-all": "^3.0.4",
|
||||||
"jsdoc": "^4.0.2",
|
"jsdoc": "^4.0.2",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"playwright-test": "^14.0.0",
|
"playwright-test": "^14.1.6",
|
||||||
"rimraf": "^5.0.5",
|
"rimraf": "^5.0.5",
|
||||||
"standard": "^17.1.0",
|
"standard": "^17.1.0",
|
||||||
"stream-browserify": "^3.0.0",
|
|
||||||
"webpack": "^5.89.0",
|
"webpack": "^5.89.0",
|
||||||
"webpack-cli": "^5.1.4"
|
"webpack-cli": "^5.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -84,7 +84,7 @@ const IPFSAccessController = ({ write, storage } = {}) => async ({ orbitdb, iden
|
|||||||
// Allow if the write access list contain the writer's id or is '*'
|
// Allow if the write access list contain the writer's id or is '*'
|
||||||
if (write.includes(id) || write.includes('*')) {
|
if (write.includes(id) || write.includes('*')) {
|
||||||
// Check that the identity is valid
|
// Check that the identity is valid
|
||||||
return identities.verifyIdentity(writerIdentity)
|
return await identities.verifyIdentity(writerIdentity)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@ const OrbitDBAccessController = ({ write } = {}) => async ({ orbitdb, identities
|
|||||||
// If the ACL contains the writer's public key or it contains '*'
|
// If the ACL contains the writer's public key or it contains '*'
|
||||||
const hasWriteAccess = await hasCapability('write', id) || await hasCapability('admin', id)
|
const hasWriteAccess = await hasCapability('write', id) || await hasCapability('admin', id)
|
||||||
if (hasWriteAccess) {
|
if (hasWriteAccess) {
|
||||||
return identities.verifyIdentity(writerIdentity)
|
return await identities.verifyIdentity(writerIdentity)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -52,7 +52,7 @@ const PublicKeyIdentityProvider = ({ keystore }) => async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const key = await keystore.getKey(id) || await keystore.createKey(id)
|
const key = await keystore.getKey(id) || await keystore.createKey(id)
|
||||||
return uint8ArrayToString(key.public.marshal(), 'base16')
|
return uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
* const storage = await MemoryStorage()
|
* const storage = await MemoryStorage()
|
||||||
* const keystore = await KeyStore({ storage })
|
* const keystore = await KeyStore({ storage })
|
||||||
*/
|
*/
|
||||||
import * as crypto from '@libp2p/crypto'
|
import { privateKeyFromRaw, publicKeyFromRaw, generateKeyPair } from '@libp2p/crypto/keys'
|
||||||
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
||||||
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
||||||
import { compare as uint8ArrayCompare } from 'uint8arrays/compare'
|
import { compare as uint8ArrayCompare } from 'uint8arrays/compare'
|
||||||
@ -16,9 +16,6 @@ import ComposedStorage from './storage/composed.js'
|
|||||||
import LevelStorage from './storage/level.js'
|
import LevelStorage from './storage/level.js'
|
||||||
import LRUStorage from './storage/lru.js'
|
import LRUStorage from './storage/lru.js'
|
||||||
|
|
||||||
const unmarshal = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey
|
|
||||||
const unmarshalPubKey = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PublicKey
|
|
||||||
|
|
||||||
const verifySignature = async (signature, publicKey, data) => {
|
const verifySignature = async (signature, publicKey, data) => {
|
||||||
if (!signature) {
|
if (!signature) {
|
||||||
throw new Error('No signature given')
|
throw new Error('No signature given')
|
||||||
@ -38,7 +35,7 @@ const verifySignature = async (signature, publicKey, data) => {
|
|||||||
|
|
||||||
let res = false
|
let res = false
|
||||||
try {
|
try {
|
||||||
const pubKey = unmarshalPubKey(uint8ArrayFromString(publicKey, 'base16'))
|
const pubKey = publicKeyFromRaw(uint8ArrayFromString(publicKey, 'base16'))
|
||||||
res = await isValid(pubKey, data, uint8ArrayFromString(signature, 'base16'))
|
res = await isValid(pubKey, data, uint8ArrayFromString(signature, 'base16'))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Catch error: sig length wrong
|
// Catch error: sig length wrong
|
||||||
@ -195,7 +192,7 @@ const KeyStore = async ({ storage, path } = {}) => {
|
|||||||
const { privateKey } = key
|
const { privateKey } = key
|
||||||
await storage.put('private_' + id, privateKey)
|
await storage.put('private_' + id, privateKey)
|
||||||
// Unmarshal the key and add it to the cache
|
// Unmarshal the key and add it to the cache
|
||||||
const unmarshaledPrivateKey = unmarshal(privateKey)
|
const unmarshaledPrivateKey = privateKeyFromRaw(privateKey)
|
||||||
await keyCache.put(id, unmarshaledPrivateKey)
|
await keyCache.put(id, unmarshaledPrivateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,17 +210,16 @@ const KeyStore = async ({ storage, path } = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate a private key
|
// Generate a private key
|
||||||
const keyPair = await crypto.keys.generateKeyPair('secp256k1')
|
const keyPair = await generateKeyPair('secp256k1')
|
||||||
const keys = await crypto.keys.unmarshalPrivateKey(keyPair.bytes)
|
|
||||||
|
|
||||||
const key = {
|
const key = {
|
||||||
publicKey: keys.public.marshal(),
|
publicKey: keyPair.publicKey.raw,
|
||||||
privateKey: keys.marshal()
|
privateKey: keyPair.raw
|
||||||
}
|
}
|
||||||
|
|
||||||
await addKey(id, key)
|
await addKey(id, key)
|
||||||
|
|
||||||
return keys
|
return keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -254,7 +250,8 @@ const KeyStore = async ({ storage, path } = {}) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
key = unmarshal(storedKey)
|
key = privateKeyFromRaw(storedKey)
|
||||||
|
|
||||||
await keyCache.put(id, key)
|
await keyCache.put(id, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +278,7 @@ const KeyStore = async ({ storage, path } = {}) => {
|
|||||||
throw new Error('Supported formats are `hex` and `buffer`')
|
throw new Error('Supported formats are `hex` and `buffer`')
|
||||||
}
|
}
|
||||||
|
|
||||||
const pubKey = keys.public.marshal()
|
const pubKey = keys.publicKey.raw
|
||||||
|
|
||||||
return format === 'buffer' ? pubKey : uint8ArrayToString(pubKey, 'base16')
|
return format === 'buffer' ? pubKey : uint8ArrayToString(pubKey, 'base16')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,13 +16,17 @@ const ManifestStore = async ({ ipfs, storage } = {}) => {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
storage = storage || await ComposedStorage(
|
storage = storage || await ComposedStorage(
|
||||||
await LRUStorage({ size: 1000 }),
|
await LRUStorage({ size: 100000 }),
|
||||||
await IPFSBlockStorage({ ipfs, pin: true })
|
await IPFSBlockStorage({ ipfs, pin: true })
|
||||||
)
|
)
|
||||||
|
|
||||||
const get = async (address) => {
|
const get = async (address) => {
|
||||||
const bytes = await storage.get(address)
|
const bytes = await storage.get(address)
|
||||||
const { value } = await Block.decode({ bytes, codec, hasher })
|
const { value } = await Block.decode({ bytes, codec, hasher })
|
||||||
|
if (value) {
|
||||||
|
// Write to storage to make sure it gets pinned on IPFS
|
||||||
|
await storage.put(address, bytes)
|
||||||
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -194,6 +194,7 @@ const OrbitDB = async ({ ipfs, id, identity, identities, directory } = {}) => {
|
|||||||
ipfs,
|
ipfs,
|
||||||
directory,
|
directory,
|
||||||
keystore,
|
keystore,
|
||||||
|
identities,
|
||||||
identity,
|
identity,
|
||||||
peerId
|
peerId
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/sync.js
10
src/sync.js
@ -197,9 +197,8 @@ const Sync = async ({ ipfs, log, events, onSynced, start, timeout }) => {
|
|||||||
const stream = await libp2p.dialProtocol(remotePeer, headsSyncAddress, { signal })
|
const stream = await libp2p.dialProtocol(remotePeer, headsSyncAddress, { signal })
|
||||||
await pipe(sendHeads, stream, receiveHeads(peerId))
|
await pipe(sendHeads, stream, receiveHeads(peerId))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
|
||||||
peers.delete(peerId)
|
peers.delete(peerId)
|
||||||
if (e.code === 'ERR_UNSUPPORTED_PROTOCOL') {
|
if (e.name === 'UnsupportedProtocolError') {
|
||||||
// Skip peer, they don't have this database currently
|
// Skip peer, they don't have this database currently
|
||||||
} else {
|
} else {
|
||||||
events.emit('error', e)
|
events.emit('error', e)
|
||||||
@ -236,6 +235,10 @@ const Sync = async ({ ipfs, log, events, onSynced, start, timeout }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handlePeerDisconnected = async event => {
|
||||||
|
peers.delete(event.detail.toString())
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a log entry to the Sync Protocol to be sent to peers.
|
* Add a log entry to the Sync Protocol to be sent to peers.
|
||||||
* @function add
|
* @function add
|
||||||
@ -264,6 +267,7 @@ const Sync = async ({ ipfs, log, events, onSynced, start, timeout }) => {
|
|||||||
pubsub.removeEventListener('message', handleUpdateMessage)
|
pubsub.removeEventListener('message', handleUpdateMessage)
|
||||||
await libp2p.unhandle(headsSyncAddress)
|
await libp2p.unhandle(headsSyncAddress)
|
||||||
await pubsub.unsubscribe(address)
|
await pubsub.unsubscribe(address)
|
||||||
|
libp2p.removeEventListener('peer:disconnect', handlePeerDisconnected)
|
||||||
peers.clear()
|
peers.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,6 +286,8 @@ const Sync = async ({ ipfs, log, events, onSynced, start, timeout }) => {
|
|||||||
pubsub.addEventListener('message', handleUpdateMessage)
|
pubsub.addEventListener('message', handleUpdateMessage)
|
||||||
// Subscribe to the pubsub channel for this database through which updates are sent
|
// Subscribe to the pubsub channel for this database through which updates are sent
|
||||||
await pubsub.subscribe(address)
|
await pubsub.subscribe(address)
|
||||||
|
// Remove disconnected peers from `peers`, as otherwise they will not resync heads on reconnection
|
||||||
|
libp2p.addEventListener('peer:disconnect', handlePeerDisconnected)
|
||||||
started = true
|
started = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,7 @@
|
|||||||
import * as crypto from '@libp2p/crypto'
|
import { privateKeyFromRaw } from '@libp2p/crypto/keys'
|
||||||
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
||||||
import { Identities, KeyStore } from '../../src/index.js'
|
import { Identities, KeyStore } from '../../src/index.js'
|
||||||
|
|
||||||
const unmarshal = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey
|
|
||||||
const unmarshalPubKey = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PublicKey
|
|
||||||
|
|
||||||
const keysPath = './testkeys'
|
const keysPath = './testkeys'
|
||||||
|
|
||||||
const isBrowser = () => typeof window !== 'undefined'
|
const isBrowser = () => typeof window !== 'undefined'
|
||||||
@ -52,10 +49,10 @@ before(async () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
for (let user of users) {
|
for (let user of users) {
|
||||||
const privateKey1 = unmarshal(uint8ArrayFromString(user.privateKey, 'base16'))
|
const privateKey1 = privateKeyFromRaw(uint8ArrayFromString(user.privateKey, 'base16'))
|
||||||
const privateKey2 = unmarshal(uint8ArrayFromString(user.identity.privateKey, 'base16'))
|
const privateKey2 = privateKeyFromRaw(uint8ArrayFromString(user.identity.privateKey, 'base16'))
|
||||||
await keystore.addKey(user.id, { privateKey: privateKey1.marshal() })
|
await keystore.addKey(user.id, { privateKey: privateKey1.raw })
|
||||||
await keystore.addKey(user.identity.id, { privateKey: privateKey2.marshal() })
|
await keystore.addKey(user.identity.id, { privateKey: privateKey2.raw })
|
||||||
}
|
}
|
||||||
|
|
||||||
await keystore.close()
|
await keystore.close()
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import createHelia from '../../utils/create-helia.js'
|
|||||||
const keysPath = './testkeys'
|
const keysPath = './testkeys'
|
||||||
|
|
||||||
describe('Documents Database Replication', function () {
|
describe('Documents Database Replication', function () {
|
||||||
this.timeout(30000)
|
this.timeout(10000)
|
||||||
|
|
||||||
let ipfs1, ipfs2
|
let ipfs1, ipfs2
|
||||||
let keystore
|
let keystore
|
||||||
|
|||||||
@ -38,7 +38,7 @@ describe('Identities', function () {
|
|||||||
identities = await Identities({ path: keysPath })
|
identities = await Identities({ path: keysPath })
|
||||||
identity = await identities.createIdentity({ id })
|
identity = await identities.createIdentity({ id })
|
||||||
const key = await identities.keystore.getKey(id)
|
const key = await identities.keystore.getKey(id)
|
||||||
const externalId = uint8ArrayToString(key.public.marshal(), 'base16')
|
const externalId = uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
assert.strictEqual(identity.id, externalId)
|
assert.strictEqual(identity.id, externalId)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -106,7 +106,7 @@ describe('Identities', function () {
|
|||||||
identity = await identities.createIdentity({ id })
|
identity = await identities.createIdentity({ id })
|
||||||
keystore = identities.keystore
|
keystore = identities.keystore
|
||||||
const key = await keystore.getKey(id)
|
const key = await keystore.getKey(id)
|
||||||
const externalId = uint8ArrayToString(key.public.marshal(), 'base16')
|
const externalId = uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
assert.strictEqual(identity.id, externalId)
|
assert.strictEqual(identity.id, externalId)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ describe('Identities', function () {
|
|||||||
|
|
||||||
it('has the correct public key', async () => {
|
it('has the correct public key', async () => {
|
||||||
const key = await keystore.getKey(id)
|
const key = await keystore.getKey(id)
|
||||||
const externalId = uint8ArrayToString(key.public.marshal(), 'base16')
|
const externalId = uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
const signingKey = await keystore.getKey(externalId)
|
const signingKey = await keystore.getKey(externalId)
|
||||||
assert.notStrictEqual(signingKey, undefined)
|
assert.notStrictEqual(signingKey, undefined)
|
||||||
assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
|
assert.strictEqual(identity.publicKey, keystore.getPublic(signingKey))
|
||||||
@ -125,10 +125,10 @@ describe('Identities', function () {
|
|||||||
|
|
||||||
it('has a signature for the id', async () => {
|
it('has a signature for the id', async () => {
|
||||||
const key = await keystore.getKey(id)
|
const key = await keystore.getKey(id)
|
||||||
const externalId = uint8ArrayToString(key.public.marshal(), 'base16')
|
const externalId = uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
const signingKey = await keystore.getKey(externalId)
|
const signingKey = await keystore.getKey(externalId)
|
||||||
const idSignature = await signMessage(signingKey, externalId)
|
const idSignature = await signMessage(signingKey, externalId)
|
||||||
const publicKey = uint8ArrayToString(signingKey.public.marshal(), 'base16')
|
const publicKey = uint8ArrayToString(signingKey.publicKey.raw, 'base16')
|
||||||
const verifies = await verifyMessage(idSignature, publicKey, externalId)
|
const verifies = await verifyMessage(idSignature, publicKey, externalId)
|
||||||
assert.strictEqual(verifies, true)
|
assert.strictEqual(verifies, true)
|
||||||
assert.strictEqual(identity.signatures.id, idSignature)
|
assert.strictEqual(identity.signatures.id, idSignature)
|
||||||
@ -136,7 +136,7 @@ describe('Identities', function () {
|
|||||||
|
|
||||||
it('has a signature for the publicKey', async () => {
|
it('has a signature for the publicKey', async () => {
|
||||||
const key = await keystore.getKey(id)
|
const key = await keystore.getKey(id)
|
||||||
const externalId = uint8ArrayToString(key.public.marshal(), 'base16')
|
const externalId = uint8ArrayToString(key.publicKey.raw, 'base16')
|
||||||
const signingKey = await keystore.getKey(externalId)
|
const signingKey = await keystore.getKey(externalId)
|
||||||
const idSignature = await signMessage(signingKey, externalId)
|
const idSignature = await signMessage(signingKey, externalId)
|
||||||
const externalKey = await keystore.getKey(id)
|
const externalKey = await keystore.getKey(id)
|
||||||
@ -171,7 +171,7 @@ describe('Identities', function () {
|
|||||||
|
|
||||||
it('has the correct id', async () => {
|
it('has the correct id', async () => {
|
||||||
const key = await savedKeysKeyStore.getKey(id)
|
const key = await savedKeysKeyStore.getKey(id)
|
||||||
assert.strictEqual(identity.id, uint8ArrayToString(key.public.marshal(), 'base16'))
|
assert.strictEqual(identity.id, uint8ArrayToString(key.publicKey.raw, 'base16'))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has the correct public key', async () => {
|
it('has the correct public key', async () => {
|
||||||
|
|||||||
@ -145,7 +145,7 @@ describe('KeyStore', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Options', () => {
|
describe('Options', () => {
|
||||||
const unmarshal = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey
|
const unmarshal = crypto.keys.privateKeyFromRaw
|
||||||
const privateKey = '198594a8de39fd97017d11996d619b3746211605a9d290964badf58bc79bdb33'
|
const privateKey = '198594a8de39fd97017d11996d619b3746211605a9d290964badf58bc79bdb33'
|
||||||
const publicKey = '0260baeaffa1de1e4135e5b395e0380563a622b9599d1b8e012a0f7603f516bdaa'
|
const publicKey = '0260baeaffa1de1e4135e5b395e0380563a622b9599d1b8e012a0f7603f516bdaa'
|
||||||
let privateKeyBuffer, publicKeyBuffer, unmarshalledPrivateKey
|
let privateKeyBuffer, publicKeyBuffer, unmarshalledPrivateKey
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { deepStrictEqual } from 'assert'
|
import { deepStrictEqual, strictEqual } from 'assert'
|
||||||
import { rimraf } from 'rimraf'
|
import { rimraf } from 'rimraf'
|
||||||
import { createOrbitDB } from '../src/index.js'
|
import { createOrbitDB } from '../src/index.js'
|
||||||
import connectPeers from './utils/connect-nodes.js'
|
import connectPeers from './utils/connect-nodes.js'
|
||||||
import waitFor from './utils/wait-for.js'
|
import waitFor from './utils/wait-for.js'
|
||||||
import createHelia from './utils/create-helia.js'
|
import createHelia from './utils/create-helia.js'
|
||||||
|
import { CID } from 'multiformats/cid'
|
||||||
|
import { base58btc } from 'multiformats/bases/base58'
|
||||||
|
|
||||||
describe('Replicating databases', function () {
|
describe('Replicating databases', function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
@ -23,8 +25,8 @@ describe('Replicating databases', function () {
|
|||||||
after(async () => {
|
after(async () => {
|
||||||
await orbitdb1.stop()
|
await orbitdb1.stop()
|
||||||
await orbitdb2.stop()
|
await orbitdb2.stop()
|
||||||
await ipfs1.blockstore.child.child.close()
|
await ipfs1.blockstore.child.child.child.close()
|
||||||
await ipfs2.blockstore.child.child.close()
|
await ipfs2.blockstore.child.child.child.close()
|
||||||
await ipfs1.stop()
|
await ipfs1.stop()
|
||||||
await ipfs2.stop()
|
await ipfs2.stop()
|
||||||
|
|
||||||
@ -136,8 +138,12 @@ describe('Replicating databases', function () {
|
|||||||
|
|
||||||
await orbitdb1.stop()
|
await orbitdb1.stop()
|
||||||
await orbitdb2.stop()
|
await orbitdb2.stop()
|
||||||
await ipfs1.blockstore.child.child.close()
|
// TODO: Strange issue with ClassicLevel. Causes subsequent Helia
|
||||||
await ipfs2.blockstore.child.child.close()
|
// instantiations to error with db closed. Explicitly closing the
|
||||||
|
// nested ClassicLevel db seems to resolve the issue. Requires further
|
||||||
|
// investigation.
|
||||||
|
await ipfs1.blockstore.child.child.child.close()
|
||||||
|
await ipfs2.blockstore.child.child.child.close()
|
||||||
await ipfs1.stop()
|
await ipfs1.stop()
|
||||||
await ipfs2.stop()
|
await ipfs2.stop()
|
||||||
|
|
||||||
@ -163,5 +169,26 @@ describe('Replicating databases', function () {
|
|||||||
|
|
||||||
console.log('events:', amount)
|
console.log('events:', amount)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('pins all entries in the replicated database', async () => {
|
||||||
|
const db1 = await orbitdb1.open('helloworld', { referencesCount: 0 })
|
||||||
|
const hash = await db1.add('hello world')
|
||||||
|
|
||||||
|
let replicated = false
|
||||||
|
|
||||||
|
const onJoin = async (peerId, heads) => {
|
||||||
|
replicated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const db2 = await orbitdb2.open(db1.address)
|
||||||
|
|
||||||
|
db2.events.on('join', onJoin)
|
||||||
|
|
||||||
|
await waitFor(() => replicated, () => true)
|
||||||
|
|
||||||
|
const cid = CID.parse(hash, base58btc)
|
||||||
|
strictEqual(await ipfs1.pins.isPinned(cid), true)
|
||||||
|
strictEqual(await ipfs2.pins.isPinned(cid), true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -72,8 +72,8 @@ describe('OrbitDB', function () {
|
|||||||
const privateKey = await orbitdb1.keystore.getKey(orbitdb1.identity.id)
|
const privateKey = await orbitdb1.keystore.getKey(orbitdb1.identity.id)
|
||||||
notStrictEqual(privateKey, undefined)
|
notStrictEqual(privateKey, undefined)
|
||||||
strictEqual(privateKey.constructor.name, 'Secp256k1PrivateKey')
|
strictEqual(privateKey.constructor.name, 'Secp256k1PrivateKey')
|
||||||
notStrictEqual(privateKey._key, undefined)
|
notStrictEqual(privateKey.raw, undefined)
|
||||||
notStrictEqual(privateKey._publicKey, undefined)
|
notStrictEqual(privateKey.publicKey, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a keystore that contains a public key that matches the identity\'s public key', async () => {
|
it('has a keystore that contains a public key that matches the identity\'s public key', async () => {
|
||||||
@ -102,8 +102,8 @@ describe('OrbitDB', function () {
|
|||||||
notStrictEqual(orbitdb1.peerId, undefined)
|
notStrictEqual(orbitdb1.peerId, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a peerId of type Ed25519PeerIdImpl', async () => {
|
it('has a peerId of type Ed25519', async () => {
|
||||||
strictEqual(orbitdb1.peerId.constructor.name, 'Ed25519PeerIdImpl')
|
strictEqual(orbitdb1.peerId.type, 'Ed25519')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a peerId that matches the IPFS id', async () => {
|
it('has a peerId that matches the IPFS id', async () => {
|
||||||
@ -164,8 +164,8 @@ describe('OrbitDB', function () {
|
|||||||
const privateKey = await orbitdb1.keystore.getKey(orbitdb1.identity.id)
|
const privateKey = await orbitdb1.keystore.getKey(orbitdb1.identity.id)
|
||||||
notStrictEqual(privateKey, undefined)
|
notStrictEqual(privateKey, undefined)
|
||||||
strictEqual(privateKey.constructor.name, 'Secp256k1PrivateKey')
|
strictEqual(privateKey.constructor.name, 'Secp256k1PrivateKey')
|
||||||
notStrictEqual(privateKey._key, undefined)
|
notStrictEqual(privateKey.raw, undefined)
|
||||||
notStrictEqual(privateKey._publicKey, undefined)
|
notStrictEqual(privateKey.publicKey, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a keystore that contains a public key that matches the identity\'s public key', async () => {
|
it('has a keystore that contains a public key that matches the identity\'s public key', async () => {
|
||||||
@ -194,8 +194,8 @@ describe('OrbitDB', function () {
|
|||||||
notStrictEqual(orbitdb1.peerId, undefined)
|
notStrictEqual(orbitdb1.peerId, undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a peerId of type Ed25519PeerIdImpl', async () => {
|
it('has a peerId of type Ed25519', async () => {
|
||||||
strictEqual(orbitdb1.peerId.constructor.name, 'Ed25519PeerIdImpl')
|
strictEqual(orbitdb1.peerId.type, 'Ed25519')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has a peerId that matches the IPFS id', async () => {
|
it('has a peerId that matches the IPFS id', async () => {
|
||||||
|
|||||||
@ -21,13 +21,9 @@ const Libp2pOptions = {
|
|||||||
transports: [
|
transports: [
|
||||||
webSockets({
|
webSockets({
|
||||||
filter: all
|
filter: all
|
||||||
}),
|
|
||||||
webRTC(),
|
|
||||||
circuitRelayTransport({
|
|
||||||
discoverRelays: 1
|
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionGater: {
|
connectionGater: {
|
||||||
denyDialMultiaddr: () => false
|
denyDialMultiaddr: () => false
|
||||||
@ -43,18 +39,16 @@ const Libp2pOptions = {
|
|||||||
*/
|
*/
|
||||||
const Libp2pBrowserOptions = {
|
const Libp2pBrowserOptions = {
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: ['/webrtc']
|
listen: ['/webrtc', '/p2p-circuit']
|
||||||
},
|
},
|
||||||
transports: [
|
transports: [
|
||||||
webSockets({
|
webSockets({
|
||||||
filter: all
|
filter: all
|
||||||
}),
|
}),
|
||||||
webRTC(),
|
webRTC(),
|
||||||
circuitRelayTransport({
|
circuitRelayTransport()
|
||||||
discoverRelays: 1
|
|
||||||
})
|
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
connectionGater: {
|
connectionGater: {
|
||||||
denyDialMultiaddr: () => false
|
denyDialMultiaddr: () => false
|
||||||
|
|||||||
@ -5,21 +5,18 @@ import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
|
|||||||
import { webSockets } from '@libp2p/websockets'
|
import { webSockets } from '@libp2p/websockets'
|
||||||
import * as filters from '@libp2p/websockets/filters'
|
import * as filters from '@libp2p/websockets/filters'
|
||||||
import { identify } from '@libp2p/identify'
|
import { identify } from '@libp2p/identify'
|
||||||
import { createFromPrivKey } from '@libp2p/peer-id-factory'
|
|
||||||
import { unmarshalPrivateKey } from '@libp2p/crypto/keys'
|
|
||||||
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
||||||
|
import { privateKeyFromProtobuf } from '@libp2p/crypto/keys'
|
||||||
|
|
||||||
// output of: console.log(server.peerId.privateKey.toString('hex'))
|
// output of: console.log(server.peerId.privateKey.toString('hex'))
|
||||||
const relayPrivKey = '08011240821cb6bc3d4547fcccb513e82e4d718089f8a166b23ffcd4a436754b6b0774cf07447d1693cd10ce11ef950d7517bad6e9472b41a927cd17fc3fb23f8c70cd99'
|
const relayPrivKey = '08011240821cb6bc3d4547fcccb513e82e4d718089f8a166b23ffcd4a436754b6b0774cf07447d1693cd10ce11ef950d7517bad6e9472b41a927cd17fc3fb23f8c70cd99'
|
||||||
// the peer id of the above key
|
// the peer id of the above key
|
||||||
// const relayId = '12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE'
|
// const relayId = '12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE'
|
||||||
|
|
||||||
const encoded = uint8ArrayFromString(relayPrivKey, 'hex')
|
const privateKey = privateKeyFromProtobuf(uint8ArrayFromString(relayPrivKey, 'hex'))
|
||||||
const privateKey = await unmarshalPrivateKey(encoded)
|
|
||||||
const peerId = await createFromPrivKey(privateKey)
|
|
||||||
|
|
||||||
const server = await createLibp2p({
|
const server = await createLibp2p({
|
||||||
peerId,
|
privateKey,
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: ['/ip4/0.0.0.0/tcp/12345/ws']
|
listen: ['/ip4/0.0.0.0/tcp/12345/ws']
|
||||||
},
|
},
|
||||||
@ -28,14 +25,13 @@ const server = await createLibp2p({
|
|||||||
filter: filters.all
|
filter: filters.all
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
connectionEncryption: [noise()],
|
connectionEncrypters: [noise()],
|
||||||
streamMuxers: [yamux()],
|
streamMuxers: [yamux()],
|
||||||
services: {
|
services: {
|
||||||
identify: identify(),
|
identify: identify(),
|
||||||
relay: circuitRelayServer({
|
relay: circuitRelayServer({
|
||||||
reservations: {
|
reservations: {
|
||||||
maxReservations: 5000,
|
maxReservations: 5000,
|
||||||
reservationTtl: 1000,
|
|
||||||
defaultDataLimit: BigInt(1024 * 1024 * 1024)
|
defaultDataLimit: BigInt(1024 * 1024 * 1024)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user