Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use nurkel for the tree instead of urkel. #804

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions lib/blockchain/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class Chain extends AsyncEmitter {
// tree interval. We might also need to recover from a
// failed compactTree() operation. Either way, there might have been
// new blocks added to the chain since then.
const currentRoot = this.db.treeRoot();
const currentRoot = await this.db.treeRoot();

// We store commit height for the tree in the tree state.
// commitHeight is the height of the block that committed tree root.
Expand Down Expand Up @@ -211,7 +211,8 @@ class Chain extends AsyncEmitter {
await this.db.saveNames(view, entry, false);
}

this.logger.info('Synchronized Tree Root: %x.', this.db.txn.rootHash());
this.logger.info('Synchronized Tree Root: %x.',
await this.db.txn.txRootHash());
}

/**
Expand Down Expand Up @@ -737,7 +738,7 @@ class Chain extends AsyncEmitter {
const view = new CoinView();
const height = prev.height + 1;

assert(block.treeRoot.equals(this.db.treeRoot()));
assert(block.treeRoot.equals(await this.db.treeRoot()));

for (let i = 0; i < block.txs.length; i++) {
const tx = block.txs[i];
Expand Down Expand Up @@ -786,7 +787,7 @@ class Chain extends AsyncEmitter {
let reward = 0;

// Check the name tree root.
if (!block.treeRoot.equals(this.db.treeRoot())) {
if (!block.treeRoot.equals(await this.db.treeRoot())) {
throw new VerifyError(block,
'invalid',
'bad-tree-root',
Expand Down Expand Up @@ -1815,7 +1816,7 @@ class Chain extends AsyncEmitter {
this.emit('reconnect', entry, block);

if ((entry.height % this.network.names.treeInterval) === 0)
this.emit('tree commit', this.db.tree.rootHash(), entry, block);
this.emit('tree commit', await this.db.tree.treeRootHash(), entry, block);

return this.emitAsync('connect', entry, block, view);
}
Expand Down Expand Up @@ -1914,7 +1915,7 @@ class Chain extends AsyncEmitter {
this.emit('block', block, entry);

if ((entry.height % this.network.names.treeInterval) === 0)
this.emit('tree commit', this.db.tree.rootHash(), entry, block);
this.emit('tree commit', await this.db.tree.treeRootHash(), entry, block);

return this.emitAsync('connect', entry, block, view);
}
Expand Down
76 changes: 43 additions & 33 deletions lib/blockchain/chaindb.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
const assert = require('bsert');
const bdb = require('bdb');
const bio = require('bufio');
const blake2b = require('bcrypto/lib/blake2b');
const LRU = require('blru');
const {Tree} = require('urkel');
const nurkel = require('nurkel');
const {Tree} = nurkel;
const {BufferMap, BufferSet} = require('buffer-map');
const ChainMigrator = require('./migrations');
const Amount = require('../ui/amount');
Expand Down Expand Up @@ -53,14 +53,11 @@ class ChainDB {
this.db = bdb.create(this.options);
this.name = 'chain';
this.version = 3;
this.tree = new Tree({
hash: blake2b,
bits: 256,
this.tree = nurkel.create({
prefix: this.options.treePrefix,
cacheOnly: true,
initCacheSize: -1
memory: this.options.memory || !this.options.treePrefix
});
this.txn = this.tree.txn();
this.txn = null;
this.treeState = new TreeState();
this.stateCache = new StateCache(this.network);
this.state = new ChainState();
Expand All @@ -84,6 +81,9 @@ class ChainDB {
await this.db.open();
await this.tree.open();

this.txn = this.tree.vtxn();
await this.txn.open();

const migrator = new ChainMigrator({
...this.options,
chainDB: this,
Expand Down Expand Up @@ -137,8 +137,6 @@ class ChainDB {
this.logger.info('ChainDB successfully loaded.');
}

this.txn = this.tree.txn();

this.logger.info(
'Chain State: hash=%x tx=%d coin=%d value=%s burned=%s.',
this.state.tip,
Expand All @@ -147,7 +145,7 @@ class ChainDB {
Amount.coin(this.state.value),
Amount.coin(this.state.burned));

this.logger.info('Tree Root: %x.', this.tree.rootHash());
this.logger.info('Tree Root: %x.', await this.tree.treeRootHash());
}

/**
Expand Down Expand Up @@ -224,8 +222,10 @@ class ChainDB {
*/

async close() {
await this.txn.close();
this.txn = null;

await this.tree.close();
this.txn = this.tree.txn();
return this.db.close();
}

Expand Down Expand Up @@ -630,8 +630,9 @@ class ChainDB {
if (this.options.spv)
throw new Error('Cannot lookup in SPV mode.');

const tree = this.tree.snapshot(root);
return tree.get(key);
const snap = this.tree.snapshot(root);
await snap.open();
return snap.get(key);
}

