diff --git a/README.md b/README.md index 0df35b5a..3a9d8e56 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,32 @@ Bitcore Node ============ -A Bitcoin full node for building applications and services with Node.js. A node is extensible and can be configured to run additional services. At the minimum a node has an interface to [Bitcoin Core with additional indexing](https://github.com/bitpay/bitcoin/tree/0.12.1-bitcore) for more advanced address queries. Additional services can be enabled to make a node more useful such as exposing new APIs, running a block explorer and wallet service. +A Bitcoin blockchain indexing and query service. Intended to be used with as a Bitcoin full node or in conjunction with a Bitcoin full node. ## Install ```bash npm install -g bitcore-node -bitcore-node start +./bin/bitcore-node start ``` -Note: For your convenience, we distribute bitcoind binaries for x86_64 Linux and x86_64 Mac OS X. Upon npm install, the binaries for your platform will be downloaded. For more detailed installation instructions, or if you want to compile the project yourself, then please see the Bitcore branch of [Bitcoin Core with additional indexing](https://github.com/bitpay/bitcoin/tree/0.12.1-bitcore). +Note: A default configuration file is placed in the bitcore user's home directory (~/.bitcore/bitcore-node.json). Or, alternatively, you can copy the provided "bitcore-node.json.sample" file to the project's root directory as bitcore-node.json and edit it for your preferences. If you don't have a preferred block source (trusted peer), [Bcoin](https://github.com/bcoin-org/bcoin) will be started automatically and synchronized with the mainnet chain. ## Prerequisites -- GNU/Linux x86_32/x86_64, or OSX 64bit *(for bitcoind distributed binaries)* -- Node.js v0.10, v0.12 or v4 -- ZeroMQ *(libzmq3-dev for Ubuntu/Debian or zeromq on OSX)* -- ~200GB of disk storage -- ~8GB of RAM +- Node.js v8.2.0+ +- ~500GB of disk storage +- ~4GB of RAM ## Configuration -Bitcore includes a Command Line Interface (CLI) for managing, configuring and interfacing with your Bitcore Node. +The main configuration file is called "bitcore-node.json". This file instructs bitcore-node for the following options: -```bash -bitcore-node create -d mynode -cd mynode -bitcore-node install -bitcore-node install https://github.com/yourname/helloworld -``` - -This will create a directory with configuration files for your node and install the necessary dependencies. For more information about (and developing) services, please see the [Service Documentation](docs/services.md). +- location of database files (datadir) +- tcp port for web services, if configured (port) +- bitcoin network type (e.g. mainnet, testnet3, regtest), (network) +- what services to include (services) +- the services' configuration (servicesConfig) ## Add-on Services @@ -45,7 +40,15 @@ There are several add-on services available to extend the functionality of Bitco - [Upgrade Notes](docs/upgrade.md) - [Services](docs/services.md) - - [Bitcoind](docs/services/bitcoind.md) - Interface to Bitcoin Core + - [Fee](docs/services/fee.md) - Creates a service to handle fee queries + - [Header](docs/services/header.md) - Creates a service to handle block headers + - [Block](docs/services/block.md) - Creates a service to handle blocks + - [Transaction](docs/services/transaction.md) - Creates a service to handle transactions + - [Address](docs/services/address.md) - Creates a service to handle addresses + - [Mempool](docs/services/mempool.md) - Creates a service to handle mempool + - [Timestamp](docs/services/timestamp.md) - Creates a service to handle timestamp + - [Db](docs/services/db.md) - Creates a service to handle the database + - [p2p](docs/services/p2p.md) - Creates a service to handle the peer-to-peer network - [Web](docs/services/web.md) - Creates an express application over which services can expose their web/API content - [Development Environment](docs/development.md) - Guide for setting up a development environment - [Node](docs/node.md) - Details on the node constructor @@ -60,6 +63,6 @@ Please send pull requests for bug fixes, code optimization, and ideas for improv Code released under [the MIT license](https://github.com/bitpay/bitcore-node/blob/master/LICENSE). -Copyright 2013-2015 BitPay, Inc. +Copyright 2013-2017 BitPay, Inc. - bitcoin: Copyright (c) 2009-2015 Bitcoin Core Developers (MIT License) diff --git a/docs/services/address.md b/docs/services/address.md new file mode 100644 index 00000000..aed1c1ef --- /dev/null +++ b/docs/services/address.md @@ -0,0 +1,22 @@ +# Address Service + +The address service provides an address index for the Bitcoin blockchain. Specifically, it builds and maintains the following information about every address ever used on the Bitcoin network: + +- block heights the address appeared in +- transaction ids and the index in the transaction +- whether the address appeared in an input or output +- the timestamp for the block + +Additionally, the address index also maintains the unspent transaction output index for the Bitcoin blockchain. Example queries for this type of data is provided by 'getAddressUnspentOutputs', 'getAddressSummary', and 'getAddressHistory'. + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- header +- transaction +- timestamp diff --git a/docs/services/bitcoind.md b/docs/services/bitcoind.md deleted file mode 100644 index 753174b4..00000000 --- a/docs/services/bitcoind.md +++ /dev/null @@ -1,333 +0,0 @@ -# Bitcoin Service - -The Bitcoin Service is a Node.js interface to [Bitcoin Core](https://github.com/bitcoin/bitcoin) for querying information about the bitcoin block chain. It will manage starting and stopping `bitcoind` or connect to several running `bitcoind` processes. It uses a branch of a [branch of Bitcoin Core](https://github.com/bitpay/bitcoin/tree/0.12.1-bitcore) with additional indexes for querying information about addresses and blocks. Results are cached for performance and there are several additional API methods added for common queries. - -## Configuration - -The default configuration will include a "spawn" configuration in "bitcoind". This defines the location of the block chain database and the location of the `bitcoind` daemon executable. The below configuration points to a local clone of `bitcoin`, and will start `bitcoind` automatically with your Node.js application. - -```json - "servicesConfig": { - "bitcoind": { - "spawn": { - "datadir": "/home/bitcore/.bitcoin", - "exec": "/home/bitcore/bitcoin/src/bitcoind" - } - } - } -``` - -It's also possible to connect to separately managed `bitcoind` processes with round-robin quering, for example: - -```json - "servicesConfig": { - "bitcoind": { - "connect": [ - { - "rpchost": "127.0.0.1", - "rpcport": 30521, - "rpcuser": "bitcoin", - "rpcpassword": "local321", - "zmqpubrawtx": "tcp://127.0.0.1:30611" - }, - { - "rpchost": "127.0.0.1", - "rpcport": 30522, - "rpcuser": "bitcoin", - "rpcpassword": "local321", - "zmqpubrawtx": "tcp://127.0.0.1:30622" - }, - { - "rpchost": "127.0.0.1", - "rpcport": 30523, - "rpcuser": "bitcoin", - "rpcpassword": "local321", - "zmqpubrawtx": "tcp://127.0.0.1:30633" - } - ] - } - } -``` - -**Note**: For detailed example configuration see [`regtest/cluster.js`](regtest/cluster.js) - - -## API Documentation -Methods are available by directly interfacing with the service: - -```js -node.services.bitcoind. -``` - -### Chain - -**Getting Latest Blocks** - -```js -// gives the block hashes sorted from low to high within a range of timestamps -var high = 1460393372; // Mon Apr 11 2016 12:49:25 GMT-0400 (EDT) -var low = 1460306965; // Mon Apr 10 2016 12:49:25 GMT-0400 (EDT) -node.services.bitcoind.getBlockHashesByTimestamp(high, low, function(err, blockHashes) { - //... -}); - -// get the current tip of the chain -node.services.bitcoind.getBestBlockHash(function(err, blockHash) { - //... -}) -``` - -**Getting Synchronization and Node Status** - -```js -// gives a boolean if the daemon is fully synced (not the initial block download) -node.services.bitcoind.isSynced(function(err, synced) { - //... -}) - -// gives the current estimate of blockchain download as a percentage -node.services.bitcoind.syncPercentage(function(err, percent) { - //... -}); - -// gives information about the chain including total number of blocks -node.services.bitcoind.getInfo(function(err, info) { - //... -}); -``` - -**Generate Blocks** - -```js -// will generate a block for the "regtest" network (development purposes) -var numberOfBlocks = 10; -node.services.bitcoind.generateBlock(numberOfBlocks, function(err, blockHashes) { - //... -}); -``` - -### Blocks and Transactions - -**Getting Block Information** - -It's possible to query blocks by both block hash and by height. Blocks are given as Node.js Buffers and can be parsed via Bitcore: - -```js -var blockHeight = 0; -node.services.bitcoind.getRawBlock(blockHeight, function(err, blockBuffer) { - if (err) { - throw err; - } - var block = bitcore.Block.fromBuffer(blockBuffer); - console.log(block); -}; - -// get a bitcore object of the block (as above) -node.services.bitcoind.getBlock(blockHash, function(err, block) { - //... -}; - -// get only the block header and index (including chain work, height, and previous hash) -node.services.bitcoind.getBlockHeader(blockHeight, function(err, blockHeader) { - //... -}); - -// get the block with a list of txids -node.services.bitcoind.getBlockOverview(blockHash, function(err, blockOverview) { - //... -}; -``` - -**Retrieving and Sending Transactions** - -Get a transaction asynchronously by reading it from disk: - -```js -var txid = '7426c707d0e9705bdd8158e60983e37d0f5d63529086d6672b07d9238d5aa623'; -node.services.bitcoind.getRawTransaction(txid, function(err, transactionBuffer) { - if (err) { - throw err; - } - var transaction = bitcore.Transaction().fromBuffer(transactionBuffer); -}); - -// get a bitcore object of the transaction (as above) -node.services.bitcoind.getTransaction(txid, function(err, transaction) { - //... -}); - -// retrieve the transaction with input values, fees, spent and block info -node.services.bitcoind.getDetailedTransaction(txid, function(err, transaction) { - //... -}); -``` - -Send a transaction to the network: - -```js -var numberOfBlocks = 3; -node.services.bitcoind.estimateFee(numberOfBlocks, function(err, feesPerKilobyte) { - //... -}); - -node.services.bitcoind.sendTransaction(transaction.serialize(), function(err, hash) { - //... -}); -``` - -### Addresses - -**Get Unspent Outputs** - -One of the most common uses will be to retrieve unspent outputs necessary to create a transaction, here is how to get the unspent outputs for an address: - -```js -var address = 'mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW'; -node.services.bitcoind.getAddressUnspentOutputs(address, options, function(err, unspentOutputs) { - // see below -}); -``` - -The `unspentOutputs` will have the format: - -```js -[ - { - address: 'mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW', - txid: '9d956c5d324a1c2b12133f3242deff264a9b9f61be701311373998681b8c1769', - outputIndex: 1, - height: 150, - satoshis: 1000000000, - script: '76a9140b2f0a0c31bfe0406b0ccc1381fdbe311946dadc88ac', - confirmations: 3 - } -] -``` - -**View Balances** - -```js -var address = 'mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW'; -node.services.bitcoind.getAddressBalance(address, options, function(err, balance) { - // balance will be in satoshis with "received" and "balance" -}); -``` - -**View Address History** - -This method will give history of an address limited by a range of block heights by using the "start" and "end" arguments. The "start" value is the more recent, and greater, block height. The "end" value is the older, and lesser, block height. This feature is most useful for synchronization as previous history can be omitted. Furthermore for large ranges of block heights, results can be paginated by using the "from" and "to" arguments. - -If "queryMempool" is set as true (it is true by default), it will show unconfirmed transactions from the bitcoin mempool. However, if you specify "start" and "end", "queryMempool" is ignored and is always false. - -If "queryMempoolOnly" is set as true (it is false by default), it will show *only* unconfirmed transactions from mempool. - -```js -var addresses = ['mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW']; -var options = { - start: 345000, - end: 344000, - queryMempool: true // since we presented range, queryMempool will be ignored -}; -node.services.bitcoind.getAddressHistory(addresses, options, function(err, history) { - // see below -}); -``` - -The history format will be: - -```js -{ - totalCount: 1, // The total number of items within "start" and "end" - items: [ - { - addresses: { - 'mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW': { - inputIndexes: [], - outputIndexes: [0] - } - }, - satoshis: 1000000000, - tx: // the same format as getDetailedTransaction - } - ] -} -``` - -**View Address Summary** - -```js -var address = 'mgY65WSfEmsyYaYPQaXhmXMeBhwp4EcsQW'; -var options = { - noTxList: false -}; - -node.services.bitcoind.getAddressSummary(address, options, function(err, summary) { - // see below -}); -``` - -The `summary` will have the format (values are in satoshis): - -```js -{ - totalReceived: 1000000000, - totalSpent: 0, - balance: 1000000000, - unconfirmedBalance: 1000000000, - appearances: 1, - unconfirmedAppearances: 0, - txids: [ - '3f7d13efe12e82f873f4d41f7e63bb64708fc4c942eb8c6822fa5bd7606adb00' - ] -} -``` -**Notes**: -- `totalReceived` does not exclude change *(the amount of satoshis originating from the same address)* -- `unconfirmedBalance` is the delta that the unconfirmed transactions have on the total balance *(can be both positive and negative)* -- `unconfirmedAppearances` is the total number of unconfirmed transactions -- `appearances` is the total confirmed transactions -- `txids` Are sorted in block order with the most recent at the beginning. A maximum of 1000 *(default)* will be returned, the `from` and `to` options can be used to get further values. - - -## Events -The Bitcoin Service exposes two events via the Bus, and there are a few events that can be directly registered: - -```js -node.services.bitcoind.on('tip', function(blockHash) { - // a new block tip has been added, if there is a rapid update (with a second) this will not emit every tip update -}); - -node.services.bitcoind.on('tx', function(transactionBuffer) { - // a new transaction has entered the mempool -}); - -node.services.bitcoind.on('block', function(blockHash) { - // a new block has been added -}); -``` - -For details on instantiating a bus for a node, see the [Bus Documentation](../bus.md). -- Name: `bitcoind/rawtransaction` -- Name: `bitcoind/hashblock` -- Name: `bitcoind/addresstxid`, Arguments: [address, address...] - -**Examples:** - -```js -bus.subscribe('bitcoind/rawtransaction'); -bus.subscribe('bitcoind/hashblock'); -bus.subscribe('bitcoind/addresstxid', ['13FMwCYz3hUhwPcaWuD2M1U2KzfTtvLM89']); - -bus.on('bitcoind/rawtransaction', function(transactionHex) { - //... -}); - -bus.on('bitcoind/hashblock', function(blockhashHex) { - //... -}); - -bus.on('bitcoind/addresstxid', function(data) { - // data.address; - // data.txid; -}); -``` diff --git a/docs/services/block.md b/docs/services/block.md new file mode 100644 index 00000000..9cf6255b --- /dev/null +++ b/docs/services/block.md @@ -0,0 +1,20 @@ +# Block Service + +The block service provides a block index for the Bitcoin blockchain. Specifically, there are two data points this service tracks: + +- block hash +- raw block + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- header +- timestamp +- p2p +- db + diff --git a/docs/services/db.md b/docs/services/db.md new file mode 100644 index 00000000..8a4105f2 --- /dev/null +++ b/docs/services/db.md @@ -0,0 +1,13 @@ +# Db Service + +The db service provides an abstraction over the underlying database used to store the indexes in bitcore-node. + +## Service Configuration + +None + +## Other services this service Depends on + +None + + diff --git a/docs/services/fee.md b/docs/services/fee.md new file mode 100644 index 00000000..eeadeedf --- /dev/null +++ b/docs/services/fee.md @@ -0,0 +1,22 @@ +# Fee Service + +The fee service is a requirement of the insight-api service (not a bitcore-node built-in service). Its primary purpose is to query a bitcoin full node for the most up-to-date miner fees for transactions. A bitcoin full node such as [BTC1](https://github.com/btc1/bitcoin) or [bcoin](https://github.com/bcoin-org/bcoin) with an available RPC interface is required. + +## Service Configuration + +```json +"fee": { + "rpc": { + "user": "user", + "pass": "pass", + "host": "localhost", + "protocol": "http", + "port": 8332 + } +} +``` +## Usage Example + +```bash +curl http://localhost:3001/insight-api/estimateFee +``` diff --git a/docs/services/header.md b/docs/services/header.md new file mode 100644 index 00000000..7abb55c2 --- /dev/null +++ b/docs/services/header.md @@ -0,0 +1,19 @@ +# Header Service + +The header service provides a header index for the Bitcoin blockchain. Specifically, it builds and maintains the following information about every bitcoin block header: + +- block hash +- block height +- block header + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- db +- p2p + diff --git a/docs/services/mempool.md b/docs/services/mempool.md new file mode 100644 index 00000000..066594a0 --- /dev/null +++ b/docs/services/mempool.md @@ -0,0 +1,16 @@ +# Mempool Service + +The mempool service provides a mempool transaction index for the Bitcoin blockchain. Specifically, it maintains a larger index of mempool transactions than a typical full node can manage on its own. + +- transaction id +- transaction + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- db diff --git a/docs/services/p2p.md b/docs/services/p2p.md new file mode 100644 index 00000000..140f9a95 --- /dev/null +++ b/docs/services/p2p.md @@ -0,0 +1,21 @@ +# P2P Service + +The p2p service provides a peer-to-peer interface for the Bitcoin blockchain. This service abstracts the connection and commnuication interface between the Bitcoin and the rest of bitcore node. + + +This service also provides the publisher interface on bitcore-node bus architecture. The P2P service will publish header, block and transaction events. + +## Service Configuration + +```json +"p2p": { + "peers": [ + { "ip": { "v4": "127.0.0.1" }, "port": 8333 } + ] +} +``` + +## Other services this service Depends on + +None + diff --git a/docs/services/timestamp.md b/docs/services/timestamp.md new file mode 100644 index 00000000..9039ec3e --- /dev/null +++ b/docs/services/timestamp.md @@ -0,0 +1,18 @@ +# Timestamp Service + +The timestamp service provides a block timestamp index for the Bitcoin blockchain. The only reason this index needs to exist is to ensure that block timestamps are always strictly greater than all the previous block timestamps. In the native block timestamps, this is not always the case. Without this index, accounting systems that are based on time spans (pretty much all of them), there will be issues accounting for transactions accurately. + +- block timestamp +- block hash + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- db + + diff --git a/docs/services/transaction.md b/docs/services/transaction.md new file mode 100644 index 00000000..c7d0020b --- /dev/null +++ b/docs/services/transaction.md @@ -0,0 +1,21 @@ +# Transaction Service + +The transaction service provides a transaction index for the Bitcoin blockchain. Specifically, it builds and maintains the following information about every transaction on the Bitcoin network: + +- transaction ids and transactions +- input values for every transaction +- the timestamp for the block that the transaction appears in +- the block height for the block that the transaction appears in + +This service is generally used to support other services and is not used externally. + +## Service Configuration + +none + +## Other services this service Depends on + +- p2p +- db +- timestamp +- mempool diff --git a/lib/services/address/index.js b/lib/services/address/index.js index 1339d672..e80f4238 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -15,11 +15,11 @@ var assert = require('assert'); var AddressService = function(options) { BaseService.call(this, options); - this._db = this.node.services.db; this._tx = this.node.services.transaction; this._header = this.node.services.header; this._timestamp = this.node.services.timestamp; this._network = this.node.network; + this._db = this.node.services.db; if (this._network === 'livenet') { this._network = 'main'; } @@ -28,9 +28,8 @@ var AddressService = function(options) { inherits(AddressService, BaseService); AddressService.dependencies = [ - 'p2p', 'db', - 'block', + 'header', 'transaction', 'timestamp' ]; diff --git a/lib/services/mempool/index.js b/lib/services/mempool/index.js index 6a352be9..8de50038 100644 --- a/lib/services/mempool/index.js +++ b/lib/services/mempool/index.js @@ -15,7 +15,7 @@ var MempoolService = function(options) { util.inherits(MempoolService, BaseService); -MempoolService.dependencies = ['db', 'block']; +MempoolService.dependencies = ['db']; MempoolService.prototype.getAPIMethods = function() { var methods = [ diff --git a/lib/services/transaction/index.js b/lib/services/transaction/index.js index ed689a75..6789fc5f 100644 --- a/lib/services/transaction/index.js +++ b/lib/services/transaction/index.js @@ -13,7 +13,6 @@ function TransactionService(options) { BaseService.call(this, options); this._db = this.node.services.db; this._mempool = this.node.services.mempool; - this._block = this.node.services.block; this._header = this.node.services.header; this._p2p = this.node.services.p2p; this._timestamp = this.node.services.timestamp; @@ -24,7 +23,6 @@ inherits(TransactionService, BaseService); TransactionService.dependencies = [ 'p2p', 'db', - 'block', 'timestamp', 'mempool' ];