identity, sign, verify - values for creating a cryptographically signed
feed. See below.

You can also pass in an identity and sign/verify functions which can be
used to create a signed log:

{
identity: aPublicKeyBuffer, // will be added to all nodes you insertsign:function (node, cb) {
// will be called with all nodes you addvar signatureBuffer =someCrypto.sign(node.key, mySecretKey)
cb(null, signatureBuffer)
},
verify:function (node, cb) {
// will be called with all nodes you receiveif (!node.signature) returncb(null, false)
cb(null, someCrypto.verify(node.key, node.signature. node.identity))
}
}

log.add(links, value, opts={}, [cb])

Add a new node to the graph. links should be an array of node keys that this node links to.
If it doesn't link to any nodes use null or an empty array. value is the value that you want to store
in the node. This should be a string or a buffer. The callback is called with the inserted node:

log.add([link], value, function(err, node) {
// node looks like this
{
change:...// the change number for this node in the local log
key:...// the hash of the node. this is also the key of the node
value:...// the value (as the valueEncoding type, default buffer) you inserted
log:...// the peer log this node was appended to
seq:...// the peer log seq number
links: ['hash-of-link-1', ...]
}
})

Optionally supply an opts.valueEncoding.

log.append(value, opts={}, [cb])

Add a value that links all the current heads.

Optionally supply an opts.valueEncoding.

log.batch(docs, opts={}, [cb])

Add many documents atomically to the log at once: either all the docs are
inserted successfully or nothing is inserted.

{
since: changeNumber // only returns changes AFTER the number
live:false// never close the change stream
tail:false// since = lastChange
limit: number // only return up to `limit` changes
until: number // (for non-live streams) only returns changes BEFORE the number
valueEncoding:'binary'
}

replicationStream = log.replicate([options])

Replicate the log to another one using a replication stream.
Simply pipe your replication stream together with another log's replication stream.

If you send metadata it will be emitted as an metadata event on the stream.
A detailed write up on how the graph replicates will be added later.

log.on('preadd', function (node) {})

On the same tick as log.add() is called, this event fires with the node
about to be inserted into the log. At this stage of the add process, node has
these properties:

node.log

node.key

node.value

node.links

log.on('add', function (node) {})

After a node has been successfully added to the log, this event fires with the
full node object that the callback to .add() gets.

log.on('reject', function (node) {})

When a node is rejected, this event fires. Otherwise the add event will fire.

You can track preadd events against both add and reject events in
combination to know when the log is completely caught up.

Hyperlog Hygiene

A hyperlog will refer to potentially many different logs as it replicates with
others, each with its own ID. Bear in mind that each hyperlog's underlying
leveldb contains a notion of what its own local ID is. If you make a copy of a
hyperlog's leveldb and write different data to each copy, the results are
unpredictable and likely disastrous. Always only use the included replication
mechanism for making hyperlog copies!