From 0b0dd58a913fe5203142527821a7eea57476035f Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Thu, 7 Mar 2019 11:02:22 -0800 Subject: [PATCH] node: add blockstore to full node --- lib/blockchain/chain.js | 7 +++++++ lib/blockchain/chaindb.js | 21 ++++++++------------- lib/node/fullnode.js | 15 ++++++++++++++- test/chain-test.js | 9 +++++++++ test/mempool-test.js | 10 +++++++++- test/pow-test.js | 10 +++++++++- 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js index 5dab1d9f..08d6dfaa 100644 --- a/lib/blockchain/chain.js +++ b/lib/blockchain/chain.js @@ -49,6 +49,7 @@ class Chain extends AsyncEmitter { this.network = this.options.network; this.logger = this.options.logger.context('chain'); + this.blocks = this.options.blocks; this.workers = this.options.workers; this.db = new ChainDB(this.options); @@ -2662,6 +2663,7 @@ class ChainOptions { constructor(options) { this.network = Network.primary; this.logger = Logger.global; + this.blocks = null; this.workers = null; this.prefix = null; @@ -2695,6 +2697,11 @@ class ChainOptions { */ fromOptions(options) { + assert(options.blocks && typeof options.blocks === 'object', + 'Chain requires a blockstore.'); + + this.blocks = options.blocks; + if (options.network != null) this.network = Network.get(options.network); diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js index aa6845e4..20eefea1 100644 --- a/lib/blockchain/chaindb.js +++ b/lib/blockchain/chaindb.js @@ -11,7 +11,6 @@ const assert = require('bsert'); const bdb = require('bdb'); const bio = require('bufio'); const LRU = require('blru'); -const {resolve} = require('path'); const {BufferMap, BufferSet} = require('buffer-map'); const Amount = require('../btc/amount'); const Network = require('../protocol/network'); @@ -25,7 +24,6 @@ const Address = require('../primitives/address'); const ChainEntry = require('./chainentry'); const TXMeta = require('../primitives/txmeta'); const CoinEntry = require('../coins/coinentry'); -const FileBlockStore = require('../blockstore/file'); /** * ChainDB @@ -42,15 +40,14 @@ class ChainDB { this.options = options; this.network = this.options.network; this.logger = this.options.logger.context('chaindb'); + this.blocks = this.options.blocks; this.db = bdb.create(this.options); + this.stateCache = new StateCache(this.network); this.state = new ChainState(); this.pending = null; this.current = null; - this.blockStore = new FileBlockStore({ - location: resolve(options.location, '../blocks') - }); this.cacheHash = new LRU(this.options.entryCache, null, BufferMap); this.cacheHeight = new LRU(this.options.entryCache); @@ -66,7 +63,6 @@ class ChainDB { await this.db.open(); await this.db.verify(layout.V.encode(), 'chain', 5); - await this.blockStore.open(); const state = await this.getState(); @@ -108,7 +104,6 @@ class ChainDB { */ async close() { - await this.blockStore.close(); return this.db.close(); } @@ -776,7 +771,7 @@ class ChainDB { throw new Error(`Cannot find hash for ${i}.`); b.del(layout.u.encode(hash)); - await this.blockStore.prune(hash); + await this.blocks.prune(hash); } try { @@ -1059,7 +1054,7 @@ class ChainDB { if (!hash) return null; - return this.blockStore.read(hash); + return this.blocks.read(hash); } /** @@ -1646,7 +1641,7 @@ class ChainDB { this.del(layout.p.encode(tip.hash)); this.del(layout.h.encode(tip.hash)); this.del(layout.e.encode(tip.hash)); - await this.blockStore.prune(tip.hash); + await this.blocks.prune(tip.hash); // Queue up hash to be removed // on successful write. @@ -1674,7 +1669,7 @@ class ChainDB { // Write actual block data (this may be // better suited to flat files in the future). - await this.blockStore.write(hash, block.toRaw()); + await this.blocks.write(hash, block.toRaw()); if (!view) return; @@ -1698,7 +1693,7 @@ class ChainDB { if (!block) throw new Error('Block not found.'); - await this.blockStore.prune(block.hash()); + await this.blocks.prune(block.hash()); return this.disconnectBlock(entry, block); } @@ -1859,7 +1854,7 @@ class ChainDB { return; this.del(layout.u.encode(hash)); - await this.blockStore.prune(hash); + await this.blocks.prune(hash); } /** diff --git a/lib/node/fullnode.js b/lib/node/fullnode.js index 0e6a8d0e..99e1ad9b 100644 --- a/lib/node/fullnode.js +++ b/lib/node/fullnode.js @@ -16,6 +16,7 @@ const Miner = require('../mining/miner'); const Node = require('./node'); const HTTP = require('./http'); const RPC = require('./rpc'); +const blockstore = require('../blockstore'); /** * Full Node @@ -40,10 +41,20 @@ class FullNode extends Node { // SPV flag. this.spv = false; - // Instantiate blockchain. + // Instantiate block storage. + this.blocks = blockstore.create({ + network: this.network, + logger: this.logger, + prefix: this.config.prefix, + cacheSize: this.config.mb('block-cache-size'), + memory: this.config.bool('memory') + }); + + // Chain needs access to blocks. this.chain = new Chain({ network: this.network, logger: this.logger, + blocks: this.blocks, workers: this.workers, memory: this.config.bool('memory'), prefix: this.config.prefix, @@ -218,6 +229,7 @@ class FullNode extends Node { this.opened = true; await this.handlePreopen(); + await this.blocks.open(); await this.chain.open(); await this.mempool.open(); await this.miner.open(); @@ -250,6 +262,7 @@ class FullNode extends Node { await this.miner.close(); await this.mempool.close(); await this.chain.close(); + await this.blocks.close(); await this.handleClose(); } diff --git a/test/chain-test.js b/test/chain-test.js index d50237ac..9c915031 100644 --- a/test/chain-test.js +++ b/test/chain-test.js @@ -17,6 +17,7 @@ const Output = require('../lib/primitives/output'); const common = require('../lib/blockchain/common'); const nodejsUtil = require('util'); const Opcode = require('../lib/script/opcode'); +const BlockStore = require('../lib/blockstore/level'); const opcodes = Script.opcodes; const ZERO_KEY = Buffer.alloc(33, 0x00); @@ -30,8 +31,14 @@ const workers = new WorkerPool({ enabled: true }); +const blocks = new BlockStore({ + memory: true, + network +}); + const chain = new Chain({ memory: true, + blocks, network, workers }); @@ -115,6 +122,7 @@ describe('Chain', function() { this.timeout(process.browser ? 1200000 : 60000); it('should open chain and miner', async () => { + await blocks.open(); await chain.open(); await miner.open(); }); @@ -895,5 +903,6 @@ describe('Chain', function() { it('should cleanup', async () => { await miner.close(); await chain.close(); + await blocks.close(); }); }); diff --git a/test/mempool-test.js b/test/mempool-test.js index ed76f869..247720f6 100644 --- a/test/mempool-test.js +++ b/test/mempool-test.js @@ -18,6 +18,7 @@ const Script = require('../lib/script/script'); const opcodes = Script.opcodes; const Witness = require('../lib/script/witness'); const MemWallet = require('./util/memwallet'); +const BlockStore = require('../lib/blockstore/level'); const ALL = Script.hashType.ALL; const ONE_HASH = Buffer.alloc(32, 0x00); @@ -27,9 +28,14 @@ const workers = new WorkerPool({ enabled: true }); +const blocks = new BlockStore({ + memory: true +}); + const chain = new Chain({ memory: true, - workers + workers, + blocks }); const mempool = new Mempool({ @@ -68,6 +74,7 @@ describe('Mempool', function() { it('should open mempool', async () => { await workers.open(); + await blocks.open(); await chain.open(); await mempool.open(); chain.state.flags |= Script.flags.VERIFY_WITNESS; @@ -453,6 +460,7 @@ describe('Mempool', function() { it('should destroy mempool', async () => { await mempool.close(); await chain.close(); + await blocks.close(); await workers.close(); }); }); diff --git a/test/pow-test.js b/test/pow-test.js index bd2707f5..6f54ad5a 100644 --- a/test/pow-test.js +++ b/test/pow-test.js @@ -7,6 +7,7 @@ const assert = require('./util/assert'); const Chain = require('../lib/blockchain/chain'); const ChainEntry = require('../lib/blockchain/chainentry'); const Network = require('../lib/protocol/network'); +const BlockStore = require('../lib/blockstore/level'); const network = Network.get('main'); @@ -14,13 +15,20 @@ function random(max) { return Math.floor(Math.random() * max); } -const chain = new Chain({ +const blocks = new BlockStore({ memory: true, network }); +const chain = new Chain({ + memory: true, + network, + blocks +}); + describe('Difficulty', function() { it('should open chain', async () => { + await blocks.open(); await chain.open(); });