modules: more refactoring.
This commit is contained in:
parent
729aea3b41
commit
0631148705
@ -24,17 +24,6 @@ function processEnv(str) {
|
||||
'$1this.$2 = require(\'$3\')');
|
||||
}
|
||||
|
||||
function processLazy(str) {
|
||||
str.replace(
|
||||
/^( *)lazy\('(\w+)', '([^']+)'\)/gm,
|
||||
function(_, sp, w1, w2) {
|
||||
str += sp + 'if (0) require(\'' + w2 + '\');\n';
|
||||
return '';
|
||||
}
|
||||
);
|
||||
return str;
|
||||
}
|
||||
|
||||
function transformer(file, process) {
|
||||
var stream = new Transform();
|
||||
var decoder = new StringDecoder('utf8');
|
||||
@ -62,12 +51,6 @@ function end(file, offset) {
|
||||
}
|
||||
|
||||
module.exports = function(file) {
|
||||
if (end(file, 3) === 'lib/utils/utils.js')
|
||||
return transformer(file, processLazy);
|
||||
|
||||
if (end(file, 3) === 'lib/crypto/crypto.js')
|
||||
return transformer(file, processLazy);
|
||||
|
||||
if (end(file, 2) === 'lib/env.js')
|
||||
return transformer(file, processEnv);
|
||||
|
||||
|
||||
@ -13,12 +13,14 @@ var Logger = require('../node/logger');
|
||||
var ChainDB = require('./chaindb');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var Locker = require('../utils/locker');
|
||||
var ChainEntry = require('./chainentry');
|
||||
var CoinView = require('./coinview');
|
||||
var assert = require('assert');
|
||||
var VerifyError = require('../utils/errors').VerifyError;
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var errors = require('../utils/errors');
|
||||
var VerifyError = errors.VerifyError;
|
||||
var VerifyResult = errors.VerifyResult;
|
||||
var time = require('../net/timedata');
|
||||
var co = require('../utils/co');
|
||||
|
||||
@ -1859,7 +1861,7 @@ Chain.prototype.retarget = function retarget(prev, first) {
|
||||
return prev.bits;
|
||||
|
||||
actualTimespan = prev.ts - first.ts;
|
||||
target = utils.fromCompact(prev.bits);
|
||||
target = btcutils.fromCompact(prev.bits);
|
||||
|
||||
if (actualTimespan < targetTimespan / 4 | 0)
|
||||
actualTimespan = targetTimespan / 4 | 0;
|
||||
@ -1873,7 +1875,7 @@ Chain.prototype.retarget = function retarget(prev, first) {
|
||||
if (target.cmp(pow.limit) > 0)
|
||||
return pow.bits;
|
||||
|
||||
return utils.toCompact(target);
|
||||
return btcutils.toCompact(target);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -13,6 +13,7 @@ var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var encoding = require('../utils/encoding');
|
||||
var co = require('../utils/co');
|
||||
var Network = require('../protocol/network');
|
||||
var CoinView = require('./coinview');
|
||||
@ -26,7 +27,7 @@ var Outpoint = require('../primitives/outpoint');
|
||||
var TX = require('../primitives/tx');
|
||||
var Address = require('../primitives/address');
|
||||
var ChainEntry = require('./chainentry');
|
||||
var U32 = utils.U32;
|
||||
var U32 = encoding.U32;
|
||||
var DUMMY = new Buffer([0]);
|
||||
|
||||
/**
|
||||
|
||||
@ -11,6 +11,7 @@ var BN = require('bn.js');
|
||||
var Network = require('../protocol/network');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
@ -124,7 +125,7 @@ ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
|
||||
*/
|
||||
|
||||
ChainEntry.prototype.getProof = function getProof() {
|
||||
var target = utils.fromCompact(this.bits);
|
||||
var target = btcutils.fromCompact(this.bits);
|
||||
if (target.isNeg() || target.cmpn(0) === 0)
|
||||
return new BN(0);
|
||||
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
||||
|
||||
@ -739,6 +739,8 @@ AES.cbc.decrypt = function decrypt(data, key, iv) {
|
||||
AES.Key = AESKey;
|
||||
AES.Cipher = AESCipher;
|
||||
AES.Decipher = AESDecipher;
|
||||
AES.encipher = AES.cbc.encrypt;
|
||||
AES.decipher = AES.cbc.decrypt;
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
|
||||
@ -10,16 +10,9 @@
|
||||
var assert = require('assert');
|
||||
var scrypt = require('./scrypt');
|
||||
var scryptAsync = require('./scrypt-async');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var native = require('../utils/native').binding;
|
||||
var backend = require('./backend');
|
||||
var lazy = utils.lazy(require, exports);
|
||||
|
||||
/**
|
||||
* @exports crypto
|
||||
*/
|
||||
|
||||
var crypto = exports;
|
||||
|
||||
/**
|
||||
@ -221,109 +214,6 @@ crypto.scryptAsync = function _scrypt(passwd, salt, N, r, p, len) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Derive a key using pbkdf2 with 50,000 iterations.
|
||||
* @param {Buffer|String} passphrase
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.derive = function derive(passphrase) {
|
||||
return crypto.pbkdf2Async(passphrase, 'bcoin', 50000, 32, 'sha256');
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt with aes-256-cbc. Derives key with {@link crypto.derive}.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer|String} passphrase
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.encrypt = co(function* encrypt(data, passphrase, iv) {
|
||||
var key;
|
||||
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(passphrase, 'No passphrase.');
|
||||
assert(Buffer.isBuffer(iv));
|
||||
|
||||
key = yield crypto.derive(passphrase);
|
||||
|
||||
try {
|
||||
data = crypto.encipher(data, key, iv);
|
||||
} catch (e) {
|
||||
crypto.cleanse(key);
|
||||
throw e;
|
||||
}
|
||||
|
||||
crypto.cleanse(key);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
/**
|
||||
* Encrypt with aes-256-cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 256 bit key.
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
crypto.encipher = function encipher(data, key, iv) {
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
|
||||
return backend.encipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt with aes-256-cbc. Derives key with {@link crypto.derive}.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer|String} passphrase
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
crypto.decrypt = co(function* decrypt(data, passphrase, iv) {
|
||||
var key;
|
||||
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(passphrase, 'No passphrase.');
|
||||
assert(Buffer.isBuffer(iv));
|
||||
|
||||
key = yield crypto.derive(passphrase);
|
||||
|
||||
try {
|
||||
data = crypto.decipher(data, key, iv);
|
||||
} catch (e) {
|
||||
crypto.cleanse(key);
|
||||
throw e;
|
||||
}
|
||||
|
||||
crypto.cleanse(key);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
/**
|
||||
* Decrypt with aes-256-cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 256 bit key.
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
crypto.decipher = function decipher(data, key, iv) {
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
return backend.decipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform key derivation using PBKDF2.
|
||||
* @private
|
||||
@ -414,74 +304,6 @@ crypto.hkdfExpand = function hkdfExpand(prk, info, len, alg) {
|
||||
return okm;
|
||||
};
|
||||
|
||||
/**
|
||||
* memcmp in constant time (can only return true or false).
|
||||
* This protects us against timing attacks when
|
||||
* comparing an input against a secret string.
|
||||
* @see https://cryptocoding.net/index.php/Coding_rules
|
||||
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
|
||||
* @param {Buffer} a
|
||||
* @param {Buffer} b
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
crypto.ccmp = function ccmp(a, b) {
|
||||
var i, res;
|
||||
|
||||
if (!Buffer.isBuffer(a))
|
||||
return false;
|
||||
|
||||
if (!Buffer.isBuffer(b))
|
||||
return false;
|
||||
|
||||
if (b.length === 0)
|
||||
return a.length === 0;
|
||||
|
||||
res = a.length ^ b.length;
|
||||
|
||||
for (i = 0; i < a.length; i++)
|
||||
res |= a[i] ^ b[i % b.length];
|
||||
|
||||
return res === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two bytes in constant time.
|
||||
* @param {Number} a
|
||||
* @param {Number} b
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
crypto.ceq = function ceq(a, b) {
|
||||
var r = ~(a ^ b) & 0xff;
|
||||
r &= r >>> 4;
|
||||
r &= r >>> 2;
|
||||
r &= r >>> 1;
|
||||
return r === 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A maybe-secure memzero.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
crypto.cleanse = function cleanse(data) {
|
||||
var ctr = crypto._counter;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
data[i] = ctr & 0xff;
|
||||
ctr += i;
|
||||
}
|
||||
|
||||
crypto._counter = ctr >>> 0;
|
||||
};
|
||||
|
||||
crypto._counter = 0;
|
||||
|
||||
if (native)
|
||||
crypto.cleanse = native.cleanse;
|
||||
|
||||
/**
|
||||
* Build a merkle tree from leaves.
|
||||
* @param {Buffer[]} leaves
|
||||
@ -503,7 +325,7 @@ crypto.buildMerkleTree = function buildMerkleTree(leaves) {
|
||||
right = tree[j + i2];
|
||||
|
||||
if (i2 === i + 1 && i2 + 1 === size
|
||||
&& utils.cmp(left, right) === 0) {
|
||||
&& left.compare(right) === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -600,6 +422,109 @@ crypto.checkMerkleBranch = function checkMerkleBranch(hash, branch, index) {
|
||||
if (native)
|
||||
crypto.checkMerkleBranch = native.checkMerkleBranch;
|
||||
|
||||
/**
|
||||
* Encrypt with aes-256-cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 256 bit key.
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
crypto.encipher = function encipher(data, key, iv) {
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
|
||||
return backend.encipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt with aes-256-cbc.
|
||||
* @param {Buffer} data
|
||||
* @param {Buffer} key - 256 bit key.
|
||||
* @param {Buffer} iv - 128 bit initialization vector.
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
crypto.decipher = function decipher(data, key, iv) {
|
||||
assert(Buffer.isBuffer(data));
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(Buffer.isBuffer(iv));
|
||||
assert(key.length === 32);
|
||||
assert(iv.length === 16);
|
||||
return backend.decipher(data, key, iv);
|
||||
};
|
||||
|
||||
/**
|
||||
* memcmp in constant time (can only return true or false).
|
||||
* This protects us against timing attacks when
|
||||
* comparing an input against a secret string.
|
||||
* @see https://cryptocoding.net/index.php/Coding_rules
|
||||
* @see `$ man 3 memcmp` (NetBSD's consttime_memequal)
|
||||
* @param {Buffer} a
|
||||
* @param {Buffer} b
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
crypto.ccmp = function ccmp(a, b) {
|
||||
var i, res;
|
||||
|
||||
if (!Buffer.isBuffer(a))
|
||||
return false;
|
||||
|
||||
if (!Buffer.isBuffer(b))
|
||||
return false;
|
||||
|
||||
if (b.length === 0)
|
||||
return a.length === 0;
|
||||
|
||||
res = a.length ^ b.length;
|
||||
|
||||
for (i = 0; i < a.length; i++)
|
||||
res |= a[i] ^ b[i % b.length];
|
||||
|
||||
return res === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two bytes in constant time.
|
||||
* @param {Number} a
|
||||
* @param {Number} b
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
crypto.ceq = function ceq(a, b) {
|
||||
var r = ~(a ^ b) & 0xff;
|
||||
r &= r >>> 4;
|
||||
r &= r >>> 2;
|
||||
r &= r >>> 1;
|
||||
return r === 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* A maybe-secure memzero.
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
crypto.cleanse = function cleanse(data) {
|
||||
var ctr = crypto._counter;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
data[i] = ctr & 0xff;
|
||||
ctr += i;
|
||||
}
|
||||
|
||||
crypto._counter = ctr >>> 0;
|
||||
};
|
||||
|
||||
crypto._counter = 0;
|
||||
|
||||
if (native)
|
||||
crypto.cleanse = native.cleanse;
|
||||
|
||||
/**
|
||||
* Generate some random bytes.
|
||||
* @function
|
||||
@ -635,14 +560,3 @@ crypto.randomRange = function randomRange(min, max) {
|
||||
var num = crypto.randomInt();
|
||||
return Math.floor((num / 0x100000000) * (max - min) + min);
|
||||
};
|
||||
|
||||
/*
|
||||
* Expose other objects.
|
||||
*/
|
||||
|
||||
lazy('aes', './aes');
|
||||
lazy('chachapoly', './chachapoly');
|
||||
lazy('ec', './ec'); // ec-secp256k1 - circular
|
||||
lazy('schnorr', './schnorr'); // circular
|
||||
lazy('siphash', './siphash');
|
||||
lazy('pk', './pk'); // circular
|
||||
|
||||
10
lib/env.js
10
lib/env.js
@ -119,6 +119,7 @@ function Environment() {
|
||||
|
||||
// Utils
|
||||
this.require('utils', './utils/utils');
|
||||
this.require('btcutils', './utils/btcutils');
|
||||
this.require('locker', './utils/locker');
|
||||
this.require('reader', './utils/reader');
|
||||
this.require('writer', './utils/writer');
|
||||
@ -127,10 +128,15 @@ function Environment() {
|
||||
this.require('uri', './utils/uri');
|
||||
this.require('errors', './utils/errors');
|
||||
this.require('co', './utils/co');
|
||||
this.require('base58', './utils/base58');
|
||||
this.require('asn1', './utils/asn1');
|
||||
this.require('pem', './utils/pem');
|
||||
this.require('protobuf', './utils/protobuf');
|
||||
|
||||
// Crypto
|
||||
this.require('ec', './crypto/ec');
|
||||
this.require('crypto', './crypto/crypto');
|
||||
this.require('ec', './crypto/ec');
|
||||
this.require('schnorr', './crypto/schnorr');
|
||||
|
||||
// DB
|
||||
this.require('lowlevelup', './db/lowlevelup');
|
||||
@ -251,7 +257,7 @@ Environment.prototype.cache = function cache() {
|
||||
this.fullnode;
|
||||
this.spvnode;
|
||||
this.http;
|
||||
this.crypto.schnorr;
|
||||
this.schnorr;
|
||||
this.uri;
|
||||
this.bip70;
|
||||
};
|
||||
|
||||
103
lib/hd/common.js
Normal file
103
lib/hd/common.js
Normal file
@ -0,0 +1,103 @@
|
||||
/*!
|
||||
* common.js - common functions for hd
|
||||
* Copyright (c) 2015-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var LRU = require('../utils/lru');
|
||||
var constants = require('../protocol/constants');
|
||||
var common = exports;
|
||||
|
||||
/**
|
||||
* LRU cache to avoid deriving keys twice.
|
||||
* @type {LRU}
|
||||
*/
|
||||
|
||||
common.cache = new LRU(500);
|
||||
|
||||
/**
|
||||
* Parse a derivation path and return an array of indexes.
|
||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
||||
* @param {String} path
|
||||
* @param {Number?} max - Max index.
|
||||
* @returns {Number[]}
|
||||
*/
|
||||
|
||||
common.parsePath = function parsePath(path, max) {
|
||||
var parts = path.split('/');
|
||||
var root = parts.shift();
|
||||
var result = [];
|
||||
var i, hardened, index;
|
||||
|
||||
if (max == null)
|
||||
max = constants.hd.MAX_INDEX;
|
||||
|
||||
if (root !== 'm'
|
||||
&& root !== 'M'
|
||||
&& root !== 'm\''
|
||||
&& root !== 'M\'') {
|
||||
throw new Error('Bad path root.');
|
||||
}
|
||||
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
index = parts[i];
|
||||
hardened = index[index.length - 1] === '\'';
|
||||
|
||||
if (hardened)
|
||||
index = index.slice(0, -1);
|
||||
|
||||
if (!/^\d+$/.test(index))
|
||||
throw new Error('Non-number path index.');
|
||||
|
||||
index = parseInt(index, 10);
|
||||
|
||||
if (hardened)
|
||||
index += constants.hd.HARDENED;
|
||||
|
||||
if (!(index >= 0 && index < max))
|
||||
throw new Error('Index out of range.');
|
||||
|
||||
result.push(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the key is a master key.
|
||||
* @param {HDPrivateKey|HDPublicKey} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
common.isMaster = function isMaster(key) {
|
||||
return key.depth === 0
|
||||
&& key.childIndex === 0
|
||||
&& key.parentFingerPrint.readUInt32LE(0, true) === 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the key is (most likely) a BIP44 account key.
|
||||
* @param {HDPrivateKey|HDPublicKey} key
|
||||
* @param {Number?} accountIndex
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
common.isAccount44 = function isAccount44(key, accountIndex) {
|
||||
if (accountIndex != null) {
|
||||
if (key.childIndex !== constants.hd.HARDENED + accountIndex)
|
||||
return false;
|
||||
}
|
||||
return key.depth === 3 && key.childIndex >= constants.hd.HARDENED;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether the key is a BIP45 purpose key.
|
||||
* @param {HDPrivateKey|HDPublicKey} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
common.isPurpose45 = function isPurpose45(key) {
|
||||
return key.depth === 1 && key.childIndex === constants.hd.HARDENED + 45;
|
||||
};
|
||||
57
lib/hd/hd.js
57
lib/hd/hd.js
@ -7,8 +7,6 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var LRU = require('../utils/lru');
|
||||
var Mnemonic = require('./mnemonic');
|
||||
var HDPrivateKey = require('./private');
|
||||
var HDPublicKey = require('./public');
|
||||
@ -151,61 +149,6 @@ HD.isRaw = function isRaw(data) {
|
||||
|| HDPublicKey.isRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a derivation path and return an array of indexes.
|
||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
||||
* @param {String} path
|
||||
* @param {Number?} max - Max index.
|
||||
* @returns {Number[]}
|
||||
*/
|
||||
|
||||
HD.parsePath = function parsePath(path, max) {
|
||||
var parts = path.split('/');
|
||||
var root = parts.shift();
|
||||
var result = [];
|
||||
var i, hardened, index;
|
||||
|
||||
if (max == null)
|
||||
max = constants.hd.MAX_INDEX;
|
||||
|
||||
if (root !== 'm'
|
||||
&& root !== 'M'
|
||||
&& root !== 'm\''
|
||||
&& root !== 'M\'') {
|
||||
throw new Error('Bad path root.');
|
||||
}
|
||||
|
||||
for (i = 0; i < parts.length; i++) {
|
||||
index = parts[i];
|
||||
hardened = index[index.length - 1] === '\'';
|
||||
|
||||
if (hardened)
|
||||
index = index.slice(0, -1);
|
||||
|
||||
if (!/^\d+$/.test(index))
|
||||
throw new Error('Non-number path index.');
|
||||
|
||||
index = parseInt(index, 10);
|
||||
|
||||
if (hardened)
|
||||
index += constants.hd.HARDENED;
|
||||
|
||||
if (!(index >= 0 && index < max))
|
||||
throw new Error('Index out of range.');
|
||||
|
||||
result.push(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* LRU cache to avoid deriving keys twice.
|
||||
* @type {LRU}
|
||||
*/
|
||||
|
||||
HD.cache = new LRU(500);
|
||||
|
||||
/**
|
||||
* Test whether an object is an HD key.
|
||||
* @param {Object} obj
|
||||
|
||||
@ -12,7 +12,6 @@ var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
var wordlist = require('./wordlist');
|
||||
var nfkd = require('../utils/nfkd');
|
||||
|
||||
@ -147,20 +146,6 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
|
||||
2048, 64, 'sha512');
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate seed and create an hd private key.
|
||||
* @param {String?} passphrase
|
||||
* @param {(Network|NetworkType)?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.toKey = function toKey(passphrase, network) {
|
||||
var seed = this.toSeed(passphrase);
|
||||
var key = HD.PrivateKey.fromSeed(seed, network);
|
||||
key.mnemonic = this;
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get or generate entropy.
|
||||
* @returns {Buffer}
|
||||
|
||||
@ -15,7 +15,10 @@ var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
var base58 = require('../utils/base58');
|
||||
var Mnemonic = require('./mnemonic');
|
||||
var HDPublicKey = require('./public');
|
||||
var common = require('./common');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -99,7 +102,7 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
this.publicKey = ec.publicKeyCreate(options.privateKey, true);
|
||||
|
||||
if (options.mnemonic) {
|
||||
assert(options.mnemonic instanceof HD.Mnemonic);
|
||||
assert(options.mnemonic instanceof Mnemonic);
|
||||
this.mnemonic = options.mnemonic;
|
||||
}
|
||||
|
||||
@ -125,7 +128,7 @@ HDPrivateKey.prototype.__defineGetter__('hdPublicKey', function() {
|
||||
var key = this._hdPublicKey;
|
||||
|
||||
if (!key) {
|
||||
key = new HD.PublicKey();
|
||||
key = new HDPublicKey();
|
||||
key.network = this.network;
|
||||
key.depth = this.depth;
|
||||
key.parentFingerPrint = this.parentFingerPrint;
|
||||
@ -197,7 +200,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened, cache) {
|
||||
}
|
||||
|
||||
if (!cache)
|
||||
cache = HD.cache;
|
||||
cache = common.cache;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.derivePath(index, cache);
|
||||
@ -306,9 +309,7 @@ HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45(cache) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.isMaster = function isMaster() {
|
||||
return this.depth === 0
|
||||
&& this.childIndex === 0
|
||||
&& this.parentFingerPrint.readUInt32LE(0, true) === 0;
|
||||
return common.isMaster(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -318,11 +319,7 @@ HDPrivateKey.prototype.isMaster = function isMaster() {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
|
||||
if (accountIndex != null) {
|
||||
if (this.childIndex !== constants.hd.HARDENED + accountIndex)
|
||||
return false;
|
||||
}
|
||||
return this.depth === 3 && this.childIndex >= constants.hd.HARDENED;
|
||||
return common.isAccount44(this, accountIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -331,7 +328,7 @@ HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.isPurpose45 = function isPurpose45() {
|
||||
return this.depth === 1 && this.childIndex === constants.hd.HARDENED + 45;
|
||||
return common.isPurpose45(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -395,7 +392,7 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
|
||||
return false;
|
||||
|
||||
try {
|
||||
HD.parsePath(path, constants.hd.MAX_INDEX);
|
||||
common.parsePath(path, constants.hd.MAX_INDEX);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
@ -410,7 +407,7 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.derivePath = function derivePath(path, cache) {
|
||||
var indexes = HD.parsePath(path, constants.hd.MAX_INDEX);
|
||||
var indexes = common.parsePath(path, constants.hd.MAX_INDEX);
|
||||
var key = this;
|
||||
var i;
|
||||
|
||||
@ -534,8 +531,8 @@ HDPrivateKey.fromSeed = function fromSeed(seed, network) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
||||
if (!(mnemonic instanceof HD.Mnemonic))
|
||||
mnemonic = new HD.Mnemonic(mnemonic);
|
||||
if (!(mnemonic instanceof Mnemonic))
|
||||
mnemonic = new Mnemonic(mnemonic);
|
||||
this.fromSeed(mnemonic.toSeed(), network);
|
||||
this.mnemonic = mnemonic;
|
||||
return this;
|
||||
@ -604,7 +601,7 @@ HDPrivateKey.generate = function generate(network) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
this.fromRaw(utils.fromBase58(xkey));
|
||||
this.fromRaw(base58.decode(xkey));
|
||||
this._xprivkey = xkey;
|
||||
return this;
|
||||
};
|
||||
@ -650,7 +647,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.toBase58 = function toBase58(network) {
|
||||
return utils.toBase58(this.toRaw(network));
|
||||
return base58.encode(this.toRaw(network));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -717,7 +714,7 @@ HDPrivateKey.prototype.fromExtended = function fromExtended(data) {
|
||||
var p = new BufferReader(data);
|
||||
this.fromRaw(p);
|
||||
if (p.readU8() === 1)
|
||||
this.mnemonic = HD.Mnemonic.fromRaw(p);
|
||||
this.mnemonic = Mnemonic.fromRaw(p);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -775,7 +772,7 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
||||
this.fromBase58(json.xprivkey);
|
||||
|
||||
if (json.mnemonic)
|
||||
this.mnemonic = HD.Mnemonic.fromJSON(json.mnemonic);
|
||||
this.mnemonic = Mnemonic.fromJSON(json.mnemonic);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -15,7 +15,8 @@ var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var HD = require('./hd');
|
||||
var base58 = require('../utils/base58');
|
||||
var common = require('./common');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -150,7 +151,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened, cache) {
|
||||
}
|
||||
|
||||
if (!cache)
|
||||
cache = HD.cache;
|
||||
cache = common.cache;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.derivePath(index, cache);
|
||||
@ -248,7 +249,7 @@ HDPublicKey.prototype.derivePurpose45 = function derivePurpose45() {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.isMaster = function() {
|
||||
return HD.PrivateKey.prototype.isMaster.call(this);
|
||||
return common.isMaster(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -259,7 +260,7 @@ HDPublicKey.prototype.isMaster = function() {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.isAccount44 = function(accountIndex) {
|
||||
return HD.PrivateKey.prototype.isAccount44.call(this, accountIndex);
|
||||
return common.isAccount44(this, accountIndex);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -269,7 +270,7 @@ HDPublicKey.prototype.isAccount44 = function(accountIndex) {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.isPurpose45 = function() {
|
||||
return HD.PrivateKey.prototype.isPurpose45.call(this);
|
||||
return common.isPurpose45(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -284,7 +285,7 @@ HDPublicKey.isValidPath = function isValidPath(path) {
|
||||
return false;
|
||||
|
||||
try {
|
||||
HD.parsePath(path, constants.hd.HARDENED);
|
||||
common.parsePath(path, constants.hd.HARDENED);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
@ -300,7 +301,7 @@ HDPublicKey.isValidPath = function isValidPath(path) {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.derivePath = function derivePath(path, cache) {
|
||||
var indexes = HD.parsePath(path, constants.hd.HARDENED);
|
||||
var indexes = common.parsePath(path, constants.hd.HARDENED);
|
||||
var key = this;
|
||||
var i;
|
||||
|
||||
@ -454,7 +455,7 @@ HDPublicKey.isRaw = function isRaw(data) {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
this.fromRaw(utils.fromBase58(xkey));
|
||||
this.fromRaw(base58.decode(xkey));
|
||||
this._xpubkey = xkey;
|
||||
return this;
|
||||
};
|
||||
@ -498,7 +499,7 @@ HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.toBase58 = function toBase58(network) {
|
||||
return utils.toBase58(this.toRaw(network));
|
||||
return base58.encode(this.toRaw(network));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -16,6 +16,7 @@ var constants = require('../protocol/constants');
|
||||
var HTTPBase = require('./base');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var base58 = require('../utils/base58');
|
||||
var Address = require('../primitives/address');
|
||||
var Bloom = require('../utils/bloom');
|
||||
var TX = require('../primitives/tx');
|
||||
@ -69,7 +70,7 @@ function HTTPServer(options) {
|
||||
this.rpc = null;
|
||||
|
||||
if (!this.apiKey)
|
||||
this.apiKey = utils.toBase58(crypto.randomBytes(20));
|
||||
this.apiKey = base58.encode(crypto.randomBytes(20));
|
||||
|
||||
if (!this.serviceKey)
|
||||
this.serviceKey = this.apiKey;
|
||||
|
||||
@ -12,8 +12,9 @@ var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var assert = require('assert');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var VerifyError = require('../utils/errors').VerifyError;
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var errors = require('../utils/errors');
|
||||
var VerifyError = errors.VerifyError;
|
||||
var VerifyResult = errors.VerifyResult;
|
||||
var flags = constants.flags;
|
||||
var Bloom = require('../utils/bloom');
|
||||
var Address = require('../primitives/address');
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var TX = require('../primitives/tx');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
|
||||
/**
|
||||
* Represents a mempool entry.
|
||||
@ -151,7 +151,7 @@ MempoolEntry.prototype.getFee = function getFee() {
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.getRate = function getRate() {
|
||||
return TX.getRate(this.size, this.fee);
|
||||
return btcutils.getRate(this.size, this.fee);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -7,10 +7,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var BN = require('bn.js');
|
||||
@ -52,7 +53,7 @@ function MinerBlock(options) {
|
||||
this.version = options.version;
|
||||
this.height = options.tip.height + 1;
|
||||
this.bits = options.bits;
|
||||
this.target = utils.fromCompact(this.bits).toArrayLike(Buffer, 'le', 32);
|
||||
this.target = btcutils.fromCompact(this.bits).toArrayLike(Buffer, 'le', 32);
|
||||
this.locktime = options.locktime;
|
||||
this.flags = options.flags;
|
||||
this.extraNonce = new BN(0);
|
||||
@ -62,7 +63,7 @@ function MinerBlock(options) {
|
||||
this.address = options.address;
|
||||
this.network = Network.get(options.network);
|
||||
this.destroyed = false;
|
||||
this.reward = Block.reward(this.height, this.network);
|
||||
this.reward = btcutils.getReward(this.height, this.network.halvingInterval);
|
||||
|
||||
this.sigops = 0;
|
||||
this.weight = 0;
|
||||
|
||||
@ -17,6 +17,7 @@ var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var ec = require('../crypto/ec');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var base58 = require('../utils/base58');
|
||||
|
||||
/**
|
||||
* Represents a BIP150 input and output stream.
|
||||
@ -286,7 +287,7 @@ BIP150.address = function address(key) {
|
||||
p.writeU16BE(0xff01);
|
||||
p.writeBytes(crypto.hash160(key));
|
||||
p.writeChecksum();
|
||||
return utils.toBase58(p.render());
|
||||
return base58.encode(p.render());
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -405,10 +405,7 @@ CompactBlock.prototype.destroy = function destroy() {
|
||||
};
|
||||
|
||||
CompactBlock.prototype.toHeaders = function toHeaders() {
|
||||
var headers = new Headers(this);
|
||||
headers._hash = this._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
return Headers.fromBlock(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -14,9 +14,10 @@ var utils = require('../utils/utils');
|
||||
var IP = require('../utils/ip');
|
||||
var co = require('../utils/co');
|
||||
var constants = require('../protocol/constants');
|
||||
var VerifyError = require('../utils/errors').VerifyError;
|
||||
var errors = require('../utils/errors');
|
||||
var VerifyError = errors.VerifyError;
|
||||
var VerifyResult = errors.VerifyResult;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var Address = require('../primitives/address');
|
||||
var BIP150 = require('./bip150');
|
||||
var Bloom = require('../utils/bloom');
|
||||
|
||||
@ -7,11 +7,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var time = require('../net/timedata');
|
||||
var InvItem = require('./invitem');
|
||||
@ -211,14 +212,14 @@ AbstractBlock.prototype.verifyHeaders = function verifyHeaders(ret) {
|
||||
if (!ret)
|
||||
ret = new VerifyResult();
|
||||
|
||||
// Check proof of work
|
||||
if (!utils.testTarget(this.hash(), this.bits)) {
|
||||
// Check proof of work.
|
||||
if (!this.verifyPOW()) {
|
||||
ret.reason = 'high-hash';
|
||||
ret.score = 50;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check timestamp against now + 2 hours
|
||||
// Check timestamp against adjusted-time + 2 hours.
|
||||
if (this.ts > time.now() + 2 * 60 * 60) {
|
||||
ret.reason = 'time-too-new';
|
||||
ret.score = 0;
|
||||
@ -228,6 +229,15 @@ AbstractBlock.prototype.verifyHeaders = function verifyHeaders(ret) {
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify proof-of-work.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
AbstractBlock.prototype.verifyPOW = function verifyPOW() {
|
||||
return btcutils.verifyPOW(this.hash(), this.bits);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the `height` property and the `height`
|
||||
* property of all transactions within the block.
|
||||
|
||||
@ -15,6 +15,7 @@ var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var base58 = require('../utils/base58');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
|
||||
/**
|
||||
@ -136,7 +137,7 @@ Address.prototype.toRaw = function toRaw(network) {
|
||||
*/
|
||||
|
||||
Address.prototype.toBase58 = function toBase58(network) {
|
||||
return utils.toBase58(this.toRaw(network));
|
||||
return base58.encode(this.toRaw(network));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -225,7 +226,7 @@ Address.fromRaw = function fromRaw(data) {
|
||||
|
||||
Address.prototype.fromBase58 = function fromBase58(data) {
|
||||
assert(typeof data === 'string');
|
||||
return this.fromRaw(utils.fromBase58(data));
|
||||
return this.fromRaw(base58.decode(data));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -7,12 +7,13 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var constants = require('../protocol/constants');
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var TX = require('./tx');
|
||||
@ -492,8 +493,10 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
||||
*/
|
||||
|
||||
Block.prototype.getReward = function getReward(network) {
|
||||
var reward = Block.reward(this.height, network);
|
||||
var i, fee;
|
||||
var i, reward, fee;
|
||||
|
||||
network = Network.get(network);
|
||||
reward = btcutils.getReward(this.height, network.halvingInterval);
|
||||
|
||||
for (i = 1; i < this.txs.length; i++) {
|
||||
fee = this.txs[i].getFee();
|
||||
@ -528,36 +531,6 @@ Block.prototype.getClaimed = function getClaimed() {
|
||||
return this.txs[0].getOutputValue();
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate block subsidy.
|
||||
* @param {Number} height - Reward era by height.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
Block.reward = function reward(height, network) {
|
||||
var halvings;
|
||||
|
||||
assert(height >= 0, 'Bad height for reward.');
|
||||
|
||||
network = Network.get(network);
|
||||
halvings = height / network.halvingInterval | 0;
|
||||
|
||||
// BIP 42 (well, our own version of it,
|
||||
// since we can only handle 32 bit shifts).
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki
|
||||
if (halvings >= 33)
|
||||
return 0;
|
||||
|
||||
// We need to shift right by `halvings`,
|
||||
// but 50 btc is a 33 bit number, so we
|
||||
// cheat. We only start halving once the
|
||||
// halvings are at least 1.
|
||||
if (halvings === 0)
|
||||
return 5000000000;
|
||||
|
||||
return 2500000000 >>> (halvings - 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all unique outpoint hashes in the
|
||||
* block. Coinbases are ignored.
|
||||
@ -795,10 +768,7 @@ Block.prototype.frameWitness = function frameWitness(writer) {
|
||||
*/
|
||||
|
||||
Block.prototype.toHeaders = function toHeaders() {
|
||||
var headers = new Headers(this);
|
||||
headers._hash = this._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
return Headers.fromBlock(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -184,6 +184,19 @@ Headers.prototype.toHeaders = function toHeaders() {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the block to a headers object.
|
||||
* @param {Block|MerkleBlock} block
|
||||
* @returns {Headers}
|
||||
*/
|
||||
|
||||
Headers.fromBlock = function fromBlock(block) {
|
||||
var headers = new Headers(block);
|
||||
headers._hash = block._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test an object to see if it is a Headers object.
|
||||
* @param {Object} obj
|
||||
|
||||
@ -15,6 +15,7 @@ var networks = require('../protocol/networks');
|
||||
var Network = require('../protocol/network');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var base58 = require('../utils/base58');
|
||||
var Script = require('../script/script');
|
||||
var Address = require('./address');
|
||||
var Input = require('./input');
|
||||
@ -281,7 +282,7 @@ KeyRing.prototype.toSecret = function toSecret() {
|
||||
|
||||
p.writeChecksum();
|
||||
|
||||
return utils.toBase58(p.render());
|
||||
return base58.encode(p.render());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -291,7 +292,7 @@ KeyRing.prototype.toSecret = function toSecret() {
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromSecret = function fromSecret(data) {
|
||||
var p = new BufferReader(utils.fromBase58(data), true);
|
||||
var p = new BufferReader(base58.decode(data), true);
|
||||
var i, prefix, version, type, key, compressed;
|
||||
|
||||
version = p.readU8();
|
||||
@ -356,7 +357,7 @@ KeyRing.prototype.getPrivateKey = function getPrivateKey(enc) {
|
||||
|
||||
KeyRing.prototype.getPublicKey = function getPublicKey(enc) {
|
||||
if (enc === 'base58')
|
||||
return utils.toBase58(this.publicKey);
|
||||
return base58.encode(this.publicKey);
|
||||
|
||||
if (enc === 'hex')
|
||||
return this.publicKey.toString('hex');
|
||||
|
||||
@ -199,10 +199,7 @@ MemBlock.prototype.toBlock = function toBlock() {
|
||||
*/
|
||||
|
||||
MemBlock.prototype.toHeaders = function toHeaders() {
|
||||
var headers = new Headers(this);
|
||||
headers._hash = this._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
return Headers.fromBlock(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -13,7 +13,7 @@ var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var DUMMY = new Buffer([0]);
|
||||
var AbstractBlock = require('./abstractblock');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var Headers = require('./headers');
|
||||
@ -644,10 +644,7 @@ MerkleBlock.isMerkleBlock = function isMerkleBlock(obj) {
|
||||
*/
|
||||
|
||||
MerkleBlock.prototype.toHeaders = function toHeaders() {
|
||||
var headers = new Headers(this);
|
||||
headers._hash = this._hash;
|
||||
headers._valid = true;
|
||||
return headers;
|
||||
return Headers.fromBlock(this);
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -7,8 +7,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var constants = require('../protocol/constants');
|
||||
var Script = require('../script/script');
|
||||
var opcodes = Script.opcodes;
|
||||
@ -20,6 +21,7 @@ var Coin = require('./coin');
|
||||
var KeyRing = require('./keyring');
|
||||
var Address = require('./address');
|
||||
var workers = require('../workers/workers');
|
||||
var encoding = require('../utils/encoding');
|
||||
|
||||
/**
|
||||
* A mutable transaction object.
|
||||
@ -973,7 +975,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
size = input.script.getSize();
|
||||
total -= utils.sizeVarint(size) + size;
|
||||
total -= encoding.sizeVarint(size) + size;
|
||||
}
|
||||
|
||||
// Add size for signatures and public keys
|
||||
@ -1016,7 +1018,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
||||
if (redeem) {
|
||||
// The regular redeem script
|
||||
// is now worth 4 points.
|
||||
size += utils.sizeVarint(size);
|
||||
size += encoding.sizeVarint(size);
|
||||
size *= 4;
|
||||
} else {
|
||||
// Add one varint byte back
|
||||
@ -1035,7 +1037,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
||||
if (redeem) {
|
||||
prev = redeem;
|
||||
sz = prev.getSize();
|
||||
size += utils.sizeVarint(sz);
|
||||
size += encoding.sizeVarint(sz);
|
||||
size += sz;
|
||||
}
|
||||
} else if (prev.isWitnessPubkeyhash()) {
|
||||
@ -1104,7 +1106,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
||||
} else {
|
||||
// Byte for varint
|
||||
// size of input script.
|
||||
size += utils.sizeVarint(size);
|
||||
size += encoding.sizeVarint(size);
|
||||
}
|
||||
|
||||
total += size;
|
||||
@ -1658,9 +1660,9 @@ CoinSelector.prototype.getFee = function getFee(size) {
|
||||
var fee;
|
||||
|
||||
if (this.round)
|
||||
fee = TX.getRoundFee(size, this.rate);
|
||||
fee = btcutils.getRoundFee(size, this.rate);
|
||||
else
|
||||
fee = TX.getMinFee(size, this.rate);
|
||||
fee = btcutils.getMinFee(size, this.rate);
|
||||
|
||||
if (fee > constants.tx.MAX_FEE)
|
||||
fee = constants.tx.MAX_FEE;
|
||||
|
||||
@ -7,15 +7,16 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var Script = require('../script/script');
|
||||
var Stack = require('../script/stack');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var VerifyResult = utils.VerifyResult;
|
||||
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||
var Input = require('./input');
|
||||
var Output = require('./output');
|
||||
var Outpoint = require('./outpoint');
|
||||
@ -1850,7 +1851,7 @@ TX.prototype.getMinFee = function getMinFee(size, rate) {
|
||||
if (size == null)
|
||||
size = this.maxSize();
|
||||
|
||||
return TX.getMinFee(size, rate);
|
||||
return btcutils.getMinFee(size, rate);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1867,7 +1868,7 @@ TX.prototype.getRoundFee = function getRoundFee(size, rate) {
|
||||
if (size == null)
|
||||
size = this.maxSize();
|
||||
|
||||
return TX.getRoundFee(size, rate);
|
||||
return btcutils.getRoundFee(size, rate);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1881,7 +1882,7 @@ TX.prototype.getRate = function getRate(size) {
|
||||
if (size == null)
|
||||
size = this.maxSize();
|
||||
|
||||
return TX.getRate(size, this.getFee());
|
||||
return btcutils.getRate(size, this.getFee());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2021,137 +2022,6 @@ TX.prototype.toInv = function toInv() {
|
||||
return new InvItem(constants.inv.TX, this.hash('hex'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate minimum fee based on rate and size.
|
||||
* @param {Number?} size
|
||||
* @param {Rate?} rate - Rate of satoshi per kB.
|
||||
* @returns {Amount} fee
|
||||
*/
|
||||
|
||||
TX.getMinFee = function getMinFee(size, rate) {
|
||||
var fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = constants.tx.MIN_RELAY;
|
||||
|
||||
fee = Math.floor(rate * size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
|
||||
return fee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the minimum fee in order for the transaction
|
||||
* to be relayable, but _round to the nearest kilobyte
|
||||
* when taking into account size.
|
||||
* @param {Number?} size
|
||||
* @param {Rate?} rate - Rate of satoshi per kB.
|
||||
* @returns {Amount} fee
|
||||
*/
|
||||
|
||||
TX.getRoundFee = function getRoundFee(size, rate) {
|
||||
var fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = constants.tx.MIN_RELAY;
|
||||
|
||||
fee = rate * Math.ceil(size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
|
||||
return fee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate a fee rate based on size and fees.
|
||||
* @param {Number} size
|
||||
* @param {Amount} fee
|
||||
* @returns {Rate}
|
||||
*/
|
||||
|
||||
TX.getRate = function getRate(size, fee) {
|
||||
return Math.floor(fee * 1000 / size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort an array of transactions in dependency order.
|
||||
* @param {TX[]} txs
|
||||
* @returns {TX[]}
|
||||
*/
|
||||
|
||||
TX.sort = function sort(txs) {
|
||||
var depMap = {};
|
||||
var count = {};
|
||||
var result = [];
|
||||
var top = [];
|
||||
var map = txs;
|
||||
var i, j, tx, hash, input;
|
||||
var prev, hasDeps, deps;
|
||||
|
||||
if (Array.isArray(txs)) {
|
||||
map = {};
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
hash = tx.hash('hex');
|
||||
map[hash] = tx;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
hash = tx.hash('hex');
|
||||
hasDeps = false;
|
||||
|
||||
count[hash] = 0;
|
||||
|
||||
for (j = 0; j < tx.inputs.length; j++) {
|
||||
input = tx.inputs[j];
|
||||
prev = input.prevout.hash;
|
||||
|
||||
if (!map[prev])
|
||||
continue;
|
||||
|
||||
count[hash] += 1;
|
||||
hasDeps = true;
|
||||
|
||||
if (!depMap[prev])
|
||||
depMap[prev] = [];
|
||||
|
||||
depMap[prev].push(tx);
|
||||
}
|
||||
|
||||
if (hasDeps)
|
||||
continue;
|
||||
|
||||
top.push(tx);
|
||||
}
|
||||
|
||||
for (i = 0; i < top.length; i++) {
|
||||
tx = top[i];
|
||||
hash = tx.hash('hex');
|
||||
|
||||
result.push(tx);
|
||||
|
||||
deps = depMap[hash];
|
||||
|
||||
if (!deps)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < deps.length; j++) {
|
||||
tx = deps[j];
|
||||
hash = tx.hash('hex');
|
||||
|
||||
if (--count[hash] === 0)
|
||||
top.push(tx);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inspect the transaction and return a more
|
||||
* user-friendly representation of the data.
|
||||
|
||||
@ -1579,7 +1579,7 @@ Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
|
||||
assert(m >= 1 && m <= n);
|
||||
assert(n >= 1 && n <= 15);
|
||||
|
||||
keys = utils.sortKeys(keys);
|
||||
keys = sortKeys(keys);
|
||||
|
||||
this.push(Opcode.fromSmall(m));
|
||||
|
||||
@ -3644,6 +3644,16 @@ Script.isScript = function isScript(obj) {
|
||||
&& typeof obj.getSubscript === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function sortKeys(keys) {
|
||||
return keys.slice().sort(function(a, b) {
|
||||
return utils.cmp(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Expose
|
||||
*/
|
||||
|
||||
@ -31,7 +31,7 @@ for (var i = 0; i < base58.length; i++)
|
||||
* @returns {Base58String}
|
||||
*/
|
||||
|
||||
exports.toBase58 = function toBase58(data) {
|
||||
exports.encode = function encode(data) {
|
||||
var zeroes = 0;
|
||||
var length = 0;
|
||||
var str = '';
|
||||
@ -76,7 +76,7 @@ exports.toBase58 = function toBase58(data) {
|
||||
};
|
||||
|
||||
if (native)
|
||||
exports.toBase58 = native.toBase58;
|
||||
exports.encode = native.toBase58;
|
||||
|
||||
/**
|
||||
* Decode a base58 string.
|
||||
@ -86,7 +86,7 @@ if (native)
|
||||
* @throws on non-base58 character.
|
||||
*/
|
||||
|
||||
exports.fromBase58 = function fromBase58(str) {
|
||||
exports.decode = function decode(str) {
|
||||
var zeroes = 0;
|
||||
var length = 0;
|
||||
var i = 0;
|
||||
@ -137,4 +137,4 @@ exports.fromBase58 = function fromBase58(str) {
|
||||
};
|
||||
|
||||
if (native)
|
||||
exports.fromBase58 = native.fromBase58;
|
||||
exports.decode = native.fromBase58;
|
||||
|
||||
403
lib/utils/btcutils.js
Normal file
403
lib/utils/btcutils.js
Normal file
@ -0,0 +1,403 @@
|
||||
/*!
|
||||
* btcutils.js - bitcoin-related utils for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var BN = require('bn.js');
|
||||
var constants = require('../protocol/constants');
|
||||
var utils = require('./utils');
|
||||
var btcutils = exports;
|
||||
|
||||
/**
|
||||
* Convert a compact number to a big number.
|
||||
* Used for `block.bits` -> `target` conversion.
|
||||
* @param {Number} compact
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
btcutils.fromCompact = function fromCompact(compact) {
|
||||
var exponent = compact >>> 24;
|
||||
var negative = (compact >>> 23) & 1;
|
||||
var mantissa = compact & 0x7fffff;
|
||||
var num;
|
||||
|
||||
if (compact === 0)
|
||||
return new BN(0);
|
||||
|
||||
// Logic ported from btcd since
|
||||
// the bitcoind code is a nightmare.
|
||||
if (exponent <= 3) {
|
||||
mantissa >>>= 8 * (3 - exponent);
|
||||
num = new BN(mantissa);
|
||||
} else {
|
||||
num = new BN(mantissa);
|
||||
num.iushln(8 * (exponent - 3));
|
||||
}
|
||||
|
||||
if (negative)
|
||||
num.ineg();
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a big number to a compact number.
|
||||
* Used for `target` -> `block.bits` conversion.
|
||||
* @param {BN} num
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
btcutils.toCompact = function toCompact(num) {
|
||||
var mantissa, exponent, compact;
|
||||
|
||||
if (num.cmpn(0) === 0)
|
||||
return 0;
|
||||
|
||||
exponent = num.byteLength();
|
||||
|
||||
// Logic ported from btcd since
|
||||
// the bitcoind code is a nightmare.
|
||||
if (exponent <= 3) {
|
||||
mantissa = num.toNumber();
|
||||
mantissa <<= 8 * (3 - exponent);
|
||||
} else {
|
||||
mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
|
||||
}
|
||||
|
||||
if (mantissa & 0x800000) {
|
||||
mantissa >>= 8;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
compact = (exponent << 24) | mantissa;
|
||||
|
||||
if (num.isNeg())
|
||||
compact |= 0x800000;
|
||||
|
||||
compact >>>= 0;
|
||||
|
||||
return compact;
|
||||
};
|
||||
|
||||
/**
|
||||
* Verify proof-of-work.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
btcutils.verifyPOW = function verifyPOW(hash, bits) {
|
||||
var target = btcutils.fromCompact(bits);
|
||||
|
||||
if (target.isNeg() || target.cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
hash = new BN(hash, 'le');
|
||||
|
||||
if (hash.cmp(target) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate block subsidy.
|
||||
* @param {Number} height - Reward era by height.
|
||||
* @returns {Amount}
|
||||
*/
|
||||
|
||||
btcutils.getReward = function getReward(height, interval) {
|
||||
var halvings = height / interval | 0;
|
||||
|
||||
assert(height >= 0, 'Bad height for reward.');
|
||||
|
||||
// BIP 42 (well, our own version of it,
|
||||
// since we can only handle 32 bit shifts).
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki
|
||||
if (halvings >= 33)
|
||||
return 0;
|
||||
|
||||
// We need to shift right by `halvings`,
|
||||
// but 50 btc is a 33 bit number, so we
|
||||
// cheat. We only start halving once the
|
||||
// halvings are at least 1.
|
||||
if (halvings === 0)
|
||||
return 5000000000;
|
||||
|
||||
return 2500000000 >>> (halvings - 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate minimum fee based on rate and size.
|
||||
* @param {Number?} size
|
||||
* @param {Rate?} rate - Rate of satoshi per kB.
|
||||
* @returns {Amount} fee
|
||||
*/
|
||||
|
||||
btcutils.getMinFee = function getMinFee(size, rate) {
|
||||
var fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = constants.tx.MIN_RELAY;
|
||||
|
||||
fee = Math.floor(rate * size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
|
||||
return fee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate the minimum fee in order for the transaction
|
||||
* to be relayable, but _round to the nearest kilobyte
|
||||
* when taking into account size.
|
||||
* @param {Number?} size
|
||||
* @param {Rate?} rate - Rate of satoshi per kB.
|
||||
* @returns {Amount} fee
|
||||
*/
|
||||
|
||||
btcutils.getRoundFee = function getRoundFee(size, rate) {
|
||||
var fee;
|
||||
|
||||
if (rate == null)
|
||||
rate = constants.tx.MIN_RELAY;
|
||||
|
||||
fee = rate * Math.ceil(size / 1000);
|
||||
|
||||
if (fee === 0 && rate > 0)
|
||||
fee = rate;
|
||||
|
||||
return fee;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate a fee rate based on size and fees.
|
||||
* @param {Number} size
|
||||
* @param {Amount} fee
|
||||
* @returns {Rate}
|
||||
*/
|
||||
|
||||
btcutils.getRate = function getRate(size, fee) {
|
||||
return Math.floor(fee * 1000 / size);
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely convert satoshis to a BTC string.
|
||||
* This function explicitly avoids any
|
||||
* floating point arithmetic.
|
||||
* @param {Amount} value - Satoshis.
|
||||
* @returns {String} BTC string.
|
||||
*/
|
||||
|
||||
btcutils.btc = function btc(value) {
|
||||
var negative = false;
|
||||
var hi, lo, result;
|
||||
|
||||
if (utils.isFloat(value))
|
||||
return value;
|
||||
|
||||
assert(utils.isInt(value), 'Non-satoshi value for conversion.');
|
||||
|
||||
if (value < 0) {
|
||||
value = -value;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
assert(value <= utils.MAX_SAFE_INTEGER, 'Number exceeds 2^53-1.');
|
||||
|
||||
value = value.toString(10);
|
||||
|
||||
assert(value.length <= 16, 'Number exceeds 2^53-1.');
|
||||
|
||||
while (value.length < 9)
|
||||
value = '0' + value;
|
||||
|
||||
hi = value.slice(0, -8);
|
||||
lo = value.slice(-8);
|
||||
|
||||
lo = lo.replace(/0+$/, '');
|
||||
|
||||
if (lo.length === 0)
|
||||
lo += '0';
|
||||
|
||||
result = hi + '.' + lo;
|
||||
|
||||
if (negative)
|
||||
result = '-' + result;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Safely convert a BTC string to satoshis.
|
||||
* This function explicitly avoids any
|
||||
* floating point arithmetic. It also does
|
||||
* extra validation to ensure the resulting
|
||||
* Number will be 53 bits or less.
|
||||
* @param {String} value - BTC
|
||||
* @returns {Amount} Satoshis.
|
||||
* @throws on parse error
|
||||
*/
|
||||
|
||||
btcutils.satoshi = function satoshi(value) {
|
||||
var negative = false;
|
||||
var parts, hi, lo, result;
|
||||
|
||||
if (utils.isInt(value))
|
||||
return value;
|
||||
|
||||
assert(utils.isFloat(value), 'Non-BTC value for conversion.');
|
||||
|
||||
if (value[0] === '-') {
|
||||
negative = true;
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
parts = value.split('.');
|
||||
|
||||
assert(parts.length <= 2, 'Bad decimal point.');
|
||||
|
||||
hi = parts[0] || '0';
|
||||
lo = parts[1] || '0';
|
||||
|
||||
hi = hi.replace(/^0+/, '');
|
||||
lo = lo.replace(/0+$/, '');
|
||||
|
||||
assert(hi.length <= 8, 'Number exceeds 2^53-1.');
|
||||
assert(lo.length <= 8, 'Too many decimal places.');
|
||||
|
||||
if (hi.length === 0)
|
||||
hi = '0';
|
||||
|
||||
while (lo.length < 8)
|
||||
lo += '0';
|
||||
|
||||
hi = parseInt(hi, 10);
|
||||
lo = parseInt(lo, 10);
|
||||
|
||||
assert(hi < 90071992 || (hi === 90071992 && lo <= 54740991),
|
||||
'Number exceeds 2^53-1.');
|
||||
|
||||
result = hi * 100000000 + lo;
|
||||
|
||||
if (negative)
|
||||
result = -result;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test and validate a satoshi value (Number).
|
||||
* @param {Number?} value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
btcutils.isSatoshi = function isSatoshi(value) {
|
||||
if (typeof value !== 'number')
|
||||
return false;
|
||||
|
||||
try {
|
||||
utils.satoshi(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test and validate a BTC string.
|
||||
* @param {String?} value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
btcutils.isBTC = function isBTC(value) {
|
||||
if (typeof value !== 'string')
|
||||
return false;
|
||||
|
||||
try {
|
||||
utils.btc(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort an array of transactions in dependency order.
|
||||
* @param {TX[]} txs
|
||||
* @returns {TX[]}
|
||||
*/
|
||||
|
||||
btcutils.sortTX = function sortTX(txs) {
|
||||
var depMap = {};
|
||||
var count = {};
|
||||
var result = [];
|
||||
var top = [];
|
||||
var map = txs;
|
||||
var i, j, tx, hash, input;
|
||||
var prev, hasDeps, deps;
|
||||
|
||||
if (Array.isArray(txs)) {
|
||||
map = {};
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
hash = tx.hash('hex');
|
||||
map[hash] = tx;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < txs.length; i++) {
|
||||
tx = txs[i];
|
||||
hash = tx.hash('hex');
|
||||
hasDeps = false;
|
||||
|
||||
count[hash] = 0;
|
||||
|
||||
for (j = 0; j < tx.inputs.length; j++) {
|
||||
input = tx.inputs[j];
|
||||
prev = input.prevout.hash;
|
||||
|
||||
if (!map[prev])
|
||||
continue;
|
||||
|
||||
count[hash] += 1;
|
||||
hasDeps = true;
|
||||
|
||||
if (!depMap[prev])
|
||||
depMap[prev] = [];
|
||||
|
||||
depMap[prev].push(tx);
|
||||
}
|
||||
|
||||
if (hasDeps)
|
||||
continue;
|
||||
|
||||
top.push(tx);
|
||||
}
|
||||
|
||||
for (i = 0; i < top.length; i++) {
|
||||
tx = top[i];
|
||||
hash = tx.hash('hex');
|
||||
|
||||
result.push(tx);
|
||||
|
||||
deps = depMap[hash];
|
||||
|
||||
if (!deps)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < deps.length; j++) {
|
||||
tx = deps[j];
|
||||
hash = tx.hash('hex');
|
||||
|
||||
if (--count[hash] === 0)
|
||||
top.push(tx);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
653
lib/utils/encoding.js
Normal file
653
lib/utils/encoding.js
Normal file
@ -0,0 +1,653 @@
|
||||
/*!
|
||||
* encoding.js - encoding utils for bcoin
|
||||
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var BN = require('bn.js');
|
||||
var encoding = exports;
|
||||
|
||||
/**
|
||||
* UINT32_MAX
|
||||
* @const {BN}
|
||||
*/
|
||||
|
||||
encoding.U32_MAX = new BN(0xffffffff);
|
||||
|
||||
/**
|
||||
* UINT64_MAX
|
||||
* @const {BN}
|
||||
*/
|
||||
|
||||
encoding.U64_MAX = new BN('ffffffffffffffff', 'hex');
|
||||
|
||||
/**
|
||||
* Read uint64le.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
encoding.readU64 = function readU64(data, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = data.slice(off, off + 8);
|
||||
return new BN(num, 'le');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64be.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
encoding.readU64BE = function readU64BE(data, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = data.slice(off, off + 8);
|
||||
return new BN(num, 'be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64le.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
encoding.read64 = function read64(data, off) {
|
||||
var num;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = data.slice(off, off + 8);
|
||||
|
||||
if (num[num.length - 1] & 0x80)
|
||||
return new BN(num, 'le').notn(64).addn(1).neg();
|
||||
|
||||
return new BN(num, 'le');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64be.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
encoding.read64BE = function read64BE(data, off) {
|
||||
var num;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = data.slice(off, off + 8);
|
||||
|
||||
if (num[0] & 0x80)
|
||||
return new BN(num, 'be').notn(64).addn(1).neg();
|
||||
|
||||
return new BN(num, 'be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Write uint64le.
|
||||
* @param {BN|Number} value
|
||||
*/
|
||||
|
||||
encoding.writeU64 = function writeU64(dst, num, off) {
|
||||
return encoding.write64(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write uint64be.
|
||||
* @param {BN|Number} value
|
||||
*/
|
||||
|
||||
encoding.writeU64BE = function writeU64BE(dst, num, off) {
|
||||
return encoding.write64BE(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as a uint64le (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.writeU64N = function writeU64N(dst, num, off) {
|
||||
return encoding.write64N(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as a uint64be (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.writeU64NBE = function writeU64NBE(dst, num, off) {
|
||||
return encoding.write64NBE(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Max safe integer (53 bits).
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
encoding.MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
||||
|
||||
/**
|
||||
* Max 52 bit integer (safe for additions).
|
||||
* `(MAX_SAFE_INTEGER - 1) / 2`
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
encoding.MAX_SAFE_ADDITION = 0xfffffffffffff;
|
||||
|
||||
/**
|
||||
* Write a javascript number as an int64le (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.write64N = function write64N(dst, num, off, be) {
|
||||
var negative, hi, lo;
|
||||
|
||||
assert(typeof num === 'number');
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
negative = num < 0;
|
||||
|
||||
if (negative) {
|
||||
num = -num;
|
||||
num -= 1;
|
||||
}
|
||||
|
||||
assert(num <= encoding.MAX_SAFE_INTEGER, 'Number exceeds 2^53-1');
|
||||
|
||||
lo = num % 0x100000000;
|
||||
hi = (num - lo) / 0x100000000;
|
||||
|
||||
if (negative) {
|
||||
hi = ~hi >>> 0;
|
||||
lo = ~lo >>> 0;
|
||||
}
|
||||
|
||||
if (be) {
|
||||
dst[off + 0] = (hi >>> 24) & 0xff;
|
||||
dst[off + 1] = (hi >>> 16) & 0xff;
|
||||
dst[off + 2] = (hi >>> 8) & 0xff;
|
||||
dst[off + 3] = (hi >>> 0) & 0xff;
|
||||
dst[off + 4] = (lo >>> 24) & 0xff;
|
||||
dst[off + 5] = (lo >>> 16) & 0xff;
|
||||
dst[off + 6] = (lo >>> 8) & 0xff;
|
||||
dst[off + 7] = (lo >>> 0) & 0xff;
|
||||
} else {
|
||||
dst[off + 0] = (lo >>> 0) & 0xff;
|
||||
dst[off + 1] = (lo >>> 8) & 0xff;
|
||||
dst[off + 2] = (lo >>> 16) & 0xff;
|
||||
dst[off + 3] = (lo >>> 24) & 0xff;
|
||||
dst[off + 4] = (hi >>> 0) & 0xff;
|
||||
dst[off + 5] = (hi >>> 8) & 0xff;
|
||||
dst[off + 6] = (hi >>> 16) & 0xff;
|
||||
dst[off + 7] = (hi >>> 24) & 0xff;
|
||||
}
|
||||
|
||||
return off + 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as an int64be (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.write64NBE = function write64NBE(dst, num, off) {
|
||||
return encoding.write64N(dst, num, off, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64le as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.readU64N = function readU64N(data, off, force53, be) {
|
||||
var hi, lo;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (be) {
|
||||
hi = data.readUInt32BE(off, true);
|
||||
lo = data.readUInt32BE(off + 4, true);
|
||||
} else {
|
||||
hi = data.readUInt32LE(off + 4, true);
|
||||
lo = data.readUInt32LE(off, true);
|
||||
}
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return (hi * 0x100000000) + lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64be as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.readU64NBE = function readU64NBE(data, off, force53) {
|
||||
return encoding.readU64N(data, off, force53, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64le as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.read64N = function read64N(data, off, force53, be) {
|
||||
var hi, lo;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (be) {
|
||||
hi = data.readUInt32BE(off, true);
|
||||
lo = data.readUInt32BE(off + 4, true);
|
||||
} else {
|
||||
hi = data.readUInt32LE(off + 4, true);
|
||||
lo = data.readUInt32LE(off, true);
|
||||
}
|
||||
|
||||
if (hi & 0x80000000) {
|
||||
hi = ~hi >>> 0;
|
||||
lo = ~lo >>> 0;
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return -(hi * 0x100000000 + lo + 1);
|
||||
}
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return hi * 0x100000000 + lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64be as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
encoding.read64NBE = function read64NBE(data, off, force53) {
|
||||
return encoding.read64N(data, off, force53, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write int64le.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
encoding.write64 = function write64(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (typeof num === 'number')
|
||||
return encoding.write64N(dst, num, off);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (num.isNeg())
|
||||
num = num.neg().inotn(64).iaddn(1);
|
||||
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(encoding.U64_MAX);
|
||||
|
||||
num = num.toArray('le', 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i];
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write int64be.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
encoding.write64BE = function write64BE(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (typeof num === 'number')
|
||||
return encoding.write64NBE(dst, num, off);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (num.isNeg())
|
||||
num = num.neg().inotn(64).iaddn(1);
|
||||
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(encoding.U64_MAX);
|
||||
|
||||
num = num.toArray('be', 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i];
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a varint.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean?} big - Whether to read as a big number.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
encoding.readVarint = function readVarint(data, off, big) {
|
||||
var value, size;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
assert(off < data.length);
|
||||
|
||||
switch (data[off]) {
|
||||
case 0xff:
|
||||
size = 9;
|
||||
assert(off + size <= data.length);
|
||||
if (big) {
|
||||
value = encoding.readU64(data, off + 1);
|
||||
assert(value.bitLength() > 32);
|
||||
} else {
|
||||
value = encoding.readU64N(data, off + 1);
|
||||
assert(value > 0xffffffff);
|
||||
}
|
||||
break;
|
||||
case 0xfe:
|
||||
size = 5;
|
||||
assert(off + size <= data.length);
|
||||
value = data.readUInt32LE(off + 1, true);
|
||||
assert(value > 0xffff);
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
case 0xfd:
|
||||
size = 3;
|
||||
assert(off + size <= data.length);
|
||||
value = data[off + 1] | (data[off + 2] << 8);
|
||||
assert(value >= 0xfd);
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
default:
|
||||
size = 1;
|
||||
value = data[off];
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
}
|
||||
|
||||
return { size: size, value: value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a varint.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
encoding.writeVarint = function writeVarint(dst, num, off) {
|
||||
off = off >>> 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 32) {
|
||||
dst[off] = 0xff;
|
||||
encoding.writeU64(dst, num, off + 1);
|
||||
return off + 9;
|
||||
}
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
num = +num;
|
||||
|
||||
if (num < 0xfd) {
|
||||
dst[off] = num & 0xff;
|
||||
return off + 1;
|
||||
}
|
||||
|
||||
if (num <= 0xffff) {
|
||||
dst[off] = 0xfd;
|
||||
dst[off + 1] = num & 0xff;
|
||||
dst[off + 2] = (num >>> 8) & 0xff;
|
||||
return off + 3;
|
||||
}
|
||||
|
||||
if (num <= 0xffffffff) {
|
||||
dst[off] = 0xfe;
|
||||
dst[off + 1] = num & 0xff;
|
||||
dst[off + 2] = (num >>> 8) & 0xff;
|
||||
dst[off + 3] = (num >>> 16) & 0xff;
|
||||
dst[off + 4] = (num >>> 24) & 0xff;
|
||||
return off + 5;
|
||||
}
|
||||
|
||||
dst[off] = 0xff;
|
||||
encoding.writeU64N(dst, num, off + 1);
|
||||
|
||||
return off + 9;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate size of varint.
|
||||
* @param {BN|Number} num
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
encoding.sizeVarint = function sizeVarint(num) {
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 32)
|
||||
return 9;
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
if (num < 0xfd)
|
||||
return 1;
|
||||
|
||||
if (num <= 0xffff)
|
||||
return 3;
|
||||
|
||||
if (num <= 0xffffffff)
|
||||
return 5;
|
||||
|
||||
return 9;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a varint (type 2).
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean?} big - Whether to read as a big number.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
encoding.readVarint2 = function readVarint2(data, off, big) {
|
||||
var num = 0;
|
||||
var size = 0;
|
||||
var bnum, ch;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
for (;;) {
|
||||
assert(off < data.length);
|
||||
|
||||
ch = data[off++];
|
||||
size++;
|
||||
|
||||
if (num >= 0x3fffffffffff) {
|
||||
assert(big, 'Number exceeds 2^53-1.');
|
||||
bnum = new BN(num);
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (bnum) {
|
||||
assert(bnum.bitLength() <= 256);
|
||||
bnum.iushln(7).iaddn(ch & 0x7f);
|
||||
if ((ch & 0x80) === 0)
|
||||
break;
|
||||
bnum.iaddn(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
num = (num * 0x80) + (ch & 0x7f);
|
||||
if ((ch & 0x80) === 0)
|
||||
break;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (bnum)
|
||||
return { size: size, value: bnum };
|
||||
|
||||
if (big)
|
||||
num = new BN(num);
|
||||
|
||||
return { size: size, value: num };
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a varint (type 2).
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
encoding.writeVarint2 = function writeVarint2(dst, num, off) {
|
||||
var tmp = [];
|
||||
var len = 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 53) {
|
||||
for (;;) {
|
||||
tmp[len] = (num.words[0] & 0x7f) | (len ? 0x80 : 0x00);
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
break;
|
||||
num.iushrn(7).isubn(1);
|
||||
len++;
|
||||
}
|
||||
|
||||
assert(off + len <= dst.length);
|
||||
|
||||
do {
|
||||
dst[off++] = tmp[len];
|
||||
} while (len--);
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
off = off >>> 0;
|
||||
num = +num;
|
||||
|
||||
for (;;) {
|
||||
tmp[len] = (num & 0x7f) | (len ? 0x80 : 0x00);
|
||||
if (num <= 0x7f)
|
||||
break;
|
||||
num = ((num - (num % 0x80)) / 0x80) - 1;
|
||||
len++;
|
||||
}
|
||||
|
||||
assert(off + len <= dst.length);
|
||||
|
||||
do {
|
||||
dst[off++] = tmp[len];
|
||||
} while (len--);
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate size of varint (type 2).
|
||||
* @param {BN|Number} num
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
encoding.sizeVarint2 = function sizeVarint2(num) {
|
||||
var size = 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 53) {
|
||||
num = num.clone();
|
||||
|
||||
for (;;) {
|
||||
size++;
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
break;
|
||||
num.iushrn(7).isubn(1);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
num = +num;
|
||||
|
||||
for (;;) {
|
||||
size++;
|
||||
if (num <= 0x7f)
|
||||
break;
|
||||
num = ((num - (num % 0x80)) / 0x80) - 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize number as a u32le.
|
||||
* @param {Number} num
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
encoding.U32 = function U32(num) {
|
||||
var data = new Buffer(4);
|
||||
data.writeUInt32LE(num, 0, true);
|
||||
return data;
|
||||
};
|
||||
@ -61,6 +61,16 @@ function VerifyError(msg, code, reason, score) {
|
||||
|
||||
utils.inherits(VerifyError, Error);
|
||||
|
||||
/**
|
||||
* Verication result.
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
function VerifyResult() {
|
||||
this.reason = 'unknown';
|
||||
this.score = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* An error thrown from the scripting system,
|
||||
* potentially pertaining to Script execution.
|
||||
@ -146,5 +156,6 @@ utils.inherits(FundingError, Error);
|
||||
*/
|
||||
|
||||
exports.VerifyError = VerifyError;
|
||||
exports.VerifyResult = VerifyResult;
|
||||
exports.ScriptError = ScriptError;
|
||||
exports.FundingError = FundingError;
|
||||
|
||||
11
lib/utils/lazy-browser.js
Normal file
11
lib/utils/lazy-browser.js
Normal file
@ -0,0 +1,11 @@
|
||||
/*!
|
||||
* lazy-browser.js - lazy loading for bcoin
|
||||
* Copyright (c) 2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function lazy(require, exports) {
|
||||
return function() {};
|
||||
};
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var encoding = require('./encoding');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
|
||||
@ -207,7 +207,7 @@ BufferReader.prototype.readU32BE = function readU32BE() {
|
||||
BufferReader.prototype.readU64 = function readU64() {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.readU64(this.data, this.offset);
|
||||
ret = encoding.readU64(this.data, this.offset);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -220,7 +220,7 @@ BufferReader.prototype.readU64 = function readU64() {
|
||||
BufferReader.prototype.readU64BE = function readU64BE() {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.readU64BE(this.data, this.offset);
|
||||
ret = encoding.readU64BE(this.data, this.offset);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -234,7 +234,7 @@ BufferReader.prototype.readU64BE = function readU64BE() {
|
||||
BufferReader.prototype.readU64N = function readU64N(force53) {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.readU64N(this.data, this.offset, force53);
|
||||
ret = encoding.readU64N(this.data, this.offset, force53);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -248,7 +248,7 @@ BufferReader.prototype.readU64N = function readU64N(force53) {
|
||||
BufferReader.prototype.readU64NBE = function readU64NBE(force53) {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.readU64NBE(this.data, this.offset, force53);
|
||||
ret = encoding.readU64NBE(this.data, this.offset, force53);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -346,7 +346,7 @@ BufferReader.prototype.read32BE = function read32BE() {
|
||||
BufferReader.prototype.read64 = function read64() {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.read64(this.data, this.offset);
|
||||
ret = encoding.read64(this.data, this.offset);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -359,7 +359,7 @@ BufferReader.prototype.read64 = function read64() {
|
||||
BufferReader.prototype.read64BE = function read64BE() {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.read64BE(this.data, this.offset);
|
||||
ret = encoding.read64BE(this.data, this.offset);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -373,7 +373,7 @@ BufferReader.prototype.read64BE = function read64BE() {
|
||||
BufferReader.prototype.read64N = function read64N(force53) {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.read64N(this.data, this.offset, force53);
|
||||
ret = encoding.read64N(this.data, this.offset, force53);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -387,7 +387,7 @@ BufferReader.prototype.read64N = function read64N(force53) {
|
||||
BufferReader.prototype.read64NBE = function read64NBE(force53) {
|
||||
var ret;
|
||||
assert(this.offset + 8 <= this.data.length);
|
||||
ret = utils.read64NBE(this.data, this.offset, force53);
|
||||
ret = encoding.read64NBE(this.data, this.offset, force53);
|
||||
this.offset += 8;
|
||||
return ret;
|
||||
};
|
||||
@ -471,7 +471,7 @@ BufferReader.prototype.readDoubleBE = function readDoubleBE() {
|
||||
*/
|
||||
|
||||
BufferReader.prototype.readVarint = function readVarint(big) {
|
||||
var result = utils.readVarint(this.data, this.offset, big);
|
||||
var result = encoding.readVarint(this.data, this.offset, big);
|
||||
this.offset += result.size;
|
||||
return result.value;
|
||||
};
|
||||
@ -483,7 +483,7 @@ BufferReader.prototype.readVarint = function readVarint(big) {
|
||||
*/
|
||||
|
||||
BufferReader.prototype.readVarint2 = function readVarint2(big) {
|
||||
var result = utils.readVarint2(this.data, this.offset, big);
|
||||
var result = encoding.readVarint2(this.data, this.offset, big);
|
||||
this.offset += result.size;
|
||||
return result.value;
|
||||
};
|
||||
|
||||
@ -118,27 +118,6 @@ utils.concat = function concat(a, b) {
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode a base58 string.
|
||||
* @see https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp
|
||||
* @function
|
||||
* @param {Buffer} data
|
||||
* @returns {Base58String}
|
||||
*/
|
||||
|
||||
utils.toBase58 = base58.toBase58;
|
||||
|
||||
/**
|
||||
* Decode a base58 string.
|
||||
* @see https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp
|
||||
* @function
|
||||
* @param {Base58String} str
|
||||
* @returns {Buffer}
|
||||
* @throws on non-base58 character.
|
||||
*/
|
||||
|
||||
utils.fromBase58 = base58.fromBase58;
|
||||
|
||||
/**
|
||||
* Test whether a string is base58 (note that you
|
||||
* may get a false positive on a hex string).
|
||||
@ -390,6 +369,23 @@ utils.satoshi = function satoshi(value) {
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Max safe integer (53 bits).
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
utils.MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
||||
|
||||
/**
|
||||
* Max 52 bit integer (safe for additions).
|
||||
* `(MAX_SAFE_INTEGER - 1) / 2`
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
utils.MAX_SAFE_ADDITION = 0xfffffffffffff;
|
||||
|
||||
/**
|
||||
* Test whether a number is below MAX_SAFE_INTEGER.
|
||||
* @param {Number} value
|
||||
@ -478,36 +474,6 @@ utils.isFloat = function isFloat(value) {
|
||||
&& value !== '-';
|
||||
};
|
||||
|
||||
/**
|
||||
* Test and validate a satoshi value (Number).
|
||||
* @param {Number?} value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
utils.isSatoshi = function isSatoshi(value) {
|
||||
try {
|
||||
utils.satoshi(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test and validate a BTC string.
|
||||
* @param {String?} value
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
utils.isBTC = function isBTC(value) {
|
||||
try {
|
||||
utils.btc(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* util.inspect() with 20 levels of depth.
|
||||
* @param {Object|String} obj
|
||||
@ -595,18 +561,6 @@ utils.error = function error() {
|
||||
process.stderr.write(msg + '\n');
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort public keys lexicographically.
|
||||
* @param {Buffer[]} keys
|
||||
* @returns {Buffer[]} Sorted keys.
|
||||
*/
|
||||
|
||||
utils.sortKeys = function sortKeys(keys) {
|
||||
return keys.slice().sort(function(a, b) {
|
||||
return utils.cmp(a, b);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Unique-ify an array of strings.
|
||||
* @param {String[]} obj
|
||||
@ -628,102 +582,6 @@ utils.uniq = function uniq(obj) {
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a compact number to a big number.
|
||||
* Used for `block.bits` -> `target` conversion.
|
||||
* @param {Number} compact
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
utils.fromCompact = function fromCompact(compact) {
|
||||
var exponent = compact >>> 24;
|
||||
var negative = (compact >>> 23) & 1;
|
||||
var mantissa = compact & 0x7fffff;
|
||||
var num;
|
||||
|
||||
if (compact === 0)
|
||||
return new BN(0);
|
||||
|
||||
// Logic ported from btcd since
|
||||
// the bitcoind code is a nightmare.
|
||||
if (exponent <= 3) {
|
||||
mantissa >>>= 8 * (3 - exponent);
|
||||
num = new BN(mantissa);
|
||||
} else {
|
||||
num = new BN(mantissa);
|
||||
num.iushln(8 * (exponent - 3));
|
||||
}
|
||||
|
||||
if (negative)
|
||||
num.ineg();
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a big number to a compact number.
|
||||
* Used for `target` -> `block.bits` conversion.
|
||||
* @param {BN} num
|
||||
* @returns {Number}
|
||||
*/
|
||||
|
||||
utils.toCompact = function toCompact(num) {
|
||||
var mantissa, exponent, compact;
|
||||
|
||||
if (num.cmpn(0) === 0)
|
||||
return 0;
|
||||
|
||||
exponent = num.byteLength();
|
||||
|
||||
// Logic ported from btcd since
|
||||
// the bitcoind code is a nightmare.
|
||||
if (exponent <= 3) {
|
||||
mantissa = num.toNumber();
|
||||
mantissa <<= 8 * (3 - exponent);
|
||||
} else {
|
||||
mantissa = num.ushrn(8 * (exponent - 3)).toNumber();
|
||||
}
|
||||
|
||||
if (mantissa & 0x800000) {
|
||||
mantissa >>= 8;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
compact = (exponent << 24) | mantissa;
|
||||
|
||||
if (num.isNeg())
|
||||
compact |= 0x800000;
|
||||
|
||||
compact >>>= 0;
|
||||
|
||||
return compact;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test hash against a target.
|
||||
* @param {Buffer|Hash} hash
|
||||
* @param {BN|Number} target - Compact number or big number.
|
||||
* @returns {Boolean} True if hash is less than target.
|
||||
*/
|
||||
|
||||
utils.testTarget = function testTarget(hash, target) {
|
||||
if (typeof hash === 'string')
|
||||
hash = new Buffer(hash, 'hex');
|
||||
|
||||
if (typeof target === 'number')
|
||||
target = utils.fromCompact(target);
|
||||
|
||||
if (target.isNeg() || target.cmpn(0) === 0)
|
||||
return false;
|
||||
|
||||
hash = new BN(hash, 'le');
|
||||
|
||||
if (hash.cmp(target) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current time in unix time (seconds).
|
||||
* @returns {Number}
|
||||
@ -770,20 +628,6 @@ utils.time = function time(date) {
|
||||
return new Date(date) / 1000 | 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* UINT32_MAX
|
||||
* @const {BN}
|
||||
*/
|
||||
|
||||
utils.U32 = new BN(0xffffffff);
|
||||
|
||||
/**
|
||||
* UINT64_MAX
|
||||
* @const {BN}
|
||||
*/
|
||||
|
||||
utils.U64 = new BN('ffffffffffffffff', 'hex');
|
||||
|
||||
/**
|
||||
* Create a 64 bit nonce.
|
||||
* @returns {BN}
|
||||
@ -801,621 +645,6 @@ utils.nonce = function _nonce(buffer) {
|
||||
return new BN(nonce);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64le.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
utils.readU64 = function readU64(data, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = data.slice(off, off + 8);
|
||||
return new BN(num, 'le');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64be.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
utils.readU64BE = function readU64BE(data, off) {
|
||||
var num;
|
||||
off = off >>> 0;
|
||||
num = data.slice(off, off + 8);
|
||||
return new BN(num, 'be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64le.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
utils.read64 = function read64(data, off) {
|
||||
var num;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = data.slice(off, off + 8);
|
||||
|
||||
if (num[num.length - 1] & 0x80)
|
||||
return new BN(num, 'le').notn(64).addn(1).neg();
|
||||
|
||||
return new BN(num, 'le');
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64be.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @returns {BN}
|
||||
*/
|
||||
|
||||
utils.read64BE = function read64BE(data, off) {
|
||||
var num;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
num = data.slice(off, off + 8);
|
||||
|
||||
if (num[0] & 0x80)
|
||||
return new BN(num, 'be').notn(64).addn(1).neg();
|
||||
|
||||
return new BN(num, 'be');
|
||||
};
|
||||
|
||||
/**
|
||||
* Write uint64le.
|
||||
* @param {BN|Number} value
|
||||
*/
|
||||
|
||||
utils.writeU64 = function writeU64(dst, num, off) {
|
||||
return utils.write64(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write uint64be.
|
||||
* @param {BN|Number} value
|
||||
*/
|
||||
|
||||
utils.writeU64BE = function writeU64BE(dst, num, off) {
|
||||
return utils.write64BE(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as a uint64le (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.writeU64N = function writeU64N(dst, num, off) {
|
||||
return utils.write64N(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as a uint64be (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.writeU64NBE = function writeU64NBE(dst, num, off) {
|
||||
return utils.write64NBE(dst, num, off);
|
||||
};
|
||||
|
||||
/**
|
||||
* Max safe integer (53 bits).
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
utils.MAX_SAFE_INTEGER = 0x1fffffffffffff;
|
||||
|
||||
/**
|
||||
* Max 52 bit integer (safe for additions).
|
||||
* `(MAX_SAFE_INTEGER - 1) / 2`
|
||||
* @const {Number}
|
||||
* @default
|
||||
*/
|
||||
|
||||
utils.MAX_SAFE_ADDITION = 0xfffffffffffff;
|
||||
|
||||
/**
|
||||
* Write a javascript number as an int64le (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.write64N = function write64N(dst, num, off, be) {
|
||||
var negative, hi, lo;
|
||||
|
||||
assert(typeof num === 'number');
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
negative = num < 0;
|
||||
|
||||
if (negative) {
|
||||
num = -num;
|
||||
num -= 1;
|
||||
}
|
||||
|
||||
assert(num <= utils.MAX_SAFE_INTEGER, 'Number exceeds 2^53-1');
|
||||
|
||||
lo = num % 0x100000000;
|
||||
hi = (num - lo) / 0x100000000;
|
||||
|
||||
if (negative) {
|
||||
hi = ~hi >>> 0;
|
||||
lo = ~lo >>> 0;
|
||||
}
|
||||
|
||||
if (be) {
|
||||
dst[off + 0] = (hi >>> 24) & 0xff;
|
||||
dst[off + 1] = (hi >>> 16) & 0xff;
|
||||
dst[off + 2] = (hi >>> 8) & 0xff;
|
||||
dst[off + 3] = (hi >>> 0) & 0xff;
|
||||
dst[off + 4] = (lo >>> 24) & 0xff;
|
||||
dst[off + 5] = (lo >>> 16) & 0xff;
|
||||
dst[off + 6] = (lo >>> 8) & 0xff;
|
||||
dst[off + 7] = (lo >>> 0) & 0xff;
|
||||
} else {
|
||||
dst[off + 0] = (lo >>> 0) & 0xff;
|
||||
dst[off + 1] = (lo >>> 8) & 0xff;
|
||||
dst[off + 2] = (lo >>> 16) & 0xff;
|
||||
dst[off + 3] = (lo >>> 24) & 0xff;
|
||||
dst[off + 4] = (hi >>> 0) & 0xff;
|
||||
dst[off + 5] = (hi >>> 8) & 0xff;
|
||||
dst[off + 6] = (hi >>> 16) & 0xff;
|
||||
dst[off + 7] = (hi >>> 24) & 0xff;
|
||||
}
|
||||
|
||||
return off + 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a javascript number as an int64be (faster than big numbers).
|
||||
* @param {Number} value
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.write64NBE = function write64NBE(dst, num, off) {
|
||||
return utils.write64N(dst, num, off, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64le as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.readU64N = function readU64N(data, off, force53, be) {
|
||||
var hi, lo;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (be) {
|
||||
hi = data.readUInt32BE(off, true);
|
||||
lo = data.readUInt32BE(off + 4, true);
|
||||
} else {
|
||||
hi = data.readUInt32LE(off + 4, true);
|
||||
lo = data.readUInt32LE(off, true);
|
||||
}
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return (hi * 0x100000000) + lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read uint64be as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.readU64NBE = function readU64NBE(data, off, force53) {
|
||||
return utils.readU64N(data, off, force53, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64le as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.read64N = function read64N(data, off, force53, be) {
|
||||
var hi, lo;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (be) {
|
||||
hi = data.readUInt32BE(off, true);
|
||||
lo = data.readUInt32BE(off + 4, true);
|
||||
} else {
|
||||
hi = data.readUInt32LE(off + 4, true);
|
||||
lo = data.readUInt32LE(off, true);
|
||||
}
|
||||
|
||||
if (hi & 0x80000000) {
|
||||
hi = ~hi >>> 0;
|
||||
lo = ~lo >>> 0;
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return -(hi * 0x100000000 + lo + 1);
|
||||
}
|
||||
|
||||
if (force53)
|
||||
hi &= 0x1fffff;
|
||||
|
||||
assert((hi & 0xffe00000) === 0, 'Number exceeds 2^53-1');
|
||||
|
||||
return hi * 0x100000000 + lo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read int64be as a js number.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean} force53 - Read only 53 bits, but maintain the sign.
|
||||
* @returns {Number}
|
||||
* @throws on num > MAX_SAFE_INTEGER
|
||||
*/
|
||||
|
||||
utils.read64NBE = function read64NBE(data, off, force53) {
|
||||
return utils.read64N(data, off, force53, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write int64le.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
utils.write64 = function write64(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (typeof num === 'number')
|
||||
return utils.write64N(dst, num, off);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (num.isNeg())
|
||||
num = num.neg().inotn(64).iaddn(1);
|
||||
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
num = num.toArray('le', 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i];
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write int64be.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
utils.write64BE = function write64BE(dst, num, off) {
|
||||
var i;
|
||||
|
||||
if (typeof num === 'number')
|
||||
return utils.write64NBE(dst, num, off);
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
if (num.isNeg())
|
||||
num = num.neg().inotn(64).iaddn(1);
|
||||
|
||||
if (num.bitLength() > 64)
|
||||
num = num.uand(utils.U64);
|
||||
|
||||
num = num.toArray('be', 8);
|
||||
|
||||
for (i = 0; i < num.length; i++)
|
||||
dst[off++] = num[i];
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a varint.
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean?} big - Whether to read as a big number.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
utils.readVarint = function readVarint(data, off, big) {
|
||||
var value, size;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
assert(off < data.length);
|
||||
|
||||
switch (data[off]) {
|
||||
case 0xff:
|
||||
size = 9;
|
||||
assert(off + size <= data.length);
|
||||
if (big) {
|
||||
value = utils.readU64(data, off + 1);
|
||||
assert(value.bitLength() > 32);
|
||||
} else {
|
||||
value = utils.readU64N(data, off + 1);
|
||||
assert(value > 0xffffffff);
|
||||
}
|
||||
break;
|
||||
case 0xfe:
|
||||
size = 5;
|
||||
assert(off + size <= data.length);
|
||||
value = data.readUInt32LE(off + 1, true);
|
||||
assert(value > 0xffff);
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
case 0xfd:
|
||||
size = 3;
|
||||
assert(off + size <= data.length);
|
||||
value = data[off + 1] | (data[off + 2] << 8);
|
||||
assert(value >= 0xfd);
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
default:
|
||||
size = 1;
|
||||
value = data[off];
|
||||
if (big)
|
||||
value = new BN(value);
|
||||
break;
|
||||
}
|
||||
|
||||
return { size: size, value: value };
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a varint.
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
utils.writeVarint = function writeVarint(dst, num, off) {
|
||||
off = off >>> 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 32) {
|
||||
dst[off] = 0xff;
|
||||
utils.writeU64(dst, num, off + 1);
|
||||
return off + 9;
|
||||
}
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
num = +num;
|
||||
|
||||
if (num < 0xfd) {
|
||||
dst[off] = num & 0xff;
|
||||
return off + 1;
|
||||
}
|
||||
|
||||
if (num <= 0xffff) {
|
||||
dst[off] = 0xfd;
|
||||
dst[off + 1] = num & 0xff;
|
||||
dst[off + 2] = (num >>> 8) & 0xff;
|
||||
return off + 3;
|
||||
}
|
||||
|
||||
if (num <= 0xffffffff) {
|
||||
dst[off] = 0xfe;
|
||||
dst[off + 1] = num & 0xff;
|
||||
dst[off + 2] = (num >>> 8) & 0xff;
|
||||
dst[off + 3] = (num >>> 16) & 0xff;
|
||||
dst[off + 4] = (num >>> 24) & 0xff;
|
||||
return off + 5;
|
||||
}
|
||||
|
||||
dst[off] = 0xff;
|
||||
utils.writeU64N(dst, num, off + 1);
|
||||
|
||||
return off + 9;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate size of varint.
|
||||
* @param {BN|Number} num
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
utils.sizeVarint = function sizeVarint(num) {
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 32)
|
||||
return 9;
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
if (num < 0xfd)
|
||||
return 1;
|
||||
|
||||
if (num <= 0xffff)
|
||||
return 3;
|
||||
|
||||
if (num <= 0xffffffff)
|
||||
return 5;
|
||||
|
||||
return 9;
|
||||
};
|
||||
|
||||
/**
|
||||
* Read a varint (type 2).
|
||||
* @param {Buffer} data
|
||||
* @param {Number} off
|
||||
* @param {Boolean?} big - Whether to read as a big number.
|
||||
* @returns {Object}
|
||||
*/
|
||||
|
||||
utils.readVarint2 = function readVarint2(data, off, big) {
|
||||
var num = 0;
|
||||
var size = 0;
|
||||
var bnum, ch;
|
||||
|
||||
off = off >>> 0;
|
||||
|
||||
for (;;) {
|
||||
assert(off < data.length);
|
||||
|
||||
ch = data[off++];
|
||||
size++;
|
||||
|
||||
if (num >= 0x3fffffffffff) {
|
||||
assert(big, 'Number exceeds 2^53-1.');
|
||||
bnum = new BN(num);
|
||||
num = 0;
|
||||
}
|
||||
|
||||
if (bnum) {
|
||||
assert(bnum.bitLength() <= 256);
|
||||
bnum.iushln(7).iaddn(ch & 0x7f);
|
||||
if ((ch & 0x80) === 0)
|
||||
break;
|
||||
bnum.iaddn(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
num = (num * 0x80) + (ch & 0x7f);
|
||||
if ((ch & 0x80) === 0)
|
||||
break;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (bnum)
|
||||
return { size: size, value: bnum };
|
||||
|
||||
if (big)
|
||||
num = new BN(num);
|
||||
|
||||
return { size: size, value: num };
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a varint (type 2).
|
||||
* @param {Buffer} dst
|
||||
* @param {BN|Number} num
|
||||
* @param {Number} off
|
||||
* @returns {Number} Number of bytes written.
|
||||
*/
|
||||
|
||||
utils.writeVarint2 = function writeVarint2(dst, num, off) {
|
||||
var tmp = [];
|
||||
var len = 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 53) {
|
||||
for (;;) {
|
||||
tmp[len] = (num.words[0] & 0x7f) | (len ? 0x80 : 0x00);
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
break;
|
||||
num.iushrn(7).isubn(1);
|
||||
len++;
|
||||
}
|
||||
|
||||
assert(off + len <= dst.length);
|
||||
|
||||
do {
|
||||
dst[off++] = tmp[len];
|
||||
} while (len--);
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
off = off >>> 0;
|
||||
num = +num;
|
||||
|
||||
for (;;) {
|
||||
tmp[len] = (num & 0x7f) | (len ? 0x80 : 0x00);
|
||||
if (num <= 0x7f)
|
||||
break;
|
||||
num = ((num - (num % 0x80)) / 0x80) - 1;
|
||||
len++;
|
||||
}
|
||||
|
||||
assert(off + len <= dst.length);
|
||||
|
||||
do {
|
||||
dst[off++] = tmp[len];
|
||||
} while (len--);
|
||||
|
||||
return off;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate size of varint (type 2).
|
||||
* @param {BN|Number} num
|
||||
* @returns {Number} size
|
||||
*/
|
||||
|
||||
utils.sizeVarint2 = function sizeVarint2(num) {
|
||||
var size = 0;
|
||||
|
||||
if (BN.isBN(num)) {
|
||||
if (num.bitLength() > 53) {
|
||||
num = num.clone();
|
||||
|
||||
for (;;) {
|
||||
size++;
|
||||
if (num.cmpn(0x7f) <= 0)
|
||||
break;
|
||||
num.iushrn(7).isubn(1);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
num = num.toNumber();
|
||||
}
|
||||
|
||||
num = +num;
|
||||
|
||||
for (;;) {
|
||||
size++;
|
||||
if (num <= 0x7f)
|
||||
break;
|
||||
num = ((num - (num % 0x80)) / 0x80) - 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a buffer is all zeroes.
|
||||
* @param {Buffer} data
|
||||
@ -1477,32 +706,6 @@ utils.cmp = function cmp(a, b) {
|
||||
if (!Buffer.prototype.compare)
|
||||
utils.cmp = utils.strcmp;
|
||||
|
||||
/**
|
||||
* Memcmp for comparing a needle to a haystack.
|
||||
* @param {Buffer} target - Haystack.
|
||||
* @param {Buffer} data - Needle.
|
||||
* @param {Number} start - Index in haystack to begin the comparison.
|
||||
* @returns {Number} -1, 1, or 0.
|
||||
*/
|
||||
|
||||
utils.icmp = function icmp(target, data, start) {
|
||||
var i, a, b;
|
||||
|
||||
if (target.length - start < data.length)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < data.length; i++) {
|
||||
a = target[i + start];
|
||||
b = data[i];
|
||||
if (a < b)
|
||||
return -1;
|
||||
if (a > b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert bytes to mb.
|
||||
* @param {Number} size
|
||||
@ -1510,7 +713,7 @@ utils.icmp = function icmp(target, data, start) {
|
||||
*/
|
||||
|
||||
utils.mb = function mb(size) {
|
||||
return size / 1024 / 1024 | 0;
|
||||
return Math.floor(size / 1024 / 1024);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1892,23 +1095,6 @@ utils.mkdir = function mkdir(path, dirname) {
|
||||
|
||||
utils._paths = {};
|
||||
|
||||
/**
|
||||
* Test whether a string is eligible
|
||||
* to be used as a name or ID.
|
||||
* @param {String} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
utils.isName = function isName(key) {
|
||||
if (typeof key !== 'string')
|
||||
return false;
|
||||
|
||||
if (!/^[\-\._0-9A-Za-z]+$/.test(key))
|
||||
return false;
|
||||
|
||||
return key.length >= 1 && key.length <= 40;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure hidden-class mode for object.
|
||||
* @param {Object} obj
|
||||
@ -1917,55 +1103,3 @@ utils.isName = function isName(key) {
|
||||
utils.fastProp = function fastProp(obj) {
|
||||
({ __proto__: obj });
|
||||
};
|
||||
|
||||
/**
|
||||
* Verication result.
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
utils.VerifyResult = function VerifyResult() {
|
||||
this.reason = 'unknown';
|
||||
this.score = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialize number as a u32le.
|
||||
* @param {Number} num
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
utils.U32 = function U32(num) {
|
||||
var data = new Buffer(4);
|
||||
data.writeUInt32LE(num, 0, true);
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a lazy loader.
|
||||
* @param {Function} require
|
||||
* @param {Object} exports
|
||||
*/
|
||||
|
||||
utils.lazy = require('./lazy');
|
||||
|
||||
/*
|
||||
* Expose other objects.
|
||||
*/
|
||||
|
||||
lazy = utils.lazy(require, exports);
|
||||
|
||||
lazy('AsyncObject', './async'); // circular - inherits
|
||||
lazy('bloom', './bloom');
|
||||
lazy('errors', './errors'); // circular - inherits/btc
|
||||
lazy('ip', './ip');
|
||||
lazy('Locker', './locker'); // circular - inherits
|
||||
lazy('LRU', './lru');
|
||||
lazy('murmur3', './murmur3');
|
||||
lazy('co', './co');
|
||||
lazy('uri', './uri'); // circular - satoshi/btc/isNumber
|
||||
lazy('BufferReader', './reader'); // circular - serialization
|
||||
lazy('BufferWriter', './writer'); // circular - serialization
|
||||
lazy('protobuf', './protobuf'); // circular - inherits
|
||||
lazy('pem', './pem');
|
||||
lazy('asn1', './asn1');
|
||||
lazy('nfkd', './nfkd');
|
||||
|
||||
@ -7,9 +7,9 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var encoding = require('./encoding');
|
||||
var crypto = require('../crypto/crypto');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -87,21 +87,21 @@ BufferWriter.prototype.render = function render(keep) {
|
||||
case UI16BE: off = data.writeUInt16BE(item[1], off, true); break;
|
||||
case UI32: off = data.writeUInt32LE(item[1], off, true); break;
|
||||
case UI32BE: off = data.writeUInt32BE(item[1], off, true); break;
|
||||
case UI64: off = utils.writeU64(data, item[1], off); break;
|
||||
case UI64BE: off = utils.writeU64BE(data, item[1], off); break;
|
||||
case UI64: off = encoding.writeU64(data, item[1], off); break;
|
||||
case UI64BE: off = encoding.writeU64BE(data, item[1], off); break;
|
||||
case I8: off = data.writeInt8(item[1], off, true); break;
|
||||
case I16: off = data.writeInt16LE(item[1], off, true); break;
|
||||
case I16BE: off = data.writeInt16BE(item[1], off, true); break;
|
||||
case I32: off = data.writeInt32LE(item[1], off, true); break;
|
||||
case I32BE: off = data.writeInt32BE(item[1], off, true); break;
|
||||
case I64: off = utils.write64(data, item[1], off); break;
|
||||
case I64BE: off = utils.write64BE(data, item[1], off); break;
|
||||
case I64: off = encoding.write64(data, item[1], off); break;
|
||||
case I64BE: off = encoding.write64BE(data, item[1], off); break;
|
||||
case FL: off = data.writeFloatLE(item[1], off, true); break;
|
||||
case FLBE: off = data.writeFloatBE(item[1], off, true); break;
|
||||
case DBL: off = data.writeDoubleLE(item[1], off, true); break;
|
||||
case DBLBE: off = data.writeDoubleBE(item[1], off, true); break;
|
||||
case VARINT: off = utils.writeVarint(data, item[1], off); break;
|
||||
case VARINT2: off = utils.writeVarint2(data, item[1], off); break;
|
||||
case VARINT: off = encoding.writeVarint(data, item[1], off); break;
|
||||
case VARINT2: off = encoding.writeVarint2(data, item[1], off); break;
|
||||
case BYTES: off += item[1].copy(data, off); break;
|
||||
case STR: off += data.write(item[1], off, item[2]); break;
|
||||
case CHECKSUM:
|
||||
@ -344,7 +344,7 @@ BufferWriter.prototype.writeVarint = function writeVarint(value) {
|
||||
else
|
||||
assert(!value.isNeg());
|
||||
|
||||
this.written += utils.sizeVarint(value);
|
||||
this.written += encoding.sizeVarint(value);
|
||||
this.data.push([VARINT, value]);
|
||||
};
|
||||
|
||||
@ -359,7 +359,7 @@ BufferWriter.prototype.writeVarint2 = function writeVarint2(value) {
|
||||
else
|
||||
assert(!value.isNeg());
|
||||
|
||||
this.written += utils.sizeVarint2(value);
|
||||
this.written += encoding.sizeVarint2(value);
|
||||
this.data.push([VARINT2, value]);
|
||||
};
|
||||
|
||||
@ -379,7 +379,7 @@ BufferWriter.prototype.writeBytes = function writeBytes(value) {
|
||||
*/
|
||||
|
||||
BufferWriter.prototype.writeVarBytes = function writeVarBytes(value) {
|
||||
this.written += utils.sizeVarint(value.length);
|
||||
this.written += encoding.sizeVarint(value.length);
|
||||
this.written += value.length;
|
||||
this.data.push([VARINT, value.length]);
|
||||
this.data.push([BYTES, value]);
|
||||
@ -426,7 +426,7 @@ BufferWriter.prototype.writeVarString = function writeVarString(value, enc) {
|
||||
|
||||
size = Buffer.byteLength(value, enc);
|
||||
|
||||
this.written += utils.sizeVarint(size);
|
||||
this.written += encoding.sizeVarint(size);
|
||||
this.written += size;
|
||||
|
||||
this.data.push([VARINT, size]);
|
||||
|
||||
@ -12,6 +12,7 @@ var assert = require('assert');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var Path = require('./path');
|
||||
var common = require('./common');
|
||||
var Script = require('../script/script');
|
||||
var WalletKey = require('./walletkey');
|
||||
var HD = require('../hd/hd');
|
||||
@ -107,7 +108,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
|
||||
assert(options, 'Options are required.');
|
||||
assert(utils.isNumber(options.wid));
|
||||
assert(utils.isName(options.id), 'Bad Wallet ID.');
|
||||
assert(common.isName(options.id), 'Bad Wallet ID.');
|
||||
assert(HD.isHD(options.accountKey), 'Account key is required.');
|
||||
assert(utils.isNumber(options.accountIndex), 'Account index is required.');
|
||||
|
||||
@ -115,7 +116,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
this.id = options.id;
|
||||
|
||||
if (options.name != null) {
|
||||
assert(utils.isName(options.name), 'Bad account name.');
|
||||
assert(common.isName(options.name), 'Bad account name.');
|
||||
this.name = options.name;
|
||||
}
|
||||
|
||||
|
||||
26
lib/wallet/common.js
Normal file
26
lib/wallet/common.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* common.js - commonly required functions for wallet.
|
||||
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||
* https://github.com/bcoin-org/bcoin
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var common = exports;
|
||||
|
||||
/**
|
||||
* Test whether a string is eligible
|
||||
* to be used as a name or ID.
|
||||
* @param {String} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
|
||||
common.isName = function isName(key) {
|
||||
if (typeof key !== 'string')
|
||||
return false;
|
||||
|
||||
if (!/^[\-\._0-9A-Za-z]+$/.test(key))
|
||||
return false;
|
||||
|
||||
return key.length >= 1 && key.length <= 40;
|
||||
};
|
||||
@ -14,6 +14,7 @@ var assert = require('assert');
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var TX = require('../primitives/tx');
|
||||
var Coin = require('../primitives/coin');
|
||||
var Outpoint = require('../primitives/outpoint');
|
||||
@ -3191,7 +3192,7 @@ Details.prototype.getFee = function getFee() {
|
||||
*/
|
||||
|
||||
Details.prototype.getRate = function getRate(fee) {
|
||||
return TX.getRate(this.vsize, fee);
|
||||
return btcutils.getRate(this.vsize, fee);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
@ -14,13 +15,14 @@ var utils = require('../utils/utils');
|
||||
var Locker = require('../utils/locker');
|
||||
var co = require('../utils/co');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var base58 = require('../utils/base58');
|
||||
var TXDB = require('./txdb');
|
||||
var Path = require('./path');
|
||||
var common = require('./common');
|
||||
var Address = require('../primitives/address');
|
||||
var TX = require('../primitives/tx');
|
||||
var MTX = require('../primitives/mtx');
|
||||
var WalletKey = require('./walletkey');
|
||||
var HD = require('../hd/hd');
|
||||
@ -124,7 +126,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
}
|
||||
|
||||
if (options.id) {
|
||||
assert(utils.isName(options.id), 'Bad wallet ID.');
|
||||
assert(common.isName(options.id), 'Bad wallet ID.');
|
||||
id = options.id;
|
||||
}
|
||||
|
||||
@ -538,7 +540,7 @@ Wallet.prototype.renameAccount = co(function* renameAccount(acct, name) {
|
||||
Wallet.prototype._renameAccount = co(function* _renameAccount(acct, name) {
|
||||
var i, account, old, paths, path;
|
||||
|
||||
if (!utils.isName(name))
|
||||
if (!common.isName(name))
|
||||
throw new Error('Bad account name.');
|
||||
|
||||
account = yield this.getAccount(acct);
|
||||
@ -628,7 +630,7 @@ Wallet.prototype.getID = function getID() {
|
||||
p.writeBytes(hash);
|
||||
p.writeChecksum();
|
||||
|
||||
return utils.toBase58(p.render());
|
||||
return base58.encode(p.render());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1651,7 +1653,7 @@ Wallet.prototype.resend = co(function* resend() {
|
||||
if (txs.length > 0)
|
||||
this.logger.info('Rebroadcasting %d transactions.', txs.length);
|
||||
|
||||
txs = TX.sort(txs);
|
||||
txs = btcutils.sortTX(txs);
|
||||
|
||||
for (i = 0; i < txs.length; i++)
|
||||
yield this.db.send(txs[i]);
|
||||
|
||||
@ -7,16 +7,19 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var assert = require('assert');
|
||||
var AsyncObject = require('../utils/async');
|
||||
var utils = require('../utils/utils');
|
||||
var co = require('../utils/co');
|
||||
var Locker = require('../utils/locker');
|
||||
var LRU = require('../utils/lru');
|
||||
var encoding = require('../utils/encoding');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var btcutils = require('../utils/btcutils');
|
||||
var constants = require('../protocol/constants');
|
||||
var Network = require('../protocol/network');
|
||||
var Path = require('./path');
|
||||
var common = require('./common');
|
||||
var Wallet = require('./wallet');
|
||||
var Account = require('./account');
|
||||
var LDB = require('../db/ldb');
|
||||
@ -32,7 +35,7 @@ var BlockMapRecord = records.BlockMapRecord;
|
||||
var BlockMeta = records.BlockMeta;
|
||||
var PathMapRecord = records.PathMapRecord;
|
||||
var OutpointMapRecord = records.OutpointMapRecord;
|
||||
var U32 = utils.U32;
|
||||
var U32 = encoding.U32;
|
||||
var DUMMY = new Buffer([0]);
|
||||
|
||||
/**
|
||||
@ -694,7 +697,7 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
||||
var old = wallet.id;
|
||||
var i, paths, path, batch;
|
||||
|
||||
if (!utils.isName(id))
|
||||
if (!common.isName(id))
|
||||
throw new Error('WDB: Bad wallet ID.');
|
||||
|
||||
if (yield this.has(id))
|
||||
@ -1300,7 +1303,7 @@ WalletDB.prototype.resend = co(function* resend() {
|
||||
txs.push(tx);
|
||||
}
|
||||
|
||||
txs = TX.sort(txs);
|
||||
txs = btcutils.sortTX(txs);
|
||||
|
||||
for (i = 0; i < txs.length; i++)
|
||||
yield this.send(txs[i]);
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
var BN = require('bn.js');
|
||||
var bcoin = require('../').set('main');
|
||||
var utils = bcoin.utils;
|
||||
var btcutils = require('../lib/utils/btcutils');
|
||||
var crypto = require('../lib/crypto/crypto');
|
||||
var constants = bcoin.constants;
|
||||
var network = bcoin.networks;
|
||||
@ -106,7 +107,7 @@ describe('Block', function() {
|
||||
var reward;
|
||||
|
||||
for (;;) {
|
||||
reward = bcoin.block.reward(height);
|
||||
reward = btcutils.getReward(height, 210000);
|
||||
assert(reward <= constants.COIN * 50);
|
||||
total += reward;
|
||||
if (reward === 0)
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
var BN = require('bn.js');
|
||||
var bcoin = require('../').set('main');
|
||||
var utils = bcoin.utils;
|
||||
var base58 = require('../lib/utils/base58');
|
||||
var crypto = require('../lib/crypto/crypto');
|
||||
var assert = require('assert');
|
||||
|
||||
@ -159,7 +160,7 @@ describe('HD', function() {
|
||||
});
|
||||
|
||||
function ub58(data) {
|
||||
return utils.fromBase58(data).toString('hex');
|
||||
return base58.decode(data).toString('hex');
|
||||
}
|
||||
|
||||
function equal(a, b) {
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var BN = require('bn.js');
|
||||
var bcoin = require('../').set('main');
|
||||
var assert = require('assert');
|
||||
var utils = bcoin.utils;
|
||||
var BN = require('bn.js');
|
||||
var utils = require('../lib/utils/utils');
|
||||
var ec = require('../lib/crypto/ec');
|
||||
var btcutils = require('../lib/utils/btcutils');
|
||||
var base58 = require('../lib/utils/base58');
|
||||
var encoding = require('../lib/utils/encoding');
|
||||
var crypto = require('../lib/crypto/crypto');
|
||||
var schnorr = require('../lib/crypto/schnorr');
|
||||
|
||||
@ -25,64 +28,63 @@ describe('Utils', function() {
|
||||
|
||||
it('should encode/decode base58', function() {
|
||||
var arr = new Buffer([ 0, 0, 0, 0xde, 0xad, 0xbe, 0xef ]);
|
||||
var b = utils.toBase58(arr);
|
||||
var b = base58.encode(arr);
|
||||
assert.equal(b, '1116h8cQN');
|
||||
assert.deepEqual(utils.fromBase58(b), arr);
|
||||
assert.deepEqual(base58.decode(b), arr);
|
||||
for (var i = 0; i < vectors.length; i++) {
|
||||
var r = new Buffer(vectors[i][0], 'hex');
|
||||
var b = vectors[i][1];
|
||||
assert.equal(utils.toBase58(r), b);
|
||||
assert.deepEqual(utils.fromBase58(b), r);
|
||||
assert.equal(base58.encode(r), b);
|
||||
assert.deepEqual(base58.decode(b), r);
|
||||
}
|
||||
});
|
||||
|
||||
it('should translate bits to target', function() {
|
||||
var bits = 0x1900896c;
|
||||
it('should verify proof-of-work', function() {
|
||||
var hash = new Buffer(
|
||||
'672b3f1bb11a994267ea4171069ba0aa4448a840f38e8f340000000000000000',
|
||||
'hex'
|
||||
);
|
||||
var target = utils.fromCompact(bits);
|
||||
assert(utils.testTarget(hash, target));
|
||||
var bits = 0x1900896c;
|
||||
assert(btcutils.verifyPOW(hash, bits));
|
||||
});
|
||||
|
||||
it('should convert satoshi to btc', function() {
|
||||
var btc = utils.btc(5460);
|
||||
var btc = btcutils.btc(5460);
|
||||
assert.equal(btc, '0.0000546');
|
||||
btc = utils.btc(54678 * 1000000);
|
||||
btc = btcutils.btc(54678 * 1000000);
|
||||
assert.equal(btc, '546.78');
|
||||
btc = utils.btc(5460 * 10000000);
|
||||
btc = btcutils.btc(5460 * 10000000);
|
||||
assert.equal(btc, '546.0');
|
||||
});
|
||||
|
||||
it('should convert btc to satoshi', function() {
|
||||
var btc = utils.satoshi('0.0000546');
|
||||
var btc = btcutils.satoshi('0.0000546');
|
||||
assert(btc === 5460);
|
||||
btc = utils.satoshi('546.78');
|
||||
btc = btcutils.satoshi('546.78');
|
||||
assert(btc === 54678 * 1000000);
|
||||
btc = utils.satoshi('546');
|
||||
btc = btcutils.satoshi('546');
|
||||
assert(btc === 5460 * 10000000);
|
||||
btc = utils.satoshi('546.0');
|
||||
btc = btcutils.satoshi('546.0');
|
||||
assert(btc === 5460 * 10000000);
|
||||
btc = utils.satoshi('546.0000');
|
||||
btc = btcutils.satoshi('546.0000');
|
||||
assert(btc === 5460 * 10000000);
|
||||
assert.doesNotThrow(function() {
|
||||
utils.satoshi('546.00000000000000000');
|
||||
btcutils.satoshi('546.00000000000000000');
|
||||
});
|
||||
assert.throws(function() {
|
||||
utils.satoshi('546.00000000000000001');
|
||||
btcutils.satoshi('546.00000000000000001');
|
||||
});
|
||||
assert.doesNotThrow(function() {
|
||||
utils.satoshi('90071992.54740991');
|
||||
btcutils.satoshi('90071992.54740991');
|
||||
});
|
||||
assert.doesNotThrow(function() {
|
||||
utils.satoshi('090071992.547409910');
|
||||
btcutils.satoshi('090071992.547409910');
|
||||
});
|
||||
assert.throws(function() {
|
||||
utils.satoshi('90071992.54740992');
|
||||
btcutils.satoshi('90071992.54740992');
|
||||
});
|
||||
assert.throws(function() {
|
||||
utils.satoshi('190071992.54740991');
|
||||
btcutils.satoshi('190071992.54740991');
|
||||
});
|
||||
});
|
||||
|
||||
@ -99,64 +101,64 @@ describe('Utils', function() {
|
||||
var n = 0;
|
||||
var b = new Buffer(1);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 0, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 0);
|
||||
encoding.writeVarint2(b, 0, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 0);
|
||||
assert.deepEqual(b, [0]);
|
||||
|
||||
var b = new Buffer(1);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 1, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 1);
|
||||
encoding.writeVarint2(b, 1, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 1);
|
||||
assert.deepEqual(b, [1]);
|
||||
|
||||
var b = new Buffer(1);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 127, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 127);
|
||||
encoding.writeVarint2(b, 127, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 127);
|
||||
assert.deepEqual(b, [0x7f]);
|
||||
|
||||
var b = new Buffer(2);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 128, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 128);
|
||||
encoding.writeVarint2(b, 128, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 128);
|
||||
assert.deepEqual(b, [0x80, 0x00]);
|
||||
|
||||
var b = new Buffer(2);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 255, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 255);
|
||||
encoding.writeVarint2(b, 255, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 255);
|
||||
assert.deepEqual(b, [0x80, 0x7f]);
|
||||
|
||||
var b = new Buffer(2);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 16383, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 16383);
|
||||
encoding.writeVarint2(b, 16383, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 16383);
|
||||
assert.deepEqual(b, [0xfe, 0x7f]);
|
||||
|
||||
var b = new Buffer(2);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 16384, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 16384);
|
||||
encoding.writeVarint2(b, 16384, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 16384);
|
||||
assert.deepEqual(b, [0xff, 0x00]);
|
||||
|
||||
var b = new Buffer(3);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 16511, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 16511);
|
||||
encoding.writeVarint2(b, 16511, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 16511);
|
||||
// assert.deepEqual(b, [0x80, 0xff, 0x7f]);
|
||||
assert.deepEqual(b, [0xff, 0x7f, 0x00]);
|
||||
|
||||
var b = new Buffer(3);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, 65535, 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, 65535);
|
||||
encoding.writeVarint2(b, 65535, 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, 65535);
|
||||
// assert.deepEqual(b, [0x82, 0xfd, 0x7f]);
|
||||
assert.deepEqual(b, [0x82, 0xfe, 0x7f]);
|
||||
|
||||
var b = new Buffer(5);
|
||||
b.fill(0x00);
|
||||
utils.writeVarint2(b, Math.pow(2, 32), 0);
|
||||
assert.equal(utils.readVarint2(b, 0).value, Math.pow(2, 32));
|
||||
encoding.writeVarint2(b, Math.pow(2, 32), 0);
|
||||
assert.equal(encoding.readVarint2(b, 0).value, Math.pow(2, 32));
|
||||
assert.deepEqual(b, [0x8e, 0xfe, 0xfe, 0xff, 0x00]);
|
||||
});
|
||||
|
||||
@ -189,11 +191,11 @@ describe('Utils', function() {
|
||||
var buf2 = new Buffer(8);
|
||||
var msg = 'should write+read a ' + num.bitLength() + ' bit unsigned int';
|
||||
it(msg, function() {
|
||||
utils.writeU64(buf1, num, 0);
|
||||
utils.writeU64N(buf2, num.toNumber(), 0);
|
||||
encoding.writeU64(buf1, num, 0);
|
||||
encoding.writeU64N(buf2, num.toNumber(), 0);
|
||||
assert.deepEqual(buf1, buf2);
|
||||
var n1 = utils.readU64(buf1, 0);
|
||||
var n2 = utils.readU64N(buf2, 0);
|
||||
var n1 = encoding.readU64(buf1, 0);
|
||||
var n2 = encoding.readU64N(buf2, 0);
|
||||
assert.equal(n1.toNumber(), n2);
|
||||
});
|
||||
});
|
||||
@ -204,26 +206,26 @@ describe('Utils', function() {
|
||||
var msg = 'should write+read a ' + num.bitLength()
|
||||
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int';
|
||||
it(msg, function() {
|
||||
utils.write64(buf1, num, 0);
|
||||
utils.write64N(buf2, num.toNumber(), 0);
|
||||
encoding.write64(buf1, num, 0);
|
||||
encoding.write64N(buf2, num.toNumber(), 0);
|
||||
assert.deepEqual(buf1, buf2);
|
||||
var n1 = utils.read64(buf1, 0);
|
||||
var n2 = utils.read64N(buf2, 0);
|
||||
var n1 = encoding.read64(buf1, 0);
|
||||
var n2 = encoding.read64N(buf2, 0);
|
||||
assert.equal(n1.toNumber(), n2);
|
||||
});
|
||||
var msg = 'should write+read a ' + num.bitLength()
|
||||
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int as unsigned';
|
||||
it(msg, function() {
|
||||
utils.writeU64(buf1, num, 0);
|
||||
utils.writeU64N(buf2, num.toNumber(), 0);
|
||||
encoding.writeU64(buf1, num, 0);
|
||||
encoding.writeU64N(buf2, num.toNumber(), 0);
|
||||
assert.deepEqual(buf1, buf2);
|
||||
var n1 = utils.readU64(buf1, 0);
|
||||
var n1 = encoding.readU64(buf1, 0);
|
||||
if (num.isNeg()) {
|
||||
assert.throws(function() {
|
||||
utils.readU64N(buf2, 0);
|
||||
encoding.readU64N(buf2, 0);
|
||||
});
|
||||
} else {
|
||||
var n2 = utils.readU64N(buf2, 0);
|
||||
var n2 = encoding.readU64N(buf2, 0);
|
||||
assert.equal(n1.toNumber(), n2);
|
||||
}
|
||||
});
|
||||
@ -294,8 +296,8 @@ describe('Utils', function() {
|
||||
});
|
||||
|
||||
it('should do proper schnorr', function() {
|
||||
var key = bcoin.ec.generatePrivateKey();
|
||||
var pub = bcoin.ec.publicKeyCreate(key, true);
|
||||
var key = ec.generatePrivateKey();
|
||||
var pub = ec.publicKeyCreate(key, true);
|
||||
var msg = crypto.hash256(new Buffer('foo', 'ascii'));
|
||||
var sig = schnorr.sign(msg, key);
|
||||
assert(schnorr.verify(msg, sig, pub));
|
||||
|
||||
@ -5,6 +5,7 @@ var bcoin = require('../').set('main');
|
||||
var constants = bcoin.constants;
|
||||
var network = bcoin.networks;
|
||||
var utils = bcoin.utils;
|
||||
var encoding = require('../lib/utils/encoding');
|
||||
var crypto = require('../lib/crypto/crypto');
|
||||
var assert = require('assert');
|
||||
var scriptTypes = constants.scriptTypes;
|
||||
@ -26,8 +27,8 @@ function nextBlock(height) {
|
||||
if (height == null)
|
||||
height = globalHeight++;
|
||||
|
||||
hash = crypto.hash256(utils.U32(height)).toString('hex');
|
||||
prev = crypto.hash256(utils.U32(height - 1)).toString('hex');
|
||||
hash = crypto.hash256(encoding.U32(height)).toString('hex');
|
||||
prev = crypto.hash256(encoding.U32(height - 1)).toString('hex');
|
||||
|
||||
return {
|
||||
hash: hash,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user