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

Indexer fixes and improvements #758

Merged
merged 40 commits into from
May 16, 2019
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
05794f5
indexer: add module indexer
tuxcanfly Jun 29, 2018
33de39c
migrate: remove txindex and addrindex from chaindb
tuxcanfly Mar 22, 2019
51ac4a7
changelog: add indexer to changelog
tuxcanfly Mar 22, 2019
9f89c79
indexer: work with blockstore
tuxcanfly Mar 20, 2019
f9aab08
indexer: add block position to tx
braydonf Mar 22, 2019
8bff122
indexer: use chain and blocks for indexer, remove chain client
braydonf Mar 22, 2019
b9e8c7b
changelog: merge blockstore and indexer changes
braydonf Mar 23, 2019
05d55ef
indexer: fix memory and cpu exhaustion for addrindex
braydonf Mar 23, 2019
7dc55c9
indexer: remove address coin index
braydonf Mar 25, 2019
32904c7
changelog: fix memory and cpu exhaustion for addrindex
braydonf Mar 25, 2019
7342952
migrate: update chaindb5to6 migration
tuxcanfly Mar 27, 2019
9f86dbc
chaindb: bump to v6
tuxcanfly Mar 27, 2019
aa3f02d
test: initial http tests for indexer
braydonf Mar 26, 2019
e2a6a92
addrindexer: index by address prefix
tuxcanfly Mar 28, 2019
93c6ff8
indexer: fix, simplify and rewrite indexer base
braydonf Apr 6, 2019
ebc40a5
indexer: trim disk usage for tx and addr indexes
braydonf Apr 15, 2019
06ef0e3
indexer: simplify addrindex query
braydonf Apr 15, 2019
4c8f11e
node: update http for addrindex
braydonf Apr 16, 2019
bd26dbf
mempool: update for addrindex
braydonf Apr 16, 2019
bb79760
node: add http indexer info
braydonf Apr 16, 2019
b37ac59
test: add utility to wait for values
braydonf Apr 16, 2019
80aaa14
test: add mempool index persistence test
nodech Apr 17, 2019
f30276b
test: add mempool indexing tests
nodech Apr 17, 2019
fae647b
indexer: simplify block meta and remove records
braydonf Apr 18, 2019
69e9844
test: cleanup and add txindex tests
braydonf Apr 18, 2019
b4be857
test: improve addrindex tests
braydonf Apr 18, 2019
865f740
test: add test for retroactively enabling indexer
braydonf Apr 19, 2019
efb2551
indexer: fix reset and reorg handling
braydonf Apr 19, 2019
5d18f9b
indexer: index the genesis block
braydonf Apr 23, 2019
cede31d
indexer: cleanup and check pruned and index options
braydonf Apr 23, 2019
ed06c21
indexer: check that blocks are connected
braydonf Apr 23, 2019
5111af0
migrate: update latest migration
tuxcanfly Apr 18, 2019
677b45f
migrate: upgrade from chaindb 4 to 6
braydonf Apr 24, 2019
a6fd1be
changelog: update with latest migration
braydonf Apr 24, 2019
ce16bc9
node: simplify index-prefix option
braydonf May 15, 2019
372b9f9
changelog: update with new indexer fields for info endpoint
braydonf May 15, 2019
662a68c
blockchain: cleanup deprecated methods
braydonf May 15, 2019
34e8f22
indexer: update and fix documentation
braydonf May 16, 2019
7e9d00a
node: pass options from `getTXByAddress` to `getMetaByAddress`
braydonf May 16, 2019
6c497d4
changelog: update and fix chain changes
braydonf May 16, 2019
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
73 changes: 69 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,28 @@
### How to upgrade

The way that block data is stored has changed for greater performance,
efficiency, reliability and portability. To upgrade to the new disk layout
it's necessary to move block data from LevelDB (e.g. `~/.bcoin/chain`) to
a new file based block storage (e.g. `~./.bcoin/blocks`).
efficiency, reliability and portability.