/**
Expand All @@ -645,17 +646,30 @@ class ChainDB {
if (this.options.spv)
throw new Error('Cannot prove in SPV mode.');

const tree = this.tree.snapshot(root);
return tree.prove(key);
const snap = this.tree.snapshot(root);
await snap.open();
return snap.prove(key);
}

/**
* Verify Proof
* @param {Proof}
* @param {Buffer} root
* @param {Buffer} key
* @returns {Promise<Array>}
*/

async verify(root, key, proof) {
return Tree.verify(root, key, proof);
}

/**
* Get the current name tree root.
* @returns {Hash}
* @returns {Promise<Hash>}
*/

treeRoot() {
return this.tree.rootHash();
return this.tree.treeRootHash();
}

/**
Expand Down Expand Up @@ -990,6 +1004,8 @@ class ChainDB {
*/

async compactTree(entry) {
assert(!this.options.memory && this.options.treePrefix,
'Can not compact in memory.');
// Before doing anything to the tree,
// save the target tree root hash to chain database.
// If the tree data gets out of sync or corrupted
Expand All @@ -1006,30 +1022,24 @@ class ChainDB {

const tmpDir = this.options.treePrefix + '~';

const tmpTree = new Tree({
hash: blake2b,
bits: 256,
prefix: tmpDir
});

// Make sure to remove the tmp directory first.
// There should not be directory, unless it was
// stopped in the middle of compaction.
// Otherwise compacted tree would add on top
// of the previsouly compacted db.
const tmpTree = nurkel.create({
prefix: tmpDir
});

await tmpTree.open();
const tmpStore = tmpTree.store;
await tmpTree.close();
await tmpStore.destroy();

// Rewind tree to historical commitment
await this.tree.inject(entry.treeRoot);
await Tree.destroy(tmpDir);

// Delete historical data
await this.tree.compact(tmpDir);
await this.tree.compact(tmpDir, entry.treeRoot);

// Reset in-memory tree delta
this.txn = this.tree.txn();
this.txn = this.tree.vtxn();
await this.txn.open();

// Mark tree compaction complete
this.start();
Expand Down Expand Up @@ -2081,7 +2091,7 @@ class ChainDB {
// Chain will need to recover current txn
// from treeState.commitHeight + 1 (including).
this.put(layout.s.encode(), this.pendingTreeState.commit(
this.tree.rootHash(),
await this.tree.treeRootHash(),
entry.height
));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/mining/miner.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ class Miner extends EventEmitter {

const state = await this.chain.getDeployments(time, tip);
const target = await this.chain.getTarget(time, tip);
const root = this.chain.db.treeRoot();
const root = await this.chain.db.treeRoot();

const attempt = new BlockTemplate({
prevBlock: tip.hash,
Expand Down
9 changes: 4 additions & 5 deletions lib/net/packets.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

const assert = require('bsert');
const bio = require('bufio');
const blake2b = require('bcrypto/lib/blake2b');
const UrkelProof = require('urkel').Proof;
const UrkelProof = require('nurkel').Proof;
const {BloomFilter} = require('bfilter');
const common = require('./common');
const util = require('../utils/util');
Expand Down Expand Up @@ -1669,7 +1668,7 @@ class ProofPacket extends Packet {

getSize() {
let size = 64;
size += this.proof.getSize(blake2b, 256);
size += this.proof.getSize();
return size;
}

Expand All @@ -1681,7 +1680,7 @@ class ProofPacket extends Packet {
write(bw) {
bw.writeHash(this.root);
bw.writeBytes(this.key);
this.proof.writeBW(bw, blake2b, 256);
this.proof.writeBW(bw);
return this;
}

Expand All @@ -1694,7 +1693,7 @@ class ProofPacket extends Packet {
read(br) {
this.root = br.readHash();
this.key = br.readBytes(32);
this.proof = UrkelProof.readBR(br, blake2b, 256);
this.proof = UrkelProof.readBR(br);
return this;
}
}
Expand Down
3 changes: 1 addition & 2 deletions lib/net/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const socks = require('bsocks');
const List = require('blst');
const base32 = require('bcrypto/lib/encoding/base32');
const {BufferMap, BufferSet} = require('buffer-map');
const blake2b = require('bcrypto/lib/blake2b');
const {BloomFilter, RollingFilter} = require('bfilter');
const rng = require('bcrypto/lib/random');
const secp256k1 = require('bcrypto/lib/secp256k1');
Expand Down Expand Up @@ -3284,7 +3283,7 @@ class Pool extends EventEmitter {
return;
}

const [code, data] = proof.verify(root, key, blake2b, 256);
const [code, data] = await this.chain.db.verify(root, key, proof);

if (code !== 0) {
this.logger.warning(
Expand Down
3 changes: 1 addition & 2 deletions lib/node/rpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2404,8 +2404,7 @@ class RPC extends RPCBase {

const iter = txn.iterator();

while (await iter.next()) {
const {key, value} = iter;
for await (const [key, value] of iter) {
const ns = NameState.decode(value);
ns.nameHash = key;

Expand Down
Loading