bcoin: use buffer-map. see #533.
This commit is contained in:
parent
eea4013dcf
commit
b92839c82a
12
bench/tx.js
12
bench/tx.js
@ -84,7 +84,7 @@ const tx10 = common.readTX('tx10');
|
||||
const end = bench('input hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx.getInputHashes(null, 'hex');
|
||||
tx.getInputHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
@ -94,7 +94,7 @@ const tx10 = common.readTX('tx10');
|
||||
const end = bench('output hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx.getOutputHashes('hex');
|
||||
tx.getOutputHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
@ -104,7 +104,7 @@ const tx10 = common.readTX('tx10');
|
||||
const end = bench('all hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx.getHashes(null, 'hex');
|
||||
tx.getHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
@ -176,7 +176,7 @@ const tx2 = mtx.toTX();
|
||||
const end = bench('input hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx2.getInputHashes(null, 'hex');
|
||||
tx2.getInputHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
@ -185,7 +185,7 @@ const tx2 = mtx.toTX();
|
||||
const end = bench('output hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx2.getOutputHashes('hex');
|
||||
tx2.getOutputHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
@ -194,7 +194,7 @@ const tx2 = mtx.toTX();
|
||||
const end = bench('all hashes');
|
||||
|
||||
for (let i = 0; i < 10000; i++)
|
||||
tx2.getHashes(null, 'hex');
|
||||
tx2.getHashes();
|
||||
|
||||
end(10000);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
2
bin/node
2
bin/node
@ -2,6 +2,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
Buffer.poolSize = 2;
|
||||
|
||||
process.title = 'bcoin';
|
||||
|
||||
if (process.argv.indexOf('--help') !== -1
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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'])
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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'])
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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.');
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ class InvItem {
|
||||
|
||||
fromReader(br) {
|
||||
this.type = br.readU32();
|
||||
this.hash = br.readHash('hex');
|
||||
this.hash = br.readHash();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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}`
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -3270,7 +3270,7 @@ class Script {
|
||||
*/
|
||||
|
||||
fromRaw(data) {
|
||||
const br = bio.read(data, true);
|
||||
const br = bio.read(data);
|
||||
|
||||
this.raw = data;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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');
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
};
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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.');
|
||||
|
||||
|
||||
@ -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'])
|
||||
};
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
11
package.json
11
package.json
@ -26,7 +26,7 @@
|
||||
"bcfg": "~0.1.0",
|
||||
"bclient": "~0.1.1",
|
||||
"bcrypto": "~0.3.7",
|
||||
"bdb": "~0.2.1",
|
||||
"bdb": "~0.2.2",
|
||||
"bdns": "~0.1.0",
|
||||
"bevent": "~0.1.0",
|
||||
"bfile": "~0.1.0",
|
||||
@ -34,19 +34,20 @@
|
||||
"bheep": "~0.1.0",
|
||||
"binet": "~0.3.0",
|
||||
"blgr": "~0.1.0",
|
||||
"blru": "~0.1.0",
|
||||
"blru": "~0.1.1",
|
||||
"blst": "~0.1.0",
|
||||
"bmutex": "~0.1.0",
|
||||
"bmutex": "~0.1.1",
|
||||
"bn.js": "~4.11.8",
|
||||
"bsip": "~0.1.0",
|
||||
"bsock": "~0.1.2",
|
||||
"bsocks": "~0.2.0",
|
||||
"bstring": "~0.1.0",
|
||||
"btcp": "~0.1.0",
|
||||
"buffer-map": "~0.0.0",
|
||||
"bufio": "~0.2.0",
|
||||
"bupnp": "~0.2.1",
|
||||
"bval": "~0.1.0",
|
||||
"bweb": "~0.1.3",
|
||||
"bval": "~0.1.1",
|
||||
"bweb": "~0.1.1",
|
||||
"mrmr": "~0.1.0",
|
||||
"n64": "~0.2.0"
|
||||
},
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
}
|
||||
});
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user