- Block and undo block data has been moved from LevelDB into flat files.
- The transaction and address indexes have been moved into separate
LevelDB databases.
- The transaction has been de-duplicated, and will reduce disk usage by
half for those running with `txindex` enabled.
- The `txindex` and `addrindex` can now be enabled after the initial
block download.
- The `addrindex` has been sorted to support querying for large sets
of results, and will no longer cause CPU and memory exhaustion issues.
- The `addrindex` will correctly distinguish between `p2pkh` and
`p2wpkh` addresses.

To upgrade to the new disk layout it's necessary to move block data
from LevelDB (e.g. `~/.bcoin/chain`) to a new file based block
storage (e.g. `~./.bcoin/blocks`), and remove `txindex` and `addrindex`
data from the chain database, for those that have that feature enabled.

To do this you can run:
```
node ./migrate/chaindb4to5.js /path/to/bcoin/chain
node ./migrate/chaindb4to6.js /path/to/bcoin/chain
```

The migration will take 1-3 hours, depending on hardware. The block data
Expand All @@ -22,6 +37,11 @@ Alternatively, you can also sync the chain again, however the above
migration will be faster as additional network bandwidth won't be used
for downloading the blocks again.

For those with `txindex` and `addrindex` enabled, the indexes will be
regenerated by rescanning the chain on next startup, this process might
take a while. Please take the potential downtime in re-indexing into
account before upgrading.

### Wallet API changes

#### HTTP
Expand Down Expand Up @@ -50,6 +70,31 @@ for downloading the blocks again.
`iswitness`, `witness_version` and `witness_program`.
(a28ffa272a3c4d90d0273d9aa223a23becc08e0e)

### Node API changes

#### HTTP

Several CPU and memory exhaustion issues have been resolved with some
additional arguments for querying multiple sets of results for addresses
that have many transactions.
braydonf marked this conversation as resolved.
Show resolved Hide resolved

- `GET /tx/address/:address` has several new arguments: `after`, `reverse`
and `limit`. The `after` argument is a txid, for querying additional results
after a previous result. The `reverse` argument will change the order that
results are returned, the default order is oldest to latest. The `limit`
argument can be used to give results back in smaller sets if necessary.
- `POST /tx/address` This has been deprecated, instead query for each address
individually with `GET /tx/address/:address` with the expectation that
there could be _many_ results that would additionally need to be queried
in a subsequent query using the `after` argument to request the next set.
- `POST /coin/address` and `GET /coin/address/:address` are deprecated as
coins can be generated using results from `/tx/address/:address` and
querying by only a range of the latest transactions to stay synchronized.
Coins could otherwise be removed from results at any point, and thus the
entire set of results would need to be queried every time to discover
which coins have been spent and are currently available.
- `GET /` has new fields `.indexes.{addr,tx}` for the status of indexers.

### Network changes

- Regtest params have been updated to correspond with other bitcoin
Expand All @@ -76,6 +121,9 @@ for downloading the blocks again.
- The option for `coin-cache` has been removed, this setting was causing
issues during the sync with out-of-memory errors and was making performance
worse instead of better.
- The database location for indexes can be configured via the
`--index-prefix` option. Default locations are `prefix` + `/index`
(e.g. `~/.bcoin/testnet/index/tx` and `~/.bcoin/testnet/index/addr`).

### Script changes

Expand All @@ -97,6 +145,23 @@ for downloading the blocks again.
- Config file `wallet.conf` won't be read during test runs that was
causing issues with some testing environments.

### Chain changes

- The method `getSpentView` accepts a `TXMeta` instead of `TX`.
braydonf marked this conversation as resolved.
Show resolved Hide resolved
- The transaction index methods are now implemented at `node.txindex`:
- `getMeta(hash)`
- `getTX(hash)`
- `hasTX(hash)`
- `getSpentView(tx)`
- The address index method is now implemented at `node.addrindex`:
- `getHashesByAddress(addrs)`
braydonf marked this conversation as resolved.
Show resolved Hide resolved
- The following methods require `getHashesByAddress` in conjunction with
`node.txindex.getTX` and `node.txindex.getMeta` respectively.
- `getTXByAddress(addrs)`
- `getMetaByAddress(addrs)`
- The following method has been deprecated:
- `getCoinsByAddress(addrs)`

### Other changes

