diff --git a/bench/tx.js b/bench/tx.js
index 32a975fc8..cd37affa9 100644
--- a/bench/tx.js
+++ b/bench/tx.js
@@ -84,7 +84,7 @@ const tx10 = common.readTX('tx10');
const end = bench('input hashes');
for (let i = 0; i < 10000; i++)
- tx.getInputHashes(null, 'hex');
+ tx.getInputHashes();
end(10000);
}
@@ -94,7 +94,7 @@ const tx10 = common.readTX('tx10');
const end = bench('output hashes');
for (let i = 0; i < 10000; i++)
- tx.getOutputHashes('hex');
+ tx.getOutputHashes();
end(10000);
}
@@ -104,7 +104,7 @@ const tx10 = common.readTX('tx10');
const end = bench('all hashes');
for (let i = 0; i < 10000; i++)
- tx.getHashes(null, 'hex');
+ tx.getHashes();
end(10000);
}
@@ -176,7 +176,7 @@ const tx2 = mtx.toTX();
const end = bench('input hashes');
for (let i = 0; i < 10000; i++)
- tx2.getInputHashes(null, 'hex');
+ tx2.getInputHashes();
end(10000);
}
@@ -185,7 +185,7 @@ const tx2 = mtx.toTX();
const end = bench('output hashes');
for (let i = 0; i < 10000; i++)
- tx2.getOutputHashes('hex');
+ tx2.getOutputHashes();
end(10000);
}
@@ -194,7 +194,7 @@ const tx2 = mtx.toTX();
const end = bench('all hashes');
for (let i = 0; i < 10000; i++)
- tx2.getHashes(null, 'hex');
+ tx2.getHashes();
end(10000);
}
diff --git a/bench/walletdb.js b/bench/walletdb.js
index a399919ba..23a92faad 100644
--- a/bench/walletdb.js
+++ b/bench/walletdb.js
@@ -7,7 +7,7 @@ const MTX = require('../lib/primitives/mtx');
const Outpoint = require('../lib/primitives/outpoint');
function dummy() {
- const hash = random.randomBytes(32).toString('hex');
+ const hash = random.randomBytes(32);
return new Outpoint(hash, 0);
}
diff --git a/bin/node b/bin/node
index 4e1f9a314..635cd3fdf 100755
--- a/bin/node
+++ b/bin/node
@@ -2,6 +2,8 @@
'use strict';
+Buffer.poolSize = 2;
+
process.title = 'bcoin';
if (process.argv.indexOf('--help') !== -1
diff --git a/browser/src/app.js b/browser/src/app.js
index c72caddf3..1d8a9f73c 100644
--- a/browser/src/app.js
+++ b/browser/src/app.js
@@ -4,6 +4,7 @@ const Logger = require('blgr');
const FullNode = require('../../lib/node/fullnode');
const Amount = require('../../lib/btc/amount');
const plugin = require('../../lib/wallet/plugin');
+const util = require('../../lib/utils/util');
const ProxySocket = require('./proxysocket');
const body = document.getElementsByTagName('body')[0];
@@ -268,8 +269,9 @@ async function _formatWallet(wallet) {
wdiv.innerHTML = html;
for (const tx of det) {
+ const hash = util.revHex(tx.hash);
const el = create(
- `${tx.hash}`);
+ `${hash}`);
wdiv.appendChild(el);
setMouseup(el, tx.toJSON());
}
diff --git a/docs/Examples/wallet.js b/docs/Examples/wallet.js
index e579ebd43..1e6f177d5 100644
--- a/docs/Examples/wallet.js
+++ b/docs/Examples/wallet.js
@@ -4,7 +4,7 @@ const bcoin = require('../..');
const random = require('bcrypto/lib/random');
function dummy() {
- const hash = random.randomBytes(32).toString('hex');
+ const hash = random.randomBytes(32);
return new bcoin.Outpoint(hash, 0);
}
@@ -36,7 +36,7 @@ const walletdb = new bcoin.wallet.WalletDB({
await walletdb.addTX(tx);
- const wtx = await wallet.getTX(tx.hash('hex'));
+ const wtx = await wallet.getTX(tx.hash());
console.log('Added transaction');
console.log(wtx);
diff --git a/lib/blockchain/chain.js b/lib/blockchain/chain.js
index 5a91eb86d..d0af56638 100644
--- a/lib/blockchain/chain.js
+++ b/lib/blockchain/chain.js
@@ -13,6 +13,7 @@ const AsyncEmitter = require('bevent');
const Logger = require('blgr');
const {Lock} = require('bmutex');
const LRU = require('blru');
+const {BufferMap} = require('buffer-map');
const Network = require('../protocol/network');
const ChainDB = require('./chaindb');
const common = require('./common');
@@ -52,16 +53,16 @@ class Chain extends AsyncEmitter {
this.db = new ChainDB(this.options);
- this.locker = new Lock(true);
- this.invalid = new LRU(100);
+ this.locker = new Lock(true, BufferMap);
+ this.invalid = new LRU(100, null, BufferMap);
this.state = new DeploymentState();
this.tip = new ChainEntry();
this.height = -1;
this.synced = false;
- this.orphanMap = new Map();
- this.orphanPrev = new Map();
+ this.orphanMap = new BufferMap();
+ this.orphanPrev = new BufferMap();
}
/**
@@ -327,11 +328,11 @@ class Chain extends AsyncEmitter {
assert(typeof flags === 'number');
// Extra sanity check.
- if (block.prevBlock !== prev.hash)
+ if (!block.prevBlock.equals(prev.hash))
throw new VerifyError(block, 'invalid', 'bad-prevblk', 0);
// Verify a checkpoint if there is one.
- const hash = block.hash('hex');
+ const hash = block.hash();
if (!this.verifyCheckpoint(prev, hash)) {
throw new VerifyError(block,
'checkpoint',
@@ -351,9 +352,9 @@ class Chain extends AsyncEmitter {
if (flags & common.flags.VERIFY_BODY) {
assert(typeof block.createMerkleRoot === 'function');
- const root = block.createMerkleRoot('hex');
+ const root = block.createMerkleRoot();
- if (!root || block.merkleRoot !== root) {
+ if (!root || !block.merkleRoot.equals(root)) {
throw new VerifyError(block,
'invalid',
'bad-txnmrklroot',
@@ -661,7 +662,7 @@ class Chain extends AsyncEmitter {
// Blocks 91842 and 91880 created duplicate
// txids by using the same exact output script
// and extraNonce.
- if (!hash || block.hash('hex') !== hash)
+ if (!hash || !block.hash().equals(hash))
throw new VerifyError(block, 'invalid', 'bad-txns-BIP30', 100);
}
}
@@ -821,14 +822,14 @@ class Chain extends AsyncEmitter {
*/
async findFork(fork, longer) {
- while (fork.hash !== longer.hash) {
+ while (!fork.hash.equals(longer.hash)) {
while (longer.height > fork.height) {
longer = await this.getPrevious(longer);
if (!longer)
throw new Error('No previous entry for new tip.');
}
- if (fork.hash === longer.hash)
+ if (fork.hash.equals(longer.hash))
return fork;
fork = await this.getPrevious(fork);
@@ -858,7 +859,7 @@ class Chain extends AsyncEmitter {
// Blocks to disconnect.
const disconnect = [];
let entry = tip;
- while (entry.hash !== fork.hash) {
+ while (!entry.hash.equals(fork.hash)) {
disconnect.push(entry);
entry = await this.getPrevious(entry);
assert(entry);
@@ -867,7 +868,7 @@ class Chain extends AsyncEmitter {
// Blocks to connect.
const connect = [];
entry = competitor;
- while (entry.hash !== fork.hash) {
+ while (!entry.hash.equals(fork.hash)) {
connect.push(entry);
entry = await this.getPrevious(entry);
assert(entry);
@@ -915,7 +916,7 @@ class Chain extends AsyncEmitter {
// Buffer disconnected blocks.
const disconnect = [];
let entry = tip;
- while (entry.hash !== fork.hash) {
+ while (!entry.hash.equals(fork.hash)) {
disconnect.push(entry);
entry = await this.getPrevious(entry);
assert(entry);
@@ -1044,7 +1045,7 @@ class Chain extends AsyncEmitter {
async setBestChain(entry, block, prev, flags) {
// A higher fork has arrived.
// Time to reorganize the chain.
- if (entry.prevBlock !== this.tip.hash) {
+ if (!entry.prevBlock.equals(this.tip.hash)) {
this.logger.warning('WARNING: Reorganizing chain.');
// In spv-mode, we reset the
@@ -1303,7 +1304,7 @@ class Chain extends AsyncEmitter {
*/
async add(block, flags, id) {
- const hash = block.hash('hex');
+ const hash = block.hash();
const unlock = await this.locker.lock(hash);
try {
return await this._add(block, flags, id);
@@ -1322,7 +1323,7 @@ class Chain extends AsyncEmitter {
*/
async _add(block, flags, id) {
- const hash = block.hash('hex');
+ const hash = block.hash();
if (flags == null)
flags = common.flags.DEFAULT_FLAGS;
@@ -1331,7 +1332,7 @@ class Chain extends AsyncEmitter {
id = -1;
// Special case for genesis block.
- if (hash === this.network.genesis.hash) {
+ if (hash.equals(this.network.genesis.hash)) {
this.logger.debug('Saw genesis block: %s.', block.rhash());
throw new VerifyError(block, 'duplicate', 'duplicate', 0);
}
@@ -1400,7 +1401,7 @@ class Chain extends AsyncEmitter {
const start = util.bench();
// Sanity check.
- assert(block.prevBlock === prev.hash);
+ assert(block.prevBlock.equals(prev.hash));
// Explanation: we try to keep as much data
// off the javascript heap as possible. Blocks
@@ -1559,7 +1560,7 @@ class Chain extends AsyncEmitter {
if (!checkpoint)
return true;
- if (hash === checkpoint) {
+ if (hash.equals(checkpoint)) {
this.logger.debug('Hit checkpoint block %s (%d).',
util.revHex(hash), height);
this.emit('checkpoint', hash, height);
@@ -1596,8 +1597,8 @@ class Chain extends AsyncEmitter {
// The orphan chain forked.
if (orphan) {
- assert(orphan.block.hash('hex') !== block.hash('hex'));
- assert(orphan.block.prevBlock === block.prevBlock);
+ assert(!orphan.block.hash().equals(block.hash()));
+ assert(orphan.block.prevBlock.equals(block.prevBlock));
this.logger.warning(
'Removing forked orphan block: %s (%d).',
@@ -1625,7 +1626,7 @@ class Chain extends AsyncEmitter {
addOrphan(orphan) {
const block = orphan.block;
- const hash = block.hash('hex');
+ const hash = block.hash();
assert(!this.orphanMap.has(hash));
assert(!this.orphanPrev.has(block.prevBlock));
@@ -1646,7 +1647,7 @@ class Chain extends AsyncEmitter {
removeOrphan(orphan) {
const block = orphan.block;
- const hash = block.hash('hex');
+ const hash = block.hash();
assert(this.orphanMap.has(hash));
assert(this.orphanPrev.has(block.prevBlock));
@@ -1737,7 +1738,7 @@ class Chain extends AsyncEmitter {
*/
hasInvalid(block) {
- const hash = block.hash('hex');
+ const hash = block.hash();
if (this.invalid.has(hash))
return true;
@@ -2152,7 +2153,7 @@ class Chain extends AsyncEmitter {
if (start == null)
start = this.tip.hash;
- assert(typeof start === 'string');
+ assert(Buffer.isBuffer(start));
let entry = await this.getEntry(start);
diff --git a/lib/blockchain/chaindb.js b/lib/blockchain/chaindb.js
index 833255f3a..88026ede0 100644
--- a/lib/blockchain/chaindb.js
+++ b/lib/blockchain/chaindb.js
@@ -11,6 +11,7 @@ const assert = require('assert');
const bdb = require('bdb');
const bio = require('bufio');
const LRU = require('blru');
+const {BufferMap, BufferSet} = require('buffer-map');
const Amount = require('../btc/amount');
const Network = require('../protocol/network');
const CoinView = require('../coins/coinview');
@@ -47,8 +48,8 @@ class ChainDB {
this.pending = null;
this.current = null;
- this.coinCache = new LRU(this.options.coinCache, getSize);
- this.cacheHash = new LRU(this.options.entryCache);
+ this.coinCache = new LRU(this.options.coinCache, getSize, BufferMap);
+ this.cacheHash = new LRU(this.options.entryCache, null, BufferMap);
this.cacheHeight = new LRU(this.options.entryCache);
}
@@ -224,7 +225,7 @@ class ChainDB {
if (typeof block === 'number')
return this.cacheHeight.has(block);
- assert(typeof block === 'string');
+ assert(Buffer.isBuffer(block));
return this.cacheHash.has(block);
}
@@ -238,7 +239,7 @@ class ChainDB {
if (typeof block === 'number')
return this.cacheHeight.get(block);
- assert(typeof block === 'string');
+ assert(Buffer.isBuffer(block));
return this.cacheHash.get(block);
}
@@ -253,9 +254,9 @@ class ChainDB {
if (typeof hash === 'number')
return hash;
- assert(typeof hash === 'string');
+ assert(Buffer.isBuffer(hash));
- if (hash === consensus.NULL_HASH)
+ if (hash.equals(consensus.ZERO_HASH))
return -1;
const entry = this.cacheHash.get(hash);
@@ -279,7 +280,7 @@ class ChainDB {
*/
async getHash(height) {
- if (typeof height === 'string')
+ if (Buffer.isBuffer(height))
return height;
assert(typeof height === 'number');
@@ -292,12 +293,7 @@ class ChainDB {
if (entry)
return entry.hash;
- const hash = await this.db.get(layout.H.build(height));
-
- if (!hash)
- return null;
-
- return hash.toString('hex');
+ return this.db.get(layout.H.build(height));
}
/**
@@ -317,13 +313,11 @@ class ChainDB {
if (cache)
return cache;
- const data = await this.db.get(layout.H.build(height));
+ const hash = await this.db.get(layout.H.build(height));
- if (!data)
+ if (!hash)
return null;
- const hash = data.toString('hex');
-
const state = this.state;
const entry = await this.getEntryByHash(hash);
@@ -346,9 +340,9 @@ class ChainDB {
*/
async getEntryByHash(hash) {
- assert(typeof hash === 'string');
+ assert(Buffer.isBuffer(hash));
- if (hash === consensus.NULL_HASH)
+ if (hash.equals(consensus.ZERO_HASH))
return null;
const cache = this.cacheHash.get(hash);
@@ -473,7 +467,7 @@ class ChainDB {
return null;
// Not on main chain.
- if (next.prevBlock !== entry.hash)
+ if (!next.prevBlock.equals(entry.hash))
return null;
return next;
@@ -810,12 +804,7 @@ class ChainDB {
*/
async getNextHash(hash) {
- const data = await this.db.get(layout.n.build(hash));
-
- if (!data)
- return null;
-
- return data.toString('hex');
+ return this.db.get(layout.n.build(hash));
}
/**
@@ -825,15 +814,15 @@ class ChainDB {
*/
async isMainHash(hash) {
- assert(typeof hash === 'string');
+ assert(Buffer.isBuffer(hash));
- if (hash === consensus.NULL_HASH)
+ if (hash.equals(consensus.ZERO_HASH))
return false;
- if (hash === this.network.genesis.hash)
+ if (hash.equals(this.network.genesis.hash))
return true;
- if (hash === this.state.tip)
+ if (hash.equals(this.state.tip))
return true;
const cacheHash = this.cacheHash.get(hash);
@@ -841,7 +830,7 @@ class ChainDB {
if (cacheHash) {
const cacheHeight = this.cacheHeight.get(cacheHash.height);
if (cacheHeight)
- return cacheHeight.hash === hash;
+ return cacheHeight.hash.equals(hash);
}
if (await this.getNextHash(hash))
@@ -860,13 +849,13 @@ class ChainDB {
if (entry.isGenesis())
return true;
- if (entry.hash === this.state.tip)
+ if (entry.hash.equals(this.state.tip))
return true;
const cache = this.getCache(entry.height);
if (cache)
- return entry.hash === cache.hash;
+ return entry.hash.equals(cache.hash);
if (await this.getNextHash(entry.hash))
return true;
@@ -893,8 +882,7 @@ class ChainDB {
return this.db.values({
gte: layout.H.min(start),
- lte: layout.H.max(end),
- parse: data => data.toString('hex')
+ lte: layout.H.max(end)
});
}
@@ -1203,7 +1191,7 @@ class ChainDB {
if (!this.options.indexTX || !this.options.indexAddress)
return [];
- const hashes = Object.create(null);
+ const set = new BufferSet();
for (const addr of addrs) {
const hash = Address.getHash(addr);
@@ -1213,12 +1201,12 @@ class ChainDB {
lte: layout.T.max(hash),
parse: (key) => {
const [, txid] = layout.T.parse(key);
- hashes[txid] = true;
+ set.add(txid);
}
});
}
- return Object.keys(hashes);
+ return set.toArray();
}
/**
@@ -1576,7 +1564,7 @@ class ChainDB {
this.start();
// Stop once we hit our target tip.
- if (tip.hash === entry.hash) {
+ if (tip.hash.equals(entry.hash)) {
this.put(layout.R.build(), this.pending.commit(tip.hash));
await this.commit();
break;
@@ -1735,14 +1723,17 @@ class ChainDB {
for (const [index, coin] of coins.outputs) {
if (coin.spent) {
this.del(layout.c.build(hash, index));
- this.coinCache.unpush(hash + index);
+ if (this.coinCache.capacity > 0)
+ this.coinCache.unpush(Outpoint.toKey(hash, index));
continue;
}
const raw = coin.toRaw();
this.put(layout.c.build(hash, index), raw);
- this.coinCache.push(hash + index, raw);
+
+ if (this.coinCache.capacity > 0)
+ this.coinCache.push(Outpoint.toKey(hash, index), raw);
}
}
}
@@ -2130,7 +2121,7 @@ class ChainState {
*/
constructor() {
- this.tip = consensus.NULL_HASH;
+ this.tip = consensus.ZERO_HASH;
this.tx = 0;
this.coin = 0;
this.value = 0;
@@ -2169,8 +2160,6 @@ class ChainState {
}
commit(hash) {
- if (typeof hash !== 'string')
- hash = hash.toString('hex');
this.tip = hash;
this.committed = true;
return this.toRaw();
@@ -2188,7 +2177,7 @@ class ChainState {
static fromRaw(data) {
const state = new ChainState();
const br = bio.read(data);
- state.tip = br.readHash('hex');
+ state.tip = br.readHash();
state.tx = br.readU64();
state.coin = br.readU64();
state.value = br.readU64();
@@ -2220,7 +2209,7 @@ class StateCache {
for (const {bit} of this.network.deploys) {
assert(!this.bits[bit]);
- this.bits[bit] = new Map();
+ this.bits[bit] = new BufferMap();
}
}
diff --git a/lib/blockchain/chainentry.js b/lib/blockchain/chainentry.js
index 0dae696d6..88d636d0e 100644
--- a/lib/blockchain/chainentry.js
+++ b/lib/blockchain/chainentry.js
@@ -50,10 +50,10 @@ class ChainEntry {
*/
constructor(options) {
- this.hash = consensus.NULL_HASH;
+ this.hash = consensus.ZERO_HASH;
this.version = 1;
- this.prevBlock = consensus.NULL_HASH;
- this.merkleRoot = consensus.NULL_HASH;
+ this.prevBlock = consensus.ZERO_HASH;
+ this.merkleRoot = consensus.ZERO_HASH;
this.time = 0;
this.bits = 0;
this.nonce = 0;
@@ -72,10 +72,10 @@ class ChainEntry {
fromOptions(options) {
assert(options, 'Block data is required.');
- assert(typeof options.hash === 'string');
+ assert(Buffer.isBuffer(options.hash));
assert((options.version >>> 0) === options.version);
- assert(typeof options.prevBlock === 'string');
- assert(typeof options.merkleRoot === 'string');
+ assert(Buffer.isBuffer(options.prevBlock));
+ assert(Buffer.isBuffer(options.merkleRoot));
assert((options.time >>> 0) === options.time);
assert((options.bits >>> 0) === options.bits);
assert((options.nonce >>> 0) === options.nonce);
@@ -188,7 +188,7 @@ class ChainEntry {
*/
fromBlock(block, prev) {
- this.hash = block.hash('hex');
+ this.hash = block.hash();
this.version = block.version;
this.prevBlock = block.prevBlock;
this.merkleRoot = block.merkleRoot;
@@ -243,10 +243,10 @@ class ChainEntry {
br.seek(-80);
- this.hash = hash.toString('hex');
+ this.hash = hash;
this.version = br.readU32();
- this.prevBlock = br.readHash('hex');
- this.merkleRoot = br.readHash('hex');
+ this.prevBlock = br.readHash();
+ this.merkleRoot = br.readHash();
this.time = br.readU32();
this.bits = br.readU32();
this.nonce = br.readU32();
@@ -303,10 +303,10 @@ class ChainEntry {
assert((json.nonce >>> 0) === json.nonce);
assert(typeof json.chainwork === 'string');
- this.hash = util.revHex(json.hash);
+ this.hash = util.fromRev(json.hash);
this.version = json.version;
- this.prevBlock = util.revHex(json.prevBlock);
- this.merkleRoot = util.revHex(json.merkleRoot);
+ this.prevBlock = util.fromRev(json.prevBlock);
+ this.merkleRoot = util.fromRev(json.merkleRoot);
this.time = json.time;
this.bits = json.bits;
this.nonce = json.nonce;
diff --git a/lib/blockchain/layout.js b/lib/blockchain/layout.js
index 1bc801d57..3a65c0fb9 100644
--- a/lib/blockchain/layout.js
+++ b/lib/blockchain/layout.js
@@ -33,18 +33,18 @@ const layout = {
O: bdb.key('O'),
R: bdb.key('R'),
D: bdb.key('D'),
- e: bdb.key('e', ['hash256']),
- h: bdb.key('h', ['hash256']),
+ e: bdb.key('e', ['bhash256']),
+ h: bdb.key('h', ['bhash256']),
H: bdb.key('H', ['uint32']),
- n: bdb.key('n', ['hash256']),
- p: bdb.key('p', ['hash256']),
- b: bdb.key('b', ['hash256']),
- t: bdb.key('t', ['hash256']),
- c: bdb.key('c', ['hash256', 'uint32']),
- u: bdb.key('u', ['hash256']),
- v: bdb.key('v', ['uint8', 'hash256']),
- T: bdb.key('T', ['hash', 'hash256']),
- C: bdb.key('C', ['hash', 'hash256', 'uint32'])
+ n: bdb.key('n', ['bhash256']),
+ p: bdb.key('p', ['bhash256']),
+ b: bdb.key('b', ['bhash256']),
+ t: bdb.key('t', ['bhash256']),
+ c: bdb.key('c', ['bhash256', 'uint32']),
+ u: bdb.key('u', ['bhash256']),
+ v: bdb.key('v', ['uint8', 'bhash256']),
+ T: bdb.key('T', ['bhash', 'bhash256']),
+ C: bdb.key('C', ['bhash', 'bhash256', 'uint32'])
};
/*
diff --git a/lib/coins/coinview.js b/lib/coins/coinview.js
index 83a8cf1ab..c82097c94 100644
--- a/lib/coins/coinview.js
+++ b/lib/coins/coinview.js
@@ -6,6 +6,7 @@
'use strict';
+const {BufferMap} = require('buffer-map');
const Coins = require('./coins');
const UndoCoins = require('./undocoins');
const CoinEntry = require('./coinentry');
@@ -26,7 +27,7 @@ class CoinView {
*/
constructor() {
- this.map = new Map();
+ this.map = new BufferMap();
this.undo = new UndoCoins();
}
@@ -102,7 +103,7 @@ class CoinView {
*/
addTX(tx, height) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const coins = Coins.fromTX(tx, height);
return this.add(hash, coins);
}
@@ -115,7 +116,7 @@ class CoinView {
*/
removeTX(tx, height) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const coins = Coins.fromTX(tx, height);
for (const coin of coins.outputs.values())
@@ -170,7 +171,7 @@ class CoinView {
*/
addIndex(tx, index, height) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const coins = this.ensure(hash);
return coins.addIndex(tx, index, height);
}
diff --git a/lib/mempool/fees.js b/lib/mempool/fees.js
index 3f65d3724..d458f1b75 100644
--- a/lib/mempool/fees.js
+++ b/lib/mempool/fees.js
@@ -11,6 +11,7 @@
const assert = require('assert');
const bio = require('bufio');
const Logger = require('blgr');
+const {BufferMap} = require('buffer-map');
const util = require('../utils/util');
const binary = require('../utils/binary');
const consensus = require('../protocol/consensus');
@@ -420,7 +421,7 @@ class PolicyEstimator {
this.priUnlikely = 0;
this.priLikely = INF_PRIORITY;
- this.map = new Map();
+ this.map = new BufferMap();
this.bestHeight = 0;
if (policy.MIN_RELAY >= MIN_FEERATE)
@@ -536,7 +537,7 @@ class PolicyEstimator {
processTX(entry, current) {
const height = entry.height;
- const hash = entry.hash('hex');
+ const hash = entry.hash();
if (this.map.has(hash)) {
this.logger.debug('Mempool tx %s already tracked.', entry.txid());
diff --git a/lib/mempool/layout.js b/lib/mempool/layout.js
index 81fddc34f..4982c9ea0 100644
--- a/lib/mempool/layout.js
+++ b/lib/mempool/layout.js
@@ -21,7 +21,7 @@ const layout = {
v: bdb.key('v'),
R: bdb.key('R'),
F: bdb.key('F'),
- e: bdb.key('e', ['hash256'])
+ e: bdb.key('e', ['bhash256'])
};
/*
diff --git a/lib/mempool/mempool.js b/lib/mempool/mempool.js
index 500cd8b54..1c98e3f93 100644
--- a/lib/mempool/mempool.js
+++ b/lib/mempool/mempool.js
@@ -12,6 +12,7 @@ const EventEmitter = require('events');
const bdb = require('bdb');
const {RollingFilter} = require('bfilter');
const Heap = require('bheep');
+const {BufferMap, BufferSet} = require('buffer-map');
const common = require('../blockchain/common');
const consensus = require('../protocol/consensus');
const policy = require('../protocol/policy');
@@ -66,10 +67,10 @@ class Mempool extends EventEmitter {
this.lastFlush = 0;
this.tip = this.network.genesis.hash;
- this.waiting = new Map();
- this.orphans = new Map();
- this.map = new Map();
- this.spents = new Map();
+ this.waiting = new BufferMap();
+ this.orphans = new BufferMap();
+ this.map = new BufferMap();
+ this.spents = new BufferMap();
this.rejects = new RollingFilter(120000, 0.000001);
this.coinIndex = new CoinIndex();
@@ -174,7 +175,7 @@ class Mempool extends EventEmitter {
for (let i = txs.length - 1; i >= 1; i--) {
const tx = txs[i];
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const entry = this.getEntry(hash);
if (!entry) {
@@ -253,7 +254,7 @@ class Mempool extends EventEmitter {
for (let i = 1; i < txs.length; i++) {
const tx = txs[i];
- const hash = tx.hash('hex');
+ const hash = tx.hash();
if (this.hasEntry(hash))
continue;
@@ -433,7 +434,7 @@ class Mempool extends EventEmitter {
while (queue.size() > 0) {
const entry = queue.shift();
- const hash = entry.hash('hex');
+ const hash = entry.hash();
assert(this.hasEntry(hash));
@@ -558,7 +559,7 @@ class Mempool extends EventEmitter {
const out = [];
for (const addr of addrs) {
- const hash = Address.getHash(addr, 'hex');
+ const hash = Address.getHash(addr);
const coins = this.coinIndex.get(hash);
for (const coin of coins)
@@ -581,7 +582,7 @@ class Mempool extends EventEmitter {
const out = [];
for (const addr of addrs) {
- const hash = Address.getHash(addr, 'hex');
+ const hash = Address.getHash(addr);
const txs = this.txIndex.get(hash);
for (const tx of txs)
@@ -604,7 +605,7 @@ class Mempool extends EventEmitter {
const out = [];
for (const addr of addrs) {
- const hash = Address.getHash(addr, 'hex');
+ const hash = Address.getHash(addr);
const txs = this.txIndex.getMeta(hash);
for (const tx of txs)
@@ -685,7 +686,7 @@ class Mempool extends EventEmitter {
*/
hasReject(hash) {
- return this.rejects.test(hash, 'hex');
+ return this.rejects.test(hash);
}
/**
@@ -699,7 +700,7 @@ class Mempool extends EventEmitter {
*/
async addTX(tx, id) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const unlock = await this.locker.lock(hash);
try {
return await this._addTX(tx, id);
@@ -754,7 +755,7 @@ class Mempool extends EventEmitter {
const lockFlags = common.lockFlags.STANDARD_LOCKTIME_FLAGS;
const height = this.chain.height;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
// Basic sanity checks.
// This is important because it ensures
@@ -1112,14 +1113,14 @@ class Mempool extends EventEmitter {
removeEntry(entry) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
this.untrackEntry(entry);
if (this.fees)
this.fees.removeTX(hash);
- this.cache.remove(tx.hash());
+ this.cache.remove(hash);
this.emit('remove entry', entry);
}
@@ -1144,7 +1145,7 @@ class Mempool extends EventEmitter {
removeSpenders(entry) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
for (let i = 0; i < tx.outputs.length; i++) {
const spender = this.getSpent(hash, i);
@@ -1165,7 +1166,7 @@ class Mempool extends EventEmitter {
*/
countAncestors(entry) {
- return this._countAncestors(entry, new Set(), entry, nop);
+ return this._countAncestors(entry, new BufferSet(), entry, nop);
}
/**
@@ -1178,7 +1179,7 @@ class Mempool extends EventEmitter {
*/
updateAncestors(entry, map) {
- return this._countAncestors(entry, new Set(), entry, map);
+ return this._countAncestors(entry, new BufferSet(), entry, map);
}
/**
@@ -1228,7 +1229,7 @@ class Mempool extends EventEmitter {
*/
countDescendants(entry) {
- return this._countDescendants(entry, new Set());
+ return this._countDescendants(entry, new BufferSet());
}
/**
@@ -1242,7 +1243,7 @@ class Mempool extends EventEmitter {
_countDescendants(entry, set) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
for (let i = 0; i < tx.outputs.length; i++) {
const child = this.getSpent(hash, i);
@@ -1250,7 +1251,7 @@ class Mempool extends EventEmitter {
if (!child)
continue;
- const next = child.hash('hex');
+ const next = child.hash();
if (set.has(next))
continue;
@@ -1270,7 +1271,7 @@ class Mempool extends EventEmitter {
*/
getAncestors(entry) {
- return this._getAncestors(entry, [], new Set());
+ return this._getAncestors(entry, [], new BufferSet());
}
/**
@@ -1311,7 +1312,7 @@ class Mempool extends EventEmitter {
*/
getDescendants(entry) {
- return this._getDescendants(entry, [], new Set());
+ return this._getDescendants(entry, [], new BufferSet());
}
/**
@@ -1324,7 +1325,7 @@ class Mempool extends EventEmitter {
_getDescendants(entry, entries, set) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
for (let i = 0; i < tx.outputs.length; i++) {
const child = this.getSpent(hash, i);
@@ -1332,7 +1333,7 @@ class Mempool extends EventEmitter {
if (!child)
continue;
- const next = child.hash('hex');
+ const next = child.hash();
if (set.has(next))
continue;
@@ -1441,7 +1442,7 @@ class Mempool extends EventEmitter {
*/
maybeOrphan(tx, view, id) {
- const hashes = new Set();
+ const hashes = new BufferSet();
const missing = [];
for (const {prevout} of tx.inputs) {
@@ -1484,11 +1485,11 @@ class Mempool extends EventEmitter {
this.limitOrphans();
- const hash = tx.hash('hex');
+ const hash = tx.hash();
for (const prev of hashes.keys()) {
if (!this.waiting.has(prev))
- this.waiting.set(prev, new Set());
+ this.waiting.set(prev, new BufferSet());
this.waiting.get(prev).add(hash);
@@ -1551,7 +1552,7 @@ class Mempool extends EventEmitter {
this.logger.debug(
'Transaction %s was double-orphaned in mempool.',
tx.txid());
- this.removeOrphan(tx.hash('hex'));
+ this.removeOrphan(tx.hash());
continue;
}
@@ -1569,7 +1570,7 @@ class Mempool extends EventEmitter {
*/
resolveOrphans(parent) {
- const hash = parent.hash('hex');
+ const hash = parent.hash();
const set = this.waiting.get(hash);
if (!set)
@@ -1779,7 +1780,7 @@ class Mempool extends EventEmitter {
trackEntry(entry, view) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
assert(!this.map.has(hash));
this.map.set(hash, entry);
@@ -1805,7 +1806,7 @@ class Mempool extends EventEmitter {
untrackEntry(entry) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
assert(this.map.has(hash));
this.map.delete(hash);
@@ -1852,7 +1853,7 @@ class Mempool extends EventEmitter {
unindexEntry(entry) {
const tx = entry.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
this.txIndex.remove(hash);
@@ -2148,10 +2149,10 @@ class TXIndex {
constructor() {
// Map of addr->entries.
- this.index = new Map();
+ this.index = new BufferMap();
// Map of txid->addrs.
- this.map = new Map();
+ this.map = new BufferMap();
}
reset() {
@@ -2192,8 +2193,8 @@ class TXIndex {
insert(entry, view) {
const tx = entry.tx;
- const hash = tx.hash('hex');
- const addrs = tx.getHashes(view, 'hex');
+ const hash = tx.hash();
+ const addrs = tx.getHashes(view);
if (addrs.length === 0)
return;
@@ -2202,7 +2203,7 @@ class TXIndex {
let items = this.index.get(addr);
if (!items) {
- items = new Map();
+ items = new BufferMap();
this.index.set(addr, items);
}
@@ -2248,10 +2249,10 @@ class CoinIndex {
constructor() {
// Map of addr->coins.
- this.index = new Map();
+ this.index = new BufferMap();
// Map of outpoint->addr.
- this.map = new Map();
+ this.map = new BufferMap();
}
reset() {
@@ -2275,8 +2276,8 @@ class CoinIndex {
insert(tx, index) {
const output = tx.outputs[index];
- const hash = tx.hash('hex');
- const addr = output.getHash('hex');
+ const hash = tx.hash();
+ const addr = output.getHash();
if (!addr)
return;
@@ -2284,7 +2285,7 @@ class CoinIndex {
let items = this.index.get(addr);
if (!items) {
- items = new Map();
+ items = new BufferMap();
this.index.set(addr, items);
}
@@ -2397,12 +2398,7 @@ class MempoolCache {
}
async getTip() {
- const hash = await this.db.get(layout.R.build());
-
- if (!hash)
- return null;
-
- return hash.toString('hex');
+ return this.db.get(layout.R.build());
}
async getFees() {
@@ -2478,7 +2474,7 @@ class MempoolCache {
if (!this.db)
return;
- this.batch.put(layout.R.build(), Buffer.from(tip, 'hex'));
+ this.batch.put(layout.R.build(), tip);
}
writeFees(fees) {
@@ -2505,7 +2501,7 @@ class MempoolCache {
async init(hash) {
const batch = this.db.batch();
batch.put(layout.v.build(), fromU32(MempoolCache.VERSION));
- batch.put(layout.R.build(), Buffer.from(hash, 'hex'));
+ batch.put(layout.R.build(), hash);
await batch.write();
}
@@ -2536,7 +2532,7 @@ class MempoolCache {
tip = await this.getTip();
- if (tip !== this.chain.tip.hash) {
+ if (!tip || !tip.equals(this.chain.tip.hash)) {
this.logger.warning(
'Mempool tip not consistent with chain tip (%s != %s)!',
util.revHex(tip),
@@ -2557,7 +2553,7 @@ class MempoolCache {
batch.del(key);
batch.put(layout.v.build(), fromU32(MempoolCache.VERSION));
- batch.put(layout.R.build(), Buffer.from(this.chain.tip.hash, 'hex'));
+ batch.put(layout.R.build(), this.chain.tip.hash);
batch.del(layout.F.build());
await batch.write();
diff --git a/lib/mining/common.js b/lib/mining/common.js
index 00f39e750..526fc3592 100644
--- a/lib/mining/common.js
+++ b/lib/mining/common.js
@@ -41,17 +41,6 @@ common.swap32 = function swap32(data) {
return data;
};
-/**
- * Swap 32 bit endianness of uint256 (hex).
- * @param {String} str
- * @returns {String}
- */
-
-common.swap32hex = function swap32hex(str) {
- const data = Buffer.from(str, 'hex');
- return common.swap32(data).toString('hex');
-};
-
/**
* Compare two uint256le's.
* @param {Buffer} a
diff --git a/lib/mining/cpuminer.js b/lib/mining/cpuminer.js
index 98171428e..7a4f92f08 100644
--- a/lib/mining/cpuminer.js
+++ b/lib/mining/cpuminer.js
@@ -54,7 +54,7 @@ class CPUMiner extends EventEmitter {
if (!this.job)
return;
- if (this.job.attempt.prevBlock === tip.prevBlock)
+ if (this.job.attempt.prevBlock.equals(tip.prevBlock))
this.job.destroy();
});
}
diff --git a/lib/mining/miner.js b/lib/mining/miner.js
index 7e01696b9..fcf03ddf0 100644
--- a/lib/mining/miner.js
+++ b/lib/mining/miner.js
@@ -10,6 +10,7 @@
const assert = require('assert');
const EventEmitter = require('events');
const Heap = require('bheep');
+const {BufferMap} = require('buffer-map');
const Amount = require('../btc/amount');
const Address = require('../primitives/address');
const BlockTemplate = require('./template');
@@ -250,10 +251,10 @@ class Miner extends EventEmitter {
return;
}
- assert(this.mempool.tip === this.chain.tip.hash,
+ assert(this.mempool.tip.equals(this.chain.tip.hash),
'Mempool/chain tip mismatch! Unsafe to create block.');
- const depMap = new Map();
+ const depMap = new BufferMap();
const queue = new Heap(cmpRate);
let priority = this.options.priorityWeight > 0;
diff --git a/lib/mining/template.js b/lib/mining/template.js
index bb7815653..eae2f885a 100644
--- a/lib/mining/template.js
+++ b/lib/mining/template.js
@@ -42,7 +42,7 @@ class BlockTemplate {
*/
constructor(options) {
- this.prevBlock = consensus.NULL_HASH;
+ this.prevBlock = consensus.ZERO_HASH;
this.version = 1;
this.height = 0;
this.time = 0;
@@ -79,7 +79,7 @@ class BlockTemplate {
assert(options);
if (options.prevBlock != null) {
- assert(typeof options.prevBlock === 'string');
+ assert(Buffer.isBuffer(options.prevBlock));
this.prevBlock = options.prevBlock;
}
@@ -467,7 +467,7 @@ class BlockTemplate {
block.version = this.version;
block.prevBlock = this.prevBlock;
- block.merkleRoot = root.toString('hex');
+ block.merkleRoot = root;
block.time = time;
block.bits = this.bits;
block.nonce = nonce;
@@ -608,7 +608,7 @@ class BlockEntry {
constructor(tx) {
this.tx = tx;
- this.hash = tx.hash('hex');
+ this.hash = tx.hash();
this.fee = 0;
this.rate = 0;
this.priority = 0;
@@ -682,7 +682,7 @@ class BlockProof {
}
rhash() {
- return util.revHex(this.hash.toString('hex'));
+ return util.revHex(this.hash);
}
verify(target) {
diff --git a/lib/net/bip152.js b/lib/net/bip152.js
index 904e6466f..aec7bbbb8 100644
--- a/lib/net/bip152.js
+++ b/lib/net/bip152.js
@@ -366,11 +366,7 @@ class CompactBlock extends AbstractBlock {
*/
sid(hash) {
- if (typeof hash === 'string')
- hash = Buffer.from(hash, 'hex');
-
const [hi, lo] = siphash(hash, this.sipKey);
-
return (hi & 0xffff) * 0x100000000 + (lo >>> 0);
}
@@ -554,7 +550,7 @@ class TXRequest {
*/
constructor(options) {
- this.hash = consensus.NULL_HASH;
+ this.hash = consensus.ZERO_HASH;
this.indexes = [];
if (options)
@@ -595,7 +591,7 @@ class TXRequest {
*/
fromCompact(block) {
- this.hash = block.hash('hex');
+ this.hash = block.hash();
for (let i = 0; i < block.available.length; i++) {
if (!block.available[i])
@@ -623,7 +619,7 @@ class TXRequest {
*/
fromReader(br) {
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
const count = br.readVarint();
@@ -749,7 +745,7 @@ class TXResponse {
*/
constructor(options) {
- this.hash = consensus.NULL_HASH;
+ this.hash = consensus.ZERO_HASH;
this.txs = [];
if (options)
@@ -790,7 +786,7 @@ class TXResponse {
*/
fromReader(br) {
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
const count = br.readVarint();
diff --git a/lib/net/packets.js b/lib/net/packets.js
index 535b398d0..c75bbc17a 100644
--- a/lib/net/packets.js
+++ b/lib/net/packets.js
@@ -1039,11 +1039,11 @@ class GetBlocksPacket extends Packet {
assert(count <= common.MAX_INV, 'Too many block hashes.');
for (let i = 0; i < count; i++)
- this.locator.push(br.readHash('hex'));
+ this.locator.push(br.readHash());
- this.stop = br.readHash('hex');
+ this.stop = br.readHash();
- if (this.stop === consensus.NULL_HASH)
+ if (this.stop.equals(consensus.ZERO_HASH))
this.stop = null;
return this;
@@ -1626,7 +1626,7 @@ class RejectPacket extends Packet {
switch (this.message) {
case 'block':
case 'tx':
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
break;
default:
this.hash = null;
diff --git a/lib/net/peer.js b/lib/net/peer.js
index ece374145..ea968f6ee 100644
--- a/lib/net/peer.js
+++ b/lib/net/peer.js
@@ -15,6 +15,7 @@ const tcp = require('btcp');
const dns = require('bdns');
const Logger = require('blgr');
const {RollingFilter} = require('bfilter');
+const {BufferMap} = require('buffer-map');
const util = require('../utils/util');
const Parser = require('./parser');
const Framer = require('./framer');
@@ -138,10 +139,10 @@ class Peer extends EventEmitter {
this.addrFilter = new RollingFilter(5000, 0.001);
this.invFilter = new RollingFilter(50000, 0.000001);
- this.blockMap = new Map();
- this.txMap = new Map();
+ this.blockMap = new BufferMap();
+ this.txMap = new BufferMap();
this.responseMap = new Map();
- this.compactBlocks = new Map();
+ this.compactBlocks = new BufferMap();
this.init();
}
@@ -589,7 +590,7 @@ class Peer extends EventEmitter {
// Check the fee filter.
if (this.feeRate !== -1) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const rate = this.options.getRate(hash);
if (rate !== -1 && rate < this.feeRate)
continue;
@@ -650,7 +651,7 @@ class Peer extends EventEmitter {
const items = [];
for (const item of queue) {
- if (!this.invFilter.added(item.hash, 'hex'))
+ if (!this.invFilter.added(item.hash))
continue;
items.push(item);
@@ -678,7 +679,7 @@ class Peer extends EventEmitter {
items = [items];
for (const item of items)
- this.invFilter.add(item.hash, 'hex');
+ this.invFilter.add(item.hash);
if (items.length === 0)
return;
diff --git a/lib/net/pool.js b/lib/net/pool.js
index 3786ca560..732aa6e52 100644
--- a/lib/net/pool.js
+++ b/lib/net/pool.js
@@ -17,6 +17,7 @@ const UPNP = require('bupnp');
const socks = require('bsocks');
const List = require('blst');
const {BloomFilter, RollingFilter} = require('bfilter');
+const {BufferMap, BufferSet} = require('buffer-map');
const util = require('../utils/util');
const common = require('./common');
const chainCommon = require('../blockchain/common');
@@ -59,17 +60,17 @@ class Pool extends EventEmitter {
this.server = this.options.createServer();
this.nonces = this.options.nonces;
- this.locker = new Lock(true);
+ this.locker = new Lock(true, BufferMap);
this.connected = false;
this.disconnecting = false;
this.syncing = false;
this.discovering = false;
this.spvFilter = null;
this.txFilter = null;
- this.blockMap = new Set();
- this.txMap = new Set();
- this.compactBlocks = new Set();
- this.invMap = new Map();
+ this.blockMap = new BufferSet();
+ this.txMap = new BufferSet();
+ this.compactBlocks = new BufferSet();
+ this.invMap = new BufferMap();
this.pendingFilter = null;
this.pendingRefill = null;
@@ -871,7 +872,7 @@ class Pool extends EventEmitter {
let total = 0;
for (let peer = this.peers.head(); peer; peer = peer.next) {
- if (peer.bestHash !== hash)
+ if (!peer.bestHash || !peer.bestHash.equals(hash))
continue;
if (peer.bestHeight !== height) {
@@ -1566,7 +1567,7 @@ class Pool extends EventEmitter {
unknown = item.type;
continue;
}
- peer.invFilter.add(item.hash, 'hex');
+ peer.invFilter.add(item.hash);
}
this.logger.spam(
@@ -1824,7 +1825,7 @@ class Pool extends EventEmitter {
}
}
- if (item.hash === peer.hashContinue) {
+ if (peer.hashContinue && item.hash.equals(peer.hashContinue)) {
peer.sendInv([new InvItem(invTypes.BLOCK, this.chain.tip.hash)]);
peer.hashContinue = null;
}
@@ -1910,7 +1911,7 @@ class Pool extends EventEmitter {
while (hash) {
blocks.push(new InvItem(invTypes.BLOCK, hash));
- if (hash === packet.stop)
+ if (packet.stop && hash.equals(packet.stop))
break;
if (blocks.length === 500) {
@@ -1963,7 +1964,7 @@ class Pool extends EventEmitter {
while (entry) {
headers.push(entry.toHeaders());
- if (entry.hash === packet.stop)
+ if (packet.stop && entry.hash.equals(packet.stop))
break;
if (headers.length === 2000)
@@ -2030,7 +2031,7 @@ class Pool extends EventEmitter {
for (const header of headers) {
const last = this.headerChain.tail;
- const hash = header.hash('hex');
+ const hash = header.hash();
const height = last.height + 1;
if (!header.verify()) {
@@ -2042,7 +2043,7 @@ class Pool extends EventEmitter {
return;
}
- if (header.prevBlock !== last.hash) {
+ if (!header.prevBlock.equals(last.hash)) {
this.logger.warning(
'Peer sent a bad header chain (%s).',
peer.hostname());
@@ -2053,7 +2054,7 @@ class Pool extends EventEmitter {
node = new HeaderEntry(hash, height);
if (node.height === this.headerTip.height) {
- if (node.hash !== this.headerTip.hash) {
+ if (!node.hash.equals(this.headerTip.hash)) {
this.logger.warning(
'Peer sent an invalid checkpoint (%s).',
peer.hostname());
@@ -2134,7 +2135,7 @@ class Pool extends EventEmitter {
*/
async addBlock(peer, block, flags) {
- const hash = block.hash('hex');
+ const hash = block.hash();
const unlock = await this.locker.lock(hash);
try {
return await this._addBlock(peer, block, flags);
@@ -2156,7 +2157,7 @@ class Pool extends EventEmitter {
if (!this.syncing)
return;
- const hash = block.hash('hex');
+ const hash = block.hash();
if (!this.resolveBlock(peer, hash)) {
this.logger.warning(
@@ -2241,7 +2242,7 @@ class Pool extends EventEmitter {
assert(node);
- if (hash !== node.hash) {
+ if (!hash.equals(node.hash)) {
this.logger.warning(
'Header hash mismatch %s != %s (%s).',
util.revHex(hash),
@@ -2365,7 +2366,7 @@ class Pool extends EventEmitter {
*/
async handleTX(peer, packet) {
- const hash = packet.tx.hash('hex');
+ const hash = packet.tx.hash();
const unlock = await this.locker.lock(hash);
try {
return await this._handleTX(peer, packet);
@@ -2385,7 +2386,7 @@ class Pool extends EventEmitter {
async _handleTX(peer, packet) {
const tx = packet.tx;
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const flags = chainCommon.flags.VERIFY_NONE;
const block = peer.merkleBlock;
@@ -2563,7 +2564,7 @@ class Pool extends EventEmitter {
*/
async handleMerkleBlock(peer, packet) {
- const hash = packet.block.hash('hex');
+ const hash = packet.block.hash();
const unlock = await this.locker.lock(hash);
try {
return await this._handleMerkleBlock(peer, packet);
@@ -2594,7 +2595,7 @@ class Pool extends EventEmitter {
}
const block = packet.block;
- const hash = block.hash('hex');
+ const hash = block.hash();
if (!peer.blockMap.has(hash)) {
this.logger.warning(
@@ -2631,7 +2632,7 @@ class Pool extends EventEmitter {
peer.merkleBlock = block;
peer.merkleTime = Date.now();
peer.merkleMatches = tree.matches.length;
- peer.merkleMap = new Set();
+ peer.merkleMap = new BufferSet();
}
/**
@@ -2668,7 +2669,7 @@ class Pool extends EventEmitter {
async handleCmpctBlock(peer, packet) {
const block = packet.block;
- const hash = block.hash('hex');
+ const hash = block.hash();
const witness = peer.compactWitness;
if (!this.syncing)
@@ -3348,7 +3349,7 @@ class Pool extends EventEmitter {
if (!this.mempool) {
// Check the TX filter if
// we don't have a mempool.
- if (!this.txFilter.added(hash, 'hex'))
+ if (!this.txFilter.added(hash))
return true;
} else {
// Check the mempool.
@@ -3447,7 +3448,7 @@ class Pool extends EventEmitter {
*/
broadcast(msg) {
- const hash = msg.hash('hex');
+ const hash = msg.hash();
let item = this.invMap.get(hash);
@@ -4231,30 +4232,28 @@ class NonceList {
*/
constructor() {
- this.map = new Map();
+ this.map = new BufferMap();
this.hosts = new Map();
}
alloc(hostname) {
for (;;) {
const nonce = common.nonce();
- const key = nonce.toString('hex');
- if (this.map.has(key))
+ if (this.map.has(nonce))
continue;
- this.map.set(key, hostname);
+ this.map.set(nonce, hostname);
assert(!this.hosts.has(hostname));
- this.hosts.set(hostname, key);
+ this.hosts.set(hostname, nonce);
return nonce;
}
}
has(nonce) {
- const key = nonce.toString('hex');
- return this.map.has(key);
+ return this.map.has(nonce);
}
remove(hostname) {
diff --git a/lib/node/http.js b/lib/node/http.js
index 2f75035dd..be1dd6046 100644
--- a/lib/node/http.js
+++ b/lib/node/http.js
@@ -168,7 +168,7 @@ class HTTP extends Server {
// UTXO by id
this.get('/coin/:hash/:index', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
const index = valid.u32('index');
enforce(hash, 'Hash is required.');
@@ -205,7 +205,7 @@ class HTTP extends Server {
// TX by hash
this.get('/tx/:hash', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
enforce(hash, 'Hash is required.');
enforce(!this.chain.options.spv, 'Cannot get TX in SPV mode.');
@@ -263,7 +263,7 @@ class HTTP extends Server {
// Block by hash/height
this.get('/block/:block', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.uintrhash('block');
+ const hash = valid.uintbrhash('block');
enforce(hash != null, 'Hash or height required.');
enforce(!this.chain.options.spv, 'Cannot get block in SPV mode.');
@@ -427,7 +427,7 @@ class HTTP extends Server {
socket.hook('get entry', async (...args) => {
const valid = new Validator(args);
- const block = valid.uintrhash(0);
+ const block = valid.uintbrhash(0);
if (block == null)
throw new Error('Invalid parameter.');
@@ -509,7 +509,7 @@ class HTTP extends Server {
socket.hook('rescan', (...args) => {
const valid = new Validator(args);
- const start = valid.uintrhash(0);
+ const start = valid.uintbrhash(0);
if (start == null)
throw new Error('Invalid parameter.');
diff --git a/lib/node/rpc.js b/lib/node/rpc.js
index ab4d221ea..f5a60df40 100644
--- a/lib/node/rpc.js
+++ b/lib/node/rpc.js
@@ -11,6 +11,7 @@ const bweb = require('bweb');
const {Lock} = require('bmutex');
const IP = require('binet');
const Validator = require('bval');
+const {BufferMap, BufferSet} = require('buffer-map');
const hash160 = require('bcrypto/lib/hash160');
const hash256 = require('bcrypto/lib/hash256');
const ccmp = require('bcrypto/lib/ccmp');
@@ -109,7 +110,7 @@ class RPC extends RPCBase {
this.boundChain = false;
this.nonce1 = 0;
this.nonce2 = 0;
- this.merkleMap = new Map();
+ this.merkleMap = new BufferMap();
this.pollers = [];
this.init();
@@ -607,7 +608,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'getblock "hash" ( verbose )');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const verbose = valid.bool(1, true);
const details = valid.bool(2, false);
@@ -701,7 +702,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'getblockheader "hash" ( verbose )');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const verbose = valid.bool(1, true);
if (!hash)
@@ -772,7 +773,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'getmempoolancestors txid (verbose)');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const verbose = valid.bool(1, false);
if (!this.mempool)
@@ -807,7 +808,7 @@ class RPC extends RPCBase {
}
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const verbose = valid.bool(1, false);
if (!this.mempool)
@@ -840,7 +841,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'getmempoolentry txid');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
if (!this.mempool)
throw new RPCError(errs.MISC_ERROR, 'No mempool available.');
@@ -887,7 +888,7 @@ class RPC extends RPCBase {
}
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const index = valid.u32(1);
const mempool = valid.bool(2, true);
@@ -931,7 +932,7 @@ class RPC extends RPCBase {
const valid = new Validator(args);
const txids = valid.array(0);
- const hash = valid.rhash(1);
+ const hash = valid.brhash(1);
if (this.chain.options.spv)
throw new RPCError(errs.MISC_ERROR, 'Cannot get coins in SPV mode.');
@@ -943,13 +944,13 @@ class RPC extends RPCBase {
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid TXIDs.');
const items = new Validator(txids);
- const set = new Set();
+ const set = new BufferSet();
const hashes = [];
let last = null;
for (let i = 0; i < txids.length; i++) {
- const hash = items.rhash(i);
+ const hash = items.brhash(i);
if (!hash)
throw new RPCError(errs.TYPE_ERROR, 'Invalid TXID.');
@@ -1007,7 +1008,7 @@ class RPC extends RPCBase {
if (!block.verify())
return [];
- const entry = await this.chain.getEntry(block.hash('hex'));
+ const entry = await this.chain.getEntry(block.hash());
if (!entry)
throw new RPCError(errs.MISC_ERROR, 'Block not found in chain.');
@@ -1016,7 +1017,7 @@ class RPC extends RPCBase {
const out = [];
for (const hash of tree.matches)
- out.push(util.revHex(hash.toString('hex')));
+ out.push(util.revHex(hash));
return out;
}
@@ -1248,7 +1249,7 @@ class RPC extends RPCBase {
const block = Block.fromRaw(data);
- if (block.prevBlock !== this.chain.tip.hash)
+ if (!block.prevBlock.equals(this.chain.tip.hash))
return 'inconclusive-not-best-prevblk';
try {
@@ -1365,7 +1366,7 @@ class RPC extends RPCBase {
}
// Build an index of every transaction.
- const index = new Map();
+ const index = new BufferMap();
for (let i = 0; i < attempt.items.length; i++) {
const entry = attempt.items[i];
index.set(entry.hash, i + 1);
@@ -1461,7 +1462,7 @@ class RPC extends RPCBase {
vbrequired: 0,
height: attempt.height,
previousblockhash: util.revHex(attempt.prevBlock),
- target: util.revHex(attempt.target.toString('hex')),
+ target: util.revHex(attempt.target),
bits: hex32(attempt.bits),
noncerange: '00000000ffffffff',
curtime: attempt.time,
@@ -1586,7 +1587,7 @@ class RPC extends RPCBase {
}
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const pri = valid.i64(1);
const fee = valid.i64(2);
@@ -1733,7 +1734,7 @@ class RPC extends RPCBase {
for (const obj of inputs) {
const valid = new Validator(obj);
- const hash = valid.rhash('txid');
+ const hash = valid.brhash('txid');
const index = valid.u32('vout');
let sequence = valid.u32('sequence', 0xffffffff);
@@ -1834,7 +1835,7 @@ class RPC extends RPCBase {
}
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const verbose = valid.bool(1, false);
if (!hash)
@@ -1905,7 +1906,7 @@ class RPC extends RPCBase {
const tx = MTX.fromRaw(data);
tx.view = await this.mempool.getSpentView(tx);
- const map = new Map();
+ const map = new BufferMap();
const keys = [];
if (secrets) {
@@ -1913,7 +1914,7 @@ class RPC extends RPCBase {
for (let i = 0; i < secrets.length; i++) {
const secret = valid.str(i, '');
const key = parseSecret(secret, this.network);
- map.set(key.getPublicKey('hex'), key);
+ map.set(key.getPublicKey(), key);
keys.push(key);
}
}
@@ -1921,7 +1922,7 @@ class RPC extends RPCBase {
if (prevout) {
for (const prev of prevout) {
const valid = new Validator(prev);
- const hash = valid.rhash('txid');
+ const hash = valid.brhash('txid');
const index = valid.u32('vout');
const scriptRaw = valid.buf('scriptPubKey');
const value = valid.ufixed('amount', 8);
@@ -1954,7 +1955,7 @@ class RPC extends RPCBase {
if (!op.data)
continue;
- const key = map.get(op.data.toString('hex'));
+ const key = map.get(op.data);
if (key) {
key.script = redeem;
@@ -2208,7 +2209,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'invalidateblock "hash"');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
if (!hash)
throw new RPCError(errs.TYPE_ERROR, 'Invalid block hash.');
@@ -2223,7 +2224,7 @@ class RPC extends RPCBase {
throw new RPCError(errs.MISC_ERROR, 'reconsiderblock "hash"');
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
if (!hash)
throw new RPCError(errs.TYPE_ERROR, 'Invalid block hash.');
@@ -2287,7 +2288,7 @@ class RPC extends RPCBase {
const hash = util.revHex(watched);
- if (this.chain.tip.hash !== hash)
+ if (!this.chain.tip.hash.equals(hash))
return;
await this.longpoll();
@@ -2376,9 +2377,8 @@ class RPC extends RPCBase {
const n2 = this.nonce2;
const root = attempt.getRoot(n1, n2);
- const hash = root.toString('hex');
- this.merkleMap.set(hash, [n1, n2]);
+ this.merkleMap.set(root, [n1, n2]);
return attempt;
}
@@ -2394,11 +2394,10 @@ class RPC extends RPCBase {
const n2 = this.nonce2;
const root = attempt.getRoot(n1, n2);
- const hash = root.toString('hex');
this.attempt = attempt;
this.lastActivity = util.now();
- this.merkleMap.set(hash, [n1, n2]);
+ this.merkleMap.set(root, [n1, n2]);
return attempt;
}
@@ -2704,7 +2703,7 @@ class RPC extends RPCBase {
bits: entry.bits,
difficulty: toDifficulty(entry.bits),
chainwork: entry.chainwork.toString('hex', 64),
- previousblockhash: entry.prevBlock !== consensus.NULL_HASH
+ previousblockhash: !entry.prevBlock.equals(consensus.ZERO_HASH)
? util.revHex(entry.prevBlock)
: null,
nextblockhash: next ? util.revHex(next) : null
@@ -2742,7 +2741,7 @@ class RPC extends RPCBase {
bits: entry.bits,
difficulty: toDifficulty(entry.bits),
chainwork: entry.chainwork.toString('hex', 64),
- previousblockhash: entry.prevBlock !== consensus.NULL_HASH
+ previousblockhash: !entry.prevBlock.equals(consensus.ZERO_HASH)
? util.revHex(entry.prevBlock)
: null,
nextblockhash: next ? util.revHex(next) : null
diff --git a/lib/primitives/abstractblock.js b/lib/primitives/abstractblock.js
index 0559a65df..84ba06743 100644
--- a/lib/primitives/abstractblock.js
+++ b/lib/primitives/abstractblock.js
@@ -35,8 +35,8 @@ class AbstractBlock {
constructor() {
this.version = 1;
- this.prevBlock = consensus.NULL_HASH;
- this.merkleRoot = consensus.NULL_HASH;
+ this.prevBlock = consensus.ZERO_HASH;
+ this.merkleRoot = consensus.ZERO_HASH;
this.time = 0;
this.bits = 0;
this.nonce = 0;
@@ -56,8 +56,8 @@ class AbstractBlock {
parseOptions(options) {
assert(options, 'Block data is required.');
assert((options.version >>> 0) === options.version);
- assert(typeof options.prevBlock === 'string');
- assert(typeof options.merkleRoot === 'string');
+ assert(Buffer.isBuffer(options.prevBlock));
+ assert(Buffer.isBuffer(options.merkleRoot));
assert((options.time >>> 0) === options.time);
assert((options.bits >>> 0) === options.bits);
assert((options.nonce >>> 0) === options.nonce);
@@ -93,8 +93,8 @@ class AbstractBlock {
assert((json.nonce >>> 0) === json.nonce);
this.version = json.version;
- this.prevBlock = util.revHex(json.prevBlock);
- this.merkleRoot = util.revHex(json.merkleRoot);
+ this.prevBlock = util.fromRev(json.prevBlock);
+ this.merkleRoot = util.fromRev(json.merkleRoot);
this.time = json.time;
this.bits = json.bits;
this.nonce = json.nonce;
@@ -197,8 +197,8 @@ class AbstractBlock {
readHead(br) {
this.version = br.readU32();
- this.prevBlock = br.readHash('hex');
- this.merkleRoot = br.readHash('hex');
+ this.prevBlock = br.readHash();
+ this.merkleRoot = br.readHash();
this.time = br.readU32();
this.bits = br.readU32();
this.nonce = br.readU32();
@@ -244,7 +244,7 @@ class AbstractBlock {
*/
rhash() {
- return util.revHex(this.hash('hex'));
+ return util.revHex(this.hash());
}
/**
@@ -253,7 +253,7 @@ class AbstractBlock {
*/
toInv() {
- return new InvItem(InvItem.types.BLOCK, this.hash('hex'));
+ return new InvItem(InvItem.types.BLOCK, this.hash());
}
}
diff --git a/lib/primitives/address.js b/lib/primitives/address.js
index f2c4799a4..fb0cbbd3b 100644
--- a/lib/primitives/address.js
+++ b/lib/primitives/address.js
@@ -82,7 +82,7 @@ class Address {
getHash(enc) {
if (enc === 'hex')
- return this.hash.toString(enc);
+ return this.hash.toString('hex');
return this.hash;
}
@@ -560,9 +560,6 @@ class Address {
*/
fromHash(hash, type, version) {
- if (typeof hash === 'string')
- hash = Buffer.from(hash, 'hex');
-
if (typeof type === 'string') {
type = Address.types[type.toUpperCase()];
assert(type != null, 'Not a valid address type.');
@@ -719,9 +716,6 @@ class Address {
assert(version >= 0, 'Bad version for witness program.');
- if (typeof hash === 'string')
- hash = Buffer.from(hash, 'hex');
-
return this.fromHash(hash, type, version);
}
@@ -804,18 +798,13 @@ class Address {
* @returns {Hash}
*/
- static getHash(data, enc, network) {
+ static getHash(data, network) {
if (!data)
throw new Error('Object is not an address.');
let hash;
- if (typeof data === 'string') {
- if (data.length === 40 || data.length === 64)
- return enc === 'hex' ? data : Buffer.from(data, 'hex');
-
- hash = Address.fromString(data, network).hash;
- } else if (Buffer.isBuffer(data)) {
+ if (Buffer.isBuffer(data)) {
if (data.length !== 20 && data.length !== 32)
throw new Error('Object is not an address.');
hash = data;
@@ -825,9 +814,7 @@ class Address {
throw new Error('Object is not an address.');
}
- return enc === 'hex'
- ? hash.toString('hex')
- : hash;
+ return hash;
}
/**
diff --git a/lib/primitives/block.js b/lib/primitives/block.js
index f620df724..be3462a61 100644
--- a/lib/primitives/block.js
+++ b/lib/primitives/block.js
@@ -260,7 +260,7 @@ class Block extends AbstractBlock {
indexOf(hash) {
for (let i = 0; i < this.txs.length; i++) {
const tx = this.txs[i];
- if (tx.hash('hex') === hash)
+ if (tx.hash().equals(hash))
return i;
}
@@ -337,8 +337,8 @@ class Block extends AbstractBlock {
getMerkleRoot(enc) {
if (enc === 'hex')
- return this.merkleRoot;
- return Buffer.from(this.merkleRoot, 'hex');
+ return this.merkleRoot.toString('hex');
+ return this.merkleRoot;
}
/**
@@ -428,14 +428,14 @@ class Block extends AbstractBlock {
return [false, 'bad-cb-missing', 100];
// Check merkle root.
- const root = this.createMerkleRoot('hex');
+ const root = this.createMerkleRoot();
// If the merkle is mutated,
// we have duplicate txs.
if (!root)
return [false, 'bad-txns-duplicate', 100];
- if (this.merkleRoot !== root)
+ if (!this.merkleRoot.equals(root))
return [false, 'bad-txnmrklroot', 100];
// Test all transactions.
diff --git a/lib/primitives/coin.js b/lib/primitives/coin.js
index f51d19f37..9c777b8ba 100644
--- a/lib/primitives/coin.js
+++ b/lib/primitives/coin.js
@@ -42,7 +42,7 @@ class Coin extends Output {
this.version = 1;
this.height = -1;
this.coinbase = false;
- this.hash = consensus.NULL_HASH;
+ this.hash = consensus.ZERO_HASH;
this.index = 0;
if (options)
@@ -90,7 +90,7 @@ class Coin extends Output {
}
if (options.hash != null) {
- assert(typeof options.hash === 'string', 'Hash must be a string.');
+ assert(Buffer.isBuffer(options.hash));
this.hash = options.hash;
}
@@ -152,7 +152,7 @@ class Coin extends Output {
*/
toKey() {
- return this.hash + this.index;
+ return this.toRaw();
}
/**
@@ -163,10 +163,7 @@ class Coin extends Output {
*/
fromKey(key) {
- assert(key.length > 64);
- this.hash = key.slice(0, 64);
- this.index = parseInt(key.slice(64), 10);
- return this;
+ return this.fromRaw(key);
}
/**
@@ -281,7 +278,7 @@ class Coin extends Output {
assert(typeof json.hash === 'string', 'Hash must be a string.');
assert(json.hash.length === 64, 'Hash must be a string.');
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
- this.hash = util.revHex(json.hash);
+ this.hash = util.fromRev(json.hash);
this.index = json.index;
}
@@ -404,7 +401,7 @@ class Coin extends Output {
this.value = tx.outputs[index].value;
this.script = tx.outputs[index].script;
this.coinbase = tx.isCoinbase();
- this.hash = tx.hash('hex');
+ this.hash = tx.hash();
this.index = index;
return this;
}
diff --git a/lib/primitives/headers.js b/lib/primitives/headers.js
index 1e52440a5..14b3e35b3 100644
--- a/lib/primitives/headers.js
+++ b/lib/primitives/headers.js
@@ -145,7 +145,7 @@ class Headers extends AbstractBlock {
headers.time = entry.time;
headers.bits = entry.bits;
headers.nonce = entry.nonce;
- headers._hash = Buffer.from(entry.hash, 'hex');
+ headers._hash = entry.hash;
headers._hhash = entry.hash;
return headers;
}
diff --git a/lib/primitives/input.js b/lib/primitives/input.js
index b8ad59cfe..a53b6d7bd 100644
--- a/lib/primitives/input.js
+++ b/lib/primitives/input.js
@@ -442,7 +442,7 @@ class Input {
*/
fromOutpoint(outpoint) {
- assert(typeof outpoint.hash === 'string');
+ assert(Buffer.isBuffer(outpoint.hash));
assert(typeof outpoint.index === 'number');
this.prevout.hash = outpoint.hash;
this.prevout.index = outpoint.index;
@@ -466,7 +466,7 @@ class Input {
*/
fromCoin(coin) {
- assert(typeof coin.hash === 'string');
+ assert(Buffer.isBuffer(coin.hash));
assert(typeof coin.index === 'number');
this.prevout.hash = coin.hash;
this.prevout.index = coin.index;
@@ -494,7 +494,7 @@ class Input {
assert(tx);
assert(typeof index === 'number');
assert(index >= 0 && index < tx.outputs.length);
- this.prevout.hash = tx.hash('hex');
+ this.prevout.hash = tx.hash();
this.prevout.index = index;
return this;
}
diff --git a/lib/primitives/invitem.js b/lib/primitives/invitem.js
index 5a8af709d..e00f59a5a 100644
--- a/lib/primitives/invitem.js
+++ b/lib/primitives/invitem.js
@@ -68,7 +68,7 @@ class InvItem {
fromReader(br) {
this.type = br.readU32();
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
return this;
}
diff --git a/lib/primitives/merkleblock.js b/lib/primitives/merkleblock.js
index db36514b5..af0176bf2 100644
--- a/lib/primitives/merkleblock.js
+++ b/lib/primitives/merkleblock.js
@@ -9,6 +9,7 @@
const assert = require('assert');
const bio = require('bufio');
+const {BufferMap, BufferSet} = require('buffer-map');
const util = require('../utils/util');
const hash256 = require('bcrypto/lib/hash256');
const consensus = require('../protocol/consensus');
@@ -60,9 +61,7 @@ class MerkleBlock extends AbstractBlock {
assert((options.totalTX >>> 0) === options.totalTX);
if (options.hashes) {
- for (let hash of options.hashes) {
- if (typeof hash === 'string')
- hash = Buffer.from(hash, 'hex');
+ for (const hash of options.hashes) {
assert(Buffer.isBuffer(hash));
this.hashes.push(hash);
}
@@ -153,7 +152,7 @@ class MerkleBlock extends AbstractBlock {
checkBody() {
const tree = this.getTree();
- if (tree.root !== this.merkleRoot)
+ if (!tree.root.equals(this.merkleRoot))
return [false, 'bad-txnmrklroot', 100];
return [true, 'valid', 0];
@@ -186,7 +185,7 @@ class MerkleBlock extends AbstractBlock {
extractTree() {
const matches = [];
const indexes = [];
- const map = new Map();
+ const map = new BufferMap();
const hashes = this.hashes;
const flags = this.flags;
const totalTX = this.totalTX;
@@ -221,10 +220,9 @@ class MerkleBlock extends AbstractBlock {
hashUsed += 1;
if (height === 0 && parent) {
- const txid = hash.toString('hex');
matches.push(hash);
indexes.push(pos);
- map.set(txid, pos);
+ map.set(hash, pos);
}
return hash;
@@ -455,7 +453,7 @@ class MerkleBlock extends AbstractBlock {
nonce: this.nonce,
totalTX: this.totalTX,
hashes: this.hashes.map((hash) => {
- return util.revHex(hash.toString('hex'));
+ return util.revHex(hash);
}),
flags: this.flags.toString('hex')
};
@@ -475,10 +473,8 @@ class MerkleBlock extends AbstractBlock {
this.parseJSON(json);
- for (let hash of json.hashes) {
- hash = util.revHex(hash);
- this.hashes.push(Buffer.from(hash, 'hex'));
- }
+ for (const hash of json.hashes)
+ this.hashes.push(util.fromRev(hash));
this.flags = Buffer.from(json.flags, 'hex');
@@ -524,18 +520,15 @@ class MerkleBlock extends AbstractBlock {
*/
static fromHashes(block, hashes) {
- const filter = new Set();
+ const filter = new BufferSet();
- for (let hash of hashes) {
- if (Buffer.isBuffer(hash))
- hash = hash.toString('hex');
+ for (const hash of hashes)
filter.add(hash);
- }
const matches = [];
for (const tx of block.txs) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
matches.push(filter.has(hash) ? 1 : 0);
}
@@ -659,10 +652,10 @@ class MerkleBlock extends AbstractBlock {
class PartialTree {
constructor(root, matches, indexes, map) {
- this.root = root ? root.toString('hex') : consensus.NULL_HASH;
+ this.root = root || consensus.ZERO_HASH;
this.matches = matches || [];
this.indexes = indexes || [];
- this.map = map || new Map();
+ this.map = map || new BufferMap();
}
}
diff --git a/lib/primitives/mtx.js b/lib/primitives/mtx.js
index d20a507cc..4362f084d 100644
--- a/lib/primitives/mtx.js
+++ b/lib/primitives/mtx.js
@@ -9,6 +9,7 @@
const assert = require('assert');
const {encoding} = require('bufio');
+const {BufferMap} = require('buffer-map');
const Script = require('../script/script');
const TX = require('./tx');
const Input = require('./input');
@@ -1478,7 +1479,7 @@ class MTX extends TX {
const coin = Coin.fromJSON(input.coin);
- coin.hash = util.revHex(prevout.hash);
+ coin.hash = util.fromRev(prevout.hash);
coin.index = prevout.index;
this.view.addCoin(coin);
@@ -1592,7 +1593,7 @@ class CoinSelector {
this.maxFee = -1;
this.round = false;
this.changeAddress = null;
- this.inputs = new Map();
+ this.inputs = new BufferMap();
// Needed for size estimation.
this.estimate = null;
@@ -1696,7 +1697,7 @@ class CoinSelector {
const prevout = options.inputs[i];
assert(prevout && typeof prevout === 'object');
const {hash, index} = prevout;
- assert(typeof hash === 'string');
+ assert(Buffer.isBuffer(hash));
assert(typeof index === 'number');
this.inputs.set(Outpoint.toKey(hash, index), i);
}
diff --git a/lib/primitives/outpoint.js b/lib/primitives/outpoint.js
index f9c39270b..a037de044 100644
--- a/lib/primitives/outpoint.js
+++ b/lib/primitives/outpoint.js
@@ -28,11 +28,11 @@ class Outpoint {
*/
constructor(hash, index) {
- this.hash = consensus.NULL_HASH;
+ this.hash = consensus.ZERO_HASH;
this.index = 0xffffffff;
if (hash != null) {
- assert(typeof hash === 'string', 'Hash must be a string.');
+ assert(Buffer.isBuffer(hash));
assert((index >>> 0) === index, 'Index must be a uint32.');
this.hash = hash;
this.index = index;
@@ -47,7 +47,7 @@ class Outpoint {
fromOptions(options) {
assert(options, 'Outpoint data is required.');
- assert(typeof options.hash === 'string', 'Hash must be a string.');
+ assert(Buffer.isBuffer(options.hash));
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
this.hash = options.hash;
this.index = options.index;
@@ -84,7 +84,7 @@ class Outpoint {
equals(prevout) {
assert(Outpoint.isOutpoint(prevout));
- return this.hash === prevout.hash
+ return this.hash.equals(prevout.hash)
&& this.index === prevout.index;
}
@@ -112,7 +112,7 @@ class Outpoint {
*/
isNull() {
- return this.index === 0xffffffff && this.hash === consensus.NULL_HASH;
+ return this.index === 0xffffffff && this.hash.equals(consensus.ZERO_HASH);
}
/**
@@ -140,7 +140,7 @@ class Outpoint {
*/
toKey() {
- return Outpoint.toKey(this.hash, this.index);
+ return this.toRaw();
}
/**
@@ -151,9 +151,8 @@ class Outpoint {
*/
fromKey(key) {
- assert(key.length > 64);
- this.hash = key.slice(0, 64);
- this.index = parseInt(key.slice(64), 10);
+ this.hash = key.slice(0, 32);
+ this.index = bio.readU32(key, 32);
return this;
}
@@ -203,7 +202,7 @@ class Outpoint {
*/
fromReader(br) {
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
this.index = br.readU32();
return this;
}
@@ -248,7 +247,7 @@ class Outpoint {
assert(json, 'Outpoint data is required.');
assert(typeof json.hash === 'string', 'Hash must be a string.');
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
- this.hash = util.revHex(json.hash);
+ this.hash = util.fromRev(json.hash);
this.index = json.index;
return this;
}
@@ -289,7 +288,7 @@ class Outpoint {
assert(tx);
assert(typeof index === 'number');
assert(index >= 0);
- this.hash = tx.hash('hex');
+ this.hash = tx.hash();
this.index = index;
return this;
}
@@ -314,10 +313,7 @@ class Outpoint {
*/
static toKey(hash, index) {
- assert(typeof hash === 'string');
- assert(hash.length === 64);
- assert(index >= 0);
- return hash + index;
+ return new Outpoint(hash, index).toKey();
}
/**
diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js
index 09051c33a..39cdefe6c 100644
--- a/lib/primitives/tx.js
+++ b/lib/primitives/tx.js
@@ -11,6 +11,7 @@ const assert = require('assert');
const bio = require('bufio');
const hash256 = require('bcrypto/lib/hash256');
const secp256k1 = require('bcrypto/lib/secp256k1');
+const {BufferSet} = require('buffer-map');
const util = require('../utils/util');
const Amount = require('../btc/amount');
const Network = require('../protocol/network');
@@ -1005,7 +1006,7 @@ class TX {
*/
_getInputAddresses(view) {
- const table = Object.create(null);
+ const table = new BufferSet();
const addrs = [];
if (this.isCoinbase())
@@ -1018,10 +1019,10 @@ class TX {
if (!addr)
continue;
- const hash = addr.getHash('hex');
+ const hash = addr.getHash();
- if (!table[hash]) {
- table[hash] = true;
+ if (!table.has(hash)) {
+ table.add(hash);
addrs.push(addr);
}
}
@@ -1036,7 +1037,7 @@ class TX {
*/
_getOutputAddresses() {
- const table = Object.create(null);
+ const table = new BufferSet();
const addrs = [];
for (const output of this.outputs) {
@@ -1045,10 +1046,10 @@ class TX {
if (!addr)
continue;
- const hash = addr.getHash('hex');
+ const hash = addr.getHash();
- if (!table[hash]) {
- table[hash] = true;
+ if (!table.has(hash)) {
+ table.add(hash);
addrs.push(addr);
}
}
@@ -1068,10 +1069,10 @@ class TX {
const output = this.getOutputAddresses();
for (const addr of output) {
- const hash = addr.getHash('hex');
+ const hash = addr.getHash();
- if (!table[hash]) {
- table[hash] = true;
+ if (!table.has(hash)) {
+ table.add(hash);
addrs.push(addr);
}
}
@@ -1118,18 +1119,12 @@ class TX {
*/
getInputHashes(view, enc) {
- if (enc === 'hex') {
- const [, table] = this._getInputAddresses(view);
- return Object.keys(table);
- }
-
- const addrs = this.getInputAddresses(view);
- const hashes = [];
+ const [, table] = this._getInputAddresses(view);
- for (const addr of addrs)
- hashes.push(addr.getHash());
+ if (enc !== 'hex')
+ return table.toArray();
- return hashes;
+ return table.toArray().map(h => h.toString('hex'));
}
/**
@@ -1138,18 +1133,12 @@ class TX {
*/
getOutputHashes(enc) {
- if (enc === 'hex') {
- const [, table] = this._getOutputAddresses();
- return Object.keys(table);
- }
+ const [, table] = this._getOutputAddresses();
- const addrs = this.getOutputAddresses();
- const hashes = [];
+ if (enc !== 'hex')
+ return table.toArray();
- for (const addr of addrs)
- hashes.push(addr.getHash());
-
- return hashes;
+ return table.toArray().map(h => h.toString('hex'));
}
/**
@@ -1159,18 +1148,12 @@ class TX {
*/
getHashes(view, enc) {
- if (enc === 'hex') {
- const [, table] = this._getAddresses(view);
- return Object.keys(table);
- }
-
- const addrs = this.getAddresses(view);
- const hashes = [];
+ const [, table] = this._getAddresses(view);
- for (const addr of addrs)
- hashes.push(addr.getHash());
+ if (enc !== 'hex')
+ return table.toArray();
- return hashes;
+ return table.toArray().map(h => h.toString('hex'));
}
/**
@@ -1448,7 +1431,7 @@ class TX {
return [false, 'bad-txns-txouttotal-toolarge', 100];
}
- const prevout = new Set();
+ const prevout = new BufferSet();
for (const input of this.inputs) {
const key = input.prevout.toKey();
@@ -1940,12 +1923,12 @@ class TX {
if (this.isCoinbase())
return [];
- const prevout = Object.create(null);
+ const prevout = new BufferSet();
for (const input of this.inputs)
- prevout[input.prevout.hash] = true;
+ prevout.add(input.prevout.hash);
- return Object.keys(prevout);
+ return prevout.toArray();
}
/**
@@ -2012,7 +1995,7 @@ class TX {
*/
rhash() {
- return util.revHex(this.hash('hex'));
+ return util.revHex(this.hash());
}
/**
@@ -2021,7 +2004,7 @@ class TX {
*/
rwhash() {
- return util.revHex(this.witnessHash('hex'));
+ return util.revHex(this.witnessHash());
}
/**
@@ -2048,7 +2031,7 @@ class TX {
*/
toInv() {
- return new InvItem(InvItem.types.TX, this.hash('hex'));
+ return new InvItem(InvItem.types.TX, this.hash());
}
/**
diff --git a/lib/primitives/txmeta.js b/lib/primitives/txmeta.js
index 8b725c193..0aa03a3ed 100644
--- a/lib/primitives/txmeta.js
+++ b/lib/primitives/txmeta.js
@@ -59,7 +59,7 @@ class TXMeta {
}
if (options.block !== undefined) {
- assert(options.block === null || typeof options.block === 'string');
+ assert(options.block == null || Buffer.isBuffer(options.block));
this.block = options.block;
}
@@ -184,7 +184,7 @@ class TXMeta {
this.mtime = json.mtime;
this.height = json.height;
- this.block = util.revHex(json.block);
+ this.block = util.fromRev(json.block);
this.index = json.index;
return this;
@@ -267,7 +267,7 @@ class TXMeta {
this.mtime = br.readU32();
if (br.readU8() === 1) {
- this.block = br.readHash('hex');
+ this.block = br.readHash();
this.height = br.readU32();
this.time = br.readU32();
this.index = br.readU32();
diff --git a/lib/protocol/consensus.js b/lib/protocol/consensus.js
index 36f8e0729..5e1625638 100644
--- a/lib/protocol/consensus.js
+++ b/lib/protocol/consensus.js
@@ -234,15 +234,6 @@ exports.BIP16_TIME = 1333238400;
exports.ZERO_HASH = Buffer.alloc(32, 0x00);
-/**
- * A hash of all zeroes.
- * @const {String}
- * @default
- */
-
-exports.NULL_HASH =
- '0000000000000000000000000000000000000000000000000000000000000000';
-
/**
* Convert a compact number to a big number.
* Used for `block.bits` -> `target` conversion.
diff --git a/lib/protocol/errors.js b/lib/protocol/errors.js
index 2cdef39d2..030717bdb 100644
--- a/lib/protocol/errors.js
+++ b/lib/protocol/errors.js
@@ -52,7 +52,7 @@ class VerifyError extends Error {
this.code = code;
this.reason = reason;
this.score = score;
- this.hash = msg.hash('hex');
+ this.hash = msg.hash();
this.malleated = malleated || false;
this.message = `Verification failure: ${reason}`
diff --git a/lib/protocol/networks.js b/lib/protocol/networks.js
index 19df6b579..63e81668a 100644
--- a/lib/protocol/networks.js
+++ b/lib/protocol/networks.js
@@ -15,6 +15,14 @@ const BN = require('bn.js');
const network = exports;
+/*
+ * Helpers
+ */
+
+function b(hash) {
+ return Buffer.from(hash, 'hex');
+}
+
/**
* Network type list.
* @memberof module:protocol/networks
@@ -78,35 +86,35 @@ main.port = 8333;
*/
main.checkpointMap = {
- 11111: '1d7c6eb2fd42f55925e92efad68b61edd22fba29fde8783df744e26900000000',
- 33333: 'a6d0b5df7d0df069ceb1e736a216ad187a50b07aaa4e78748a58d52d00000000',
- 74000: '201a66b853f9e7814a820e2af5f5dc79c07144e31ce4c9a39339570000000000',
- 105000: '97dc6b1d15fbeef373a744fee0b254b0d2c820a3ae7f0228ce91020000000000',
- 134444: 'feb0d2420d4a18914c81ac30f494a5d4ff34cd15d34cfd2fb105000000000000',
- 168000: '63b703835cb735cb9a89d733cbe66f212f63795e0172ea619e09000000000000',
- 193000: '17138bca83bdc3e6f60f01177c3877a98266de40735f2a459f05000000000000',
- 210000: '2e3471a19b8e22b7f939c63663076603cf692f19837e34958b04000000000000',
- 216116: '4edf231bf170234e6a811460f95c94af9464e41ee833b4f4b401000000000000',
- 225430: '32595730b165f097e7b806a679cf7f3e439040f750433808c101000000000000',
- 250000: '14d2f24d29bed75354f3f88a5fb50022fc064b02291fdf873800000000000000',
- 279000: '407ebde958e44190fa9e810ea1fc3a7ef601c3b0a0728cae0100000000000000',
- 295000: '83a93246c67003105af33ae0b29dd66f689d0f0ff54e9b4d0000000000000000',
- 300255: 'b2f3a0f0de4120c1089d5f5280a263059f9b6e7c520428160000000000000000',
- 319400: '3bf115fd057391587ca39a531c5d4989e1adec9b2e05c6210000000000000000',
- 343185: '548536d48e7678fcfa034202dd45d4a76b1ad061f38b2b070000000000000000',
- 352940: 'ffc9520143e41c94b6e03c2fa3e62bb76b55ba2df45d75100000000000000000',
- 382320: 'b28afdde92b0899715e40362f56afdb20e3d135bedc68d0a0000000000000000',
- 401465: 'eed16cb3e893ed9366f27c39a9ecd95465d02e3ef40e45010000000000000000',
- 420000: 'a1ff746b2d42b834cb7d6b8981b09c265c2cabc016e8cc020000000000000000',
- 440000: '9bf296b8de5f834f7635d5e258a434ad51b4dbbcf7c08c030000000000000000',
- 450000: '0ba2070c62cd9da1f8cef88a0648c661a411d33e728340010000000000000000',
- 460000: '8c25fc7e414d3e868d6ce0ec473c30ad44e7e8bc1b75ef000000000000000000',
- 470000: '89756d1ed75901437300af10d5ab69070a282e729c536c000000000000000000',
- 480000: 'b1a896fd31e639e0c74d1abeb1dbc93f176b767a5d4c02010000000000000000',
- 490000: '90dec4d0153f20fbdcb245b1d5fb3d5a8d7bb1379106de000000000000000000',
- 500000: '045d94a1c33354c3759cc0512dcc49fd81bf4c3637fb24000000000000000000',
- 510000: '297301b8ca28584cb0c31c7e3fed51696bc33ef8782615000000000000000000',
- 525000: '1dde8e3fb49bbd5ab66a1b847544d67fff10b108a1fa2f000000000000000000'
+ 11111: b('1d7c6eb2fd42f55925e92efad68b61edd22fba29fde8783df744e26900000000'),
+ 33333: b('a6d0b5df7d0df069ceb1e736a216ad187a50b07aaa4e78748a58d52d00000000'),
+ 74000: b('201a66b853f9e7814a820e2af5f5dc79c07144e31ce4c9a39339570000000000'),
+ 105000: b('97dc6b1d15fbeef373a744fee0b254b0d2c820a3ae7f0228ce91020000000000'),
+ 134444: b('feb0d2420d4a18914c81ac30f494a5d4ff34cd15d34cfd2fb105000000000000'),
+ 168000: b('63b703835cb735cb9a89d733cbe66f212f63795e0172ea619e09000000000000'),
+ 193000: b('17138bca83bdc3e6f60f01177c3877a98266de40735f2a459f05000000000000'),
+ 210000: b('2e3471a19b8e22b7f939c63663076603cf692f19837e34958b04000000000000'),
+ 216116: b('4edf231bf170234e6a811460f95c94af9464e41ee833b4f4b401000000000000'),
+ 225430: b('32595730b165f097e7b806a679cf7f3e439040f750433808c101000000000000'),
+ 250000: b('14d2f24d29bed75354f3f88a5fb50022fc064b02291fdf873800000000000000'),
+ 279000: b('407ebde958e44190fa9e810ea1fc3a7ef601c3b0a0728cae0100000000000000'),
+ 295000: b('83a93246c67003105af33ae0b29dd66f689d0f0ff54e9b4d0000000000000000'),
+ 300255: b('b2f3a0f0de4120c1089d5f5280a263059f9b6e7c520428160000000000000000'),
+ 319400: b('3bf115fd057391587ca39a531c5d4989e1adec9b2e05c6210000000000000000'),
+ 343185: b('548536d48e7678fcfa034202dd45d4a76b1ad061f38b2b070000000000000000'),
+ 352940: b('ffc9520143e41c94b6e03c2fa3e62bb76b55ba2df45d75100000000000000000'),
+ 382320: b('b28afdde92b0899715e40362f56afdb20e3d135bedc68d0a0000000000000000'),
+ 401465: b('eed16cb3e893ed9366f27c39a9ecd95465d02e3ef40e45010000000000000000'),
+ 420000: b('a1ff746b2d42b834cb7d6b8981b09c265c2cabc016e8cc020000000000000000'),
+ 440000: b('9bf296b8de5f834f7635d5e258a434ad51b4dbbcf7c08c030000000000000000'),
+ 450000: b('0ba2070c62cd9da1f8cef88a0648c661a411d33e728340010000000000000000'),
+ 460000: b('8c25fc7e414d3e868d6ce0ec473c30ad44e7e8bc1b75ef000000000000000000'),
+ 470000: b('89756d1ed75901437300af10d5ab69070a282e729c536c000000000000000000'),
+ 480000: b('b1a896fd31e639e0c74d1abeb1dbc93f176b767a5d4c02010000000000000000'),
+ 490000: b('90dec4d0153f20fbdcb245b1d5fb3d5a8d7bb1379106de000000000000000000'),
+ 500000: b('045d94a1c33354c3759cc0512dcc49fd81bf4c3637fb24000000000000000000'),
+ 510000: b('297301b8ca28584cb0c31c7e3fed51696bc33ef8782615000000000000000000'),
+ 525000: b('1dde8e3fb49bbd5ab66a1b847544d67fff10b108a1fa2f000000000000000000')
};
/**
@@ -131,10 +139,11 @@ main.halvingInterval = 210000;
main.genesis = {
version: 1,
- hash: '6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000',
- prevBlock: '0000000000000000000000000000000000000000000000000000000000000000',
+ hash: b('6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000'),
+ prevBlock:
+ b('0000000000000000000000000000000000000000000000000000000000000000'),
merkleRoot:
- '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a',
+ b('3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'),
time: 1231006505,
bits: 486604799,
nonce: 2083236893,
@@ -252,7 +261,8 @@ main.block = {
* Hash of the block that activated bip34.
*/
- bip34hash: 'b808089c756add1591b1d17bab44bba3fed9e02f942ab4894b02000000000000',
+ bip34hash:
+ b('b808089c756add1591b1d17bab44bba3fed9e02f942ab4894b02000000000000'),
/**
* Height at which bip65 was activated.
@@ -264,7 +274,8 @@ main.block = {
* Hash of the block that activated bip65.
*/
- bip65hash: 'f035476cfaeb9f677c2cdad00fd908c556775ded24b6c2040000000000000000',
+ bip65hash:
+ b('f035476cfaeb9f677c2cdad00fd908c556775ded24b6c2040000000000000000'),
/**
* Height at which bip66 was activated.
@@ -276,7 +287,8 @@ main.block = {
* Hash of the block that activated bip66.
*/
- bip66hash: '3109b588941188a9f1c2576aae462d729b8cce9da1ea79030000000000000000',
+ bip66hash:
+ b('3109b588941188a9f1c2576aae462d729b8cce9da1ea79030000000000000000'),
/**
* Safe height to start pruning.
@@ -314,8 +326,8 @@ main.block = {
*/
main.bip30 = {
- 91842: 'eccae000e3c8e4e093936360431f3b7603c563c1ff6181390a4d0a0000000000',
- 91880: '21d77ccb4c08386a04ac0196ae10f6a1d2c2a377558ca190f143070000000000'
+ 91842: b('eccae000e3c8e4e093936360431f3b7603c563c1ff6181390a4d0a0000000000'),
+ 91880: b('21d77ccb4c08386a04ac0196ae10f6a1d2c2a377558ca190f143070000000000')
};
/**
@@ -508,39 +520,40 @@ testnet.magic = 0x0709110b;
testnet.port = 18333;
testnet.checkpointMap = {
- 546: '70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000',
- 10000: '02a1b43f52591e53b660069173ac83b675798e12599dbb0442b7580000000000',
- 50000: '0c6ceabe803cec55ba2831e445956d0a43ba9521743a802cddac7e0700000000',
- 90000: 'cafc21e17faf90461a5905aa03302c394912651ed9475ae711723e0d00000000',
- 100000: '1e0a16bbadccde1d80c66597b1939e45f91b570d29f95fc158299e0000000000',
- 140000: '92c0877b54c556889b72175ccbe0c91a1208f6ef7efb2c006101062300000000',
- 170000: '508125560d202b89757889bb0e49c712477be20440058f05db4f0e0000000000',
- 210000: '32365454b5f29a826bff8ad9b0448cad0072fc73d50e482d91a3dece00000000',
- 230000: 'b11a447e62643e0b27406eb0fc270cb8126d7b5b70822fb642d9513400000000',
- 270000: '1c42b811cf9c163932f6e95ec55bf9b5e2cb5324e7e93001572e000000000000',
- 300000: 'a141bf3972424853f04367b47995e220e0b5a2706e5618766f22000000000000',
- 340000: '67edd4d92e405608109164b15f92b193377d49325b0ed036739c010000000000',
- 350000: '592b44bc0f7a4286cf07ead8497114c6952c1c7dea7305193deacf8e00000000',
- 390000: 'f217e183484fb6d695609cc71fa2ae24c3020943407e0150b298030000000000',
- 420000: 'de9e73a3b91fbb014e036e8583a17d6b638a699aeb2de8573d12580800000000',
- 460000: '2e8baaffc107f15c87aebe01664b63d07476afa53bcbada1281a030000000000',
- 500000: '06f60922a2aab2757317820fc6ffaf6a470e2cbb0f63a2aac0a7010000000000',
- 540000: '8dd0bebfbc4878f5af09d3e848dcc57827d2c1cebea8ec5d8cbe420500000000',
- 570000: '87acbd4cd3c40ec9bd648f8698ed226b31187274c06cc7a9af79030000000000',
- 600000: '169a05b3bb04b7d13ad628915630900a5ed2e89f3a9dc6064f62000000000000',
- 630000: 'bbbe117035432a6a4effcb297207a02b031735b43e0d19a9217c000000000000',
- 670000: '080bfe75caed8624fcfdfbc65973c8f962d7bdc495a891f5d16b7d0000000000',
- 700000: 'c14d3f6a1e7c7d66fd940951e44f3c3be1273bea4d2ab1786140000000000000',
- 740000: 'b3b423f0462fd78a01e4f1a59a2737a0525b5dbb9bba0b4634f9000000000000',
- 780000: '0381582e34c3755964dc2813e2b33e521e5596367144e1670851050000000000',
- 800000: '03b5f8ab257e02903f509f5ff2935220eec2e77b1819651d099b200000000000',
- 840000: 'dac1648107bd4394e57e4083c86d42b548b1cfb119665f179ea80a0000000000',
- 880000: 'ff90b4bb07eded8e96715bf595c09c7d21dd8c61b8306ff48705d60000000000',
- 900000: '9bd8ac418beeb1a2cf5d68c8b5c6ebaa947a5b766e5524898d6f350000000000',
- 940000: 'c98f1651a475b00d12f8c25eb166ee843affaa90610e36a19d68030000000000',
- 980000: 'cc8e9774542d044a9698ca2336ae02d5987157e676f1c76aa3877c0000000000',
- 1010000: '9d9fb11abc2712d80368229e97b8d827b2a07d27eb5335e5c924000000000000',
- 1050000: 'd8190cf0af7f08e179cab51d67db0b44b87951a78f7fdc31b4a01a0000000000'
+ 546: b('70cb6af7ebbcb1315d3414029c556c55f3e2fc353c4c9063a76c932a00000000'),
+ 10000: b('02a1b43f52591e53b660069173ac83b675798e12599dbb0442b7580000000000'),
+ 50000: b('0c6ceabe803cec55ba2831e445956d0a43ba9521743a802cddac7e0700000000'),
+ 90000: b('cafc21e17faf90461a5905aa03302c394912651ed9475ae711723e0d00000000'),
+ 100000: b('1e0a16bbadccde1d80c66597b1939e45f91b570d29f95fc158299e0000000000'),
+ 140000: b('92c0877b54c556889b72175ccbe0c91a1208f6ef7efb2c006101062300000000'),
+ 170000: b('508125560d202b89757889bb0e49c712477be20440058f05db4f0e0000000000'),
+ 210000: b('32365454b5f29a826bff8ad9b0448cad0072fc73d50e482d91a3dece00000000'),
+ 230000: b('b11a447e62643e0b27406eb0fc270cb8126d7b5b70822fb642d9513400000000'),
+ 270000: b('1c42b811cf9c163932f6e95ec55bf9b5e2cb5324e7e93001572e000000000000'),
+ 300000: b('a141bf3972424853f04367b47995e220e0b5a2706e5618766f22000000000000'),
+ 340000: b('67edd4d92e405608109164b15f92b193377d49325b0ed036739c010000000000'),
+ 350000: b('592b44bc0f7a4286cf07ead8497114c6952c1c7dea7305193deacf8e00000000'),
+ 390000: b('f217e183484fb6d695609cc71fa2ae24c3020943407e0150b298030000000000'),
+ 420000: b('de9e73a3b91fbb014e036e8583a17d6b638a699aeb2de8573d12580800000000'),
+ 460000: b('2e8baaffc107f15c87aebe01664b63d07476afa53bcbada1281a030000000000'),
+ 500000: b('06f60922a2aab2757317820fc6ffaf6a470e2cbb0f63a2aac0a7010000000000'),
+ 540000: b('8dd0bebfbc4878f5af09d3e848dcc57827d2c1cebea8ec5d8cbe420500000000'),
+ 570000: b('87acbd4cd3c40ec9bd648f8698ed226b31187274c06cc7a9af79030000000000'),
+ 600000: b('169a05b3bb04b7d13ad628915630900a5ed2e89f3a9dc6064f62000000000000'),
+ 630000: b('bbbe117035432a6a4effcb297207a02b031735b43e0d19a9217c000000000000'),
+ 670000: b('080bfe75caed8624fcfdfbc65973c8f962d7bdc495a891f5d16b7d0000000000'),
+ 700000: b('c14d3f6a1e7c7d66fd940951e44f3c3be1273bea4d2ab1786140000000000000'),
+ 740000: b('b3b423f0462fd78a01e4f1a59a2737a0525b5dbb9bba0b4634f9000000000000'),
+ 780000: b('0381582e34c3755964dc2813e2b33e521e5596367144e1670851050000000000'),
+ 800000: b('03b5f8ab257e02903f509f5ff2935220eec2e77b1819651d099b200000000000'),
+ 840000: b('dac1648107bd4394e57e4083c86d42b548b1cfb119665f179ea80a0000000000'),
+ 880000: b('ff90b4bb07eded8e96715bf595c09c7d21dd8c61b8306ff48705d60000000000'),
+ 900000: b('9bd8ac418beeb1a2cf5d68c8b5c6ebaa947a5b766e5524898d6f350000000000'),
+ 940000: b('c98f1651a475b00d12f8c25eb166ee843affaa90610e36a19d68030000000000'),
+ 980000: b('cc8e9774542d044a9698ca2336ae02d5987157e676f1c76aa3877c0000000000'),
+ 1010000:
+ b('9d9fb11abc2712d80368229e97b8d827b2a07d27eb5335e5c924000000000000'),
+ 1050000: b('d8190cf0af7f08e179cab51d67db0b44b87951a78f7fdc31b4a01a0000000000')
};
testnet.lastCheckpoint = 1050000;
@@ -549,10 +562,11 @@ testnet.halvingInterval = 210000;
testnet.genesis = {
version: 1,
- hash: '43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000',
- prevBlock: '0000000000000000000000000000000000000000000000000000000000000000',
+ hash: b('43497fd7f826957108f4a30fd9cec3aeba79972084e90ead01ea330900000000'),
+ prevBlock:
+ b('0000000000000000000000000000000000000000000000000000000000000000'),
merkleRoot:
- '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a',
+ b('3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'),
time: 1296688602,
bits: 486604799,
nonce: 414098458,
@@ -589,11 +603,14 @@ testnet.pow = {
testnet.block = {
bip34height: 21111,
- bip34hash: 'f88ecd9912d00d3f5c2a8e0f50417d3e415c75b3abe584346da9b32300000000',
+ bip34hash:
+ b('f88ecd9912d00d3f5c2a8e0f50417d3e415c75b3abe584346da9b32300000000'),
bip65height: 581885,
- bip65hash: 'b61e864fbec41dfaf09da05d1d76dc068b0dd82ee7982ff255667f0000000000',
+ bip65hash:
+ b('b61e864fbec41dfaf09da05d1d76dc068b0dd82ee7982ff255667f0000000000'),
bip66height: 330776,
- bip66hash: '82a14b9e5ea81d4832b8e2cd3c2a6092b5a3853285a8995ec4c8042100000000',
+ bip66hash:
+ b('82a14b9e5ea81d4832b8e2cd3c2a6092b5a3853285a8995ec4c8042100000000'),
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 24 * 60 * 60,
@@ -712,10 +729,11 @@ regtest.halvingInterval = 150;
regtest.genesis = {
version: 1,
- hash: '06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f',
- prevBlock: '0000000000000000000000000000000000000000000000000000000000000000',
+ hash: b('06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f'),
+ prevBlock:
+ b('0000000000000000000000000000000000000000000000000000000000000000'),
merkleRoot:
- '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a',
+ b('3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'),
time: 1296688602,
bits: 545259519,
nonce: 2,
@@ -876,10 +894,12 @@ simnet.halvingInterval = 210000;
simnet.genesis = {
version: 1,
- hash: 'f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68',
- prevBlock: '0000000000000000000000000000000000000000000000000000000000000000',
+ hash:
+ b('f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68'),
+ prevBlock:
+ b('0000000000000000000000000000000000000000000000000000000000000000'),
merkleRoot:
- '3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a',
+ b('3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a'),
time: 1401292357,
bits: 545259519,
nonce: 2,
@@ -917,11 +937,14 @@ simnet.pow = {
simnet.block = {
bip34height: 0,
- bip34hash: 'f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68',
+ bip34hash:
+ b('f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68'),
bip65height: 0,
- bip65hash: 'f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68',
+ bip65hash:
+ b('f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68'),
bip66height: 0,
- bip66hash: 'f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68',
+ bip66hash:
+ b('f67ad7695d9b662a72ff3d8edbbb2de0bfa67b13974bb9910d116d5cbd863e68'),
pruneAfterHeight: 1000,
keepBlocks: 10000,
maxTipAge: 0xffffffff,
diff --git a/lib/script/script.js b/lib/script/script.js
index 7f2290330..8506949ce 100644
--- a/lib/script/script.js
+++ b/lib/script/script.js
@@ -3270,7 +3270,7 @@ class Script {
*/
fromRaw(data) {
- const br = bio.read(data, true);
+ const br = bio.read(data);
this.raw = data;
diff --git a/lib/script/sigcache.js b/lib/script/sigcache.js
index 2fe96aa5e..a8bb148b2 100644
--- a/lib/script/sigcache.js
+++ b/lib/script/sigcache.js
@@ -7,6 +7,7 @@
'use strict';
const assert = require('assert');
+const {BufferMap} = require('buffer-map');
const secp256k1 = require('bcrypto/lib/secp256k1');
/**
@@ -32,7 +33,7 @@ class SigCache {
this.size = size;
this.keys = [];
- this.valid = new Map();
+ this.valid = new BufferMap();
}
/**
@@ -51,37 +52,37 @@ class SigCache {
/**
* Add item to the sigcache.
* Potentially evict a random member.
- * @param {Hash} hash - Sig hash.
+ * @param {Hash} msg - Sig hash.
* @param {Buffer} sig
* @param {Buffer} key
*/
- add(hash, sig, key) {
+ add(msg, sig, key) {
if (this.size === 0)
return;
- this.valid.set(hash, new SigCacheEntry(sig, key));
+ this.valid.set(msg, new SigCacheEntry(sig, key));
if (this.keys.length >= this.size) {
const i = Math.floor(Math.random() * this.keys.length);
const k = this.keys[i];
this.valid.delete(k);
- this.keys[i] = hash;
+ this.keys[i] = msg;
} else {
- this.keys.push(hash);
+ this.keys.push(msg);
}
}
/**
* Test whether the sig exists.
- * @param {Hash} hash - Sig hash.
+ * @param {Hash} msg - Sig hash.
* @param {Buffer} sig
* @param {Buffer} key
* @returns {Boolean}
*/
- has(hash, sig, key) {
- const entry = this.valid.get(hash);
+ has(msg, sig, key) {
+ const entry = this.valid.get(msg);
if (!entry)
return false;
@@ -102,9 +103,7 @@ class SigCache {
if (this.size === 0)
return secp256k1.verifyDER(msg, sig, key);
- const hash = msg.toString('hex');
-
- if (this.has(hash, sig, key))
+ if (this.has(msg, sig, key))
return true;
const result = secp256k1.verifyDER(msg, sig, key);
@@ -112,7 +111,7 @@ class SigCache {
if (!result)
return false;
- this.add(hash, sig, key);
+ this.add(msg, sig, key);
return true;
}
diff --git a/lib/utils/util.js b/lib/utils/util.js
index a43ce46aa..4c15b9cf2 100644
--- a/lib/utils/util.js
+++ b/lib/utils/util.js
@@ -100,7 +100,20 @@ util.time = function time(date) {
* @returns {String} Reversed hex string.
*/
-util.revHex = function revHex(str) {
+util.revHex = function revHex(buf) {
+ assert(Buffer.isBuffer(buf));
+
+ const str = buf.toString('hex');
+
+ let out = '';
+
+ for (let i = str.length - 2; i >= 0; i -= 2)
+ out += str[i] + str[i + 1];
+
+ return out;
+};
+
+util.fromRev = function fromRev(str) {
assert(typeof str === 'string');
assert((str.length & 1) === 0);
@@ -109,5 +122,5 @@ util.revHex = function revHex(str) {
for (let i = str.length - 2; i >= 0; i -= 2)
out += str[i] + str[i + 1];
- return out;
+ return Buffer.from(out, 'hex');
};
diff --git a/lib/wallet/account.js b/lib/wallet/account.js
index d0f737a47..26547d1c0 100644
--- a/lib/wallet/account.js
+++ b/lib/wallet/account.js
@@ -296,7 +296,7 @@ class Account {
return false;
const ring = this.deriveReceive(0);
- const hash = ring.getScriptHash('hex');
+ const hash = ring.getScriptHash();
return this.wdb.hasPath(this.wid, hash);
}
diff --git a/lib/wallet/client.js b/lib/wallet/client.js
index 1bdd52a3a..382c31d02 100644
--- a/lib/wallet/client.js
+++ b/lib/wallet/client.js
@@ -57,7 +57,7 @@ class WalletClient extends NodeClient {
}
async getEntry(block) {
- if (typeof block === 'string')
+ if (Buffer.isBuffer(block))
block = util.revHex(block);
return parseEntry(await super.getEntry(block));
@@ -72,7 +72,7 @@ class WalletClient extends NodeClient {
}
async rescan(start) {
- if (typeof start === 'string')
+ if (Buffer.isBuffer(start))
start = util.revHex(start);
return super.rescan(start);
@@ -87,10 +87,10 @@ function parseEntry(data) {
assert(Buffer.isBuffer(data));
assert(data.length >= 84);
- const h = hash256.digest(data.slice(0, 80));
+ const hash = hash256.digest(data.slice(0, 80));
return {
- hash: h.toString('hex'),
+ hash: hash,
height: data.readUInt32LE(80, true),
time: data.readUInt32LE(68, true)
};
diff --git a/lib/wallet/common.js b/lib/wallet/common.js
index 549acc093..01a7c209a 100644
--- a/lib/wallet/common.js
+++ b/lib/wallet/common.js
@@ -6,6 +6,8 @@
'use strict';
+const {BufferMap} = require('buffer-map');
+
/**
* @exports wallet/common
*/
@@ -81,15 +83,15 @@ common.sortCoins = function sortCoins(coins) {
*/
common.sortDeps = function sortDeps(txs) {
- const map = new Map();
+ const map = new BufferMap();
for (const tx of txs) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
map.set(hash, tx);
}
- const depMap = new Map();
- const depCount = new Map();
+ const depMap = new BufferMap();
+ const depCount = new BufferMap();
const top = [];
for (const [hash, tx] of map) {
@@ -122,8 +124,7 @@ common.sortDeps = function sortDeps(txs) {
const result = [];
for (const tx of top) {
- const hash = tx.hash('hex');
- const deps = depMap.get(hash);
+ const deps = depMap.get(tx.hash());
result.push(tx);
@@ -131,14 +132,12 @@ common.sortDeps = function sortDeps(txs) {
continue;
for (const tx of deps) {
- const hash = tx.hash('hex');
-
- let count = depCount.get(hash);
+ let count = depCount.get(tx.hash());
if (--count === 0)
top.push(tx);
- depCount.set(hash, count);
+ depCount.set(tx.hash(), count);
}
}
diff --git a/lib/wallet/http.js b/lib/wallet/http.js
index 7c3edd689..99eacf441 100644
--- a/lib/wallet/http.js
+++ b/lib/wallet/http.js
@@ -455,7 +455,7 @@ class HTTP extends Server {
const tx = await req.wallet.send(options, passphrase);
- const details = await req.wallet.getDetails(tx.hash('hex'));
+ const details = await req.wallet.getDetails(tx.hash());
res.json(200, details.toJSON(this.network, this.wdb.height));
});
@@ -536,7 +536,7 @@ class HTTP extends Server {
// Abandon Wallet TX
this.del('/wallet/:id/tx/:hash', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
enforce(hash, 'Hash is required.');
@@ -711,7 +711,7 @@ class HTTP extends Server {
// Lock coin
this.put('/wallet/:id/locked/:hash/:index', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
const index = valid.u32('index');
enforce(hash, 'Hash is required.');
@@ -727,7 +727,7 @@ class HTTP extends Server {
// Unlock coin
this.del('/wallet/:id/locked/:hash/:index', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
const index = valid.u32('index');
enforce(hash, 'Hash is required.');
@@ -743,7 +743,7 @@ class HTTP extends Server {
// Wallet Coin
this.get('/wallet/:id/coin/:hash/:index', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
const index = valid.u32('index');
enforce(hash, 'Hash is required.');
@@ -834,7 +834,7 @@ class HTTP extends Server {
// Wallet TX
this.get('/wallet/:id/tx/:hash', async (req, res) => {
const valid = Validator.fromRequest(req);
- const hash = valid.rhash('hash');
+ const hash = valid.brhash('hash');
enforce(hash, 'Hash is required.');
diff --git a/lib/wallet/layout.js b/lib/wallet/layout.js
index dfaebf5df..2c0a66c6c 100644
--- a/lib/wallet/layout.js
+++ b/lib/wallet/layout.js
@@ -35,9 +35,9 @@ exports.wdb = {
O: bdb.key('O'),
R: bdb.key('R'),
D: bdb.key('D'),
- p: bdb.key('p', ['hash']),
- P: bdb.key('P', ['uint32', 'hash']),
- r: bdb.key('r', ['uint32', 'uint32', 'hash']),
+ p: bdb.key('p', ['bhash']),
+ P: bdb.key('P', ['uint32', 'bhash']),
+ r: bdb.key('r', ['uint32', 'uint32', 'bhash']),
w: bdb.key('w', ['uint32']),
W: bdb.key('W', ['uint32']),
l: bdb.key('l', ['ascii']),
@@ -46,8 +46,8 @@ exports.wdb = {
n: bdb.key('n', ['uint32', 'uint32']),
h: bdb.key('h', ['uint32']),
b: bdb.key('b', ['uint32']),
- o: bdb.key('o', ['hash256', 'uint32']),
- T: bdb.key('T', ['hash256']),
+ o: bdb.key('o', ['bhash256', 'uint32']),
+ T: bdb.key('T', ['bhash256']),
t: bdb.key('t', ['uint32'])
};
@@ -74,17 +74,17 @@ exports.txdb = {
prefix: bdb.key('t', ['uint32']),
R: bdb.key('R'),
r: bdb.key('r', ['uint32']),
- t: bdb.key('t', ['hash256']),
- c: bdb.key('c', ['hash256', 'uint32']),
- d: bdb.key('d', ['hash256', 'uint32']),
- s: bdb.key('s', ['hash256', 'uint32']),
- p: bdb.key('p', ['hash256']),
- m: bdb.key('m', ['uint32', 'hash256']),
- h: bdb.key('h', ['uint32', 'hash256']),
- T: bdb.key('T', ['uint32', 'hash256']),
- P: bdb.key('P', ['uint32', 'hash256']),
- M: bdb.key('M', ['uint32', 'uint32', 'hash256']),
- H: bdb.key('H', ['uint32', 'uint32', 'hash256']),
- C: bdb.key('C', ['uint32', 'hash256', 'uint32']),
+ t: bdb.key('t', ['bhash256']),
+ c: bdb.key('c', ['bhash256', 'uint32']),
+ d: bdb.key('d', ['bhash256', 'uint32']),
+ s: bdb.key('s', ['bhash256', 'uint32']),
+ p: bdb.key('p', ['bhash256']),
+ m: bdb.key('m', ['uint32', 'bhash256']),
+ h: bdb.key('h', ['uint32', 'bhash256']),
+ T: bdb.key('T', ['uint32', 'bhash256']),
+ P: bdb.key('P', ['uint32', 'bhash256']),
+ M: bdb.key('M', ['uint32', 'uint32', 'bhash256']),
+ H: bdb.key('H', ['uint32', 'uint32', 'bhash256']),
+ C: bdb.key('C', ['uint32', 'bhash256', 'uint32']),
b: bdb.key('b', ['uint32'])
};
diff --git a/lib/wallet/masterkey.js b/lib/wallet/masterkey.js
index 1ed64d425..f0fdc8794 100644
--- a/lib/wallet/masterkey.js
+++ b/lib/wallet/masterkey.js
@@ -256,9 +256,6 @@ class MasterKey {
if (!this.aesKey)
return null;
- if (typeof iv === 'string')
- iv = Buffer.from(iv, 'hex');
-
return aes.encipher(data, this.aesKey, iv.slice(0, 16));
}
@@ -273,9 +270,6 @@ class MasterKey {
if (!this.aesKey)
return null;
- if (typeof iv === 'string')
- iv = Buffer.from(iv, 'hex');
-
return aes.decipher(data, this.aesKey, iv.slice(0, 16));
}
diff --git a/lib/wallet/path.js b/lib/wallet/path.js
index 7e187cd24..d81bd010c 100644
--- a/lib/wallet/path.js
+++ b/lib/wallet/path.js
@@ -240,7 +240,7 @@ class Path {
this.account = account.accountIndex;
this.version = address.version;
this.type = address.type;
- this.hash = address.getHash('hex');
+ this.hash = address.getHash();
return this;
}
diff --git a/lib/wallet/records.js b/lib/wallet/records.js
index 24521467a..3c12075a0 100644
--- a/lib/wallet/records.js
+++ b/lib/wallet/records.js
@@ -28,7 +28,7 @@ class ChainState {
constructor() {
this.startHeight = 0;
- this.startHash = consensus.NULL_HASH;
+ this.startHash = consensus.ZERO_HASH;
this.height = 0;
this.marked = false;
}
@@ -57,7 +57,7 @@ class ChainState {
const br = bio.read(data);
this.startHeight = br.readU32();
- this.startHash = br.readHash('hex');
+ this.startHash = br.readHash();
this.height = br.readU32();
this.marked = br.readU8() === 1;
@@ -106,7 +106,7 @@ class BlockMeta {
*/
constructor(hash, height, time) {
- this.hash = hash || consensus.NULL_HASH;
+ this.hash = hash || consensus.ZERO_HASH;
this.height = height != null ? height : -1;
this.time = time || 0;
}
@@ -126,7 +126,7 @@ class BlockMeta {
*/
toHash() {
- return Buffer.from(this.hash, 'hex');
+ return this.hash;
}
/**
@@ -163,7 +163,7 @@ class BlockMeta {
fromRaw(data) {
const br = bio.read(data);
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
this.height = br.readU32();
this.time = br.readU32();
return this;
@@ -262,7 +262,7 @@ class TXRecord {
fromTX(tx, block) {
this.tx = tx;
- this.hash = tx.hash('hex');
+ this.hash = tx.hash();
if (block)
this.setBlock(block);
@@ -397,11 +397,11 @@ class TXRecord {
this.tx = new TX();
this.tx.fromReader(br);
- this.hash = this.tx.hash('hex');
+ this.hash = this.tx.hash();
this.mtime = br.readU32();
if (br.readU8() === 1) {
- this.block = br.readHash('hex');
+ this.block = br.readHash();
this.height = br.readU32();
this.time = br.readU32();
this.index = br.readU32();
diff --git a/lib/wallet/rpc.js b/lib/wallet/rpc.js
index 564dc4365..7fb7d267e 100644
--- a/lib/wallet/rpc.js
+++ b/lib/wallet/rpc.js
@@ -13,6 +13,7 @@ const {Lock} = require('bmutex');
const fs = require('bfile');
const Validator = require('bval');
const hash256 = require('bcrypto/lib/hash256');
+const {BufferMap, BufferSet} = require('buffer-map');
const util = require('../utils/util');
const Amount = require('../btc/amount');
const Script = require('../script/script');
@@ -520,7 +521,7 @@ class RPC extends RPCBase {
name = 'default';
const paths = await wallet.getPaths(name);
- const filter = new Set();
+ const filter = new BufferSet();
for (const path of paths)
filter.add(path.hash);
@@ -540,7 +541,7 @@ class RPC extends RPCBase {
lastConf = conf;
for (const output of wtx.tx.outputs) {
- const hash = output.getHash('hex');
+ const hash = output.getHash();
if (hash && filter.has(hash))
total += output.value;
}
@@ -571,7 +572,7 @@ class RPC extends RPCBase {
continue;
for (const output of wtx.tx.outputs) {
- if (output.getHash('hex') === hash)
+ if (output.getHash().equals(hash))
total += output.value;
}
}
@@ -660,7 +661,7 @@ class RPC extends RPCBase {
const wallet = this.wallet;
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
const watchOnly = valid.bool(1, false);
if (!hash)
@@ -680,7 +681,7 @@ class RPC extends RPCBase {
const wallet = this.wallet;
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
if (!hash)
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
@@ -950,7 +951,7 @@ class RPC extends RPCBase {
const paths = await wallet.getPaths();
const height = this.wdb.state.height;
- const map = new Map();
+ const map = new BufferMap();
for (const path of paths) {
const addr = path.toAddress();
map.set(path.hash, {
@@ -977,7 +978,7 @@ class RPC extends RPCBase {
if (!addr)
continue;
- const hash = addr.getHash('hex');
+ const hash = addr.getHash();
const entry = map.get(hash);
if (entry) {
@@ -1031,7 +1032,7 @@ class RPC extends RPCBase {
const wallet = this.wallet;
const chainHeight = this.wdb.state.height;
const valid = new Validator(args);
- const block = valid.rhash(0);
+ const block = valid.brhash(0);
const minconf = valid.u32(1, 0);
const watchOnly = valid.bool(2, false);
@@ -1078,7 +1079,7 @@ class RPC extends RPCBase {
transactions: out,
lastblock: highest && highest.block
? util.revHex(highest.block)
- : consensus.NULL_HASH
+ : util.revHex(consensus.ZERO_HASH)
};
}
@@ -1217,7 +1218,7 @@ class RPC extends RPCBase {
const addrs = valid.array(2);
const height = this.wdb.state.height;
- const map = new Set();
+ const map = new BufferSet();
if (addrs) {
const valid = new Validator(addrs);
@@ -1249,7 +1250,7 @@ class RPC extends RPCBase {
if (!addr)
continue;
- const hash = coin.getHash('hex');
+ const hash = coin.getHash();
if (addrs) {
if (!hash || !map.has(hash))
@@ -1299,7 +1300,7 @@ class RPC extends RPCBase {
for (const output of outputs) {
const valid = new Validator(output);
- const hash = valid.rhash('txid');
+ const hash = valid.brhash('txid');
const index = valid.u32('vout');
if (hash == null || index == null)
@@ -1380,13 +1381,13 @@ class RPC extends RPCBase {
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
const to = new Validator(sendTo);
- const uniq = new Set();
+ const uniq = new BufferSet();
const outputs = [];
for (const key of Object.keys(sendTo)) {
const value = to.ufixed(key, 8);
const addr = parseAddress(key, this.network);
- const hash = addr.getHash('hex');
+ const hash = addr.getHash();
if (value == null)
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter.');
@@ -1585,12 +1586,12 @@ class RPC extends RPCBase {
const tx = TX.fromRaw(txRaw);
const block = MerkleBlock.fromRaw(blockRaw);
- const hash = block.hash('hex');
+ const hash = block.hash();
if (!block.verify())
throw new RPCError(errs.VERIFY_ERROR, 'Invalid proof.');
- if (!block.hasTX(tx.hash('hex')))
+ if (!block.hasTX(tx.hash()))
throw new RPCError(errs.VERIFY_ERROR, 'Invalid proof.');
const height = await this.client.getEntry(hash);
@@ -1616,7 +1617,7 @@ class RPC extends RPCBase {
const wallet = this.wallet;
const valid = new Validator(args);
- const hash = valid.rhash(0);
+ const hash = valid.brhash(0);
if (!hash)
throw new RPCError(errs.TYPE_ERROR, 'Invalid parameter.');
@@ -1670,7 +1671,7 @@ class RPC extends RPCBase {
function parseHash(raw, network) {
const addr = parseAddress(raw, network);
- return addr.getHash('hex');
+ return addr.getHash();
}
function parseAddress(raw, network) {
diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js
index b809bf730..d90e4778b 100644
--- a/lib/wallet/txdb.js
+++ b/lib/wallet/txdb.js
@@ -9,6 +9,7 @@
const assert = require('assert');
const bio = require('bufio');
+const {BufferSet} = require('buffer-map');
const util = require('../utils/util');
const Amount = require('../btc/amount');
const CoinView = require('../coins/coinview');
@@ -40,7 +41,7 @@ class TXDB {
this.wid = wid || 0;
this.bucket = null;
this.wallet = null;
- this.locked = new Set();
+ this.locked = new BufferSet();
}
/**
@@ -76,7 +77,7 @@ class TXDB {
*/
getPath(output) {
- const hash = output.getHash('hex');
+ const hash = output.getHash();
if (!hash)
return null;
@@ -91,7 +92,7 @@ class TXDB {
*/
hasPath(output) {
- const hash = output.getHash('hex');
+ const hash = output.getHash();
if (!hash)
return false;
@@ -413,7 +414,7 @@ class TXDB {
*/
async add(tx, block) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const existing = await this.getTX(hash);
assert(!tx.mutable, 'Cannot add mutable TX to wallet.');
@@ -1091,7 +1092,7 @@ class TXDB {
if (tx.isCoinbase())
return true;
- const txid = tx.hash('hex');
+ const txid = tx.hash();
const spends = [];
// Gather all spent records first.
@@ -1105,7 +1106,7 @@ class TXDB {
continue;
// Did _we_ spend it?
- if (spent.hash === txid)
+ if (spent.hash.equals(txid))
continue;
const spender = await this.getTX(spent.hash);
@@ -1617,7 +1618,7 @@ class TXDB {
if (tx.isCoinbase())
return [];
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const credits = [];
for (let i = 0; i < tx.inputs.length; i++)
@@ -2549,10 +2550,10 @@ class BlockRecord {
*/
constructor(hash, height, time) {
- this.hash = hash || consensus.NULL_HASH;
+ this.hash = hash || consensus.ZERO_HASH;
this.height = height != null ? height : -1;
this.time = time || 0;
- this.hashes = new Set();
+ this.hashes = new BufferSet();
}
/**
@@ -2589,14 +2590,14 @@ class BlockRecord {
fromRaw(data) {
const br = bio.read(data);
- this.hash = br.readHash('hex');
+ this.hash = br.readHash();
this.height = br.readU32();
this.time = br.readU32();
const count = br.readU32();
for (let i = 0; i < count; i++) {
- const hash = br.readHash('hex');
+ const hash = br.readHash();
this.hashes.add(hash);
}
diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js
index 608b8fd53..3dfaff9d1 100644
--- a/lib/wallet/wallet.js
+++ b/lib/wallet/wallet.js
@@ -858,7 +858,7 @@ class Wallet extends EventEmitter {
*/
async hasAddress(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
const path = await this.getPath(hash);
return path != null;
}
@@ -870,7 +870,7 @@ class Wallet extends EventEmitter {
*/
async getPath(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
return this.wdb.getPath(this.wid, hash);
}
@@ -882,7 +882,7 @@ class Wallet extends EventEmitter {
*/
async readPath(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
return this.wdb.readPath(this.wid, hash);
}
@@ -893,7 +893,7 @@ class Wallet extends EventEmitter {
*/
async hasPath(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
return this.wdb.hasPath(this.wid, hash);
}
@@ -979,7 +979,7 @@ class Wallet extends EventEmitter {
throw new Error('Cannot import privkey into watch-only wallet.');
}
- const hash = ring.getHash('hex');
+ const hash = ring.getHash();
if (await this.getPath(hash))
throw new Error('Key already exists.');
@@ -1143,7 +1143,7 @@ class Wallet extends EventEmitter {
*/
async getAccountByAddress(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
const path = await this.getPath(hash);
if (!path)
@@ -1504,7 +1504,7 @@ class Wallet extends EventEmitter {
*/
async getKey(address) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
const path = await this.getPath(hash);
if (!path)
@@ -1527,7 +1527,7 @@ class Wallet extends EventEmitter {
*/
async getPrivateKey(address, passphrase) {
- const hash = Address.getHash(address, 'hex');
+ const hash = Address.getHash(address);
const path = await this.getPath(hash);
if (!path)
@@ -1560,7 +1560,7 @@ class Wallet extends EventEmitter {
if (!mtx.hasCoins())
throw new Error('Not all coins available.');
- const hashes = mtx.getInputHashes('hex');
+ const hashes = mtx.getInputHashes();
const paths = [];
for (const hash of hashes) {
@@ -1580,7 +1580,7 @@ class Wallet extends EventEmitter {
async getOutputPaths(tx) {
const paths = [];
- const hashes = tx.getOutputHashes('hex');
+ const hashes = tx.getOutputHashes();
for (const hash of hashes) {
const path = await this.getPath(hash);
@@ -1637,7 +1637,7 @@ class Wallet extends EventEmitter {
async syncOutputDepth(tx) {
const map = new Map();
- for (const hash of tx.getOutputHashes('hex')) {
+ for (const hash of tx.getOutputHashes()) {
const path = await this.readPath(hash);
if (!path)
diff --git a/lib/wallet/walletdb.js b/lib/wallet/walletdb.js
index ab95c65f3..4bd20e39f 100644
--- a/lib/wallet/walletdb.js
+++ b/lib/wallet/walletdb.js
@@ -264,7 +264,7 @@ class WalletDB extends EventEmitter {
await piter.each((key) => {
const data = layout.p.parse(key);
- this.filter.add(data, 'hex');
+ this.filter.add(data);
hashes += 1;
});
@@ -620,7 +620,7 @@ class WalletDB extends EventEmitter {
*/
testFilter(data) {
- return this.filter.test(data, 'hex');
+ return this.filter.test(data);
}
/**
@@ -630,7 +630,7 @@ class WalletDB extends EventEmitter {
*/
addHash(hash) {
- this.filter.add(hash, 'hex');
+ this.filter.add(hash);
return this.addFilter(hash);
}
@@ -1409,8 +1409,7 @@ class WalletDB extends EventEmitter {
assert(!path.encrypted);
- const bhash = Buffer.from(hash, 'hex');
- const iv = bhash.slice(0, 16);
+ const iv = hash.slice(0, 16);
path.data = aes.encipher(path.data, key, iv);
path.encrypted = true;
@@ -1442,8 +1441,7 @@ class WalletDB extends EventEmitter {
assert(path.encrypted);
- const bhash = Buffer.from(hash, 'hex');
- const iv = bhash.slice(0, 16);
+ const iv = hash.slice(0, 16);
path.data = aes.decipher(path.data, key, iv);
path.encrypted = false;
@@ -1541,7 +1539,7 @@ class WalletDB extends EventEmitter {
}
}
- const hashes = tx.getOutputHashes('hex');
+ const hashes = tx.getOutputHashes();
for (const hash of hashes) {
if (!this.testFilter(hash))
@@ -1845,7 +1843,7 @@ class WalletDB extends EventEmitter {
return null;
const block = new BlockMeta();
- block.hash = data.toString('hex');
+ block.hash = data;
block.height = height;
return block;
diff --git a/lib/wallet/walletkey.js b/lib/wallet/walletkey.js
index 36a0bbee6..3ebd29dd7 100644
--- a/lib/wallet/walletkey.js
+++ b/lib/wallet/walletkey.js
@@ -174,7 +174,7 @@ class WalletKey extends KeyRing {
path.version = this.getVersion();
path.type = this.getType();
- path.hash = this.getHash('hex');
+ path.hash = this.getHash();
return path;
}
diff --git a/migrate/chaindb2to3.js b/migrate/chaindb2to3.js
index 011b61e1c..2357a7d2d 100644
--- a/migrate/chaindb2to3.js
+++ b/migrate/chaindb2to3.js
@@ -21,6 +21,7 @@ const hash256 = require('bcrypto/lib/hash256');
const BN = require('bn.js');
const bio = require('bufio');
const LRU = require('blru');
+const {BufferMap} = require('buffer-map');
const util = require('../lib/utils/util');
const OldCoins = require('./coins/coins');
const OldUndoCoins = require('./coins/undocoins');
@@ -53,18 +54,18 @@ const STATE_ENTRY = 3;
const STATE_FINAL = 4;
const STATE_DONE = 5;
-const metaCache = new Map();
-const lruCache = new LRU(200000);
+const metaCache = new BufferMap();
+const lruCache = new LRU(200000, null, BufferMap);
function writeJournal(batch, state, hash) {
const data = Buffer.allocUnsafe(34);
if (!hash)
- hash = consensus.NULL_HASH;
+ hash = consensus.ZERO_HASH;
data[0] = MIGRATION_ID;
data[1] = state;
- data.write(hash, 2, 'hex');
+ hash.copy(data, 2);
batch.put(JOURNAL_KEY, data);
}
@@ -73,7 +74,7 @@ async function readJournal() {
const data = await db.get(JOURNAL_KEY);
if (!data)
- return [STATE_VERSION, consensus.NULL_HASH];
+ return [STATE_VERSION, consensus.ZERO_HASH];
if (data.length !== 34)
throw new Error('Bad migration length.');
@@ -82,7 +83,7 @@ async function readJournal() {
throw new Error('Bad migration id.');
const state = data.readUInt8(1, true);
- const hash = data.toString('hex', 2, 34);
+ const hash = data.slice(2, 34);
console.log('Reading journal.');
console.log('Recovering from state %d.', state);
@@ -118,7 +119,7 @@ async function updateVersion() {
await batch.write();
- return [STATE_UNDO, consensus.NULL_HASH];
+ return [STATE_UNDO, consensus.ZERO_HASH];
}
async function reserializeUndo(hash) {
@@ -126,7 +127,7 @@ async function reserializeUndo(hash) {
const height = tip.height;
- if (hash !== consensus.NULL_HASH)
+ if (!hash.equals(consensus.ZERO_HASH))
tip = await getEntry(hash);
console.log('Reserializing undo coins from tip %s.',
@@ -254,12 +255,12 @@ async function reserializeUndo(hash) {
'Reserialized %d undo records (%d coins).',
total, totalCoins);
- return [STATE_CLEANUP, consensus.NULL_HASH];
+ return [STATE_CLEANUP, consensus.ZERO_HASH];
}
async function cleanupIndex() {
if (hasSPV)
- return [STATE_COINS, consensus.NULL_HASH];
+ return [STATE_COINS, consensus.ZERO_HASH];
const iter = db.iterator({
gte: pair(0x01, consensus.ZERO_HASH),
@@ -290,12 +291,12 @@ async function cleanupIndex() {
console.log('Cleaned up %d undo records.', total);
- return [STATE_COINS, consensus.NULL_HASH];
+ return [STATE_COINS, consensus.ZERO_HASH];
}
async function reserializeCoins(hash) {
if (hasSPV)
- return [STATE_ENTRY, consensus.NULL_HASH];
+ return [STATE_ENTRY, consensus.ZERO_HASH];
const iter = db.iterator({
gte: pair('c', hash),
@@ -306,7 +307,7 @@ async function reserializeCoins(hash) {
let start = true;
- if (hash !== consensus.NULL_HASH) {
+ if (!hash.equals(consensus.ZERO_HASH)) {
const item = await iter.next();
if (!item)
start = false;
@@ -326,7 +327,7 @@ async function reserializeCoins(hash) {
if (item.key.length !== 33)
continue;
- const hash = item.key.toString('hex', 1, 33);
+ const hash = item.key.slice(1, 33);
const old = OldCoins.fromRaw(item.value, hash);
let update = false;
@@ -367,7 +368,7 @@ async function reserializeCoins(hash) {
console.log('Reserialized %d coins.', total);
- return [STATE_ENTRY, consensus.NULL_HASH];
+ return [STATE_ENTRY, consensus.ZERO_HASH];
}
async function reserializeEntries(hash) {
@@ -379,7 +380,7 @@ async function reserializeEntries(hash) {
let start = true;
- if (hash !== consensus.NULL_HASH) {
+ if (!hash.equals(consensus.ZERO_HASH)) {
const item = await iter.next();
if (!item)
start = false;
@@ -418,7 +419,7 @@ async function reserializeEntries(hash) {
console.log('Reserialized %d entries.', total);
- return [STATE_FINAL, consensus.NULL_HASH];
+ return [STATE_FINAL, consensus.ZERO_HASH];
}
async function finalize() {
@@ -454,7 +455,7 @@ async function finalize() {
await db.compactRange();
- return [STATE_DONE, consensus.NULL_HASH];
+ return [STATE_DONE, consensus.ZERO_HASH];
}
async function getMeta(coin, prevout) {
@@ -538,7 +539,7 @@ async function getTip() {
async function getTipHash() {
const state = await db.get('R');
assert(state);
- return state.toString('hex', 0, 32);
+ return state.slice(0, 32);
}
async function getEntry(hash) {
@@ -566,7 +567,7 @@ async function isIndexed() {
}
async function isMainChain(entry, tip) {
- if (entry.hash === tip)
+ if (entry.hash.equals(tip))
return true;
if (await db.get(pair('n', entry.hash)))
@@ -582,10 +583,10 @@ function entryFromRaw(data) {
br.seek(-80);
const entry = {};
- entry.hash = hash.toString('hex');
+ entry.hash = hash.toString();
entry.version = br.readU32();
- entry.prevBlock = br.readHash('hex');
- entry.merkleRoot = br.readHash('hex');
+ entry.prevBlock = br.readHash();
+ entry.merkleRoot = br.readHash();
entry.time = br.readU32();
entry.bits = br.readU32();
entry.nonce = br.readU32();
@@ -611,10 +612,9 @@ function entryToRaw(entry, main) {
return bw.render();
}
-function write(data, str, off) {
- if (Buffer.isBuffer(str))
- return str.copy(data, off);
- return data.write(str, off, 'hex');
+function write(data, hash, off) {
+ assert(Buffer.isBuffer(hash));
+ return hash.copy(data, off);
}
function pair(prefix, hash) {
@@ -682,7 +682,7 @@ reserializeEntries;
// [state, hash] = await reserializeEntries(hash);
if (state === STATE_ENTRY)
- [state, hash] = [STATE_FINAL, consensus.NULL_HASH];
+ [state, hash] = [STATE_FINAL, consensus.ZERO_HASH];
if (state === STATE_FINAL)
[state, hash] = await finalize();
diff --git a/migrate/coins/coins.js b/migrate/coins/coins.js
index 5e8b6c868..401992697 100644
--- a/migrate/coins/coins.js
+++ b/migrate/coins/coins.js
@@ -37,7 +37,7 @@ function Coins(options) {
return new Coins(options);
this.version = 1;
- this.hash = encoding.NULL_HASH;
+ this.hash = encoding.ZERO_HASH;
this.height = -1;
this.coinbase = true;
this.outputs = [];
@@ -59,7 +59,7 @@ Coins.prototype.fromOptions = function fromOptions(options) {
}
if (options.hash) {
- assert(typeof options.hash === 'string');
+ assert(Buffer.isBuffer(options.hash));
this.hash = options.hash;
}
@@ -562,7 +562,7 @@ Coins.prototype.fromTX = function fromTX(tx, height) {
assert(typeof height === 'number');
this.version = tx.version;
- this.hash = tx.hash('hex');
+ this.hash = tx.hash();
this.height = height;
this.coinbase = tx.isCoinbase();
diff --git a/migrate/coins/coinview.js b/migrate/coins/coinview.js
index 91b9e4257..8d27a08aa 100644
--- a/migrate/coins/coinview.js
+++ b/migrate/coins/coinview.js
@@ -9,6 +9,7 @@
'use strict';
const assert = require('assert');
+const {BufferMap} = require('buffer-map');
const Coins = require('./coins');
const UndoCoins = require('./undocoins');
const CoinEntry = Coins.CoinEntry;
@@ -26,7 +27,7 @@ function CoinView() {
if (!(this instanceof CoinView))
return new CoinView();
- this.map = new Map();
+ this.map = new BufferMap();
this.undo = new UndoCoins();
}
diff --git a/migrate/walletdb5to6.js b/migrate/walletdb5to6.js
index 3757ef647..ac584fb52 100644
--- a/migrate/walletdb5to6.js
+++ b/migrate/walletdb5to6.js
@@ -89,7 +89,7 @@ async function indexPaths() {
for (let i = 0; i < items.length; i++) {
const item = items[i];
const wid = item.key.readUInt32BE(1, true);
- const hash = item.key.toString('hex', 5);
+ const hash = item.key.slice(5);
const index = item.value.readUInt32LE(0, true);
console.log('r[%d][%d][%s] -> NUL', wid, index, hash);
batch.put(r(wid, index, hash), Buffer.from([0]));
@@ -104,7 +104,7 @@ async function patchPathMaps() {
for (let i = 0; i < items.length; i++) {
const item = items[i];
- const hash = item.key.toString('hex', 1);
+ const hash = item.key.slice(1);
const wids = parseWallets(item.value);
console.log('p[%s] -> u32(%d)', hash, wids.length);
batch.put(item.key, serializeWallets(wids));
@@ -200,7 +200,7 @@ function r(wid, index, hash) {
key[0] = 0x72;
key.writeUInt32BE(wid, 1, true);
key.writeUInt32BE(index, 5, true);
- key.write(hash, 9, 'hex');
+ hash.copy(key, 9);
return key;
}
diff --git a/migrate/walletdb6to7.js b/migrate/walletdb6to7.js
index ff7a954fd..127048e8b 100644
--- a/migrate/walletdb6to7.js
+++ b/migrate/walletdb6to7.js
@@ -689,7 +689,7 @@ class BlockMapRecord {
const count = br.readU32();
for (let i = 0; i < count; i++) {
- const hash = br.readHash('hex');
+ const hash = br.readHash();
const tx = TXMapRecord.fromReader(hash, br);
this.txs.set(tx.hash, tx);
}
@@ -863,13 +863,13 @@ function serializeBalance(bal) {
function parsep(key) { // p[hash]
assert(Buffer.isBuffer(key));
assert(key.length >= 21);
- return [key.toString('hex', 1)];
+ return [key.slice(1)];
}
function parseP(key) { // P[wid][hash]
assert(Buffer.isBuffer(key));
assert(key.length >= 25);
- return [key.readUInt32BE(1, true), key.toString('hex', 5)];
+ return [key.readUInt32BE(1, true), key.slice(5)];
}
function parser(key) { // r[wid][index][hash]
@@ -878,7 +878,7 @@ function parser(key) { // r[wid][index][hash]
return [
key.readUInt32BE(1, true),
key.readUInt32BE(5, true),
- key.toString('hex', 9)
+ key.slice(9)
];
}
diff --git a/package.json b/package.json
index 05ecfa7f8..4d0a6d44f 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"bcfg": "~0.1.0",
"bclient": "~0.1.1",
"bcrypto": "~0.3.7",
- "bdb": "~0.2.1",
+ "bdb": "~0.2.2",
"bdns": "~0.1.0",
"bevent": "~0.1.0",
"bfile": "~0.1.0",
@@ -34,19 +34,20 @@
"bheep": "~0.1.0",
"binet": "~0.3.0",
"blgr": "~0.1.0",
- "blru": "~0.1.0",
+ "blru": "~0.1.1",
"blst": "~0.1.0",
- "bmutex": "~0.1.0",
+ "bmutex": "~0.1.1",
"bn.js": "~4.11.8",
"bsip": "~0.1.0",
"bsock": "~0.1.2",
"bsocks": "~0.2.0",
"bstring": "~0.1.0",
"btcp": "~0.1.0",
+ "buffer-map": "~0.0.0",
"bufio": "~0.2.0",
"bupnp": "~0.2.1",
- "bval": "~0.1.0",
- "bweb": "~0.1.3",
+ "bval": "~0.1.1",
+ "bweb": "~0.1.1",
"mrmr": "~0.1.0",
"n64": "~0.2.0"
},
diff --git a/scripts/gen.js b/scripts/gen.js
index 76b4e1b74..c9c2c80ad 100644
--- a/scripts/gen.js
+++ b/scripts/gen.js
@@ -30,7 +30,7 @@ function createGenesisBlock(options) {
version: 1,
inputs: [{
prevout: {
- hash: consensus.NULL_HASH,
+ hash: consensus.ZERO_HASH,
index: 0xffffffff
},
script: Script()
@@ -49,8 +49,8 @@ function createGenesisBlock(options) {
const block = new Block({
version: options.version,
- prevBlock: consensus.NULL_HASH,
- merkleRoot: tx.hash('hex'),
+ prevBlock: consensus.ZERO_HASH,
+ merkleRoot: tx.hash(),
time: options.time,
bits: options.bits,
nonce: options.nonce,
diff --git a/test/block-test.js b/test/block-test.js
index fbde92719..adef42237 100644
--- a/test/block-test.js
+++ b/test/block-test.js
@@ -6,6 +6,7 @@
const assert = require('./util/assert');
const common = require('./util/common');
const {BloomFilter} = require('bfilter');
+const {BufferMap} = require('buffer-map');
const Block = require('../lib/primitives/block');
const MerkleBlock = require('../lib/primitives/merkleblock');
const consensus = require('../lib/protocol/consensus');
@@ -52,7 +53,7 @@ describe('Block', function() {
const tree = block.getTree();
assert.strictEqual(tree.matches.length, 2);
- assert.strictEqual(block.hash('hex'),
+ assert.strictEqual(block.hash().toString('hex'),
'8cc72c02a958de5a8b35a23bb7e3bced8bf840cc0a4e1c820000000000000000');
assert.strictEqual(block.rhash(),
'0000000000000000821c4e0acc40f88bedbce3b73ba2358b5ade58a9022cc78c');
@@ -94,23 +95,26 @@ describe('Block', function() {
it('should parse JSON', () => {
const [block1] = block300025.getBlock();
const block2 = Block.fromJSON(block1.toJSON());
- assert.strictEqual(block2.hash('hex'),
+ assert.strictEqual(block2.hash().toString('hex'),
'8cc72c02a958de5a8b35a23bb7e3bced8bf840cc0a4e1c820000000000000000');
assert.strictEqual(block2.rhash(),
'0000000000000000821c4e0acc40f88bedbce3b73ba2358b5ade58a9022cc78c');
- assert.strictEqual(block2.merkleRoot, block2.createMerkleRoot('hex'));
+ assert.bufferEqual(block2.merkleRoot, block2.createMerkleRoot());
});
it('should create a merkle block', () => {
const filter = BloomFilter.fromRate(1000, 0.01, BloomFilter.flags.NONE);
- const item1 = '8e7445bbb8abd4b3174d80fa4c409fea6b94d96b';
- const item2 = '047b00000078da0dca3b0ec2300c00d0ab4466ed10'
+ const item1 = Buffer.from(
+ '8e7445bbb8abd4b3174d80fa4c409fea6b94d96b',
+ 'hex');
+
+ const item2 = Buffer.from('047b00000078da0dca3b0ec2300c00d0ab4466ed10'
+ 'e763272c6c9ca052972c69e3884a9022084215e2eef'
- + '0e6f781656b5d5a87231cd4349e534b6dea55ad4ff55e';
+ + '0e6f781656b5d5a87231cd4349e534b6dea55ad4ff55e', 'hex');
- filter.add(item1, 'hex');
- filter.add(item2, 'hex');
+ filter.add(item1);
+ filter.add(item2);
const [block1] = block300025.getBlock();
const block2 = MerkleBlock.fromBlock(block1, filter);
@@ -157,7 +161,7 @@ describe('Block', function() {
it('should fail with a bad merkle root', () => {
const [block] = block300025.getBlock();
const merkleRoot = block.merkleRoot;
- block.merkleRoot = consensus.NULL_HASH;
+ block.merkleRoot = consensus.ZERO_HASH;
block.refresh();
assert(!block.verifyPOW());
const [, reason] = block.checkBody();
@@ -171,7 +175,7 @@ describe('Block', function() {
it('should fail on merkle block with a bad merkle root', () => {
const [block] = merkle300025.getBlock();
const merkleRoot = block.merkleRoot;
- block.merkleRoot = consensus.NULL_HASH;
+ block.merkleRoot = consensus.ZERO_HASH;
block.refresh();
assert(!block.verifyPOW());
const [, reason] = block.checkBody();
@@ -220,11 +224,11 @@ describe('Block', function() {
assert.bufferEqual(cblock1.toRaw(), compact426884.getRaw());
assert.bufferEqual(cblock2.toRaw(), compact426884.getRaw());
- const map = new Map();
+ const map = new BufferMap();
for (let i = 1; i < block.txs.length; i++) {
const tx = block.txs[i];
- map.set(tx.hash('hex'), { tx });
+ map.set(tx.hash(), { tx });
}
const full = cblock1.fillMempool(false, { map });
@@ -246,11 +250,11 @@ describe('Block', function() {
assert.bufferEqual(cblock1.toRaw(), compact426884.getRaw());
assert.bufferEqual(cblock2.toRaw(), compact426884.getRaw());
- const map = new Map();
+ const map = new BufferMap();
for (let i = 1; i < ((block.txs.length + 1) >>> 1); i++) {
const tx = block.txs[i];
- map.set(tx.hash('hex'), { tx });
+ map.set(tx.hash(), { tx });
}
const full = cblock1.fillMempool(false, { map });
@@ -258,7 +262,7 @@ describe('Block', function() {
const rawReq = cblock1.toRequest().toRaw();
const req = TXRequest.fromRaw(rawReq);
- assert.strictEqual(req.hash, cblock1.hash('hex'));
+ assert.bufferEqual(req.hash, cblock1.hash());
const rawRes = TXResponse.fromBlock(block, req).toRaw();
const res = TXResponse.fromRaw(rawRes);
@@ -284,11 +288,11 @@ describe('Block', function() {
assert.strictEqual(cblock1.sid(block.txs[1].hash()), 125673511480291);
- const map = new Map();
+ const map = new BufferMap();
for (let i = 1; i < block.txs.length; i++) {
const tx = block.txs[i];
- map.set(tx.hash('hex'), { tx });
+ map.set(tx.hash(), { tx });
}
const full = cblock1.fillMempool(false, { map });
@@ -312,11 +316,11 @@ describe('Block', function() {
assert.strictEqual(cblock1.sid(block.txs[1].hash()), 125673511480291);
- const map = new Map();
+ const map = new BufferMap();
for (let i = 1; i < ((block.txs.length + 1) >>> 1); i++) {
const tx = block.txs[i];
- map.set(tx.hash('hex'), { tx });
+ map.set(tx.hash(), { tx });
}
const full = cblock1.fillMempool(false, { map });
@@ -324,7 +328,7 @@ describe('Block', function() {
const rawReq = cblock1.toRequest().toRaw();
const req = TXRequest.fromRaw(rawReq);
- assert.strictEqual(req.hash, cblock1.hash('hex'));
+ assert.bufferEqual(req.hash, cblock1.hash());
assert.deepStrictEqual(req.indexes, [5, 6, 7, 8, 9]);
const rawRes = TXResponse.fromBlock(block, req).toRaw();
diff --git a/test/chain-test.js b/test/chain-test.js
index 1cf13ed0e..591616627 100644
--- a/test/chain-test.js
+++ b/test/chain-test.js
@@ -154,13 +154,13 @@ describe('Chain', function() {
const blk1 = await job1.mineAsync();
const blk2 = await job2.mineAsync();
- const hash1 = blk1.hash('hex');
- const hash2 = blk2.hash('hex');
+ const hash1 = blk1.hash();
+ const hash2 = blk2.hash();
assert(await chain.add(blk1));
assert(await chain.add(blk2));
- assert.strictEqual(chain.tip.hash, hash1);
+ assert.bufferEqual(chain.tip.hash, hash1);
tip1 = await chain.getEntry(hash1);
tip2 = await chain.getEntry(hash2);
@@ -200,7 +200,7 @@ describe('Chain', function() {
assert(await chain.add(block));
assert(forked);
- assert.strictEqual(chain.tip.hash, block.hash('hex'));
+ assert.bufferEqual(chain.tip.hash, block.hash());
assert(chain.tip.chainwork.gt(tip1.chainwork));
});
@@ -224,11 +224,11 @@ describe('Chain', function() {
assert(await chain.add(block));
- const hash = block.hash('hex');
+ const hash = block.hash();
const entry = await chain.getEntry(hash);
assert(entry);
- assert.strictEqual(chain.tip.hash, entry.hash);
+ assert.bufferEqual(chain.tip.hash, entry.hash);
const result = await chain.isMainChain(entry);
assert(result);
@@ -318,7 +318,7 @@ describe('Chain', function() {
const tx = block.txs[1];
const output = Coin.fromTX(tx, 2, chain.height);
- const coin = await chain.getCoin(tx.hash('hex'), 2);
+ const coin = await chain.getCoin(tx.hash(), 2);
assert.bufferEqual(coin.toRaw(), output.toRaw());
});
@@ -334,7 +334,14 @@ describe('Chain', function() {
{
const tips = await chain.db.getTips();
- assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1);
+ let index = -1;
+
+ for (let i = 0; i < tips.length; i++) {
+ if (tips[i].equals(chain.tip.hash))
+ index = i;
+ }
+
+ assert.notStrictEqual(index, -1);
assert.strictEqual(tips.length, 2);
}
@@ -343,7 +350,14 @@ describe('Chain', function() {
{
const tips = await chain.db.getTips();
- assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1);
+ let index = -1;
+
+ for (let i = 0; i < tips.length; i++) {
+ if (tips[i].equals(chain.tip.hash))
+ index = i;
+ }
+
+ assert.notStrictEqual(index, -1);
assert.strictEqual(tips.length, 1);
}
});
@@ -578,7 +592,7 @@ describe('Chain', function() {
output.script.compile();
block.refresh(true);
- block.merkleRoot = block.createMerkleRoot('hex');
+ block.merkleRoot = block.createMerkleRoot();
assert.strictEqual(await addBlock(block, flags),
'bad-witness-merkle-match');
@@ -595,7 +609,7 @@ describe('Chain', function() {
tx.outputs.pop();
block.refresh(true);
- block.merkleRoot = block.createMerkleRoot('hex');
+ block.merkleRoot = block.createMerkleRoot();
assert.strictEqual(await addBlock(block, flags), 'unexpected-witness');
});
@@ -817,7 +831,7 @@ describe('Chain', function() {
}
block.refresh(true);
- block.merkleRoot = block.createMerkleRoot('hex');
+ block.merkleRoot = block.createMerkleRoot();
assert(await chain.add(block, flags));
}
diff --git a/test/coins-test.js b/test/coins-test.js
index 72ef2944e..daa88b9c0 100644
--- a/test/coins-test.js
+++ b/test/coins-test.js
@@ -31,7 +31,7 @@ function deepCoinsEqual(a, b) {
describe('Coins', function() {
it('should instantiate coinview from tx', () => {
const [tx] = tx1.getTX();
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const view = new CoinView();
const prevout = new Outpoint(hash, 0);
const input = Input.fromOutpoint(prevout);
@@ -59,7 +59,7 @@ describe('Coins', function() {
it('should spend an output', () => {
const [tx] = tx1.getTX();
- const hash = tx.hash('hex');
+ const hash = tx.hash();
const view = new CoinView();
view.addTX(tx, 1);
diff --git a/test/headers-test.js b/test/headers-test.js
index 41b17745c..f0512a51c 100644
--- a/test/headers-test.js
+++ b/test/headers-test.js
@@ -26,9 +26,9 @@ describe('Headers', function() {
assert.strictEqual(headers.nonce, 2573394689);
assert.strictEqual(headers.version, 1);
- assert.strictEqual(headers.prevBlock,
+ assert.strictEqual(headers.prevBlock.toString('hex'),
'6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000');
- assert.strictEqual(headers.merkleRoot,
+ assert.strictEqual(headers.merkleRoot.toString('hex'),
'982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e');
assert.strictEqual(headers.rhash(),
'00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048');
@@ -45,9 +45,9 @@ describe('Headers', function() {
assert.strictEqual(headers.nonce, 2573394689);
assert.strictEqual(headers.version, 1);
- assert.strictEqual(headers.prevBlock,
+ assert.strictEqual(headers.prevBlock.toString('hex'),
'6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000');
- assert.strictEqual(headers.merkleRoot,
+ assert.strictEqual(headers.merkleRoot.toString('hex'),
'982051fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e');
assert.strictEqual(headers.rhash(),
'00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048');
diff --git a/test/http-test.js b/test/http-test.js
index 216f46812..1f9d04716 100644
--- a/test/http-test.js
+++ b/test/http-test.js
@@ -80,7 +80,7 @@ describe('HTTP', function() {
it('should fill with funds', async () => {
const mtx = new MTX();
- mtx.addOutpoint(new Outpoint(consensus.NULL_HASH, 0));
+ mtx.addOutpoint(new Outpoint(consensus.ZERO_HASH, 0));
mtx.addOutput(addr, 50460);
mtx.addOutput(addr, 50460);
mtx.addOutput(addr, 50460);
diff --git a/test/input-test.js b/test/input-test.js
index 83e7e2f6c..8fa4f18a5 100644
--- a/test/input-test.js
+++ b/test/input-test.js
@@ -216,8 +216,9 @@ describe('Input', function() {
const options = {
prevout: {
- hash: '8759d7397a86d6c42dfe2c55612e523d' +
- '171e51708fec9e289118deb5ba994001',
+ hash: Buffer.from(
+ '8759d7397a86d6c42dfe2c55612e523d' +
+ '171e51708fec9e289118deb5ba994001', 'hex'),
index: 1
},
script: rawscript,
@@ -236,7 +237,7 @@ describe('Input', function() {
const inputs = test.inputs.map((prevout, i) => {
const input = Input.fromOptions({
prevout: {
- hash: util.revHex(prevout.txId),
+ hash: util.fromRev(prevout.txId),
index: prevout.vout
}
});
diff --git a/test/mempool-test.js b/test/mempool-test.js
index 773796327..992e82e46 100644
--- a/test/mempool-test.js
+++ b/test/mempool-test.js
@@ -81,7 +81,7 @@ describe('Mempool', function() {
const script = Script.fromPubkey(key.publicKey);
- t1.addCoin(dummyInput(script, ONE_HASH.toString('hex')));
+ t1.addCoin(dummyInput(script, ONE_HASH));
const sig = t1.signature(0, script, 70000, key.privateKey, ALL, 0);
@@ -173,7 +173,7 @@ describe('Mempool', function() {
const txs = mempool.getHistory();
assert(txs.some((tx) => {
- return tx.hash('hex') === f1.hash('hex');
+ return tx.hash().equals(f1.hash());
}));
});
@@ -185,7 +185,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromPubkey(key.publicKey);
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
tx.setLocktime(200);
@@ -207,7 +207,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromPubkey(key.publicKey);
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
tx.setLocktime(200);
@@ -238,7 +238,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromProgram(0, key.getKeyHash());
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
@@ -268,7 +268,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromPubkey(key.publicKey);
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
@@ -297,7 +297,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromProgram(0, key.getKeyHash());
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
@@ -321,7 +321,7 @@ describe('Mempool', function() {
tx.addOutput(wallet.getAddress(), 10000);
const prev = Script.fromPubkey(key.publicKey);
- const prevHash = random.randomBytes(32).toString('hex');
+ const prevHash = random.randomBytes(32);
tx.addCoin(dummyInput(prev, prevHash));
diff --git a/test/node-test.js b/test/node-test.js
index ed13cecd5..6b9937eb3 100644
--- a/test/node-test.js
+++ b/test/node-test.js
@@ -115,10 +115,10 @@ describe('Node', function() {
await chain.add(block2);
- assert.strictEqual(chain.tip.hash, block1.hash('hex'));
+ assert.bufferEqual(chain.tip.hash, block1.hash());
- tip1 = await chain.getEntry(block1.hash('hex'));
- tip2 = await chain.getEntry(block2.hash('hex'));
+ tip1 = await chain.getEntry(block1.hash());
+ tip2 = await chain.getEntry(block2.hash());
assert(tip1);
assert(tip2);
@@ -162,7 +162,7 @@ describe('Node', function() {
await chain.add(block);
assert(forked);
- assert.strictEqual(chain.tip.hash, block.hash('hex'));
+ assert.bufferEqual(chain.tip.hash, block.hash());
assert(chain.tip.chainwork.gt(tip1.chainwork));
});
@@ -190,9 +190,9 @@ describe('Node', function() {
await chain.add(block);
- const entry = await chain.getEntry(block.hash('hex'));
+ const entry = await chain.getEntry(block.hash());
assert(entry);
- assert.strictEqual(chain.tip.hash, entry.hash);
+ assert.bufferEqual(chain.tip.hash, entry.hash);
const result = await chain.isMainChain(entry);
assert(result);
@@ -246,7 +246,7 @@ describe('Node', function() {
const tx = block2.txs[1];
const output = Coin.fromTX(tx, 1, chain.height);
- const coin = await chain.getCoin(tx.hash('hex'), 1);
+ const coin = await chain.getCoin(tx.hash(), 1);
assert.bufferEqual(coin.toRaw(), output.toRaw());
});
@@ -271,7 +271,14 @@ describe('Node', function() {
{
const tips = await chain.db.getTips();
- assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1);
+ let index = -1;
+
+ for (let i = 0; i < tips.length; i++) {
+ if (tips[i].equals(chain.tip.hash))
+ index = i;
+ }
+
+ assert.notStrictEqual(index, -1);
assert.strictEqual(tips.length, 2);
}
@@ -280,7 +287,14 @@ describe('Node', function() {
{
const tips = await chain.db.getTips();
- assert.notStrictEqual(tips.indexOf(chain.tip.hash), -1);
+ let index = -1;
+
+ for (let i = 0; i < tips.length; i++) {
+ if (tips[i].equals(chain.tip.hash))
+ index = i;
+ }
+
+ assert.notStrictEqual(index, -1);
assert.strictEqual(tips.length, 1);
}
});
@@ -545,7 +559,7 @@ describe('Node', function() {
assert(!json.error);
assert.strictEqual(json.result, null);
- assert.strictEqual(node.chain.tip.hash, block.hash('hex'));
+ assert.bufferEqual(node.chain.tip.hash, block.hash());
});
it('should validate an address', async () => {
diff --git a/test/outpoint-test.js b/test/outpoint-test.js
index 46c715754..cab9ae7e4 100644
--- a/test/outpoint-test.js
+++ b/test/outpoint-test.js
@@ -44,7 +44,8 @@ describe('Outpoint', () => {
it('should compare the indexes between outpoints', () => {
const out1RevHash = out1.clone();
- out1RevHash.hash = out1RevHash.rhash();
+ out1RevHash.hash = Buffer.from(out1RevHash.hash);
+ out1RevHash.hash[0] = 0;
const out1AdjIndex = out1.clone();
out1AdjIndex.index += 1;
@@ -66,18 +67,18 @@ describe('Outpoint', () => {
});
it('should retrieve little endian hash', () => {
- assert.equal(out1.rhash(), util.revHex(out1.hash));
- assert.equal(out1.txid(), util.revHex(out1.hash));
+ assert.strictEqual(out1.rhash(), util.revHex(out1.hash));
+ assert.strictEqual(out1.txid(), util.revHex(out1.hash));
});
it('should serialize to a key suitable for hash table', () => {
- const expected = out1.hash + out1.index;
+ const expected = out1.toRaw();
const actual = out1.toKey();
- assert.equal(expected, actual);
+ assert.bufferEqual(expected, actual);
});
it('should inject properties from hash table key', () => {
- const key = out1.hash + out1.index;
+ const key = out1.toKey();
const fromKey = Outpoint.fromKey(key);
assert(out1.equals(fromKey), true);
});
@@ -112,7 +113,7 @@ describe('Outpoint', () => {
const index = 0;
const fromTX = Outpoint.fromTX(tx, index);
- assert.equal(fromTX.hash, tx.hash('hex'));
- assert.equal(fromTX.index, index);
+ assert.bufferEqual(fromTX.hash, tx.hash());
+ assert.strictEqual(fromTX.index, index);
});
});
diff --git a/test/script-test.js b/test/script-test.js
index b4ae3e46b..38bbcd886 100644
--- a/test/script-test.js
+++ b/test/script-test.js
@@ -286,7 +286,7 @@ describe('Script', function() {
version: 1,
inputs: [{
prevout: {
- hash: consensus.NULL_HASH,
+ hash: consensus.ZERO_HASH,
index: 0xffffffff
},
script: [
@@ -308,7 +308,7 @@ describe('Script', function() {
version: 1,
inputs: [{
prevout: {
- hash: prev.hash('hex'),
+ hash: prev.hash(),
index: 0
},
script: input,
diff --git a/test/tx-test.js b/test/tx-test.js
index 659d8d841..0a83eab73 100644
--- a/test/tx-test.js
+++ b/test/tx-test.js
@@ -69,7 +69,7 @@ function parseTXTest(data) {
const view = new CoinView();
for (const [txid, index, str, amount] of coins) {
- const hash = util.revHex(txid);
+ const hash = util.fromRev(txid);
const script = Script.fromString(str);
const value = parseInt(amount || '0', 10);
@@ -106,7 +106,7 @@ function parseSighashTest(data) {
const tx = TX.fromRaw(txHex, 'hex');
const script = Script.fromRaw(scriptHex, 'hex');
- const expected = util.revHex(hash);
+ const expected = util.fromRev(hash);
let hex = type & 3;
@@ -130,7 +130,7 @@ function parseSighashTest(data) {
}
function createInput(value, view) {
- const hash = random.randomBytes(32).toString('hex');
+ const hash = random.randomBytes(32);
const input = {
prevout: {
@@ -173,7 +173,7 @@ function sigopContext(scriptSig, witness, scriptPubkey) {
spend.version = 1;
const input = new Input();
- input.prevout.hash = fund.hash('hex');
+ input.prevout.hash = fund.hash();
input.prevout.index = 0;
input.script = scriptSig;
input.witness = witness;
@@ -235,7 +235,7 @@ describe('TX', function() {
assert.strictEqual(tx.outputs.length, 1980);
assert(tx.hasWitness());
assert.notStrictEqual(tx.txid(), tx.wtxid());
- assert.strictEqual(tx.witnessHash('hex'),
+ assert.strictEqual(tx.witnessHash().toString('hex'),
'088c919cd8408005f255c411f786928385688a9e8fdb2db4c9bc3578ce8c94cf');
assert.strictEqual(tx.getSize(), 62138);
assert.strictEqual(tx.getVirtualSize(), 61813);
@@ -339,7 +339,7 @@ describe('TX', function() {
it(`should get sighash of ${hash} (${hex}) ${suffix}`, () => {
const subscript = script.getSubscript(0).removeSeparators();
const hash = tx.signatureHash(index, subscript, 0, type, 0);
- assert.strictEqual(hash.toString('hex'), expected);
+ assert.bufferEqual(hash, expected);
});
}
}
@@ -695,7 +695,7 @@ describe('TX', function() {
const output = Script.fromProgram(0, key.getKeyHash());
const ctx = sigopContext(input, witness, output);
- ctx.spend.inputs[0].prevout.hash = consensus.NULL_HASH;
+ ctx.spend.inputs[0].prevout.hash = consensus.ZERO_HASH;
ctx.spend.inputs[0].prevout.index = 0xffffffff;
ctx.spend.refresh();
@@ -899,14 +899,11 @@ describe('TX', function() {
];
const hashesBuf = tx.getHashes(view);
- const hashesHex = tx.getHashes(view, 'hex');
assert.strictEqual(hashes.length, hashesBuf.length);
- assert.strictEqual(hashes.length, hashesHex.length);
hashes.forEach((hash, i) => {
assert.bufferEqual(hash, hashesBuf[i]);
- assert.strictEqual(hash.toString('hex'), hashesHex[i]);
});
});
@@ -919,14 +916,11 @@ describe('TX', function() {
];
const hashesBuf = tx.getInputHashes(view);
- const hashesHex = tx.getInputHashes(view, 'hex');
assert.strictEqual(inputHashes.length, hashesBuf.length);
- assert.strictEqual(inputHashes.length, hashesHex.length);
inputHashes.forEach((hash, i) => {
assert.bufferEqual(hash, hashesBuf[i]);
- assert.strictEqual(hash.toString('hex'), hashesHex[i]);
});
});
@@ -940,14 +934,11 @@ describe('TX', function() {
];
const hashesBuf = tx.getOutputHashes();
- const hashesHex = tx.getOutputHashes('hex');
assert.strictEqual(outputHashes.length, hashesBuf.length);
- assert.strictEqual(outputHashes.length, hashesHex.length);
outputHashes.forEach((hash, i) => {
assert.bufferEqual(hash, hashesBuf[i]);
- assert.strictEqual(hash.toString('hex'), hashesHex[i]);
});
});
@@ -963,7 +954,7 @@ describe('TX', function() {
assert(expectedPrevouts.length, prevouts.length);
expectedPrevouts.forEach((prevout, i) => {
- assert.strictEqual(prevout, prevouts[i]);
+ assert.strictEqual(prevout, prevouts[i].toString('hex'));
});
});
@@ -1063,7 +1054,9 @@ describe('TX', function() {
// hack for ChainEntry
const entry = {
height: 1000,
- hash: 'c82d447db6150d2308d9571c19bc3dc6efde97a8227d9e57bc77ec0900000000',
+ hash: Buffer.from(
+ 'c82d447db6150d2308d9571c19bc3dc6efde97a8227d9e57bc77ec0900000000',
+ 'hex'),
time: 1365870306
};
const network = 'testnet';
diff --git a/test/util/memwallet.js b/test/util/memwallet.js
index 7e9c2725d..ace6d3a2e 100644
--- a/test/util/memwallet.js
+++ b/test/util/memwallet.js
@@ -7,6 +7,7 @@
'use strict';
const assert = require('assert');
+const {BufferMap, BufferSet} = require('buffer-map');
const Network = require('../../lib/protocol/network');
const MTX = require('../../lib/primitives/mtx');
const HD = require('../../lib/hd/hd');
@@ -26,10 +27,10 @@ class MemWallet {
this.changeDepth = 1;
this.receive = null;
this.change = null;
- this.map = new Set();
- this.coins = new Map();
- this.spent = new Map();
- this.paths = new Map();
+ this.map = new BufferSet();
+ this.coins = new BufferMap();
+ this.spent = new BufferMap();
+ this.paths = new BufferMap();
this.balance = 0;
this.txs = 0;
this.filter = BloomFilter.fromRate(1000000, 0.001, -1);
@@ -102,8 +103,8 @@ class MemWallet {
createReceive() {
const index = this.receiveDepth++;
const key = this.deriveReceive(index);
- const hash = key.getHash('hex');
- this.filter.add(hash, 'hex');
+ const hash = key.getHash();
+ this.filter.add(hash);
this.paths.set(hash, new Path(hash, 0, index));
this.receive = key;
return key;
@@ -112,8 +113,8 @@ class MemWallet {
createChange() {
const index = this.changeDepth++;
const key = this.deriveChange(index);
- const hash = key.getHash('hex');
- this.filter.add(hash, 'hex');
+ const hash = key.getHash();
+ this.filter.add(hash);
this.paths.set(hash, new Path(hash, 1, index));
this.change = key;
return key;
@@ -246,7 +247,7 @@ class MemWallet {
}
addTX(tx, height) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
let result = false;
if (height == null)
@@ -270,7 +271,7 @@ class MemWallet {
for (let i = 0; i < tx.outputs.length; i++) {
const output = tx.outputs[i];
- const addr = output.getHash('hex');
+ const addr = output.getHash();
if (!addr)
continue;
@@ -297,7 +298,7 @@ class MemWallet {
}
removeTX(tx, height) {
- const hash = tx.hash('hex');
+ const hash = tx.hash();
let result = false;
if (!this.map.has(hash))
@@ -346,7 +347,7 @@ class MemWallet {
if (!coin)
continue;
- const addr = coin.getHash('hex');
+ const addr = coin.getHash();
if (!addr)
continue;
diff --git a/test/wallet-test.js b/test/wallet-test.js
index e59f7fbc9..669a88415 100644
--- a/test/wallet-test.js
+++ b/test/wallet-test.js
@@ -55,9 +55,9 @@ function fakeBlock(height) {
const root = hash256.digest(fromU32((height | 0x80000000) >>> 0));
return {
- hash: hash.toString('hex'),
- prevBlock: prev.toString('hex'),
- merkleRoot: root.toString('hex'),
+ hash: hash,
+ prevBlock: prev,
+ merkleRoot: root,
time: 500000000 + (height * (10 * 60)),
bits: 0,
nonce: 0,
@@ -66,7 +66,7 @@ function fakeBlock(height) {
}
function dummyInput() {
- const hash = random.randomBytes(32).toString('hex');
+ const hash = random.randomBytes(32);
return Input.fromOutpoint(new Outpoint(hash, 0));
}
@@ -398,7 +398,7 @@ describe('Wallet', function() {
const txs = await alice.getHistory();
assert(txs.some((wtx) => {
- return wtx.hash === f1.hash('hex');
+ return wtx.hash.equals(f1.hash());
}));
}
@@ -408,7 +408,7 @@ describe('Wallet', function() {
const txs = await bob.getHistory();
assert(txs.some((wtx) => {
- return wtx.tx.hash('hex') === f1.hash('hex');
+ return wtx.tx.hash().equals(f1.hash());
}));
}
@@ -428,7 +428,7 @@ describe('Wallet', function() {
const txs = await alice.getHistory();
assert(txs.some((wtx) => {
- return wtx.hash === f1.hash('hex');
+ return wtx.hash.equals(f1.hash());
}));
}
@@ -439,7 +439,7 @@ describe('Wallet', function() {
const txs = await bob.getHistory();
assert(txs.some((wtx) => {
- return wtx.tx.hash('hex') === f1.hash('hex');
+ return wtx.tx.hash().equals(f1.hash());
}));
}
});
@@ -589,7 +589,7 @@ describe('Wallet', function() {
const txs = await alice.getHistory();
assert(txs.some((wtx) => {
- return wtx.tx.hash('hex') === f1.hash('hex');
+ return wtx.tx.hash().equals(f1.hash());
}));
}
@@ -599,7 +599,7 @@ describe('Wallet', function() {
const txs = await bob.getHistory();
assert(txs.some((wtx) => {
- return wtx.tx.hash('hex') === f1.hash('hex');
+ return wtx.tx.hash().equals(f1.hash());
}));
}
@@ -685,7 +685,7 @@ describe('Wallet', function() {
// Coinbase
const t1 = new MTX();
- t1.addOutpoint(new Outpoint(consensus.NULL_HASH, 0));
+ t1.addOutpoint(new Outpoint(consensus.ZERO_HASH, 0));
t1.addOutput(await alice.receiveAddress(), 5460);
t1.addOutput(await alice.receiveAddress(), 5460);
t1.addOutput(await alice.receiveAddress(), 5460);
@@ -1263,9 +1263,9 @@ describe('Wallet', function() {
await wallet.importKey('default', key, 'test');
- const wkey = await wallet.getKey(key.getHash('hex'));
+ const wkey = await wallet.getKey(key.getHash());
- assert.strictEqual(wkey.getHash('hex'), key.getHash('hex'));
+ assert.bufferEqual(wkey.getHash(), key.getHash());
// Coinbase
const t1 = new MTX();
@@ -1278,9 +1278,9 @@ describe('Wallet', function() {
await wdb.addTX(t1.toTX());
- const wtx = await wallet.getTX(t1.hash('hex'));
+ const wtx = await wallet.getTX(t1.hash());
assert(wtx);
- assert.strictEqual(t1.hash('hex'), wtx.hash);
+ assert.bufferEqual(t1.hash(), wtx.hash);
const options = {
rate: 10000,
@@ -1295,7 +1295,7 @@ describe('Wallet', function() {
const t2 = await wallet.createTX(options);
await wallet.sign(t2);
assert(t2.verify());
- assert.strictEqual(t2.inputs[0].prevout.hash, wtx.hash);
+ assert.bufferEqual(t2.inputs[0].prevout.hash, wtx.hash);
importedWallet = wallet;
importedKey = key;
@@ -1311,10 +1311,10 @@ describe('Wallet', function() {
await wallet.importKey('default', pub);
- const path = await wallet.getPath(pub.getHash('hex'));
- assert.strictEqual(path.hash, pub.getHash('hex'));
+ const path = await wallet.getPath(pub.getHash());
+ assert.bufferEqual(path.hash, pub.getHash());
- const wkey = await wallet.getKey(pub.getHash('hex'));
+ const wkey = await wallet.getKey(pub.getHash());
assert(wkey);
});
@@ -1327,11 +1327,11 @@ describe('Wallet', function() {
await wallet.importAddress('default', key.getAddress());
- const path = await wallet.getPath(key.getHash('hex'));
+ const path = await wallet.getPath(key.getHash());
assert(path);
- assert.strictEqual(path.hash, key.getHash('hex'));
+ assert.bufferEqual(path.hash, key.getHash());
- const wkey = await wallet.getKey(key.getHash('hex'));
+ const wkey = await wallet.getKey(key.getHash());
assert(!wkey);
});
@@ -1401,7 +1401,7 @@ describe('Wallet', function() {
const key = await wallet.getKey(addr);
assert(key);
- assert.strictEqual(key.getHash('hex'), addr.getHash('hex'));
+ assert.bufferEqual(key.getHash(), addr.getHash());
});
it('should recover from a missed tx', async () => {