Merge branch 'master' of github.com:orbitdb/orbit-db into feat/release-notes-0.20.0

This commit is contained in:
shamb0t
2019-05-01 17:36:43 +01:00
33 changed files with 1645 additions and 1317 deletions

94
API.md
View File

@@ -6,8 +6,8 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
<!-- toc -->
- [Constructor](#constructor)
* [constructor(ipfs, [directory], [options])](#constructoripfs-directory-options)
- [Creating an OrbitDB instance](#creating-an-orbitdb-instance)
* [createInstance(ipfs, [options])](#createinstanceipfs-options)
- [Public Instance Methods](#public-instance-methods)
* [orbitdb.create(name, type, [options])](#orbitdbcreatename-type-options)
* [orbitdb.determineAddress(name, type, [options])](#orbitdbdetermineaddressname-type-options)
@@ -18,6 +18,7 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
+ [put(key, value)](#putkey-value)
+ [set(key, value)](#setkey-value)
+ [get(key)](#getkey)
+ [del(key)](#delkey)
* [orbitdb.kvstore(name|address)](#orbitdbkvstorenameaddress)
* [orbitdb.log(name|address)](#orbitdblognameaddress)
+ [add(event)](#addevent)
@@ -33,7 +34,7 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
+ [put(doc)](#putdoc)
+ [get(key)](#getkey-1)
+ [query(mapper)](#querymapper)
+ [del(key)](#delkey)
+ [del(key)](#delkey-1)
* [orbitdb.docstore(name|address, options)](#orbitdbdocstorenameaddress-options)
* [orbitdb.counter(name|address)](#orbitdbcounternameaddress)
+ [value](#value)
@@ -41,6 +42,7 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
- [Static Properties](#static-properties)
* [OrbitDB.databaseTypes](#orbitdbdatabasetypes)
- [Static Methods](#static-methods)
* [OrbitDB.createInstance(ipfs)](#orbitdbcreateinstanceipfs)
* [OrbitDB.isValidType(type)](#orbitdbisvalidtypetype)
* [OrbitDB.addDatabaseType(type, store)](#orbitdbadddatabasetypetype-store)
* [OrbitDB.getDatabaseTypes()](#orbitdbgetdatabasetypes)
@@ -50,7 +52,7 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
* [store.load([amount])](#storeloadamount)
* [store.close()](#storeclose)
* [store.drop()](#storedrop)
* [store.key](#storekey)
* [store.identity](#storeidentity)
* [store.type](#storetype)
- [Store Events](#store-events)
* [`replicated`](#replicated)
@@ -64,13 +66,15 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
<!-- tocstop -->
## Constructor
## Creating an OrbitDB instance
### constructor(ipfs, [directory], [options])
### createInstance(ipfs, [options])
```javascript
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
```
Creates and returns an instance of OrbitDB. Use the optional `directory` argument to specify a path to be used for the database files (Default: `'./orbitdb'`). In addition, you can use the optional `options` argument for further configuration. It is an object with any of these properties:
Creates and returns an instance of OrbitDB. Use the optional `options` argument for further configuration. It is an object with any of these properties:
- `directory` (string): path to be used for the database files. By default it uses `'./orbitdb'`.
- `peerId` (string): By default it uses the base58 string of the ipfs peer id.
@@ -78,7 +82,9 @@ Creates and returns an instance of OrbitDB. Use the optional `directory` argumen
- 'cache' (Cache Instance) : By default creates an instance of [Cache](https://github.com/orbitdb/orbit-db-cache). A custom cache instance can also be used.
After creating an `OrbitDB` instance , you can access the different data stores. Creating a database instance, eg. with `orbitdb.keyvalue(...)`, returns a *Promise* that resolves to a [database instance](#store-api). See the [Store](#store-api) section for details of common methods and properties.
- `identity` (Identity Instance): By default it creates an instance of [Identity](https://github.com/orbitdb/orbit-db-identity-provider/src/identity.js)
After creating an `OrbitDB` instance, you can access the different data stores. Creating a database instance, eg. with `orbitdb.keyvalue(...)`, returns a *Promise* that resolves to a [database instance](#store-api). See the [Store](#store-api) section for details of common methods and properties.
*For further details, see usage for [kvstore](https://github.com/orbitdb/orbit-db-kvstore#usage), [eventlog](https://github.com/orbitdb/orbit-db-eventstore#usage), [feed](https://github.com/orbitdb/orbit-db-feedstore#usage), [docstore](https://github.com/orbitdb/orbit-db-docstore#usage) and [counter](https://github.com/orbitdb/orbit-db-counterstore#usage).*
@@ -93,17 +99,19 @@ const db = await orbitdb.keyvalue('profile')
Returns a `Promise` that resolves to [a database instance](#store-api). `name` (string) should be the database name, not an OrbitDB address (i.e. `user.posts`). `type` is a supported database type (i.e. `eventlog` or [an added custom type](https://github.com/orbitdb/orbit-db#custom-store-types)). `options` is an object with any of the following properties:
- `directory` (string): The directory where data will be stored (Default: uses directory option passed to OrbitDB constructor or `./orbitdb` if none was provided).
- `write` (array): An array of hex encoded public keys which are used to set write access to the database. `["*"]` can be passed in to give write access to everyone. See the [GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md) guide for more info. (Default: uses the OrbitDB instance key `orbitdb.key`, which would give write access only to yourself)
- `write` (array): An array of hex encoded public keys which are used to set write access to the database. `["*"]` can be passed in to give write access to everyone. See the [GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md) guide for more info. (Default: uses the OrbitDB identity public key `orbitdb.identity.publicKey`, which would give write access only to yourself)
- `overwrite` (boolean): Overwrite an existing database (Default: `false`)
- `replicate` (boolean): Replicate the database with peers, requires IPFS PubSub. (Default: `true`)
```javascript
const db = await orbitdb.create('user.posts', 'eventlog', {
write: [
// Give access to ourselves
orbitdb.key.getPublic('hex'),
// Give access to the second peer
'042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839'
]
accessController: {
write: [
// Give access to ourselves
orbitdb.identity.publicKey,
// Give access to the second peer
'042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839'
]
}
})
// db created & opened
```
@@ -115,10 +123,11 @@ Returns a `Promise` that resolves to an orbit-db address. The parameters corresp
```javascript
const dbAddress = await orbitdb.determineAddress('user.posts', 'eventlog', {
write: [
accessController: {
write: [
// This could be someone else's public key
'042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839'
]
]}
})
```
@@ -137,7 +146,7 @@ Returns a `Promise` that resolves to [a database instance](#store-api). `address
const db = await orbitdb.open('/orbitdb/Qmd8TmZrWASypEp4Er9tgWP4kCNQnW4ncSnvjvyHQ3EVSU/first-database')
```
Convienance methods are available when opening/creating any of the default OrbitDB database types: [feed](#orbitdbfeednameaddress), [docs](#orbitdbdocsnameaddress-options), [log](#orbitdblognameaddress), [keyvalue](#orbitdbkeyvaluenameaddress), [counter](#orbitdbcounternameaddress)
Convenience methods are available when opening/creating any of the default OrbitDB database types: [feed](#orbitdbfeednameaddress), [docs](#orbitdbdocsnameaddress-options), [log](#orbitdblognameaddress), [keyvalue](#orbitdbkeyvaluenameaddress), [counter](#orbitdbcounternameaddress)
You can use: `orbitdb.feed(address, options)`
@@ -193,6 +202,13 @@ Returns an `Object` with the contents of the entry.
// { name: 'Friend' }
```
#### del(key)
Deletes the `Object` associated with `key`. Returns a `Promise` that resolves to a `String` that is the multihash of the deleted entry.
```javascript
const hash = await db.del('hello')
// QmbYHhnXEdmdfUDzZKeEg7HyG2f8veaF2wBrYFcSHJ3mvd
```
### orbitdb.kvstore(name|address)
Alias for [`orbitdb.keyvalue()`](#orbitdbkeyvaluenameaddress)
@@ -351,6 +367,10 @@ Returns an `Array` with a single `Object` if key exists.
```javascript
const profile = db.get('shamb0t')
// [{ _id: 'shamb0t', name: 'shamb0t', followers: 500 }]
// to get all the records
const profile = db.get('');
// returns all the records
// [{ _id: 'shamb0t', name: 'shamb0t', followers: 500 }]
```
#### query(mapper)
@@ -412,6 +432,13 @@ OrbitDB.databaseTypes
## Static Methods
### OrbitDB.createInstance(ipfs)
Returns a `Promise` that resolved to an instance of `OrbitDB`.
```js
const orbitdb = await OrbitDB.createInstance(ipfs)
```
### OrbitDB.isValidType(type)
Returns `true` if the provided `String` is a supported database type
```js
@@ -493,25 +520,30 @@ Returns a `Promise` that resolves once complete
await db.drop()
```
### store.key
### store.identity
Returns an instance of [`KeyPair`](https://github.com/indutny/elliptic/blob/master/lib/elliptic/ec/key.js#L8). The keypair is used to sign the database entries. See the [GUIDE](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#keys) for more information on how OrbitDB uses the keypair.
Returns an instance of [Identity](https://github.com/orbitdb/orbit-db-identity-provider/src/identity.js). The identity is used to sign the database entries. See the [GUIDE](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#identity) for more information on how OrbitDB uses identity.
```
const key = db.key
console.log(key)
// <Key priv: db8ef129f3d26ac5d7c17b402027488a8f4b2e7fa855c27d680b714cf9c1f87e
// pub: <EC Point x: f0e33d60f9824ce10b2c8983d3da0311933e82cf5ec9374cd82c0af699cbde5b
// y: ce206bfccf889465c6g6f9a7fdf452f9c3e1204a6f1b4582ec427ec12b116de9> >
```javascript
const identity = db.identity
console.log(identity.toJSON())
{ id: 'QmZyYjpG6SMJJx2rbye8HXNMufGRtpn9yFkdd27uuq6xrR',
publicKey: '0446829cbd926ad8e858acdf1988b8d586214a1ca9fa8c7932af1d59f7334d41aa2ec2342ea402e4f3c0195308a4815bea326750de0a63470e711c534932b3131c',
signatures:
{ id: '3045022058bbb2aa415623085124b32b254b8668d95370261ade8718765a8086644fc8ae022100c736b45c6b2ef60c921848027f51020a70ee50afa20bc9853877e994e6121c15',
publicKey: '3046022100d138ccc0fbd48bd41e74e40ddf05c1fa6ff903a83b2577ef7d6387a33992ea4b022100ca39e8d8aef43ac0c6ec05c1b95b41fce07630b5dc61587a32d90dc8e4cf9766'
},
type: 'orbitdb'
}
```
The public key can be retrieved with:
```
console.log(db.key.getPublic('hex'))
// 04d009bd530f2fa0cda29202e1b15e97247893cb1e88601968abfe787f7ea03828fdb7624a618fd67c4c437ad7f48e670cc5a6ea2340b896e42b0c8a3e4d54aebe
```javascript
console.log(db.identity.publicKey)
// 0446829cbd926ad8e858acdf1988b8d586214a1ca9fa8c7932af1d59f7334d41aa2ec2342ea402e4f3c0195308a4815bea326750de0a63470e711c534932b3131c
```
The key can also be accessed from the OrbitDB instance: `orbitdb.key.getPublic('hex')`.
The key can also be accessed from the OrbitDB instance: `orbitdb.identity.publicKey`.
### store.type

19
FAQ.md
View File

@@ -15,7 +15,9 @@ This document is seeded by questions from people opening issues in this reposito
- [Is every `put` to OrbitDB immediately sent to the network and persisted?](#is-every-put-to-orbitdb-immediately-sent-to-the-network-and-persisted)
- [Does OrbitDB already support pinning when using js-ipfs ?](#does-orbitdb-already-support-pinning-when-using-js-ipfs-)
- [Does orbit have a shared feed between peers where multiple peers can append to the same feed?](#does-orbit-have-a-shared-feed-between-peers-where-multiple-peers-can-append-to-the-same-feed)
- [Contribute](#contribute)
- [I'm getting a lot of 429 (Too Many Requests) errors when I run OrbitDB](#im-getting-a-lot-of-429-too-many-requests-errors-when-i-run-orbitdb)
- [Where can I learn more about security, encryption, and account recovery?](#where-can-i-learn-more-about-security-encryption-and-account-recovery)
- [How can I contribute to this FAQ?](#how-can-i-contribute-to-this-faq)
<!-- tocstop -->
@@ -49,6 +51,21 @@ However, this will change in the future as js-ipfs gets GC and we want to make s
All databases (feeds) are shared between peers, so nobody "owns them" like users do in ssb (afaik). Multiple peers can append to the same db. @tyleryasaka is right in that each peer has their own copy of the db (the log) and they may have different versions between them but, as @tyleryasaka (correctly) describes, through the syncing/replication process the peers exchange "their knowledge of the db" (heads) with each other, the dbs/logs get merged. This is what the "CRDT" in ipfs-log enables. But from address/authority/ownership perspective, they all share the same feed.
### I'm getting a lot of 429 (Too Many Requests) errors when I run OrbitDB
This happens when there's only one node with data available, and the system isn't able to effectively get all of the data it needs from it. In order to get around this, IPFS instantiates nodes with preload enabled, so that one node isn't effectively DDoSed. However, sometimes these nodes go down, as well, causing 429 errors. To get around this in example cases (certainly not in production), disable preload:
```js
this.ipfs = new Ipfs({
preload: { enabled: false },
// ...
}
```
### Where can I learn more about security, encryption, and account recovery?
The very short answer is that OrbitDB is agnostic in terms of encryption and account recovery with the aim of providing maximum flexibility with your apps. We don't do any encryption on our side; however, nothing is stopping you from encrypting data before storing it in the OrbitDB network. OrbitDB (just like IPFS) will treat encrypted the data exactly the same. Any node can replicate the data, but only nodes which have access to the encryption key from some other means will be able to decrypt it.
### How can I contribute to this FAQ?
See the introduction at the top! Please open any issues and pull requests you can to improve this FAQ.md. It is here for you. If you're confused, ask another question publicly; it's possible that other people are, too. If you don't want to open an issue, feel free to jump onto [the Gitter](https://gitter.im/orbitdb/Lobby) and ask us there, too.

168
GUIDE.md
View File

@@ -14,9 +14,12 @@ This guide is still being worked on and we would love to get [feedback and sugge
- [Create a database](#create-a-database)
* [Address](#address)
+ [Manifest](#manifest)
* [Keys](#keys)
* [Identity](#identity)
+ [Creating an identity](#creating-an-identity)
* [Access Control](#access-control)
+ [Public databases](#public-databases)
+ [Granting access after database creation](#granting-access-after-database-creation)
+ [Custom Access Controller](#custom-access-controller)
- [Add an entry](#add-an-entry)
- [Get an entry](#get-an-entry)
- [Persistency](#persistency)
@@ -40,7 +43,7 @@ This may not be intuitive or you might not be sure what the best approach would
Install [orbit-db](https://github.com/orbitdb/orbit-db) and [ipfs](https://www.npmjs.com/package/ipfs) from npm:
```
```sh
npm install orbit-db ipfs
```
@@ -67,7 +70,7 @@ const ipfs = new IPFS(ipfsOptions)
ipfs.on('ready', () => {
// Create OrbitDB instance
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
})
```
@@ -87,7 +90,7 @@ Then, create a database instance (we'll use Key-Value database in this example):
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.keyvalue('first-database')
})
```
@@ -104,7 +107,7 @@ The first part, `/orbitdb`, specifies the protocol in use. The second part, an I
In order to replicate the database with peers, the address is what you need to give to other peers in order for them to start replicating the database.
The database address can be accessed as `db.address` from the database instance:
```
```javascript
const address = db.address
// address == '/orbitdb/Qmdgwt7w4uBsw8LXduzCd18zfGXeTmBsiR8edQ1hSfzcJC/first-database'
```
@@ -113,7 +116,7 @@ For example:
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.keyvalue('first-database')
console.log(db.address.toString())
// /orbitdb/Qmd8TmZrWASypEp4Er9tgWP4kCNQnW4ncSnvjvyHQ3EVSU/first-database
@@ -135,53 +138,72 @@ The database manifest can be fetched from IPFS and it looks like this:
}
```
### Keys
### Identity
Each entry in a database is signed by who created that entry. The signing key, the key that a peer uses to sign entries, can be accessed as a member variable of the database instance:
Each entry in a database is signed by who created that entry. The identity, which includes the public key used to sign entries, can be accessed via the identity member variable of the database instance:
```
const key = db.key
console.log(key)
// <Key priv: db8ef129f3d26ac5d7c17b402027488a8f4b2e7fa855c27d680b714cf9c1f87e
// pub: <EC Point x: f0e33d60f9824ce10b2c8983d3da0311933e82cf5ec9374cd82c0af699cbde5b
// y: ce206bfccf889465c6g6f9a7fdf452f9c3e1204a6f1b4582ec427ec12b116de9> >
```javascript
const identity = db.identity
console.log(identity.toJSON())
// prints
{
id: '0443729cbd756ad8e598acdf1986c8d586214a1ca9fa8c7932af1d59f7334d41aa2ec2342ea402e4f3c0195308a4815bea326750de0a63470e711c534932b3131c',
publicKey: '0446829cbd926ad8e858acdf1988b8d586214a1ca9fa8c7932af1d59f7334d41aa2ec2342ea402e4f3c0195308a4815bea326750de0a63470e711c534932b3131c',
signatures: {
id: '3045022058bbb2aa415623085124b32b254b8668d95370261ade8718765a8086644fc8ae022100c736b45c6b2ef60c921848027f51020a70ee50afa20bc9853877e994e6121c15',
publicKey: '3046022100d138ccc0fbd48bd41e74e40ddf05c1fa6ff903a83b2577ef7d6387a33992ea4b022100ca39e8d8aef43ac0c6ec05c1b95b41fce07630b5dc61587a32d90dc8e4cf9766'
},
type: 'orbitdb'
}
```
The key contains the keypair used to sign the database entries. The public key can be retrieved with:
#### Creating an identity
```javascript
const Identities = require('orbit-db-identity-provider')
const options = { id: 'local-id' }
const identity = await Identities.createIdentity(options)
```
console.log(db.key.getPublic('hex'))
This identity can be used in OrbitDB by passing it in as an argument in the `options` object:
```javascript
const orbitdb = await OrbitDB.createInstance(ipfs, { identity: identity })
```
The identity also contains signatures proving possession of the id and OrbitDB public key. This is included to allow proof of ownership of an external public key within OrbitDB. You can read more [here](https://github.com/orbitdb/orbit-db-identity-provider)
The OrbitDB public key can be retrieved with:
```javascript
console.log(db.identity.publicKey)
// 04d009bd530f2fa0cda29202e1b15e97247893cb1e88601968abfe787f7ea03828fdb7624a618fd67c4c437ad7f48e670cc5a6ea2340b896e42b0c8a3e4d54aebe
```
The key can also be accessed from the OrbitDB instance: `orbitdb.key.getPublic('hex')`.
If you want to give access to other peers to write to a database, you need to get their public key in hex and add it to the access controller upon creating the database. If you want others to give you the access to write, you'll need to give them your public key (output of `orbitdb.key.getPublic('hex')`). For more information, see: [Access Control](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#access-control).
If you want to give access to other peers to write to a database, you need to get their public key in hex and add it to the access controller upon creating the database. If you want others to give you the access to write, you'll need to give them your public key (output of `orbitdb.identity.publicKey`). For more information, see: [Access Control](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md#access-control).
### Access Control
You can specify the peers that have write-access to a database. You can define a set of peers that can write to a database or allow anyone write to a database. **By default and if not specified otherwise, only the creator of the database will be given write-access**.
***Note!*** *OrbitDB currently supports only write-access and the keys of the writers need to be known when creating a database. That is, the access rights can't be changed after a database has been created. In the future we'll support read access control and dynamic access control in a way that access rights can be added and removed to a database at any point in time without changing the database address. At the moment, if access rights need to be changed, the address of the database will change.*
***Note!*** *OrbitDB currently supports only dynamically adding write-access. That is, write-access cannot be revoked once added. In the future OrbitDB will support access revocation and read access control. At the moment, if access rights need to be removed, the address of the database will change.*
Access rights are setup by passing an `access` object that defines the access rights of the database when created. OrbitDB currently supports write-access. The access rights are specified as an array of public keys of the peers who can write to the database.
Access rights are setup by passing an `accessController` object that specifies the access-controller type and access rights of the database when created. OrbitDB currently supports write-access. The access rights are specified as an array of public keys of the peers who can write to the database. The public keys to which access is given can be retrieved from the identity.publicKey property of each peer.
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const access = {
const orbitdb = await OrbitDB.createInstance(ipfs)
const options = {
// Give write access to ourselves
write: [orbitdb.key.getPublic('hex')],
accessController: {
write: [orbitdb.identity.publicKey]
}
}
const db = await orbitdb.keyvalue('first-database', access)
const db = await orbitdb.keyvalue('first-database', options)
console.log(db.address.toString())
// /orbitdb/Qmd8TmZrWASypEp4Er9tgWP4kCNQnW4ncSnvjvyHQ3EVSU/first-database
})
```
To give write access to another peer, you'll need to get their public key with some means. They'll need to give you the output of their OrbitDB instance's key: `orbitdb.key.getPublic('hex')`.
To give write access to another peer, you'll need to get their public key with some means. They'll need to give you the output of their OrbitDB instance's key: `orbitdb.identity.publicKey`.
The keys look like this:
`042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839`
@@ -190,19 +212,21 @@ Give access to another peer to write to the database:
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const access = {
const options = {
// Setup write access
write: [
// Give access to ourselves
orbitdb.key.getPublic('hex'),
// Give access to the second peer
'042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839',
],
accessController: {
write: [
// Give access to ourselves
orbitdb.identity.publicKey,
// Give access to the second peer
'042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839',
]
}
}
const db1 = await orbitdb.keyvalue('first-database', access)
const db1 = await orbitdb.keyvalue('first-database', options)
console.log(db1.address.toString())
// /orbitdb/Qmdgwt7w4uBsw8LXduzCd18zfGXeTmBsiR8edQ1hSfzcJC/first-database
@@ -219,14 +243,16 @@ This can be done by adding a `*` to the write access array:
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const access = {
const options = {
// Give write access to everyone
write: ['*'],
accessController: {
write: ['*']
}
}
const db = await orbitdb.keyvalue('first-database', access)
const db = await orbitdb.keyvalue('first-database', options)
console.log(db.address.toString())
// /orbitdb/QmRrauSxaAvNjpZcm2Cq6y9DcrH8wQQWGjtokF4tgCUxGP/first-database
})
@@ -234,6 +260,56 @@ ipfs.on('ready', async () => {
Note how the access controller hash is different compared to the previous example!
#### Granting access after database creation
To give access to another peer after the database has been created, you must set the access-controller `type` to an `AccessController` which supports dynamically adding write-access such as `OrbitDBAccessController`.
```javaScript
db = await orbitdb1.feed('AABB', {
accessController: {
type: 'orbitdb', //OrbitDBAccessController
write: [identity1.publicKey]
}
})
await db.access.grant('write', identity2.publicKey) // grant access to identity2
```
#### Custom Access Controller
You can create a custom access controller by implementing the `AccessController` [interface](https://github.com/orbitdb/orbit-db-access-controllers/blob/master/src/access-controller-interface.js) and adding it to the AccessControllers object before passing it to OrbitDB.
```javascript
class OtherAccessController extends AccessController {
static get type () { return 'othertype' } // Return the type for this controller
async canAppend(entry, identityProvider) {
// logic to determine if entry can be added, for example:
if (entry.payload === "hello world" && entry.identity.id === identity.id && identityProvider.verifyIdentity(entry.identity))
return true
return false
}
async grant (access, identity) {} // Logic for granting access to identity
}
let AccessControllers = require('orbit-db-access-controllers')
AccessControllers.addAccessController({ AccessController: OtherAccessController })
const orbitdb = await OrbitDB.createInstance(ipfs, {
AccessControllers: AccessControllers
})
const db = await orbitdb.keyvalue('first-database', {
accessController: {
type: 'othertype',
write: [id1.publicKey]
}
})
```
## Add an entry
To add an entry to the database, we simply call `db.put(key, value)`.
@@ -241,7 +317,7 @@ To add an entry to the database, we simply call `db.put(key, value)`.
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.keyvalue('first-database')
await db.put('name', 'hello')
})
@@ -282,7 +358,7 @@ Key-Value:
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.keyvalue('first-database')
await db.put('name', 'hello')
const value = db.get('name')
@@ -303,7 +379,7 @@ OrbitDB saves the state of the database automatically on disk. This means that u
```javascript
const ipfs = new IPFS()
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
const db1 = await orbitdb.keyvalue('first-database')
await db1.put('name', 'hello')
@@ -331,7 +407,7 @@ Replicate a database between two nodes:
const ipfs1 = new IPFS({ repo: './ipfs1' })
ipfs1.on('ready', async () => {
// Create the database
const orbitdb1 = new OrbitDB(ipfs1, './orbitdb1')
const orbitdb1 = await OrbitDB.createInstance(ipfs1, { directory: './orbitdb1' })
const db1 = await orbitdb1.log('events')
// Create the second peer
@@ -339,7 +415,7 @@ ipfs1.on('ready', async () => {
ipfs2.on('ready', async () => {
// Open the first database for the second peer,
// ie. replicate the database
const orbitdb2 = new OrbitDB(ipfs2, './orbitdb2')
const orbitdb2 = await OrbitDB.createInstance(ipfs2, { directory: './orbitdb2' })
const db2 = await orbitdb2.log(db1.address.toString())
// When the second database replicated new heads, query the database
@@ -377,7 +453,7 @@ class CustomStore extends DocumentStore {
OrbitDB.addDatabaseType(CustomStore.type, CustomStore)
// instantiate custom store
let orbitdb = new OrbitDB(ipfs, dbPath)
let orbitdb = await OrbitDB.createInstance(ipfs, { directory: dbPath })
let store = orbitdb.create(name, CustomStore.type)
```

View File

@@ -22,7 +22,7 @@ clean:
rm -rf node_modules/
clean-dependencies: clean
if [ -a package-lock.json ]; then rm package-lock.json; fi;
rm -f package-lock.json;
rebuild: | clean-dependencies build

View File

@@ -54,6 +54,7 @@ We also have regular community calls, which we announce in the issues in [the @o
* [Build](#build)
* [Benchmark](#benchmark)
* [Logging](#logging)
- [Frequently Asked Questions](#frequently-asked-questions)
- [Contributing](#contributing)
- [Sponsors](#sponsors)
- [License](#license)
@@ -81,13 +82,12 @@ If you're using `orbitd-db` to develop **browser** or **Node.js** applications,
Install dependencies:
```
npm install orbit-db ipfs@0.33.0
npm install orbit-db@rc2 ipfs
```
```javascript
const IPFS = require('ipfs')
const OrbitDB = require('orbit-db')
// OrbitDB uses Pubsub which is an experimental feature
// and need to be turned on manually.
// Note that these options need to be passed to IPFS in
@@ -103,7 +103,7 @@ const ipfs = new IPFS(ipfsOptions)
ipfs.on('error', (e) => console.error(e))
ipfs.on('ready', async () => {
const orbitdb = new OrbitDB(ipfs)
const orbitdb = await OrbitDB.createInstance(ipfs)
// Create / Open a database
const db = await orbitdb.log('hello')
@@ -130,18 +130,18 @@ Alternatively, you can use [ipfs-api](https://npmjs.org/package/ipfs-api) to use
Install dependencies:
```
npm install orbit-db ipfs-api
npm install orbit-db ipfs-http-client
```
```javascript
const IpfsApi = require('ipfs-api')
const IpfsClient = require('ipfs-http-client')
const OrbitDB = require('orbit-db')
const ipfs = IpfsApi('localhost', '5001')
const orbitdb = new OrbitDB(ipfs)
orbitdb.log('hello').then(db => {
// Do something with your db.
})
const ipfs = IpfsClient('localhost', '5001')
const orbitdb = await OrbitDB.createInstance(ipfs)
const db = await orbitdb.log('hello')
// Do something with your db.
```
## API
@@ -218,7 +218,8 @@ OrbitDB uses the following modules:
- [crdts](https://github.com/orbitdb/crdts)
- [orbit-db-cache](https://github.com/orbitdb/orbit-db-cache)
- [orbit-db-pubsub](https://github.com/orbitdb/orbit-db-pubsub)
- [orbit-db-keystore](https://github.com/orbitdb/orbit-db-keystore)
- [orbit-db-identity-provider](https://github.com/orbitdb/orbit-db-identity-provider)
- [orbit-db-access-controllers](https://github.com/orbitdb/orbit-db-access-controllers)
### OrbitDB Store Packages
- [orbit-db-store](https://github.com/orbitdb/orbit-db-store)
@@ -259,6 +260,10 @@ To enable OrbitDB's logging output, set a global ENV variable called `LOG` to `d
LOG=debug node <file>
```
## Frequently Asked Questions
We have an FAQ! [Go take a look at it](FAQ.md). If a question isn't there, open an issue and suggest adding it. We can work on the best answer together.
## Contributing
**Take a look at our organization-wide [Contributing Guide](https://github.com/orbitdb/welcome/blob/master/contributing.md).** You'll find most of your questions answered there. Some questions may be answered in the [FAQ](FAQ.md), as well.

View File

@@ -118,10 +118,8 @@ const main = (IPFS, ORBITDB) => {
await update(db)
} catch (e) {
console.error(e.toString())
if (e.toString() === 'Error: Not allowed to write') {
writerText.innerHTML = '<span style="color: red">' + e.toString() + '</span>'
clearInterval(updateInterval)
}
writerText.innerHTML = '<span style="color: red">' + e.toString() + '</span>'
clearInterval(updateInterval)
}
}, interval)
}
@@ -162,7 +160,7 @@ const main = (IPFS, ORBITDB) => {
// If "Public" flag is set, allow anyone to write to the database,
// otherwise only the creator of the database can write
accessController: {
write: publicAccess ? ['*'] : [identity.publicKey],
write: publicAccess ? ['*'] : [orbitdb.identity.publicKey],
}
})

2382
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "orbit-db",
"version": "0.19.9",
"version": "0.20.0-rc10",
"description": "Distributed p2p database on IPFS",
"author": "Haad",
"license": "MIT",
@@ -18,19 +18,18 @@
"localstorage-down": "^0.6.7",
"logplease": "^1.2.14",
"multihashes": "^0.4.12",
"orbit-db-access-controllers": "github:orbitdb/orbit-db-access-controllers",
"orbit-db-access-controllers": "next",
"orbit-db-cache": "~0.2.4",
"orbit-db-counterstore": "github:orbitdb/orbit-db-counterstore",
"orbit-db-docstore": "github:orbitdb/orbit-db-docstore",
"orbit-db-eventstore": "github:orbitdb/orbit-db-eventstore",
"orbit-db-feedstore": "github:orbitdb/orbit-db-feedstore",
"orbit-db-identity-provider": "github:orbitdb/orbit-db-identity-provider",
"orbit-db-counterstore": "next",
"orbit-db-docstore": "next",
"orbit-db-eventstore": "next",
"orbit-db-feedstore": "next",
"orbit-db-identity-provider": "rc1.3",
"orbit-db-io": "~0.0.1",
"orbit-db-keystore": "github:orbitdb/orbit-db-keystore",
"orbit-db-kvstore": "github:orbitdb/orbit-db-kvstore",
"orbit-db-keystore": "rc1.2",
"orbit-db-kvstore": "next",
"orbit-db-pubsub": "~0.5.5",
"orbit-db-store": "github:orbitdb/orbit-db-store",
"pify": "^4.0.1"
"orbit-db-store": "next"
},
"devDependencies": {
"babel-core": "^6.26.0",
@@ -39,16 +38,19 @@
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"datastore-level": "~0.10.0",
"go-ipfs-dep": "^0.4.18",
"fs-extra": "^7.0.1",
"go-ipfs-dep": "^0.4.19",
"ipfs": "^0.34.4",
"ipfs-repo": "^0.26.2",
"ipfsd-ctl": "^0.42.0",
"localstorage-level-migration": "^0.0.1",
"markdown-toc": "^1.2.0",
"mocha": "^5.2.0",
"p-each-series": "^1.0.0",
"p-map": "^1.2.0",
"p-map-series": "^1.0.0",
"p-whilst": "^1.0.0",
"pify": "^4.0.1",
"remark-cli": "^5.0.0",
"remark-validate-links": "^7.0.0",
"rimraf": "^2.6.2",
@@ -68,5 +70,10 @@
"build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.js examples/browser/lib/orbitdb.js && cp dist/orbitdb.js.map examples/browser/lib/orbitdb.js.map",
"build:docs/toc": "markdown-toc --no-first1 -i README.md && markdown-toc --no-first1 -i API.md && markdown-toc --no-first1 -i GUIDE.md && markdown-toc --no-first1 -i CHANGELOG.md && markdown-toc --no-first1 -i FAQ.md ",
"build:es5": "babel src --out-dir ./dist/es5/ --presets babel-preset-env --plugins babel-plugin-transform-runtime"
}
},
"localMaintainers": [
"haad <haad@haja.io>",
"shamb0t <shams@haja.io>",
"hajamark <mark@haja.io>"
]
}

View File

@@ -113,6 +113,10 @@ let databaseTypes = {
}
async disconnect () {
//close Keystore
if (this.keystore.close)
await this.keystore.close()
// Close all open databases
const databases = Object.values(this.stores)
for (let db of databases) {
@@ -164,8 +168,9 @@ let databaseTypes = {
cache: cache,
onClose: this._onClose.bind(this),
})
const identity = options.identity || this.identity
const store = new Store(this._ipfs, this.identity, address, opts)
const store = new Store(this._ipfs, identity, address, opts)
store.events.on('write', this._onWrite.bind(this))
// ID of the store is the address as a string
const addr = address.toString()
@@ -242,7 +247,7 @@ let databaseTypes = {
throw new Error(`Given database name is an address. Please give only the name of the database!`)
// Create an AccessController, use IPFS AC as the default
options.accessController = Object.assign({}, { type: 'ipfs' }, options.accessController)
options.accessController = Object.assign({}, { name: name , type: 'ipfs' }, options.accessController)
const accessControllerAddress = await AccessControllers.create(this, options.accessController.type, options.accessController || {})
// Save the manifest to IPFS

View File

@@ -9,6 +9,7 @@ const levelup = require('levelup')
const leveldown = require('leveldown')
const OrbitDB = require('../src/OrbitDB')
const OrbitDBAddress = require('../src/orbit-db-address')
const Identities = require('orbit-db-identity-provider')
const io = require('orbit-db-io')
// Include test utilities
const {
@@ -258,6 +259,15 @@ Object.keys(testAPIs).forEach(API => {
assert.equal(db.address.toString().indexOf('abc'), 59)
})
it('opens a database - with a different identity', async () => {
const identity = await Identities.createIdentity({ id: 'test-id' })
db = await orbitdb.open('abc', { create: true, type: 'feed', overwrite: true, identity })
assert.equal(db.address.toString().indexOf('/orbitdb'), 0)
assert.equal(db.address.toString().indexOf('zd'), 9)
assert.equal(db.address.toString().indexOf('abc'), 59)
assert.equal(db.identity, identity)
})
it('opens the same database - from an address', async () => {
db = await orbitdb.open(db.address)
assert.equal(db.address.toString().indexOf('/orbitdb'), 0)

View File

@@ -62,20 +62,20 @@ Object.keys(testAPIs).forEach(API => {
const hash = await db.add('hello1')
const items = db.iterator({ limit: -1 }).collect()
assert.notEqual(hash, null)
assert.equal(hash, last(items).cid)
assert.equal(hash, last(items).hash)
assert.equal(items.length, 1)
})
it('returns the added entry\'s hash, 2 entries', async () => {
db = await orbitdb1.feed(address)
await db.load()
const prevHash = db.iterator().collect()[0].cid
const prevHash = db.iterator().collect()[0].hash
const hash = await db.add('hello2')
const items = db.iterator({ limit: -1 }).collect()
assert.equal(items.length, 2)
assert.notEqual(hash, null)
assert.notEqual(hash, prevHash)
assert.equal(hash, last(items).cid)
assert.equal(hash, last(items).hash)
})
it('adds five items', async () => {
@@ -130,7 +130,7 @@ Object.keys(testAPIs).forEach(API => {
const firstItem = items[0]
const secondItem = items[1]
assert.equal(firstItem.cid.startsWith('zd'), true)
assert.equal(firstItem.hash.startsWith('zd'), true)
assert.equal(firstItem.payload.key, null)
assert.equal(firstItem.payload.value, 'hello2')
assert.equal(secondItem.payload.value, 'hello3')
@@ -159,7 +159,7 @@ Object.keys(testAPIs).forEach(API => {
const iter = db.iterator()
const next = iter.next().value
assert.notEqual(next, null)
assert.equal(next.cid.startsWith('zd'), true)
assert.equal(next.hash.startsWith('zd'), true)
assert.equal(next.payload.key, null)
assert.equal(next.payload.value, 'hello4')
})
@@ -178,7 +178,7 @@ Object.keys(testAPIs).forEach(API => {
const iter = db.iterator()
const first = iter.next().value
const second = iter.next().value
assert.equal(first.cid, hashes[hashes.length - 1])
assert.equal(first.hash, hashes[hashes.length - 1])
assert.equal(second, null)
assert.equal(first.payload.value, 'hello4')
})
@@ -218,7 +218,7 @@ Object.keys(testAPIs).forEach(API => {
const iter = db.iterator({ limit: 0 })
const first = iter.next().value
const second = iter.next().value
assert.equal(first.cid, last(hashes))
assert.equal(first.hash, last(hashes))
assert.equal(second, null)
})
@@ -226,7 +226,7 @@ Object.keys(testAPIs).forEach(API => {
const iter = db.iterator({ limit: 1 })
const first = iter.next().value
const second = iter.next().value
assert.equal(first.cid, last(hashes))
assert.equal(first.hash, last(hashes))
assert.equal(second, null)
})
@@ -236,16 +236,16 @@ Object.keys(testAPIs).forEach(API => {
const second = iter.next().value
const third = iter.next().value
const fourth = iter.next().value
assert.equal(first.cid, hashes[hashes.length - 3])
assert.equal(second.cid, hashes[hashes.length - 2])
assert.equal(third.cid, hashes[hashes.length - 1])
assert.equal(first.hash, hashes[hashes.length - 3])
assert.equal(second.hash, hashes[hashes.length - 2])
assert.equal(third.hash, hashes[hashes.length - 1])
assert.equal(fourth, null)
})
it('returns all items', () => {
const messages = db.iterator({ limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
messages.reverse()
assert.equal(messages.length, hashes.length)
@@ -255,7 +255,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns all items when limit is bigger than -1', () => {
const messages = db.iterator({ limit: -300 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, hashes.length)
assert.equal(messages[0], hashes[0])
@@ -264,7 +264,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns all items when limit is bigger than number of items', () => {
const messages = db.iterator({ limit: 300 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, hashes.length)
assert.equal(messages[0], hashes[0])
@@ -276,7 +276,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns 1 item when gte is the head', () => {
const messages = db.iterator({ gte: last(hashes), limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 1)
assert.equal(messages[0], last(hashes))
@@ -291,7 +291,7 @@ Object.keys(testAPIs).forEach(API => {
const gte = hashes[hashes.length - 2]
const messages = db.iterator({ gte: gte, limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 2)
assert.equal(messages[0], hashes[hashes.length - 2])
@@ -301,7 +301,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns all items when gte is the root item', () => {
const messages = db.iterator({ gte: hashes[0], limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, hashes.length)
assert.equal(messages[0], hashes[0])
@@ -311,7 +311,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns items when gt is the root item', () => {
const messages = db.iterator({ gt: hashes[0], limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, itemCount - 1)
assert.equal(messages[0], hashes[1])
@@ -321,13 +321,13 @@ Object.keys(testAPIs).forEach(API => {
it('returns items when gt is defined', () => {
const messages = db.iterator({ limit: -1})
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
const gt = messages[2]
const messages2 = db.iterator({ gt: gt, limit: 100 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages2.length, 2)
assert.equal(messages2[0], messages[messages.length - 2])
@@ -339,7 +339,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns one item after head when lt is the head', () => {
const messages = db.iterator({ lt: last(hashes) })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 1)
assert.equal(messages[0], hashes[hashes.length - 2])
@@ -348,7 +348,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns all items when lt is head and limit is -1', () => {
const messages = db.iterator({ lt: last(hashes), limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, hashes.length - 1)
assert.equal(messages[0], hashes[0])
@@ -358,7 +358,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns 3 items when lt is head and limit is 3', () => {
const messages = db.iterator({ lt: last(hashes), limit: 3 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 3)
assert.equal(messages[0], hashes[hashes.length - 4])
@@ -373,7 +373,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns one item when lte is the root item', () => {
const messages = db.iterator({ lte: hashes[0] })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 1)
assert.equal(messages[0], hashes[0])
@@ -382,7 +382,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns all items when lte is the head', () => {
const messages = db.iterator({ lte: last(hashes), limit: -1 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, itemCount)
assert.equal(messages[0], hashes[0])
@@ -392,7 +392,7 @@ Object.keys(testAPIs).forEach(API => {
it('returns 3 items when lte is the head', () => {
const messages = db.iterator({ lte: last(hashes), limit: 3 })
.collect()
.map((e) => e.cid)
.map((e) => e.hash)
assert.equal(messages.length, 3)
assert.equal(messages[0], hashes[hashes.length - 3])

View File

@@ -0,0 +1,2 @@
Û{"hash":null,"id":"/orbitdb/QmWDUfC4zcWJGgc9UHn1X3qQ5KZqBv4KCiCtjnpMmBT8JC/v0-db","payload":{"op":"ADD","key":null,"value":{"thing":"1"}},"next":[],"v":0,"clock":{"id":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78","time":1},"sig":"30460221008067ac541ab9b8ef6de41318220c6927f046188ae63620c34666d1ca00574001022100b9427217bb79b4bdad8645bb361745ffffa0bfa264778202c68aa8f2b9857ada","key":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78"}

View File

@@ -0,0 +1,2 @@
h{"name":"v0-db","type":"feed","accessController":"/ipfs/Qmc3S7aMSmH8oGmx7Zdp8UxVWcDyCq5o2H9qYFgT3GW6nM"}

View File

@@ -0,0 +1,8 @@
º{
"admin": [],
"write": [
"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78"
],
"read": []
}

View File

@@ -0,0 +1,2 @@
{"hash":null,"id":"/orbitdb/QmWDUfC4zcWJGgc9UHn1X3qQ5KZqBv4KCiCtjnpMmBT8JC/v0-db","payload":{"op":"ADD","key":null,"value":{"thing":"2"}},"next":["QmPoEJkWCkgDkuNdshm6Srw9haEBtgn1e352dkF1wpEfXt"],"v":0,"clock":{"id":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78","time":2},"sig":"30460221008067ac541ab9b8ef6de41318220c6927f046188ae63620c34666d1ca00574001022100b9427217bb79b4bdad8645bb361745ffffa0bfa264778202c68aa8f2b9857ada","key":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78"}

View File

@@ -0,0 +1,2 @@
¼{"hash":null,"id":"/orbitdb/QmWDUfC4zcWJGgc9UHn1X3qQ5KZqBv4KCiCtjnpMmBT8JC/v0-db","payload":{"op":"ADD","key":null,"value":{"thing":"3"}},"next":["QmZvMXmv66vXQ9u2q8UTWPmH59eQUKzVb24bKv8j9zbVuN","QmPoEJkWCkgDkuNdshm6Srw9haEBtgn1e352dkF1wpEfXt"],"v":0,"clock":{"id":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78","time":3},"sig":"30460221008067ac541ab9b8ef6de41318220c6927f046188ae63620c34666d1ca00574001022100b9427217bb79b4bdad8645bb361745ffffa0bfa264778202c68aa8f2b9857ada","key":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78"}

BIN
test/fixtures/ipfs/datastore/000183.ldb vendored Normal file

Binary file not shown.

BIN
test/fixtures/ipfs/datastore/000187.ldb vendored Normal file

Binary file not shown.

BIN
test/fixtures/ipfs/datastore/000192.ldb vendored Normal file

Binary file not shown.

BIN
test/fixtures/ipfs/datastore/000197.ldb vendored Normal file

Binary file not shown.

1
test/fixtures/ipfs/datastore/CURRENT vendored Normal file
View File

@@ -0,0 +1 @@
MANIFEST-000200

Binary file not shown.

View File

@@ -0,0 +1 @@
{"publicKey":"04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78","privateKey":"31cbd0193567605dba4cd27a0fe4de82151be65aac16b58f2337ec2b7ad41b38"}

View File

@@ -0,0 +1 @@
MANIFEST-000371

View File

@@ -165,10 +165,11 @@ Object.keys(testAPIs).forEach(API => {
// Write entries to each database
console.log("Writing to databases")
databaseInterfaces.forEach((dbInterface, index) => {
for (let index = 0; index < databaseInterfaces.length; index++) {
const dbInterface = databaseInterfaces[index]
const db = localDatabases[index]
mapSeries(entryArr, val => dbInterface.write(db, val))
})
await mapSeries(entryArr, val => dbInterface.write(db, val))
}
// Function to check if all databases have been replicated,
// we calculate this by checking number of 'replicated' events fired

View File

@@ -23,7 +23,7 @@ const ipfsPath2 = './orbitdb/tests/replication/2/ipfs'
Object.keys(testAPIs).forEach(API => {
describe(`orbit-db - Replication (${API})`, function() {
this.timeout(100000)
this.timeout(config.timeout)
let ipfsd1, ipfsd2, ipfs1, ipfs2
let orbitdb1, orbitdb2, db1, db2
@@ -297,10 +297,8 @@ Object.keys(testAPIs).forEach(API => {
try {
// Test the replicator state
assert.equal(db2._loader.tasksRequested >= db2.replicationStatus.progress, true)
assert.equal(db2._loader.tasksQueued <= db2.options.referenceCount, true)
assert.equal(db2.options.referenceCount, 64)
assert.equal(db2._loader.tasksRunning, 0)
assert.equal(db2._loader.tasksFinished, db2.replicationStatus.progress)
} catch (e) {
reject(e)
}
@@ -316,8 +314,7 @@ Object.keys(testAPIs).forEach(API => {
// Resolve with a little timeout to make sure we
// don't receive more than one event
setTimeout( async () => {
// console.log(eventCount['replicate.progress'], expectedEventCount)
if (eventCount['replicate.progress'] === expectedEventCount) {
if (eventCount['replicated'] === expectedEventCount) {
finished = true
}
}, 100)

View File

@@ -25,8 +25,6 @@ module.exports = {
}
},
daemon1: {
repo: './ipfs/orbitdb/tests/daemon1',
start: true,
EXPERIMENTAL: {
pubsub: true
},
@@ -49,8 +47,6 @@ module.exports = {
},
},
daemon2: {
repo: './ipfs/orbitdb/tests/daemon2',
start: true,
EXPERIMENTAL: {
pubsub: true
},
@@ -71,5 +67,5 @@ module.exports = {
}
},
},
},
}
}

View File

@@ -17,12 +17,14 @@ class CustomTestKeystore {
createKey (id) {
const key = ec.genKeyPair()
const keyPair = ec.keyPair({
pub: key.getPublic('hex'),
const keyPair = {
public: {
marshal: () => key.getPublic('hex')
},
priv: key.getPrivate('hex'),
privEnc: 'hex',
pubEnc: 'hex',
})
}
return keyPair
}
@@ -33,13 +35,15 @@ class CustomTestKeystore {
sign (key, data) {
return Promise.resolve('<signature>')
const sig = ec.sign(data, key)
return Promise.resolve(sig.toDER('hex'))
}
verify (signature, publicKey, data) {
return Promise.resolve(true)
}
getPublic (key) {
return key.public.marshal()
}
}
module.exports = (LocalStorage, mkdir) => {

105
test/v0-open-load.js Normal file
View File

@@ -0,0 +1,105 @@
'use strict'
const assert = require('assert')
const mapSeries = require('p-map-series')
const fs = require('fs-extra')
const path = require('path')
const rmrf = require('rimraf')
const levelup = require('levelup')
const leveldown = require('leveldown')
const OrbitDB = require('../src/OrbitDB')
const OrbitDBAddress = require('../src/orbit-db-address')
const io = require('orbit-db-io')
const IPFS = require('ipfs')
const Identities = require('orbit-db-identity-provider')
const migrate = require('localstorage-level-migration')
// Include test utilities
const {
config,
startIpfs,
stopIpfs,
testAPIs,
} = require('./utils')
const dbPath = './orbitdb/tests/v0'
const keyFixtures = './test/fixtures/keys/QmRfPsKJs9YqTot5krRibra4gPwoK4kghhU8iKWxBjGDDX'
const dbFixturesDir = './test/fixtures/v0'
const ipfsFixturesDir = './test/fixtures/ipfs'
Object.keys(testAPIs).forEach(API => {
describe(`orbit-db - Backward-Compatibility - Open & Load (${API})`, function() {
this.timeout(config.timeout)
let ipfsd, ipfs, orbitdb, db, address
let localDataPath
before(async () => {
ipfsd = await startIpfs(API, config.daemon1)
ipfs = ipfsd.api
//copy data files to ipfs and orbitdb repos
await fs.copy(path.join(ipfsFixturesDir, 'blocks'), path.join(ipfsd.path, 'blocks'))
await fs.copy(path.join(ipfsFixturesDir, 'datastore'), path.join(ipfsd.path, 'datastore'))
await fs.copy(dbFixturesDir, dbPath)
let identity = await Identities.createIdentity({ id: ipfs._peerInfo.id._idB58String, migrate: migrate(keyFixtures), identityKeysPath: dbPath + '/keys' })
orbitdb = await OrbitDB.createInstance(ipfs, { directory: dbPath, identity })
})
after(async () => {
rmrf.sync(dbPath)
if(orbitdb)
await orbitdb.stop()
if (ipfsd)
await stopIpfs(ipfsd)
})
describe('Open & Load', function() {
before(async () => {
db = await orbitdb.open('/orbitdb/QmWDUfC4zcWJGgc9UHn1X3qQ5KZqBv4KCiCtjnpMmBT8JC/v0-db')
await db.load()
})
after(async () => {
if (db)
await db.close()
})
it('open v0 orbitdb address', async () => {
assert.notEqual(db, null)
})
it('database has the correct v0 address', async () => {
assert.equal(db.address.toString().indexOf('/orbitdb'), 0)
assert.equal(db.address.toString().indexOf('Qm'), 9)
assert.equal(db.address.toString().indexOf('v0-db'), 56)
})
it('has the correct type', async () => {
assert.equal(db.type, 'feed')
})
it('database has the correct access-controller', async () => {
assert.equal(db.options.accessControllerAddress, '/ipfs/Qmc3S7aMSmH8oGmx7Zdp8UxVWcDyCq5o2H9qYFgT3GW6nM')
assert.equal(db.access.type, 'ipfs')
assert.strictEqual(db.access.write[0], '04b54f6ef529cd2dd2f9c6897a382c492222d42e57826269a38101ffe752aa07260ecd092a970d7eef08c4ddae2b7006ee25f07e4ab62fa5262ae3b51fdea29f78')
})
it('load v0 orbitdb address', async () => {
assert.equal(db.all.length, 3)
})
it('allows migrated key to write', async () => {
const hash = await db.add({ thing: 'new addition'})
const newEntries = db.all.filter(e => e.v === 1)
assert.equal(newEntries.length, 1)
assert.strictEqual(newEntries[0].hash, hash)
})
})
})
})