- A new module for storing block data in files.
Expand Down
6 changes: 6 additions & 0 deletions lib/bcoin-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ bcoin.HDPrivateKey = require('./hd/private');
bcoin.HDPublicKey = require('./hd/public');
bcoin.Mnemonic = require('./hd/mnemonic');

// Index
bcoin.indexer = require('./indexer');
bcoin.Indexer = require('./indexer/indexer');
bcoin.TXIndexer = require('./indexer/txindexer');
bcoin.AddrIndexer = require('./indexer/addrindexer');

// Mempool
bcoin.mempool = require('./mempool');
bcoin.Fees = require('./mempool/fees');
Expand Down
6 changes: 6 additions & 0 deletions lib/bcoin.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ bcoin.define('HDPrivateKey', './hd/private');
bcoin.define('HDPublicKey', './hd/public');
bcoin.define('Mnemonic', './hd/mnemonic');

// Index
bcoin.define('indexer', './indexer');
bcoin.define('Indexer', './indexer/indexer');
bcoin.define('TXIndexer', './indexer/txindexer');
bcoin.define('AddrIndexer', './indexer/addrindexer');

// Mempool
bcoin.define('mempool', './mempool');
bcoin.define('Fees', './mempool/fees');
Expand Down
96 changes: 0 additions & 96 deletions lib/blockchain/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -1948,75 +1948,6 @@ class Chain extends AsyncEmitter {
return this.db.getBlockView(block);
}

/**
* Get a transaction with metadata.
* @param {Hash} hash
* @returns {Promise} - Returns {@link TXMeta}.
*/

getMeta(hash) {
return this.db.getMeta(hash);
}

/**
* Retrieve a transaction.
* @param {Hash} hash
* @returns {Promise} - Returns {@link TX}.
*/

getTX(hash) {
return this.db.getTX(hash);
}

/**
* @param {Hash} hash
* @returns {Promise} - Returns Boolean.
*/

hasTX(hash) {
return this.db.hasTX(hash);
}

/**
* Get all coins pertinent to an address.
* @param {Address[]} addrs
* @returns {Promise} - Returns {@link Coin}[].
*/

getCoinsByAddress(addrs) {
return this.db.getCoinsByAddress(addrs);
}

/**
* Get all transaction hashes to an address.
* @param {Address[]} addrs
* @returns {Promise} - Returns {@link Hash}[].
*/

getHashesByAddress(addrs) {
return this.db.getHashesByAddress(addrs);
}

/**
* Get all transactions pertinent to an address.
* @param {Address[]} addrs
* @returns {Promise} - Returns {@link TX}[].
*/

getTXByAddress(addrs) {
return this.db.getTXByAddress(addrs);
}

/**
* Get all transactions pertinent to an address.
* @param {Address[]} addrs
* @returns {Promise} - Returns {@link TXMeta}[].
*/

getMetaByAddress(addrs) {
return this.db.getMetaByAddress(addrs);
}

/**
* Get an orphan block.
* @param {Hash} hash
Expand Down Expand Up @@ -2057,21 +1988,6 @@ class Chain extends AsyncEmitter {
return this.db.getCoinView(tx);
}

/**
* Get coin viewpoint (spent).
* @param {TX} tx
* @returns {Promise} - Returns {@link CoinView}.
*/

async getSpentView(tx) {
const unlock = await this.locker.lock();
try {
return await this.db.getSpentView(tx);
} finally {
unlock();
}
}

/**
* Test the chain to see if it is synced.
* @returns {Boolean}
Expand Down Expand Up @@ -2687,8 +2603,6 @@ class ChainOptions {
this.bip91 = false;
this.bip148 = false;
this.prune = false;
this.indexTX = false;
this.indexAddress = false;
this.forceFlags = false;

this.entryCache = 5000;
Expand Down Expand Up @@ -2771,16 +2685,6 @@ class ChainOptions {
this.prune = options.prune;
}

if (options.indexTX != null) {
assert(typeof options.indexTX === 'boolean');
this.indexTX = options.indexTX;
}

if (options.indexAddress != null) {
assert(typeof options.indexAddress === 'boolean');
this.indexAddress = options.indexAddress;
}

if (options.forceFlags != null) {
assert(typeof options.forceFlags === 'boolean');
this.forceFlags = options.forceFlags;
Expand Down
Loading