Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git b/index.js a/index.js
- index 0c1c1b2..bc4992d 100755
- --- b/index.js
- +++ a/index.js
- @@ -1 +1 @@
- -module.exports = require('./src/merk.js')
- +module.exports = require('./src/constellation.js')
- diff --git b/package.json a/package.json
- index bbc5b32..946785d 100755
- --- b/package.json
- +++ a/package.json
- @@ -1,7 +1,7 @@
- {
- - "name": "merk",
- - "version": "1.1.1",
- - "description": "A Merkle tree with the simplest interface ever",
- + "name": "constellationsjs",
- + "version": "0.1.6",
- + "description": "constellationsJS features a simple interface for Merkle Trees and works directly with dappJS, MoonCoin, MoonContracts and BenchCore.",
- "main": "index.js",
- "dependencies": {
- "create-hash": "^1.1.3",
- @@ -27,6 +27,6 @@
- "!test/common.js"
- ]
- },
- - "author": "Matt Bell <[email protected]>",
- + "1author": "BenchX <[email protected]>",
- "license": "MIT"
- }
- diff --git b/src/common.js a/src/common.js
- index 4c23d5e..2cc571e 100755
- --- b/src/common.js
- +++ a/src/common.js
- @@ -19,11 +19,12 @@ function isObject (value) {
- return typeof value === 'object' && value != null
- }
- -// clones an object, without any properties of type 'object'
- function baseObject (obj) {
- if (!isObject(obj)) return obj
- let base = {}
- - if (Array.isArray(obj)) base = []
- + if (Array.isArray(obj)) {
- + base.length = obj.length
- + }
- for (let key in obj) {
- let value = obj[key]
- if (isObject(value)) continue
- @@ -32,7 +33,6 @@ function baseObject (obj) {
- return base
- }
- -// gets an object property based on an array key path
- function access (obj, path) {
- if (path.length === 0) {
- return [ obj, true ]
- @@ -48,12 +48,10 @@ function access (obj, path) {
- return access(obj[key], subpath)
- }
- -// shallow clone
- function clone (value) {
- if (!isObject(value)) return value
- if (Array.isArray(value)) return value.slice()
- let cloned = {}
- - // doesn't include symbols
- for (let key in value) {
- cloned[key] = value[key]
- }
- @@ -62,13 +60,11 @@ function clone (value) {
- function pathToKey (path) {
- if (path.length === 0) return symbols.root
- - // TODO: support path components w/ "." character ('["foo.bar"]')
- return path.join('.')
- }
- function keyToPath (key) {
- if (key === symbols.root) return []
- - // TODO: support path components w/ "." character ('["foo.bar"]')
- return key.split('.')
- }
- diff --git b/src/constellation.js a/src/constellation.js
- index 7589f79..c64dc45 100755
- --- b/src/constellation.js
- +++ a/src/constellation.js
- @@ -6,13 +6,11 @@ let verify = require('./verify.js')
- let createProof = require('./proof.js')
- let { symbols } = require('./common.js')
- -async function createMerk (db) {
- +async function createConstellation (db) {
- if (!db || db.toString() !== 'LevelUP') {
- throw Error('Must provide a LevelUP instance')
- }
- - // TODO: decouple state wrapper from tree
- - // (could be used with any LevelUp)
- let tree = Tree(db)
- let mutations = MutationStore()
- @@ -27,10 +25,9 @@ async function createMerk (db) {
- function assertRoot (root) {
- if (root[symbols.mutations] != null) return
- - throw Error('Must specify a root merk object')
- + throw Error('Must specify a root constellation object')
- }
- -// revert to last commit
- function rollback (root) {
- assertRoot(root)
- let mutations = root[symbols.mutations]()
- @@ -38,7 +35,6 @@ function rollback (root) {
- mutations.rollback(unwrappedRoot)
- }
- -// flush to db
- function commit (root) {
- assertRoot(root)
- let mutations = root[symbols.mutations]()
- @@ -46,14 +42,12 @@ function commit (root) {
- return mutations.commit(db)
- }
- -// returns merkle root
- function hash (root) {
- assertRoot(root)
- let tree = root[symbols.db]()
- return tree.rootHash().toString('hex')
- }
- -// returns a merkle proof
- function proof (root, query = '') {
- assertRoot(root)
- let tree = root[symbols.db]()
- @@ -67,7 +61,7 @@ function getter (symbol) {
- }
- }
- -module.exports = Object.assign(createMerk, {
- +module.exports = Object.assign(createConstellation, {
- mutations: getter(symbols.mutations),
- rollback,
- commit,
- diff --git b/src/json.js a/src/json.js
- index 26f34e0..f749d69 100755
- --- b/src/json.js
- +++ a/src/json.js
- @@ -2,20 +2,16 @@ let stableStringify = require('json-stable-stringify')
- const base64Prefix = ':base64:'
- -// stringifies JSON deterministically, and converts Buffers to
- -// base64 strings (prefixed with ":base64:")
- function stringify (obj) {
- let convertedObj = deepClone(obj, bufferToBase64Replacer)
- return stableStringify(convertedObj)
- }
- -// parses JSON and converts strings with ":base64:" prefix to Buffers
- function parse (json) {
- let obj = JSON.parse(json)
- return convertBase64ToBuffers(obj)
- }
- -// clones an object, with a replacer function
- function deepClone (obj, replacer) {
- let newObj = Array.isArray(obj) ? [] : {}
- Object.assign(newObj, obj)
- @@ -29,8 +25,6 @@ function deepClone (obj, replacer) {
- }
- function bufferToBase64Replacer (value) {
- - // convert JSON.stringified Buffer objects to Buffer,
- - // so they can get encoded to base64
- if (
- typeof value === 'object' &&
- value.type === 'Buffer' &&
- @@ -55,12 +49,10 @@ function convertBase64ToBuffers (obj) {
- return replace(obj, base64ToBufferReplacer)
- }
- -// replaces values in an object without cloning
- function replace (obj, replacer) {
- for (let key in obj) {
- obj[key] = replacer(obj[key])
- if (typeof obj[key] === 'object' && !Buffer.isBuffer(obj[key])) {
- - // recursively replace props of objects (unless it's a Buffer)
- replace(obj[key], replacer)
- }
- }
- diff --git b/src/load.js a/src/load.js
- index e417f57..2a9aabe 100755
- --- b/src/load.js
- +++ a/src/load.js
- @@ -1,15 +1,11 @@
- let { access, keyToPath } = require('./common.js')
- let { parse } = require('./json.js')
- -// load existing data if it exists
- async function load (tree) {
- - // TODO: decouple from tree
- - // (could be levelup createReadStream)
- let rootNode = await tree.rootNode()
- - if (!rootNode) return {} // no existing data
- + if (!rootNode) return {}
- - // get root object
- let cursor = await rootNode.min()
- let root = {}
- @@ -19,8 +15,6 @@ async function load (tree) {
- cursor = await cursor.next()
- }
- - // iterate through all keys in order,
- - // create objects based on key/value
- while (cursor) {
- let path = keyToPath(cursor.key.slice(1))
- let [ parent ] = access(root, path.slice(0, -1))
- diff --git b/src/mutationStore.js a/src/mutationStore.js
- index 298ee1f..3cd4150 100755
- --- b/src/mutationStore.js
- +++ a/src/mutationStore.js
- @@ -62,7 +62,9 @@ class MutationStore {
- rollback (state) {
- // reapply previous values
- - for (let key in this.before) {
- + let beforeKeys = Object.keys(this.before)
- + beforeKeys.sort()
- + for (let key of beforeKeys) {
- let value = this.before[key]
- let path = keyToPath(key)
- @@ -72,7 +74,13 @@ class MutationStore {
- if (value === symbols.delete) {
- delete parent[lastKey]
- } else {
- - updateBase(parent[lastKey], value)
- + let base = parent[lastKey]
- + // handle restoring a deleted array child-object
- + if (Array.isArray(parent) && base == null) {
- + parent[lastKey] = value
- + } else {
- + updateBase(base, value)
- + }
- }
- }
- diff --git b/src/node.js a/src/node.js
- index 0bf7d8b..cb3ef11 100755
- --- b/src/node.js
- +++ a/src/node.js
- @@ -5,7 +5,7 @@ let { sha256, ripemd160 } = require('./common.js')
- const nullHash = Buffer.alloc(20)
- let VarString = struct.VarString(VarInt)
- -let codec = struct([
- +let adapter = struct([
- ['hash', struct.Buffer(20)],
- ['kvHash', struct.Buffer(20)],
- ['leftHeight', struct.UInt8],
- @@ -36,21 +36,21 @@ function nodeKey (key) {
- return 'n' + key
- }
- -function putNode (tx, node) {
- - let nodeBytes = codec.encode(node).toString('base64')
- - return tx.put(nodeKey(node.key), nodeBytes)
- +function putNode (ntx, node) {
- + let nodeBytes = adapter.encode(node).toString('base64')
- + return ntx.put(nodeKey(node.key), nodeBytes)
- }
- -function delNode (tx, node) {
- - return tx.del(nodeKey(node.key))
- +function delNode (ntx, node) {
- + return ntx.del(nodeKey(node.key))
- }
- module.exports = function (db) {
- - async function getNode (tx, key) {
- + async function getNode (ntx, key) {
- if (key === '') return null
- - let nodeB64 = (await tx.get(nodeKey(key))).toString()
- + let nodeB64 = (await ntx.get(nodeKey(key))).toString()
- let nodeBytes = Buffer.from(nodeB64, 'base64')
- - let decoded = codec.decode(nodeBytes)
- + let decoded = adapter.decode(nodeBytes)
- decoded.key = key
- return new Node(decoded)
- }
- @@ -82,28 +82,28 @@ module.exports = function (db) {
- return !this.isInnerNode()
- }
- - left (tx) {
- - return getNode(tx, this.leftKey)
- + left (ntx) {
- + return getNode(ntx, this.leftKey)
- }
- - right (tx) {
- - return getNode(tx, this.rightKey)
- + right (ntx) {
- + return getNode(ntx, this.rightKey)
- }
- - child (tx, left) {
- - if (left) return this.left(tx)
- - return this.right(tx)
- + child (ntx, left) {
- + if (left) return this.left(ntx)
- + return this.right(ntx)
- }
- - parent (tx) {
- - return getNode(tx, this.parentKey)
- + parent (ntx) {
- + return getNode(ntx, this.parentKey)
- }
- - save (tx) {
- - return putNode(tx, this)
- + save (ntx) {
- + return putNode(ntx, this)
- }
- - async setChild (tx, left, child, rebalance = true) {
- + async setChild (ntx, left, child, rebalance = true) {
- if (child != null) {
- child.parentKey = this.key
- } else {
- @@ -114,15 +114,15 @@ module.exports = function (db) {
- this[left ? 'leftHeight' : 'rightHeight'] = child.height()
- if (rebalance && Math.abs(this.balance()) > 1) {
- - return this.rebalance(tx)
- + return this.rebalance(ntx)
- }
- - let leftChild = left ? child : await this.left(tx)
- - let rightChild = !left ? child : await this.right(tx)
- + let leftChild = left ? child : await this.left(ntx)
- + let rightChild = !left ? child : await this.right(ntx)
- this.calculateHash(leftChild, rightChild)
- - await this.save(tx)
- - await child.save(tx)
- + await this.save(ntx)
- + await child.save(ntx)
- return this
- }
- @@ -130,27 +130,26 @@ module.exports = function (db) {
- return this.rightHeight - this.leftHeight
- }
- - async rebalance (tx) {
- + async rebalance (ntx) {
- let left = this.balance() < 0
- - let child = await this.child(tx, left)
- + let child = await this.child(ntx, left)
- - // check if we should do a double rotation
- let childLeftHeavy = child.balance() < 0
- let childRightHeavy = child.balance() > 0
- let double = left ? childRightHeavy : childLeftHeavy
- if (double) {
- - let successor = await child.rotate(tx, !left)
- - await this.setChild(tx, left, successor, false)
- + let successor = await child.rotate(ntx, !left)
- + await this.setChild(ntx, left, successor, false)
- }
- - return this.rotate(tx, left)
- + return this.rotate(ntx, left)
- }
- - async rotate (tx, left) {
- - let child = await this.child(tx, left)
- - let grandChild = await child.child(tx, !left)
- - await this.setChild(tx, left, grandChild, false)
- + async rotate (ntx, left) {
- + let child = await this.child(ntx, left)
- + let grandChild = await child.child(ntx, !left)
- + await this.setChild(ntx, left, grandChild, false)
- child.parentKey = ''
- - await child.setChild(tx, !left, this, false)
- + await child.setChild(ntx, !left, this, false)
- return child
- }
- @@ -177,69 +176,61 @@ module.exports = function (db) {
- return this.kvHash
- }
- - async put (node, tx) {
- + async put (node, ntx) {
- if (node.key === this.key) {
- - // same key, just update the value of this node
- this.value = node.value
- this.calculateKVHash()
- - this.calculateHash(await this.left(tx), await this.right(tx))
- - await this.save(tx)
- + this.calculateHash(await this.left(ntx), await this.right(ntx))
- + await this.save(ntx)
- return this
- }
- let left = node.key < this.key
- - let child = await this.child(tx, left)
- + let child = await this.child(ntx, left)
- if (child == null) {
- - // no child here, set node as child
- - let successor = await this.setChild(tx, left, node)
- + let successor = await this.setChild(ntx, left, node)
- return successor
- }
- - // recursively put node under child, then update self
- - let newChild = await child.put(node, tx)
- - let successor = await this.setChild(tx, left, newChild)
- + let newChild = await child.put(node, ntx)
- + let successor = await this.setChild(ntx, left, newChild)
- return successor
- }
- - async delete (key, tx) {
- + async delete (key, ntx) {
- if (key === this.key) {
- - // delete this node
- if (this.isLeafNode()) {
- - // no children
- - await delNode(tx, this)
- + await delNode(ntx, this)
- return null
- }
- - // promote successor child to this position
- let left = this.leftHeight > this.rightHeight
- - let successor = await this.child(tx, left)
- + let successor = await this.child(ntx, left)
- successor.parentKey = this.parentKey
- - let otherNode = await this.child(tx, !left)
- + let otherNode = await this.child(ntx, !left)
- if (otherNode) {
- - // if there is another child then put it under successor
- - successor = await successor.put(otherNode, tx)
- + successor = await successor.put(otherNode, ntx)
- }
- - await delNode(tx, this)
- + await delNode(ntx, this)
- return successor
- }
- let left = key < this.key
- - let child = await this.child(tx, left)
- + let child = await this.child(ntx, left)
- if (child == null) {
- - // no child here, key not found
- throw Error(`Key "${key}" not found`)
- }
- - let newChild = await child.delete(key, tx)
- - let successor = await this.setChild(tx, left, newChild)
- + let newChild = await child.delete(key, ntx)
- + let successor = await this.setChild(ntx, left, newChild)
- return successor
- }
- - async edge (left, tx = db) {
- + async edge (left, ntx = db) {
- let cursor = this
- while (true) {
- - let child = await cursor.child(tx, left)
- + let child = await cursor.child(ntx, left)
- if (child == null) return cursor
- cursor = child
- }
- @@ -247,29 +238,27 @@ module.exports = function (db) {
- min () { return this.edge(true) }
- max () { return this.edge(false) }
- - async step (left, tx = db) {
- - let child = await this.child(tx, left)
- - if (child) return child.edge(!left, tx)
- + async step (left, ntx = db) {
- + let child = await this.child(ntx, left)
- + if (child) return child.edge(!left, ntx)
- - // backtrack
- - let cursor = await this.parent(tx)
- + let cursor = await this.parent(ntx)
- while (cursor) {
- let skip = left
- ? cursor.key > this.key
- : cursor.key < this.key
- if (!skip) return cursor
- - cursor = await cursor.parent(tx)
- + cursor = await cursor.parent(ntx)
- }
- - // reached end
- return null
- }
- prev () { return this.step(true) }
- next () { return this.step(false) }
- - async getBranchRange (from, to, tx) {
- - let left = await this.left(tx)
- - let right = await this.right(tx)
- + async getBranchRange (from, to, ntx) {
- + let left = await this.left(ntx)
- + let right = await this.right(ntx)
- let branch = {
- left: left ? left.hash.toString('base64') : null,
- @@ -278,11 +267,13 @@ module.exports = function (db) {
- async function isInRange (node) {
- if (node.key < from) {
- - let next = await node.next(tx)
- + let next = await node.next(ntx)
- + if (next == null) return true
- return next.key >= from
- }
- if (node.key > to) {
- - let prev = await node.prev(tx)
- + let prev = await node.prev(ntx)
- + if (prev == null) return true
- return prev.key <= to
- }
- return true
- @@ -296,16 +287,16 @@ module.exports = function (db) {
- }
- if (left && this.key >= from) {
- - branch.left = await left.getBranchRange(from, to, tx)
- + branch.left = await left.getBranchRange(from, to, ntx)
- }
- if (right && this.key <= to) {
- - branch.right = await right.getBranchRange(from, to, tx)
- + branch.right = await right.getBranchRange(from, to, ntx)
- }
- return branch
- }
- }
- - Node.get = (key, tx = db) => getNode(db, key)
- + Node.get = (key, ntx = db) => getNode(db, key)
- return Node
- }
- diff --git b/src/proof.js a/src/proof.js
- index c5b6ac3..469eedd 100755
- --- b/src/proof.js
- +++ a/src/proof.js
- @@ -1,18 +1,14 @@
- module.exports = async function createProof (tree, query) {
- - // range is query path, and all its child objects
- let from = '.' + query
- - let to = '.' + query + '/' // 1 value past `query + '.'`
- + let to = '.' + query + '/'
- - // special case for root object (get all values)
- if (query === '') to = '/'
- - // check if there is a match for this query
- try {
- await tree.get(from)
- } catch (err) {
- if (!err.notFound) throw err
- - // if not, query parent object
- let path = query.split('.')
- query = path.slice(0, -1).join('.')
- from = '.' + query
- diff --git b/src/tree.js a/src/tree.js
- index fa216d2..d2350ce 100755
- --- b/src/tree.js
- +++ a/src/tree.js
- @@ -38,12 +38,12 @@ class Tree {
- return this._rootNode.hash
- }
- - async setRoot (node, tx) {
- + async setRoot (node, ntx) {
- await this.initialize
- - if (!tx) {
- - tx = createTx(this.db)
- - var createdTx = true
- + if (!ntx) {
- + ntx = createNtx(this.db)
- + var createdNtx = true
- }
- if (node != null) {
- @@ -54,8 +54,8 @@ class Tree {
- this._rootNode = node
- - if (createdTx) {
- - await tx.commit()
- + if (createdNtx) {
- + await ntx.commit()
- }
- }
- @@ -82,21 +82,21 @@ class Tree {
- let release = await this.acquireLock()
- - let tx = createTx(this.db)
- + let ntx = createNtx(this.db)
- let node = new this.Node({ key, value, db: this.db })
- // no root, set node as root
- if (this._rootNode == null) {
- - await node.save(tx)
- - await this.setRoot(node, tx)
- - await tx.commit()
- + await node.save(ntx)
- + await this.setRoot(node, ntx)
- + await ntx.commit()
- release()
- return
- }
- - let successor = await this._rootNode.put(node, tx)
- - await this.setRoot(successor, tx)
- - await tx.commit()
- + let successor = await this._rootNode.put(node, ntx)
- + await this.setRoot(successor, ntx)
- + await ntx.commit()
- release()
- }
- @@ -114,10 +114,10 @@ class Tree {
- let release = await this.acquireLock()
- - let tx = createTx(this.db)
- - let successor = await this._rootNode.delete(key, tx)
- - await this.setRoot(successor, tx)
- - await tx.commit()
- + let ntx = createNtx(this.db)
- + let successor = await this._rootNode.delete(key, ntx)
- + await this.setRoot(successor, ntx)
- + await ntx.commit()
- release()
- }
- @@ -133,14 +133,13 @@ class Tree {
- module.exports = old(Tree)
- -// promsifies level-transactions methods
- -function createTx (db) {
- - let tx = new Transaction(db)
- +function createNtx (db) {
- + let ntx = new Transaction(db)
- return {
- - get: promisify(tx, 'get'),
- - put: promisify(tx, 'put'),
- - del: promisify(tx, 'del'),
- - commit: promisify(tx, 'commit')
- + get: promisify(ntx, 'get'),
- + put: promisify(ntx, 'put'),
- + del: promisify(ntx, 'del'),
- + commit: promisify(ntx, 'commit')
- }
- }
- diff --git b/src/verify.js a/src/verify.js
- index 3604094..a26ecc2 100755
- --- b/src/verify.js
- +++ a/src/verify.js
- @@ -54,9 +54,16 @@ function flatten (node, nodes = [], path = []) {
- if (path.length === 0) {
- node.isEdge = node.left == null || node.right == null
- } else {
- - node.isEdge = (path.length === 1 ||
- - path.reduce((a, b) => a === b)) &&
- - node.left == null && node.right == null
- + let equal = true
- + for (let i = 1; i < path.length; i++) {
- + if (path[i] !== path[i - 1]) {
- + equal = false
- + break
- + }
- + }
- + let leftEdge = path[0] === false
- + let noChildOnEdge = leftEdge ? node.left == null : node.right == null
- + node.isEdge = equal && noChildOnEdge
- }
- nodes.push(node)
- @@ -77,7 +84,6 @@ module.exports = function verify (expectedRootHash, proof, query = '') {
- if (query === '') to = '/'
- let nodes = flatten(proof)
- - // get contiguous nodes which have key/value
- let valueNodes = []
- for (let node of nodes) {
- if (!node.key) {
- @@ -87,7 +93,6 @@ module.exports = function verify (expectedRootHash, proof, query = '') {
- valueNodes.push(node)
- }
- - // ensure we have proof of the entire range
- let checkRange = () => {
- let firstKeyPastFrom = valueNodes[0].key >= from
- let firstKeyIsEdge = valueNodes[0].isEdge
- @@ -102,12 +107,11 @@ module.exports = function verify (expectedRootHash, proof, query = '') {
- }
- }
- - let resultNodes = valueNodes.filter((node) => {
- + let discoveryNodes = valueNodes.filter((node) => {
- return node.key >= from && node.key <= to
- })
- - // try getting parent object
- - if (resultNodes.length === 0) {
- + if (discoveryNodes.length === 0) {
- let path = query.split('.')
- let parentKey = '.' + path.slice(0, -1).join('.')
- let valueKey = path[path.length - 1]
- @@ -130,24 +134,23 @@ module.exports = function verify (expectedRootHash, proof, query = '') {
- checkRange()
- - let result
- - for (let node of resultNodes) {
- - // remove query prefix
- + let discovery
- + for (let node of discoveryNodes) {
- let key = node.key.slice(from.length)
- if (key === '') key = symbols.root
- - // add parsed value to result
- let path = keyToPath(key)
- if (path[0] === '') path.shift()
- let value = parse(node.value)
- if (path.length === 0) {
- - result = value
- + discovery = value
- } else {
- - let [ parent ] = access(result, path.slice(0, -1))
- + if (!discovery) discovery = {}
- + let [ parent ] = access(discovery, path.slice(0, -1))
- let name = path[path.length - 1]
- parent[name] = value
- }
- }
- - return result
- + return discovery
- }
- diff --git b/src/wrap.js a/src/wrap.js
- index 03f507c..76f577f 100755
- --- b/src/wrap.js
- +++ a/src/wrap.js
- @@ -1,6 +1,5 @@
- let { isObject, baseObject, access } = require('./common.js')
- -// wraps an object with a proxy, so we can keep track of mutations
- function wrap (obj, onMutate, path = []) {
- function recordMutation (op, childPath, value) {
- let fullPath = path.concat(childPath)
- @@ -17,44 +16,37 @@ function wrap (obj, onMutate, path = []) {
- existed
- }
- onMutate(mutation)
- - // TODO: replace mutations for overriden paths
- }
- - // TODO: wrap array methods to record array-specific mutations,
- - // otherwise ops like splices and shifts will create N mutations
- -
- function put (obj, key, value, path = []) {
- if (!isObject(value)) {
- - // if we are overriding an existing object,
- - // record deletion
- if (isObject(obj[key])) {
- - // recursively delete object props
- del(obj, key)
- }
- - // record parent object update
- let parent = baseObject(obj)
- parent[key] = value
- recordMutation('put', path, parent)
- return
- }
- - // if we are overriding an existing non-object,
- - // record update of parent base object
- if (key in obj && !isObject(obj[key])) {
- let base = baseObject(obj)
- delete base[key]
- recordMutation('put', path, base)
- }
- + if (Array.isArray(obj)) {
- + let parent = baseObject(obj)
- + recordMutation('put', path, parent)
- + }
- +
- let base = baseObject(value)
- recordMutation('put', path.concat(key), base)
- for (let childKey in value) {
- let child = value[childKey]
- - // if any of our non-object children override an
- - // existing object, then record deletion
- if (!isObject(child)) {
- if (!isObject(obj[key])) continue
- if (!isObject(obj[key][childKey])) continue
- @@ -62,7 +54,6 @@ function wrap (obj, onMutate, path = []) {
- continue
- }
- - // recursively record puts for objects
- put(value, childKey, child, path.concat(key))
- }
- }
- @@ -71,14 +62,12 @@ function wrap (obj, onMutate, path = []) {
- let value = obj[key]
- if (!isObject(obj[key])) {
- - // record parent object update
- let parent = baseObject(obj)
- delete parent[key]
- recordMutation('put', path, parent)
- return
- }
- - // recursively record deletions for objects
- for (let childKey in value) {
- let child = value[childKey]
- if (!isObject(child)) continue
- @@ -89,24 +78,25 @@ function wrap (obj, onMutate, path = []) {
- }
- return new Proxy(obj, {
- - // recursively wrap child objects when accessed
- get (obj, key) {
- let value = obj[key]
- - if (!isObject(value)) return value
- + if (typeof value === 'function') {
- + return value.bind(obj)
- + }
- + if (!isObject(value)) {
- + return value
- + }
- - // if value is object, recursively wrap
- let childPath = path.concat(key)
- return wrap(value, onMutate, childPath)
- },
- - // record mutations
- set (obj, key, value) {
- put(obj, key, value)
- obj[key] = value
- return true
- },
- - // record deletions as mutations too
- deleteProperty (obj, key) {
- if (!(key in obj)) return true
- del(obj, key)
- @@ -114,7 +104,6 @@ function wrap (obj, onMutate, path = []) {
- return true
- },
- - // ovverride ownKeys to exclude symbol properties
- ownKeys () {
- return Object.getOwnPropertyNames(obj)
- }
- diff --git b/test/common.js a/test/common.js
- index e454af1..b26f758 100755
- --- b/test/common.js
- +++ a/test/common.js
- @@ -1,11 +1,10 @@
- -function mockDb (db) {
- +function simDb (db) {
- let store = db ? db.store : {}
- let gets = []
- let puts = []
- let dels = []
- - // support callbacks for level-transactions
- async function get (key, opts, cb) {
- gets.push({ key })
- let value = store[key]
- @@ -27,18 +26,17 @@ function mockDb (db) {
- delete store[key]
- }
- - let mockDb = {
- + let simDb = {
- gets, puts, dels,
- get, put, del,
- store,
- toString: () => 'LevelUP'
- }
- - // support callbacks for level-transactions
- - mockDb.batch = async function (batch, cb) {
- + simDb.batch = async function (batch, cb) {
- try {
- for (let { type, key, value } of batch) {
- - await mockDb[type](key, value)
- + await simDb[type](key, value)
- }
- } catch (err) {
- if (cb) return cb(err)
- @@ -47,9 +45,9 @@ function mockDb (db) {
- if (cb) cb()
- }
- - return mockDb
- + return simDb
- }
- module.exports = {
- - mockDb
- + simDb
- }
- diff --git b/test/constellation.js a/test/constellation.js
- index 6f6fa4c..94f7566 100755
- --- b/test/constellation.js
- +++ a/test/constellation.js
- @@ -1,37 +1,37 @@
- let test = require('ava')
- -let { mockDb } = require('./common.js')
- +let { simDb } = require('./common.js')
- let { symbols } = require('../src/common.js')
- -let merk = require('../src/merk.js')
- +let constellation = require('../src/constellation.js')
- -test('create merk without db', async (t) => {
- +test('create constellation without db', async (t) => {
- try {
- - await merk()
- + await constellation()
- t.fail()
- } catch (err) {
- t.is(err.message, 'Must provide a LevelUP instance')
- }
- try {
- - await merk({})
- + await constellation({})
- t.fail()
- } catch (err) {
- t.is(err.message, 'Must provide a LevelUP instance')
- }
- })
- -test('create merk', async (t) => {
- - let db = mockDb()
- - let obj = await merk(db)
- +test('create constellation', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- t.deepEqual(obj, {})
- - let mutations = merk.mutations(obj)
- + let mutations = constellation.mutations(obj)
- t.deepEqual(mutations.before, {})
- t.deepEqual(mutations.after, {})
- })
- -test('create merk with existing data', async (t) => {
- - let db = mockDb({
- +test('create constellation with existing data', async (t) => {
- + let db = simDb({
- store: {
- ':root': '.foo',
- 'n.foo': 'G+PH6PHsNTbVHY8Kt0AJypGvIU+9uZNSZeEldRF/R+AxQJmP7oqoQAEBB3sieCI6NX0BLgYuZm9vLnkA',
- @@ -40,20 +40,20 @@ test('create merk with existing data', async (t) => {
- }
- })
- - let obj = await merk(db)
- + let obj = await constellation(db)
- t.deepEqual(obj, {
- foo: { x: 5, y: { z: 123 } },
- bar: 'baz'
- })
- - let mutations = merk.mutations(obj)
- + let mutations = constellation.mutations(obj)
- t.deepEqual(mutations.before, {})
- t.deepEqual(mutations.after, {})
- })
- -test('create merk with existing data, with no non-objects on root', async (t) => {
- - let db = mockDb({
- +test('create constellation with existing data, with no non-objects on root', async (t) => {
- + let db = simDb({
- store: {
- ':root': '.foo',
- 'n.foo': 'nVLY483AXQKEMrv1w66IcV3v/IG9uZNSZeEldRF/R+AxQJmP7oqoQAABB3sieCI6NX0ABi5mb28ueQA=',
- @@ -61,20 +61,20 @@ test('create merk with existing data, with no non-objects on root', async (t) =>
- }
- })
- - let obj = await merk(db)
- + let obj = await constellation(db)
- t.deepEqual(obj, {
- foo: { x: 5, y: { z: 123 } }
- })
- - let mutations = merk.mutations(obj)
- + let mutations = constellation.mutations(obj)
- t.deepEqual(mutations.before, {})
- t.deepEqual(mutations.after, {})
- })
- test('rollback', async (t) => {
- - let db = mockDb()
- - let obj = await merk(db)
- + let db = simDb()
- + let obj = await constellation(db)
- t.deepEqual(obj, {})
- @@ -86,50 +86,125 @@ test('rollback', async (t) => {
- bar: 'baz'
- })
- - merk.rollback(obj)
- + constellation.rollback(obj)
- t.deepEqual(obj, {})
- })
- test('commit', async (t) => {
- - let db = mockDb()
- - let obj = await merk(db)
- + let db = simDb()
- + let obj = await constellation(db)
- obj.foo = { x: 5, y: { z: 123 } }
- obj.bar = 'baz'
- - await merk.commit(obj)
- + await constellation.commit(obj)
- t.deepEqual(obj, {
- foo: { x: 5, y: { z: 123 } },
- bar: 'baz'
- })
- - t.is(merk.hash(obj).toString('hex'), '1be3c7e8f1ec3536d51d8f0ab74009ca91af214f')
- + t.is(constellation.hash(obj).toString('hex'), '1be3c7e8f1ec3536d51d8f0ab74009ca91af214f')
- - let mutations = merk.mutations(obj)
- + let mutations = constellation.mutations(obj)
- t.deepEqual(mutations.before, {})
- t.deepEqual(mutations.after, {})
- })
- -test('call merk methods on non-merk object', async (t) => {
- +test('call constellation methods on non-constellation object', async (t) => {
- try {
- - await merk.commit({})
- + await constellation.commit({})
- t.fail()
- } catch (err) {
- - t.is(err.message, 'Must specify a root merk object')
- + t.is(err.message, 'Must specify a root constellation object')
- }
- try {
- - merk.mutations({})
- + constellation.mutations({})
- t.fail()
- } catch (err) {
- - t.is(err.message, 'Must specify a root merk object')
- + t.is(err.message, 'Must specify a root constellation object')
- }
- try {
- - merk.rollback({})
- + constellation.rollback({})
- t.fail()
- } catch (err) {
- - t.is(err.message, 'Must specify a root merk object')
- + t.is(err.message, 'Must specify a root constellation object')
- }
- })
- +
- +test('rollback on array length increase', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- +
- + obj.array = [ 1, 2, 3 ]
- +
- + await constellation.commit(obj)
- +
- + obj.array.push(4)
- +
- + constellation.rollback(obj)
- +
- + t.deepEqual(obj, { array: [ 1, 2, 3 ] })
- +})
- +
- +test('rollback on array length increase with objects', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- +
- + obj.array = [ {}, {}, {} ]
- +
- + await constellation.commit(obj)
- +
- + obj.array.push({})
- +
- + constellation.rollback(obj)
- +
- + t.deepEqual(obj, { array: [ {}, {}, {} ] })
- +})
- +
- +test('rollback on array length decrease', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- +
- + obj.array = [ 1, 2, 3 ]
- +
- + await constellation.commit(obj)
- +
- + obj.array.pop()
- +
- + constellation.rollback(obj)
- +
- + t.deepEqual(obj, { array: [ 1, 2, 3 ] })
- +})
- +
- +test('rollback on array length decrease with objects', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- +
- + obj.array = [ {}, {}, {} ]
- +
- + await constellation.commit(obj)
- +
- + obj.array.pop()
- +
- + constellation.rollback(obj)
- +
- + t.deepEqual(obj, { array: [ {}, {}, {} ] })
- +})
- +
- +test('rollback on array length increase with mixed types', async (t) => {
- + let db = simDb()
- + let obj = await constellation(db)
- +
- + obj.array = [ {}, {}, {}, 4, 5, 6 ]
- +
- + await constellation.commit(obj)
- +
- + obj.array.push({})
- +
- + constellation.rollback(obj)
- +
- + t.deepEqual(obj, { array: [ {}, {}, {}, 4, 5, 6 ] })
- +})
- diff --git b/test/mutationStore.js a/test/mutationStore.js
- index b74ef53..571dab3 100755
- --- b/test/mutationStore.js
- +++ a/test/mutationStore.js
- @@ -1,5 +1,5 @@
- let test = require('ava')
- -let { mockDb } = require('./common.js')
- +let { simDb } = require('./common.js')
- let { symbols } = require('../src/common.js')
- let MutationStore = require('../src/mutationStore.js')
- @@ -159,7 +159,7 @@ test('delete multi-level non-preexisting key', (t) => {
- })
- test('commit', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -191,7 +191,7 @@ test('commit', async (t) => {
- })
- test('mutate after commit', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -246,7 +246,7 @@ test('mutate after commit', async (t) => {
- })
- test('delete after commit', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -292,7 +292,7 @@ test('delete after commit', async (t) => {
- })
- test('commit deletion', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -344,7 +344,7 @@ test('commit deletion', async (t) => {
- })
- test('commit without root mutation', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -375,7 +375,7 @@ test('commit without root mutation', async (t) => {
- })
- test('rollback from null state', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- let obj = {
- @@ -413,7 +413,7 @@ test('rollback from null state', async (t) => {
- })
- test('rollback from committed state', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- @@ -479,7 +479,7 @@ test('rollback from committed state', async (t) => {
- })
- test('rollback without root mutation', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let ms = MutationStore()
- ms.mutate({
- diff --git b/test/node.js a/test/node.js
- index adaa5a2..a039341 100755
- --- b/test/node.js
- +++ a/test/node.js
- @@ -1,9 +1,9 @@
- let test = require('ava')
- -let { mockDb } = require('./common.js')
- +let { simDb } = require('./common.js')
- let _Node = require('../src/node.js')
- test('create node without key', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- try {
- let node = new Node({})
- @@ -14,7 +14,7 @@ test('create node without key', async (t) => {
- })
- test('create node without value', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- try {
- let node = new Node({ key: 'foo' })
- @@ -25,7 +25,7 @@ test('create node without value', async (t) => {
- })
- test('create node', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let node = new Node({ key: 'foo', value: 'bar' })
- t.is(node.key, 'foo')
- @@ -38,27 +38,27 @@ test('create node', async (t) => {
- })
- test('access null links', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- - let tx = mockDb()
- + let ntx = simDb()
- let node = new Node({ key: 'foo', value: 'bar' })
- async function access (getLink) {
- - let tx = mockDb()
- - t.is(await getLink.call(node, tx), null)
- - t.is(tx.gets.length, 0)
- + let ntx = simDb()
- + t.is(await getLink.call(node, ntx), null)
- + t.is(ntx.gets.length, 0)
- }
- await access(node.left)
- await access(node.right)
- await access(node.parent)
- - await access((tx) => node.child(tx, true))
- - await access((tx) => node.child(tx, false))
- + await access((ntx) => node.child(ntx, true))
- + await access((ntx) => node.child(ntx, false))
- })
- test('save node', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let node = new Node({ key: 'foo', value: 'bar' })
- @@ -75,15 +75,15 @@ test('save node', async (t) => {
- })
- test('save child node', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let node = new Node({ key: 'foo', value: 'bar' })
- await node.save(db)
- - let tx = mockDb()
- + let ntx = simDb()
- let node2 = new Node({ key: 'fo', value: 'bar' })
- - node = await node.put(node2, tx)
- + node = await node.put(node2, ntx)
- t.is(node2.key, 'fo')
- t.is(db.gets.length, 0)
- @@ -95,9 +95,9 @@ test('save child node', async (t) => {
- }
- ])
- - t.is(tx.gets.length, 0)
- - t.is(tx.dels.length, 0)
- - t.deepEqual(tx.puts, [
- + t.is(ntx.gets.length, 0)
- + t.is(ntx.dels.length, 0)
- + t.deepEqual(ntx.puts, [
- {
- key: 'nfoo',
- value: 'dr+bSNfQWI8G7CldNgJ45LFadOytBZ8KwnM2IWh629jJxBTapVD+iAEAA2JhcgJmbwAA'
- @@ -108,78 +108,78 @@ test('save child node', async (t) => {
- }
- ])
- - let tx2 = mockDb()
- - t.is(await node.parent(tx2), null)
- + let ntx2 = simDb()
- + t.is(await node.parent(ntx2), null)
- // get parent
- - tx = mockDb(tx)
- - let parent = await node2.parent(tx)
- + ntx = simDb(ntx)
- + let parent = await node2.parent(ntx)
- t.is(parent.key, 'foo')
- t.is(parent.value, 'bar')
- - t.deepEqual(tx.gets, [ { key: 'nfoo' } ])
- + t.deepEqual(ntx.gets, [ { key: 'nfoo' } ])
- // get child
- - tx = mockDb(tx)
- - let child = await node.left(tx)
- + ntx = simDb(ntx)
- + let child = await node.left(ntx)
- t.is(child.key, 'fo')
- t.is(child.value, 'bar')
- - t.deepEqual(tx.gets, [ { key: 'nfo' } ])
- + t.deepEqual(ntx.gets, [ { key: 'nfo' } ])
- })
- test('delete child node', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let node = new Node({ key: 'foo', value: 'bar' })
- await node.save(db)
- - let tx = mockDb(db)
- + let ntx = simDb(db)
- let node2 = new Node({ key: 'fo', value: 'bar' })
- - node = await node.put(node2, tx)
- + node = await node.put(node2, ntx)
- - tx = mockDb(tx)
- - node = await node.delete('fo', tx)
- + ntx = simDb(ntx)
- + node = await node.delete('fo', ntx)
- - t.deepEqual(tx.gets, [ { key: 'nfo' } ])
- - t.deepEqual(tx.dels, [ { key: 'nfo' } ])
- - t.deepEqual(tx.puts, [
- + t.deepEqual(ntx.gets, [ { key: 'nfo' } ])
- + t.deepEqual(ntx.dels, [ { key: 'nfo' } ])
- + t.deepEqual(ntx.puts, [
- {
- key: 'nfoo',
- value: 'gdGeF1+rlOY3B4TKbNE1jNesAMmtBZ8KwnM2IWh629jJxBTapVD+iAAAA2JhcgAAAA=='
- }
- ])
- - tx = mockDb(tx)
- - t.is(await node.left(tx), null)
- + ntx = simDb(ntx)
- + t.is(await node.left(ntx), null)
- })
- test('delete parent node', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let node = new Node({ key: 'foo', value: 'bar' })
- await node.save(db)
- - let tx = mockDb(db)
- + let ntx = simDb(db)
- let node2 = new Node({ key: 'fo', value: 'bar' })
- - node = await node.put(node2, tx)
- + node = await node.put(node2, ntx)
- - tx = mockDb(tx)
- - node = await node.delete('foo', tx)
- + ntx = simDb(ntx)
- + node = await node.delete('foo', ntx)
- - t.deepEqual(tx.gets, [ { key: 'nfo' } ])
- - t.deepEqual(tx.dels, [ { key: 'nfoo' } ])
- - t.is(tx.puts.length, 0)
- + t.deepEqual(ntx.gets, [ { key: 'nfo' } ])
- + t.deepEqual(ntx.dels, [ { key: 'nfoo' } ])
- + t.is(ntx.puts.length, 0)
- t.is(node.key, 'fo')
- - tx = mockDb(tx)
- - t.is(await node.parent(tx), null)
- + ntx = simDb(ntx)
- + t.is(await node.parent(ntx), null)
- })
- test('build 1000-node tree in fixed order', async (t) => {
- t.plan(9000)
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let root = new Node({ key: '0', value: 'value' })
- @@ -236,7 +236,7 @@ test('build 1000-node tree in fixed order', async (t) => {
- })
- test('delete non-existent key', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- let root = new Node({ key: '0', value: 'value' })
- @@ -253,7 +253,7 @@ test('delete non-existent key', async (t) => {
- test('delete (random keys)', async (t) => {
- t.plan(21)
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- // build tree
- @@ -277,7 +277,7 @@ test('delete (random keys)', async (t) => {
- })
- test('get branch', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- // build tree
- @@ -316,7 +316,7 @@ test('get branch', async (t) => {
- })
- test('get branch at edge', async (t) => {
- - let db = mockDb()
- + let db = simDb()
- let Node = _Node(db)
- // build tree
- diff --git b/test/verify.js a/test/verify.js
- index 8c8fee5..79f73e6 100755
- --- b/test/verify.js
- +++ a/test/verify.js
- @@ -1,89 +1,89 @@
- let test = require('ava')
- -let { mockDb } = require('./common.js')
- -let merk = require('../src/merk.js')
- +let { simDb } = require('./common.js')
- +let constellation = require('../src/constellation.js')
- test('verify single-node root proof', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- - await merk.commit(state)
- + await constellation.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state)
- - let value = merk.verify(rootHash, proof)
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state)
- + let value = constellation.verify(rootHash, proof)
- t.deepEqual(value, { foo: 'bar' })
- })
- test('verify single-node non-object child proof', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- - await merk.commit(state)
- + await constellation.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state, 'foo')
- - let value = merk.verify(rootHash, proof, 'foo')
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state, 'foo')
- + let value = constellation.verify(rootHash, proof, 'foo')
- t.is(value, 'bar')
- })
- test('verify multi-node root proof', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- state.baz = { x: 123 }
- - await merk.commit(state)
- + await constellation.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state)
- - let value = merk.verify(rootHash, proof)
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state)
- + let value = constellation.verify(rootHash, proof)
- t.deepEqual(value, { foo: 'bar', baz: { x: 123 } })
- })
- test('verify multi-node child proof', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- state.baz = { x: 123 }
- - await merk.commit(state)
- + await constellation.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state, 'baz')
- - let value = merk.verify(rootHash, proof, 'baz')
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state, 'baz')
- + let value = constellation.verify(rootHash, proof, 'baz')
- t.deepEqual(value, { x: 123 })
- })
- test('verify multi-node non-object child proof', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- state.baz = { x: 123 }
- - await merk.commit(state)
- + await constellation.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state, 'baz.x')
- - let value = merk.verify(rootHash, proof, 'baz.x')
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state, 'baz.x')
- + let value = constellation.verify(rootHash, proof, 'baz.x')
- t.is(value, 123)
- })
- test('verify with incorrect root hash', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.foo = 'bar'
- - await merk.commit(state)
- - let rootHash = merk.hash(state)
- + await constellation.commit(state)
- + let rootHash = constellation.hash(state)
- state.baz = { x: 123 }
- - await merk.commit(state)
- + await constellation.commit(state)
- - let proof = await merk.proof(state, 'baz')
- + let proof = await constellation.proof(state, 'baz')
- try {
- - merk.verify(rootHash, proof, 'baz')
- + constellation.verify(rootHash, proof, 'baz')
- t.fail()
- } catch (err) {
- t.is(err.message, 'Proof does not match expected root hash')
- @@ -91,15 +91,15 @@ test('verify with incorrect root hash', async (t) => {
- })
- test('verify with array range', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- // state.abc = {n: 123}
- // state.array = [{n: 0}, {n: 1}, {n: 2}, {n: 3}]
- // state.xyz = {n: 456}
- - // await merk.commit(state)
- - // let rootHash = merk.hash(state)
- - // let proof = await merk.proof(state, 'array')
- + // await constellation.commit(state)
- + // let rootHash = constellation.hash(state)
- + // let proof = await constellation.proof(state, 'array')
- let rootHash = 'ac2323c6ebaafb3174c6dfac855ed0652f4651af'
- let proof = {
- @@ -119,28 +119,28 @@ test('verify with array range', async (t) => {
- value: '{"n":1}'
- }
- - let value = merk.verify(rootHash, proof, 'array')
- + let value = constellation.verify(rootHash, proof, 'array')
- t.deepEqual(value, [{n: 0}, {n: 1}, {n: 2}, {n: 3}])
- })
- test('verify with array child', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- state.abc = {n: 123}
- state.array = [{n: 0}, {n: 1}, {n: 2}, {n: 3}]
- state.xyz = {n: 456}
- - await merk.commit(state)
- - let rootHash = merk.hash(state)
- - let proof = await merk.proof(state, 'array.1')
- + await constellation.commit(state)
- + let rootHash = constellation.hash(state)
- + let proof = await constellation.proof(state, 'array.1')
- - let value = merk.verify(rootHash, proof, 'array.1')
- + let value = constellation.verify(rootHash, proof, 'array.1')
- t.deepEqual(value, {n: 1})
- })
- test('verify with unproven range', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- let rootHash = 'ac2323c6ebaafb3174c6dfac855ed0652f4651af'
- let proof = {
- @@ -161,7 +161,7 @@ test('verify with unproven range', async (t) => {
- }
- try {
- - merk.verify(rootHash, proof, 'array')
- + constellation.verify(rootHash, proof, 'array')
- t.fail()
- } catch (err) {
- t.is(err.message, 'First key greater than beginning of range')
- @@ -169,8 +169,8 @@ test('verify with unproven range', async (t) => {
- })
- test('verify with unproven range', async (t) => {
- - let db = mockDb()
- - let state = await merk(db)
- + let db = simDb()
- + let state = await constellation(db)
- let rootHash = 'ac2323c6ebaafb3174c6dfac855ed0652f4651af'
- let proof = {
- @@ -191,9 +191,36 @@ test('verify with unproven range', async (t) => {
- }
- try {
- - merk.verify(rootHash, proof, 'array')
- + constellation.verify(rootHash, proof, 'array')
- t.fail()
- } catch (err) {
- t.is(err.message, 'Last key less than end of range')
- }
- })
- +
- +test('verify with range that was previously broken', async (t) => {
- + let db = simDb()
- + let state = await constellation(db)
- +
- + let rootHash = '8cbbf63175e9390054c2155419ccea4ce38508a0'
- + let proof = require('./fixtures/blockchat.json')
- +
- + constellation.verify(rootHash, proof, 'messages')
- + t.pass()
- +})
- +
- +test('verify with single-node tree with no root object', async (t) => {
- + let db = simDb()
- + let state = await constellation(db)
- +
- + state.foo = { beep: 'boop' }
- +
- + await constellation.commit(state)
- +
- + let proof = await constellation.proof(state)
- +
- + let rootHash = '4a492d386d845c19a691698b91d9afaddba0a0fb'
- + let value = constellation.verify(rootHash, proof)
- +
- + t.pass()
- +})
Advertisement
Add Comment
Please, Sign In to add comment