bcoin: use buffer-map. see #533.

This commit is contained in:
Christopher Jeffrey 2018-07-14 00:31:19 -07:00
parent eea4013dcf
commit b92839c82a
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
74 changed files with 776 additions and 793 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -2,6 +2,8 @@
'use strict';
Buffer.poolSize = 2;
process.title = 'bcoin';
if (process.argv.indexOf('--help') !== -1

View File

@ -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(
`<a style="display:block;" href="#${tx.hash}">${tx.hash}</a>`);
`<a style="display:block;" href="#${hash}">${hash}</a>`);
wdiv.appendChild(el);
setMouseup(el, tx.toJSON());
}

View File

@ -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);

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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'])
};
/*

View File

@ -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);
}

View File

@ -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());

View File

@ -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'])
};
/*

View File

@ -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();

View File

@ -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

View File

@ -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();
});
}

View File

@ -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;

View File

@ -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) {

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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.');

View File

@ -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

View File

@ -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());
}
}

View File

@ -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;
}
/**

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -68,7 +68,7 @@ class InvItem {
fromReader(br) {
this.type = br.readU32();
this.hash = br.readHash('hex');
this.hash = br.readHash();
return this;
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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();
}
/**

View File

@ -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 [, table] = this._getInputAddresses(view);
const addrs = this.getInputAddresses(view);
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'));
}
/**
@ -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 [, table] = this._getAddresses(view);
const addrs = this.getAddresses(view);
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'));
}
/**
@ -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());
}
/**

View File

@ -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();

View File

@ -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.

View File

@ -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}`

View File

@ -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,

View File

@ -3270,7 +3270,7 @@ class Script {
*/
fromRaw(data) {
const br = bio.read(data, true);
const br = bio.read(data);
this.raw = data;

View File

@ -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;
}

View File

@ -100,9 +100,10 @@ util.time = function time(date) {
* @returns {String} Reversed hex string.
*/
util.revHex = function revHex(str) {
assert(typeof str === 'string');
assert((str.length & 1) === 0);
util.revHex = function revHex(buf) {
assert(Buffer.isBuffer(buf));
const str = buf.toString('hex');
let out = '';
@ -111,3 +112,15 @@ util.revHex = function revHex(str) {
return out;
};
util.fromRev = function fromRev(str) {
assert(typeof str === 'string');
assert((str.length & 1) === 0);
let out = '';
for (let i = str.length - 2; i >= 0; i -= 2)
out += str[i] + str[i + 1];
return Buffer.from(out, 'hex');
};

View File

@ -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);
}

View File

@ -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)
};

View File

@ -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);
}
}

View File

@ -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.');

View File

@ -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'])
};

View File

@ -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));
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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) {

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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();

View File

@ -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();

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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)
];
}

View File

@ -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"
},

View File

@ -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,

View File

@ -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'
+ 'e763272c6c9ca052972c69e3884a9022084215e2eef'
+ '0e6f781656b5d5a87231cd4349e534b6dea55ad4ff55e';
const item1 = Buffer.from(
'8e7445bbb8abd4b3174d80fa4c409fea6b94d96b',
'hex');
filter.add(item1, 'hex');
filter.add(item2, 'hex');
const item2 = Buffer.from('047b00000078da0dca3b0ec2300c00d0ab4466ed10'
+ 'e763272c6c9ca052972c69e3884a9022084215e2eef'
+ '0e6f781656b5d5a87231cd4349e534b6dea55ad4ff55e', '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();

View File

@ -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));
}

View File

@ -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);

View File

@ -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');

View File

@ -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);

View File

@ -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
}
});

View File

@ -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));

View File

@ -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 () => {

View File

@ -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);
});
});

View File

@ -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,

View File

@ -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';

View File

@ -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;

View File

@ -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 () => {