modules: more refactoring.
This commit is contained in:
parent
729aea3b41
commit
0631148705
@ -24,17 +24,6 @@ function processEnv(str) {
|
|||||||
'$1this.$2 = require(\'$3\')');
|
'$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) {
|
function transformer(file, process) {
|
||||||
var stream = new Transform();
|
var stream = new Transform();
|
||||||
var decoder = new StringDecoder('utf8');
|
var decoder = new StringDecoder('utf8');
|
||||||
@ -62,12 +51,6 @@ function end(file, offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(file) {
|
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')
|
if (end(file, 2) === 'lib/env.js')
|
||||||
return transformer(file, processEnv);
|
return transformer(file, processEnv);
|
||||||
|
|
||||||
|
|||||||
@ -13,12 +13,14 @@ var Logger = require('../node/logger');
|
|||||||
var ChainDB = require('./chaindb');
|
var ChainDB = require('./chaindb');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
|
var btcutils = require('../utils/btcutils');
|
||||||
var Locker = require('../utils/locker');
|
var Locker = require('../utils/locker');
|
||||||
var ChainEntry = require('./chainentry');
|
var ChainEntry = require('./chainentry');
|
||||||
var CoinView = require('./coinview');
|
var CoinView = require('./coinview');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var VerifyError = require('../utils/errors').VerifyError;
|
var errors = require('../utils/errors');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyError = errors.VerifyError;
|
||||||
|
var VerifyResult = errors.VerifyResult;
|
||||||
var time = require('../net/timedata');
|
var time = require('../net/timedata');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
|
|
||||||
@ -1859,7 +1861,7 @@ Chain.prototype.retarget = function retarget(prev, first) {
|
|||||||
return prev.bits;
|
return prev.bits;
|
||||||
|
|
||||||
actualTimespan = prev.ts - first.ts;
|
actualTimespan = prev.ts - first.ts;
|
||||||
target = utils.fromCompact(prev.bits);
|
target = btcutils.fromCompact(prev.bits);
|
||||||
|
|
||||||
if (actualTimespan < targetTimespan / 4 | 0)
|
if (actualTimespan < targetTimespan / 4 | 0)
|
||||||
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)
|
if (target.cmp(pow.limit) > 0)
|
||||||
return pow.bits;
|
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 assert = require('assert');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
|
var encoding = require('../utils/encoding');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var CoinView = require('./coinview');
|
var CoinView = require('./coinview');
|
||||||
@ -26,7 +27,7 @@ var Outpoint = require('../primitives/outpoint');
|
|||||||
var TX = require('../primitives/tx');
|
var TX = require('../primitives/tx');
|
||||||
var Address = require('../primitives/address');
|
var Address = require('../primitives/address');
|
||||||
var ChainEntry = require('./chainentry');
|
var ChainEntry = require('./chainentry');
|
||||||
var U32 = utils.U32;
|
var U32 = encoding.U32;
|
||||||
var DUMMY = new Buffer([0]);
|
var DUMMY = new Buffer([0]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -11,6 +11,7 @@ var BN = require('bn.js');
|
|||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
|
var btcutils = require('../utils/btcutils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
@ -124,7 +125,7 @@ ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.getProof = function getProof() {
|
ChainEntry.prototype.getProof = function getProof() {
|
||||||
var target = utils.fromCompact(this.bits);
|
var target = btcutils.fromCompact(this.bits);
|
||||||
if (target.isNeg() || target.cmpn(0) === 0)
|
if (target.isNeg() || target.cmpn(0) === 0)
|
||||||
return new BN(0);
|
return new BN(0);
|
||||||
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
||||||
|
|||||||
@ -739,6 +739,8 @@ AES.cbc.decrypt = function decrypt(data, key, iv) {
|
|||||||
AES.Key = AESKey;
|
AES.Key = AESKey;
|
||||||
AES.Cipher = AESCipher;
|
AES.Cipher = AESCipher;
|
||||||
AES.Decipher = AESDecipher;
|
AES.Decipher = AESDecipher;
|
||||||
|
AES.encipher = AES.cbc.encrypt;
|
||||||
|
AES.decipher = AES.cbc.decrypt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
|
|||||||
@ -10,16 +10,9 @@
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var scrypt = require('./scrypt');
|
var scrypt = require('./scrypt');
|
||||||
var scryptAsync = require('./scrypt-async');
|
var scryptAsync = require('./scrypt-async');
|
||||||
var utils = require('../utils/utils');
|
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var native = require('../utils/native').binding;
|
var native = require('../utils/native').binding;
|
||||||
var backend = require('./backend');
|
var backend = require('./backend');
|
||||||
var lazy = utils.lazy(require, exports);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @exports crypto
|
|
||||||
*/
|
|
||||||
|
|
||||||
var crypto = exports;
|
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.
|
* Perform key derivation using PBKDF2.
|
||||||
* @private
|
* @private
|
||||||
@ -414,74 +304,6 @@ crypto.hkdfExpand = function hkdfExpand(prk, info, len, alg) {
|
|||||||
return okm;
|
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.
|
* Build a merkle tree from leaves.
|
||||||
* @param {Buffer[]} leaves
|
* @param {Buffer[]} leaves
|
||||||
@ -503,7 +325,7 @@ crypto.buildMerkleTree = function buildMerkleTree(leaves) {
|
|||||||
right = tree[j + i2];
|
right = tree[j + i2];
|
||||||
|
|
||||||
if (i2 === i + 1 && i2 + 1 === size
|
if (i2 === i + 1 && i2 + 1 === size
|
||||||
&& utils.cmp(left, right) === 0) {
|
&& left.compare(right) === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -600,6 +422,109 @@ crypto.checkMerkleBranch = function checkMerkleBranch(hash, branch, index) {
|
|||||||
if (native)
|
if (native)
|
||||||
crypto.checkMerkleBranch = native.checkMerkleBranch;
|
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.
|
* Generate some random bytes.
|
||||||
* @function
|
* @function
|
||||||
@ -635,14 +560,3 @@ crypto.randomRange = function randomRange(min, max) {
|
|||||||
var num = crypto.randomInt();
|
var num = crypto.randomInt();
|
||||||
return Math.floor((num / 0x100000000) * (max - min) + min);
|
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
|
// Utils
|
||||||
this.require('utils', './utils/utils');
|
this.require('utils', './utils/utils');
|
||||||
|
this.require('btcutils', './utils/btcutils');
|
||||||
this.require('locker', './utils/locker');
|
this.require('locker', './utils/locker');
|
||||||
this.require('reader', './utils/reader');
|
this.require('reader', './utils/reader');
|
||||||
this.require('writer', './utils/writer');
|
this.require('writer', './utils/writer');
|
||||||
@ -127,10 +128,15 @@ function Environment() {
|
|||||||
this.require('uri', './utils/uri');
|
this.require('uri', './utils/uri');
|
||||||
this.require('errors', './utils/errors');
|
this.require('errors', './utils/errors');
|
||||||
this.require('co', './utils/co');
|
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
|
// Crypto
|
||||||
this.require('ec', './crypto/ec');
|
|
||||||
this.require('crypto', './crypto/crypto');
|
this.require('crypto', './crypto/crypto');
|
||||||
|
this.require('ec', './crypto/ec');
|
||||||
|
this.require('schnorr', './crypto/schnorr');
|
||||||
|
|
||||||
// DB
|
// DB
|
||||||
this.require('lowlevelup', './db/lowlevelup');
|
this.require('lowlevelup', './db/lowlevelup');
|
||||||
@ -251,7 +257,7 @@ Environment.prototype.cache = function cache() {
|
|||||||
this.fullnode;
|
this.fullnode;
|
||||||
this.spvnode;
|
this.spvnode;
|
||||||
this.http;
|
this.http;
|
||||||
this.crypto.schnorr;
|
this.schnorr;
|
||||||
this.uri;
|
this.uri;
|
||||||
this.bip70;
|
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';
|
'use strict';
|
||||||
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var constants = require('../protocol/constants');
|
|
||||||
var LRU = require('../utils/lru');
|
|
||||||
var Mnemonic = require('./mnemonic');
|
var Mnemonic = require('./mnemonic');
|
||||||
var HDPrivateKey = require('./private');
|
var HDPrivateKey = require('./private');
|
||||||
var HDPublicKey = require('./public');
|
var HDPublicKey = require('./public');
|
||||||
@ -151,61 +149,6 @@ HD.isRaw = function isRaw(data) {
|
|||||||
|| HDPublicKey.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.
|
* Test whether an object is an HD key.
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
|
|||||||
@ -12,7 +12,6 @@ var assert = require('assert');
|
|||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var HD = require('./hd');
|
|
||||||
var wordlist = require('./wordlist');
|
var wordlist = require('./wordlist');
|
||||||
var nfkd = require('../utils/nfkd');
|
var nfkd = require('../utils/nfkd');
|
||||||
|
|
||||||
@ -147,20 +146,6 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) {
|
|||||||
2048, 64, 'sha512');
|
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.
|
* Get or generate entropy.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
|
|||||||
@ -15,7 +15,10 @@ var networks = require('../protocol/networks');
|
|||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
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
|
* Constants
|
||||||
@ -99,7 +102,7 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.publicKey = ec.publicKeyCreate(options.privateKey, true);
|
this.publicKey = ec.publicKeyCreate(options.privateKey, true);
|
||||||
|
|
||||||
if (options.mnemonic) {
|
if (options.mnemonic) {
|
||||||
assert(options.mnemonic instanceof HD.Mnemonic);
|
assert(options.mnemonic instanceof Mnemonic);
|
||||||
this.mnemonic = options.mnemonic;
|
this.mnemonic = options.mnemonic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ HDPrivateKey.prototype.__defineGetter__('hdPublicKey', function() {
|
|||||||
var key = this._hdPublicKey;
|
var key = this._hdPublicKey;
|
||||||
|
|
||||||
if (!key) {
|
if (!key) {
|
||||||
key = new HD.PublicKey();
|
key = new HDPublicKey();
|
||||||
key.network = this.network;
|
key.network = this.network;
|
||||||
key.depth = this.depth;
|
key.depth = this.depth;
|
||||||
key.parentFingerPrint = this.parentFingerPrint;
|
key.parentFingerPrint = this.parentFingerPrint;
|
||||||
@ -197,7 +200,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened, cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cache)
|
if (!cache)
|
||||||
cache = HD.cache;
|
cache = common.cache;
|
||||||
|
|
||||||
if (typeof index === 'string')
|
if (typeof index === 'string')
|
||||||
return this.derivePath(index, cache);
|
return this.derivePath(index, cache);
|
||||||
@ -306,9 +309,7 @@ HDPrivateKey.prototype.derivePurpose45 = function derivePurpose45(cache) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.isMaster = function isMaster() {
|
HDPrivateKey.prototype.isMaster = function isMaster() {
|
||||||
return this.depth === 0
|
return common.isMaster(this);
|
||||||
&& this.childIndex === 0
|
|
||||||
&& this.parentFingerPrint.readUInt32LE(0, true) === 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -318,11 +319,7 @@ HDPrivateKey.prototype.isMaster = function isMaster() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
|
HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
|
||||||
if (accountIndex != null) {
|
return common.isAccount44(this, accountIndex);
|
||||||
if (this.childIndex !== constants.hd.HARDENED + accountIndex)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this.depth === 3 && this.childIndex >= constants.hd.HARDENED;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,7 +328,7 @@ HDPrivateKey.prototype.isAccount44 = function isAccount44(accountIndex) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.isPurpose45 = function isPurpose45() {
|
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;
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HD.parsePath(path, constants.hd.MAX_INDEX);
|
common.parsePath(path, constants.hd.MAX_INDEX);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
@ -410,7 +407,7 @@ HDPrivateKey.isValidPath = function isValidPath(path) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.derivePath = function derivePath(path, cache) {
|
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 key = this;
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
@ -534,8 +531,8 @@ HDPrivateKey.fromSeed = function fromSeed(seed, network) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
HDPrivateKey.prototype.fromMnemonic = function fromMnemonic(mnemonic, network) {
|
||||||
if (!(mnemonic instanceof HD.Mnemonic))
|
if (!(mnemonic instanceof Mnemonic))
|
||||||
mnemonic = new HD.Mnemonic(mnemonic);
|
mnemonic = new Mnemonic(mnemonic);
|
||||||
this.fromSeed(mnemonic.toSeed(), network);
|
this.fromSeed(mnemonic.toSeed(), network);
|
||||||
this.mnemonic = mnemonic;
|
this.mnemonic = mnemonic;
|
||||||
return this;
|
return this;
|
||||||
@ -604,7 +601,7 @@ HDPrivateKey.generate = function generate(network) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||||
this.fromRaw(utils.fromBase58(xkey));
|
this.fromRaw(base58.decode(xkey));
|
||||||
this._xprivkey = xkey;
|
this._xprivkey = xkey;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -650,7 +647,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.toBase58 = function toBase58(network) {
|
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);
|
var p = new BufferReader(data);
|
||||||
this.fromRaw(p);
|
this.fromRaw(p);
|
||||||
if (p.readU8() === 1)
|
if (p.readU8() === 1)
|
||||||
this.mnemonic = HD.Mnemonic.fromRaw(p);
|
this.mnemonic = Mnemonic.fromRaw(p);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -775,7 +772,7 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.fromBase58(json.xprivkey);
|
this.fromBase58(json.xprivkey);
|
||||||
|
|
||||||
if (json.mnemonic)
|
if (json.mnemonic)
|
||||||
this.mnemonic = HD.Mnemonic.fromJSON(json.mnemonic);
|
this.mnemonic = Mnemonic.fromJSON(json.mnemonic);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,7 +15,8 @@ var networks = require('../protocol/networks');
|
|||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var HD = require('./hd');
|
var base58 = require('../utils/base58');
|
||||||
|
var common = require('./common');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
@ -150,7 +151,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened, cache) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cache)
|
if (!cache)
|
||||||
cache = HD.cache;
|
cache = common.cache;
|
||||||
|
|
||||||
if (typeof index === 'string')
|
if (typeof index === 'string')
|
||||||
return this.derivePath(index, cache);
|
return this.derivePath(index, cache);
|
||||||
@ -248,7 +249,7 @@ HDPublicKey.prototype.derivePurpose45 = function derivePurpose45() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.isMaster = function() {
|
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) {
|
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() {
|
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;
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
HD.parsePath(path, constants.hd.HARDENED);
|
common.parsePath(path, constants.hd.HARDENED);
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
@ -300,7 +301,7 @@ HDPublicKey.isValidPath = function isValidPath(path) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.derivePath = function derivePath(path, cache) {
|
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 key = this;
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
@ -454,7 +455,7 @@ HDPublicKey.isRaw = function isRaw(data) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||||
this.fromRaw(utils.fromBase58(xkey));
|
this.fromRaw(base58.decode(xkey));
|
||||||
this._xpubkey = xkey;
|
this._xpubkey = xkey;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -498,7 +499,7 @@ HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.toBase58 = function toBase58(network) {
|
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 HTTPBase = require('./base');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
|
var base58 = require('../utils/base58');
|
||||||
var Address = require('../primitives/address');
|
var Address = require('../primitives/address');
|
||||||
var Bloom = require('../utils/bloom');
|
var Bloom = require('../utils/bloom');
|
||||||
var TX = require('../primitives/tx');
|
var TX = require('../primitives/tx');
|
||||||
@ -69,7 +70,7 @@ function HTTPServer(options) {
|
|||||||
this.rpc = null;
|
this.rpc = null;
|
||||||
|
|
||||||
if (!this.apiKey)
|
if (!this.apiKey)
|
||||||
this.apiKey = utils.toBase58(crypto.randomBytes(20));
|
this.apiKey = base58.encode(crypto.randomBytes(20));
|
||||||
|
|
||||||
if (!this.serviceKey)
|
if (!this.serviceKey)
|
||||||
this.serviceKey = this.apiKey;
|
this.serviceKey = this.apiKey;
|
||||||
|
|||||||
@ -12,8 +12,9 @@ var utils = require('../utils/utils');
|
|||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var VerifyError = require('../utils/errors').VerifyError;
|
var errors = require('../utils/errors');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyError = errors.VerifyError;
|
||||||
|
var VerifyResult = errors.VerifyResult;
|
||||||
var flags = constants.flags;
|
var flags = constants.flags;
|
||||||
var Bloom = require('../utils/bloom');
|
var Bloom = require('../utils/bloom');
|
||||||
var Address = require('../primitives/address');
|
var Address = require('../primitives/address');
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var TX = require('../primitives/tx');
|
var btcutils = require('../utils/btcutils');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a mempool entry.
|
* Represents a mempool entry.
|
||||||
@ -151,7 +151,7 @@ MempoolEntry.prototype.getFee = function getFee() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
MempoolEntry.prototype.getRate = function getRate() {
|
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';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
|
var btcutils = require('../utils/btcutils');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var BN = require('bn.js');
|
var BN = require('bn.js');
|
||||||
@ -52,7 +53,7 @@ function MinerBlock(options) {
|
|||||||
this.version = options.version;
|
this.version = options.version;
|
||||||
this.height = options.tip.height + 1;
|
this.height = options.tip.height + 1;
|
||||||
this.bits = options.bits;
|
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.locktime = options.locktime;
|
||||||
this.flags = options.flags;
|
this.flags = options.flags;
|
||||||
this.extraNonce = new BN(0);
|
this.extraNonce = new BN(0);
|
||||||
@ -62,7 +63,7 @@ function MinerBlock(options) {
|
|||||||
this.address = options.address;
|
this.address = options.address;
|
||||||
this.network = Network.get(options.network);
|
this.network = Network.get(options.network);
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
this.reward = Block.reward(this.height, this.network);
|
this.reward = btcutils.getReward(this.height, this.network.halvingInterval);
|
||||||
|
|
||||||
this.sigops = 0;
|
this.sigops = 0;
|
||||||
this.weight = 0;
|
this.weight = 0;
|
||||||
|
|||||||
@ -17,6 +17,7 @@ var assert = require('assert');
|
|||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var ec = require('../crypto/ec');
|
var ec = require('../crypto/ec');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
|
var base58 = require('../utils/base58');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a BIP150 input and output stream.
|
* Represents a BIP150 input and output stream.
|
||||||
@ -286,7 +287,7 @@ BIP150.address = function address(key) {
|
|||||||
p.writeU16BE(0xff01);
|
p.writeU16BE(0xff01);
|
||||||
p.writeBytes(crypto.hash160(key));
|
p.writeBytes(crypto.hash160(key));
|
||||||
p.writeChecksum();
|
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() {
|
CompactBlock.prototype.toHeaders = function toHeaders() {
|
||||||
var headers = new Headers(this);
|
return Headers.fromBlock(this);
|
||||||
headers._hash = this._hash;
|
|
||||||
headers._valid = true;
|
|
||||||
return headers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -14,9 +14,10 @@ var utils = require('../utils/utils');
|
|||||||
var IP = require('../utils/ip');
|
var IP = require('../utils/ip');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var constants = require('../protocol/constants');
|
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 NetworkAddress = require('../primitives/netaddress');
|
||||||
var VerifyResult = utils.VerifyResult;
|
|
||||||
var Address = require('../primitives/address');
|
var Address = require('../primitives/address');
|
||||||
var BIP150 = require('./bip150');
|
var BIP150 = require('./bip150');
|
||||||
var Bloom = require('../utils/bloom');
|
var Bloom = require('../utils/bloom');
|
||||||
|
|||||||
@ -7,11 +7,12 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var btcutils = require('../utils/btcutils');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var time = require('../net/timedata');
|
var time = require('../net/timedata');
|
||||||
var InvItem = require('./invitem');
|
var InvItem = require('./invitem');
|
||||||
@ -211,14 +212,14 @@ AbstractBlock.prototype.verifyHeaders = function verifyHeaders(ret) {
|
|||||||
if (!ret)
|
if (!ret)
|
||||||
ret = new VerifyResult();
|
ret = new VerifyResult();
|
||||||
|
|
||||||
// Check proof of work
|
// Check proof of work.
|
||||||
if (!utils.testTarget(this.hash(), this.bits)) {
|
if (!this.verifyPOW()) {
|
||||||
ret.reason = 'high-hash';
|
ret.reason = 'high-hash';
|
||||||
ret.score = 50;
|
ret.score = 50;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check timestamp against now + 2 hours
|
// Check timestamp against adjusted-time + 2 hours.
|
||||||
if (this.ts > time.now() + 2 * 60 * 60) {
|
if (this.ts > time.now() + 2 * 60 * 60) {
|
||||||
ret.reason = 'time-too-new';
|
ret.reason = 'time-too-new';
|
||||||
ret.score = 0;
|
ret.score = 0;
|
||||||
@ -228,6 +229,15 @@ AbstractBlock.prototype.verifyHeaders = function verifyHeaders(ret) {
|
|||||||
return true;
|
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`
|
* Set the `height` property and the `height`
|
||||||
* property of all transactions within the block.
|
* property of all transactions within the block.
|
||||||
|
|||||||
@ -15,6 +15,7 @@ var crypto = require('../crypto/crypto');
|
|||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
|
var base58 = require('../utils/base58');
|
||||||
var scriptTypes = constants.scriptTypes;
|
var scriptTypes = constants.scriptTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,7 +137,7 @@ Address.prototype.toRaw = function toRaw(network) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toBase58 = function toBase58(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) {
|
Address.prototype.fromBase58 = function fromBase58(data) {
|
||||||
assert(typeof data === 'string');
|
assert(typeof data === 'string');
|
||||||
return this.fromRaw(utils.fromBase58(data));
|
return this.fromRaw(base58.decode(data));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,12 +7,13 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var btcutils = require('../utils/btcutils');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var AbstractBlock = require('./abstractblock');
|
var AbstractBlock = require('./abstractblock');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var TX = require('./tx');
|
var TX = require('./tx');
|
||||||
@ -492,8 +493,10 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getReward = function getReward(network) {
|
Block.prototype.getReward = function getReward(network) {
|
||||||
var reward = Block.reward(this.height, network);
|
var i, reward, fee;
|
||||||
var i, fee;
|
|
||||||
|
network = Network.get(network);
|
||||||
|
reward = btcutils.getReward(this.height, network.halvingInterval);
|
||||||
|
|
||||||
for (i = 1; i < this.txs.length; i++) {
|
for (i = 1; i < this.txs.length; i++) {
|
||||||
fee = this.txs[i].getFee();
|
fee = this.txs[i].getFee();
|
||||||
@ -528,36 +531,6 @@ Block.prototype.getClaimed = function getClaimed() {
|
|||||||
return this.txs[0].getOutputValue();
|
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
|
* Get all unique outpoint hashes in the
|
||||||
* block. Coinbases are ignored.
|
* block. Coinbases are ignored.
|
||||||
@ -795,10 +768,7 @@ Block.prototype.frameWitness = function frameWitness(writer) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toHeaders = function toHeaders() {
|
Block.prototype.toHeaders = function toHeaders() {
|
||||||
var headers = new Headers(this);
|
return Headers.fromBlock(this);
|
||||||
headers._hash = this._hash;
|
|
||||||
headers._valid = true;
|
|
||||||
return headers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -184,6 +184,19 @@ Headers.prototype.toHeaders = function toHeaders() {
|
|||||||
return this;
|
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.
|
* Test an object to see if it is a Headers object.
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
|
|||||||
@ -15,6 +15,7 @@ var networks = require('../protocol/networks');
|
|||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
|
var base58 = require('../utils/base58');
|
||||||
var Script = require('../script/script');
|
var Script = require('../script/script');
|
||||||
var Address = require('./address');
|
var Address = require('./address');
|
||||||
var Input = require('./input');
|
var Input = require('./input');
|
||||||
@ -281,7 +282,7 @@ KeyRing.prototype.toSecret = function toSecret() {
|
|||||||
|
|
||||||
p.writeChecksum();
|
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) {
|
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;
|
var i, prefix, version, type, key, compressed;
|
||||||
|
|
||||||
version = p.readU8();
|
version = p.readU8();
|
||||||
@ -356,7 +357,7 @@ KeyRing.prototype.getPrivateKey = function getPrivateKey(enc) {
|
|||||||
|
|
||||||
KeyRing.prototype.getPublicKey = function getPublicKey(enc) {
|
KeyRing.prototype.getPublicKey = function getPublicKey(enc) {
|
||||||
if (enc === 'base58')
|
if (enc === 'base58')
|
||||||
return utils.toBase58(this.publicKey);
|
return base58.encode(this.publicKey);
|
||||||
|
|
||||||
if (enc === 'hex')
|
if (enc === 'hex')
|
||||||
return this.publicKey.toString('hex');
|
return this.publicKey.toString('hex');
|
||||||
|
|||||||
@ -199,10 +199,7 @@ MemBlock.prototype.toBlock = function toBlock() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toHeaders = function toHeaders() {
|
MemBlock.prototype.toHeaders = function toHeaders() {
|
||||||
var headers = new Headers(this);
|
return Headers.fromBlock(this);
|
||||||
headers._hash = this._hash;
|
|
||||||
headers._valid = true;
|
|
||||||
return headers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -13,7 +13,7 @@ var assert = require('assert');
|
|||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var DUMMY = new Buffer([0]);
|
var DUMMY = new Buffer([0]);
|
||||||
var AbstractBlock = require('./abstractblock');
|
var AbstractBlock = require('./abstractblock');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var Headers = require('./headers');
|
var Headers = require('./headers');
|
||||||
@ -644,10 +644,7 @@ MerkleBlock.isMerkleBlock = function isMerkleBlock(obj) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.toHeaders = function toHeaders() {
|
MerkleBlock.prototype.toHeaders = function toHeaders() {
|
||||||
var headers = new Headers(this);
|
return Headers.fromBlock(this);
|
||||||
headers._hash = this._hash;
|
|
||||||
headers._valid = true;
|
|
||||||
return headers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -7,8 +7,9 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var utils = require('../utils/utils');
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var utils = require('../utils/utils');
|
||||||
|
var btcutils = require('../utils/btcutils');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var Script = require('../script/script');
|
var Script = require('../script/script');
|
||||||
var opcodes = Script.opcodes;
|
var opcodes = Script.opcodes;
|
||||||
@ -20,6 +21,7 @@ var Coin = require('./coin');
|
|||||||
var KeyRing = require('./keyring');
|
var KeyRing = require('./keyring');
|
||||||
var Address = require('./address');
|
var Address = require('./address');
|
||||||
var workers = require('../workers/workers');
|
var workers = require('../workers/workers');
|
||||||
|
var encoding = require('../utils/encoding');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A mutable transaction object.
|
* A mutable transaction object.
|
||||||
@ -973,7 +975,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
|||||||
for (i = 0; i < this.inputs.length; i++) {
|
for (i = 0; i < this.inputs.length; i++) {
|
||||||
input = this.inputs[i];
|
input = this.inputs[i];
|
||||||
size = input.script.getSize();
|
size = input.script.getSize();
|
||||||
total -= utils.sizeVarint(size) + size;
|
total -= encoding.sizeVarint(size) + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add size for signatures and public keys
|
// Add size for signatures and public keys
|
||||||
@ -1016,7 +1018,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
|||||||
if (redeem) {
|
if (redeem) {
|
||||||
// The regular redeem script
|
// The regular redeem script
|
||||||
// is now worth 4 points.
|
// is now worth 4 points.
|
||||||
size += utils.sizeVarint(size);
|
size += encoding.sizeVarint(size);
|
||||||
size *= 4;
|
size *= 4;
|
||||||
} else {
|
} else {
|
||||||
// Add one varint byte back
|
// Add one varint byte back
|
||||||
@ -1035,7 +1037,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
|||||||
if (redeem) {
|
if (redeem) {
|
||||||
prev = redeem;
|
prev = redeem;
|
||||||
sz = prev.getSize();
|
sz = prev.getSize();
|
||||||
size += utils.sizeVarint(sz);
|
size += encoding.sizeVarint(sz);
|
||||||
size += sz;
|
size += sz;
|
||||||
}
|
}
|
||||||
} else if (prev.isWitnessPubkeyhash()) {
|
} else if (prev.isWitnessPubkeyhash()) {
|
||||||
@ -1104,7 +1106,7 @@ MTX.prototype.maxSize = function maxSize(options) {
|
|||||||
} else {
|
} else {
|
||||||
// Byte for varint
|
// Byte for varint
|
||||||
// size of input script.
|
// size of input script.
|
||||||
size += utils.sizeVarint(size);
|
size += encoding.sizeVarint(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
total += size;
|
total += size;
|
||||||
@ -1658,9 +1660,9 @@ CoinSelector.prototype.getFee = function getFee(size) {
|
|||||||
var fee;
|
var fee;
|
||||||
|
|
||||||
if (this.round)
|
if (this.round)
|
||||||
fee = TX.getRoundFee(size, this.rate);
|
fee = btcutils.getRoundFee(size, this.rate);
|
||||||
else
|
else
|
||||||
fee = TX.getMinFee(size, this.rate);
|
fee = btcutils.getMinFee(size, this.rate);
|
||||||
|
|
||||||
if (fee > constants.tx.MAX_FEE)
|
if (fee > constants.tx.MAX_FEE)
|
||||||
fee = constants.tx.MAX_FEE;
|
fee = constants.tx.MAX_FEE;
|
||||||
|
|||||||
@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var btcutils = require('../utils/btcutils');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var Script = require('../script/script');
|
var Script = require('../script/script');
|
||||||
var Stack = require('../script/stack');
|
var Stack = require('../script/stack');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyResult = require('../utils/errors').VerifyResult;
|
||||||
var Input = require('./input');
|
var Input = require('./input');
|
||||||
var Output = require('./output');
|
var Output = require('./output');
|
||||||
var Outpoint = require('./outpoint');
|
var Outpoint = require('./outpoint');
|
||||||
@ -1850,7 +1851,7 @@ TX.prototype.getMinFee = function getMinFee(size, rate) {
|
|||||||
if (size == null)
|
if (size == null)
|
||||||
size = this.maxSize();
|
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)
|
if (size == null)
|
||||||
size = this.maxSize();
|
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)
|
if (size == null)
|
||||||
size = this.maxSize();
|
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'));
|
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
|
* Inspect the transaction and return a more
|
||||||
* user-friendly representation of the data.
|
* user-friendly representation of the data.
|
||||||
|
|||||||
@ -1579,7 +1579,7 @@ Script.prototype.fromMultisig = function fromMultisig(m, n, keys) {
|
|||||||
assert(m >= 1 && m <= n);
|
assert(m >= 1 && m <= n);
|
||||||
assert(n >= 1 && n <= 15);
|
assert(n >= 1 && n <= 15);
|
||||||
|
|
||||||
keys = utils.sortKeys(keys);
|
keys = sortKeys(keys);
|
||||||
|
|
||||||
this.push(Opcode.fromSmall(m));
|
this.push(Opcode.fromSmall(m));
|
||||||
|
|
||||||
@ -3644,6 +3644,16 @@ Script.isScript = function isScript(obj) {
|
|||||||
&& typeof obj.getSubscript === 'function';
|
&& typeof obj.getSubscript === 'function';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helpers
|
||||||
|
*/
|
||||||
|
|
||||||
|
function sortKeys(keys) {
|
||||||
|
return keys.slice().sort(function(a, b) {
|
||||||
|
return utils.cmp(a, b);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -31,7 +31,7 @@ for (var i = 0; i < base58.length; i++)
|
|||||||
* @returns {Base58String}
|
* @returns {Base58String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.toBase58 = function toBase58(data) {
|
exports.encode = function encode(data) {
|
||||||
var zeroes = 0;
|
var zeroes = 0;
|
||||||
var length = 0;
|
var length = 0;
|
||||||
var str = '';
|
var str = '';
|
||||||
@ -76,7 +76,7 @@ exports.toBase58 = function toBase58(data) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (native)
|
if (native)
|
||||||
exports.toBase58 = native.toBase58;
|
exports.encode = native.toBase58;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a base58 string.
|
* Decode a base58 string.
|
||||||
@ -86,7 +86,7 @@ if (native)
|
|||||||
* @throws on non-base58 character.
|
* @throws on non-base58 character.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.fromBase58 = function fromBase58(str) {
|
exports.decode = function decode(str) {
|
||||||
var zeroes = 0;
|
var zeroes = 0;
|
||||||
var length = 0;
|
var length = 0;
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@ -137,4 +137,4 @@ exports.fromBase58 = function fromBase58(str) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (native)
|
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);
|
utils.inherits(VerifyError, Error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verication result.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
function VerifyResult() {
|
||||||
|
this.reason = 'unknown';
|
||||||
|
this.score = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An error thrown from the scripting system,
|
* An error thrown from the scripting system,
|
||||||
* potentially pertaining to Script execution.
|
* potentially pertaining to Script execution.
|
||||||
@ -146,5 +156,6 @@ utils.inherits(FundingError, Error);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
exports.VerifyError = VerifyError;
|
exports.VerifyError = VerifyError;
|
||||||
|
exports.VerifyResult = VerifyResult;
|
||||||
exports.ScriptError = ScriptError;
|
exports.ScriptError = ScriptError;
|
||||||
exports.FundingError = FundingError;
|
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';
|
'use strict';
|
||||||
|
|
||||||
var utils = require('../utils/utils');
|
var encoding = require('./encoding');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ BufferReader.prototype.readU32BE = function readU32BE() {
|
|||||||
BufferReader.prototype.readU64 = function readU64() {
|
BufferReader.prototype.readU64 = function readU64() {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
assert(this.offset + 8 <= this.data.length);
|
||||||
ret = utils.readU64(this.data, this.offset);
|
ret = encoding.readU64(this.data, this.offset);
|
||||||
this.offset += 8;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -220,7 +220,7 @@ BufferReader.prototype.readU64 = function readU64() {
|
|||||||
BufferReader.prototype.readU64BE = function readU64BE() {
|
BufferReader.prototype.readU64BE = function readU64BE() {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
assert(this.offset + 8 <= this.data.length);
|
||||||
ret = utils.readU64BE(this.data, this.offset);
|
ret = encoding.readU64BE(this.data, this.offset);
|
||||||
this.offset += 8;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -234,7 +234,7 @@ BufferReader.prototype.readU64BE = function readU64BE() {
|
|||||||
BufferReader.prototype.readU64N = function readU64N(force53) {
|
BufferReader.prototype.readU64N = function readU64N(force53) {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
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;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -248,7 +248,7 @@ BufferReader.prototype.readU64N = function readU64N(force53) {
|
|||||||
BufferReader.prototype.readU64NBE = function readU64NBE(force53) {
|
BufferReader.prototype.readU64NBE = function readU64NBE(force53) {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
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;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -346,7 +346,7 @@ BufferReader.prototype.read32BE = function read32BE() {
|
|||||||
BufferReader.prototype.read64 = function read64() {
|
BufferReader.prototype.read64 = function read64() {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
assert(this.offset + 8 <= this.data.length);
|
||||||
ret = utils.read64(this.data, this.offset);
|
ret = encoding.read64(this.data, this.offset);
|
||||||
this.offset += 8;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -359,7 +359,7 @@ BufferReader.prototype.read64 = function read64() {
|
|||||||
BufferReader.prototype.read64BE = function read64BE() {
|
BufferReader.prototype.read64BE = function read64BE() {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
assert(this.offset + 8 <= this.data.length);
|
||||||
ret = utils.read64BE(this.data, this.offset);
|
ret = encoding.read64BE(this.data, this.offset);
|
||||||
this.offset += 8;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -373,7 +373,7 @@ BufferReader.prototype.read64BE = function read64BE() {
|
|||||||
BufferReader.prototype.read64N = function read64N(force53) {
|
BufferReader.prototype.read64N = function read64N(force53) {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
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;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -387,7 +387,7 @@ BufferReader.prototype.read64N = function read64N(force53) {
|
|||||||
BufferReader.prototype.read64NBE = function read64NBE(force53) {
|
BufferReader.prototype.read64NBE = function read64NBE(force53) {
|
||||||
var ret;
|
var ret;
|
||||||
assert(this.offset + 8 <= this.data.length);
|
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;
|
this.offset += 8;
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
@ -471,7 +471,7 @@ BufferReader.prototype.readDoubleBE = function readDoubleBE() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BufferReader.prototype.readVarint = function readVarint(big) {
|
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;
|
this.offset += result.size;
|
||||||
return result.value;
|
return result.value;
|
||||||
};
|
};
|
||||||
@ -483,7 +483,7 @@ BufferReader.prototype.readVarint = function readVarint(big) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BufferReader.prototype.readVarint2 = function readVarint2(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;
|
this.offset += result.size;
|
||||||
return result.value;
|
return result.value;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -118,27 +118,6 @@ utils.concat = function concat(a, b) {
|
|||||||
return data;
|
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
|
* Test whether a string is base58 (note that you
|
||||||
* may get a false positive on a hex string).
|
* may get a false positive on a hex string).
|
||||||
@ -390,6 +369,23 @@ utils.satoshi = function satoshi(value) {
|
|||||||
return result;
|
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.
|
* Test whether a number is below MAX_SAFE_INTEGER.
|
||||||
* @param {Number} value
|
* @param {Number} value
|
||||||
@ -478,36 +474,6 @@ utils.isFloat = function isFloat(value) {
|
|||||||
&& 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.
|
* util.inspect() with 20 levels of depth.
|
||||||
* @param {Object|String} obj
|
* @param {Object|String} obj
|
||||||
@ -595,18 +561,6 @@ utils.error = function error() {
|
|||||||
process.stderr.write(msg + '\n');
|
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.
|
* Unique-ify an array of strings.
|
||||||
* @param {String[]} obj
|
* @param {String[]} obj
|
||||||
@ -628,102 +582,6 @@ utils.uniq = function uniq(obj) {
|
|||||||
return out;
|
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).
|
* Get current time in unix time (seconds).
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
@ -770,20 +628,6 @@ utils.time = function time(date) {
|
|||||||
return new Date(date) / 1000 | 0;
|
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.
|
* Create a 64 bit nonce.
|
||||||
* @returns {BN}
|
* @returns {BN}
|
||||||
@ -801,621 +645,6 @@ utils.nonce = function _nonce(buffer) {
|
|||||||
return new BN(nonce);
|
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.
|
* Test whether a buffer is all zeroes.
|
||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
@ -1477,32 +706,6 @@ utils.cmp = function cmp(a, b) {
|
|||||||
if (!Buffer.prototype.compare)
|
if (!Buffer.prototype.compare)
|
||||||
utils.cmp = utils.strcmp;
|
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.
|
* Convert bytes to mb.
|
||||||
* @param {Number} size
|
* @param {Number} size
|
||||||
@ -1510,7 +713,7 @@ utils.icmp = function icmp(target, data, start) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
utils.mb = function mb(size) {
|
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 = {};
|
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.
|
* Ensure hidden-class mode for object.
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
@ -1917,55 +1103,3 @@ utils.isName = function isName(key) {
|
|||||||
utils.fastProp = function fastProp(obj) {
|
utils.fastProp = function fastProp(obj) {
|
||||||
({ __proto__: 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';
|
'use strict';
|
||||||
|
|
||||||
var utils = require('../utils/utils');
|
|
||||||
var crypto = require('../crypto/crypto');
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
var encoding = require('./encoding');
|
||||||
|
var crypto = require('../crypto/crypto');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
@ -87,21 +87,21 @@ BufferWriter.prototype.render = function render(keep) {
|
|||||||
case UI16BE: off = data.writeUInt16BE(item[1], off, true); break;
|
case UI16BE: off = data.writeUInt16BE(item[1], off, true); break;
|
||||||
case UI32: off = data.writeUInt32LE(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 UI32BE: off = data.writeUInt32BE(item[1], off, true); break;
|
||||||
case UI64: off = utils.writeU64(data, item[1], off); break;
|
case UI64: off = encoding.writeU64(data, item[1], off); break;
|
||||||
case UI64BE: off = utils.writeU64BE(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 I8: off = data.writeInt8(item[1], off, true); break;
|
||||||
case I16: off = data.writeInt16LE(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 I16BE: off = data.writeInt16BE(item[1], off, true); break;
|
||||||
case I32: off = data.writeInt32LE(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 I32BE: off = data.writeInt32BE(item[1], off, true); break;
|
||||||
case I64: off = utils.write64(data, item[1], off); break;
|
case I64: off = encoding.write64(data, item[1], off); break;
|
||||||
case I64BE: off = utils.write64BE(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 FL: off = data.writeFloatLE(item[1], off, true); break;
|
||||||
case FLBE: off = data.writeFloatBE(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 DBL: off = data.writeDoubleLE(item[1], off, true); break;
|
||||||
case DBLBE: off = data.writeDoubleBE(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 VARINT: off = encoding.writeVarint(data, item[1], off); break;
|
||||||
case VARINT2: off = utils.writeVarint2(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 BYTES: off += item[1].copy(data, off); break;
|
||||||
case STR: off += data.write(item[1], off, item[2]); break;
|
case STR: off += data.write(item[1], off, item[2]); break;
|
||||||
case CHECKSUM:
|
case CHECKSUM:
|
||||||
@ -344,7 +344,7 @@ BufferWriter.prototype.writeVarint = function writeVarint(value) {
|
|||||||
else
|
else
|
||||||
assert(!value.isNeg());
|
assert(!value.isNeg());
|
||||||
|
|
||||||
this.written += utils.sizeVarint(value);
|
this.written += encoding.sizeVarint(value);
|
||||||
this.data.push([VARINT, value]);
|
this.data.push([VARINT, value]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,7 +359,7 @@ BufferWriter.prototype.writeVarint2 = function writeVarint2(value) {
|
|||||||
else
|
else
|
||||||
assert(!value.isNeg());
|
assert(!value.isNeg());
|
||||||
|
|
||||||
this.written += utils.sizeVarint2(value);
|
this.written += encoding.sizeVarint2(value);
|
||||||
this.data.push([VARINT2, value]);
|
this.data.push([VARINT2, value]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ BufferWriter.prototype.writeBytes = function writeBytes(value) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BufferWriter.prototype.writeVarBytes = function writeVarBytes(value) {
|
BufferWriter.prototype.writeVarBytes = function writeVarBytes(value) {
|
||||||
this.written += utils.sizeVarint(value.length);
|
this.written += encoding.sizeVarint(value.length);
|
||||||
this.written += value.length;
|
this.written += value.length;
|
||||||
this.data.push([VARINT, value.length]);
|
this.data.push([VARINT, value.length]);
|
||||||
this.data.push([BYTES, value]);
|
this.data.push([BYTES, value]);
|
||||||
@ -426,7 +426,7 @@ BufferWriter.prototype.writeVarString = function writeVarString(value, enc) {
|
|||||||
|
|
||||||
size = Buffer.byteLength(value, enc);
|
size = Buffer.byteLength(value, enc);
|
||||||
|
|
||||||
this.written += utils.sizeVarint(size);
|
this.written += encoding.sizeVarint(size);
|
||||||
this.written += size;
|
this.written += size;
|
||||||
|
|
||||||
this.data.push([VARINT, size]);
|
this.data.push([VARINT, size]);
|
||||||
|
|||||||
@ -12,6 +12,7 @@ var assert = require('assert');
|
|||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
var Path = require('./path');
|
var Path = require('./path');
|
||||||
|
var common = require('./common');
|
||||||
var Script = require('../script/script');
|
var Script = require('../script/script');
|
||||||
var WalletKey = require('./walletkey');
|
var WalletKey = require('./walletkey');
|
||||||
var HD = require('../hd/hd');
|
var HD = require('../hd/hd');
|
||||||
@ -107,7 +108,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
|||||||
|
|
||||||
assert(options, 'Options are required.');
|
assert(options, 'Options are required.');
|
||||||
assert(utils.isNumber(options.wid));
|
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(HD.isHD(options.accountKey), 'Account key is required.');
|
||||||
assert(utils.isNumber(options.accountIndex), 'Account index 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;
|
this.id = options.id;
|
||||||
|
|
||||||
if (options.name != null) {
|
if (options.name != null) {
|
||||||
assert(utils.isName(options.name), 'Bad account name.');
|
assert(common.isName(options.name), 'Bad account name.');
|
||||||
this.name = options.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 constants = require('../protocol/constants');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
|
var btcutils = require('../utils/btcutils');
|
||||||
var TX = require('../primitives/tx');
|
var TX = require('../primitives/tx');
|
||||||
var Coin = require('../primitives/coin');
|
var Coin = require('../primitives/coin');
|
||||||
var Outpoint = require('../primitives/outpoint');
|
var Outpoint = require('../primitives/outpoint');
|
||||||
@ -3191,7 +3192,7 @@ Details.prototype.getFee = function getFee() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Details.prototype.getRate = function getRate(fee) {
|
Details.prototype.getRate = function getRate(fee) {
|
||||||
return TX.getRate(this.vsize, fee);
|
return btcutils.getRate(this.vsize, fee);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
@ -14,13 +15,14 @@ var utils = require('../utils/utils');
|
|||||||
var Locker = require('../utils/locker');
|
var Locker = require('../utils/locker');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var btcutils = require('../utils/btcutils');
|
||||||
var BufferReader = require('../utils/reader');
|
var BufferReader = require('../utils/reader');
|
||||||
var BufferWriter = require('../utils/writer');
|
var BufferWriter = require('../utils/writer');
|
||||||
|
var base58 = require('../utils/base58');
|
||||||
var TXDB = require('./txdb');
|
var TXDB = require('./txdb');
|
||||||
var Path = require('./path');
|
var Path = require('./path');
|
||||||
|
var common = require('./common');
|
||||||
var Address = require('../primitives/address');
|
var Address = require('../primitives/address');
|
||||||
var TX = require('../primitives/tx');
|
|
||||||
var MTX = require('../primitives/mtx');
|
var MTX = require('../primitives/mtx');
|
||||||
var WalletKey = require('./walletkey');
|
var WalletKey = require('./walletkey');
|
||||||
var HD = require('../hd/hd');
|
var HD = require('../hd/hd');
|
||||||
@ -124,7 +126,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
assert(utils.isName(options.id), 'Bad wallet ID.');
|
assert(common.isName(options.id), 'Bad wallet ID.');
|
||||||
id = options.id;
|
id = options.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +540,7 @@ Wallet.prototype.renameAccount = co(function* renameAccount(acct, name) {
|
|||||||
Wallet.prototype._renameAccount = co(function* _renameAccount(acct, name) {
|
Wallet.prototype._renameAccount = co(function* _renameAccount(acct, name) {
|
||||||
var i, account, old, paths, path;
|
var i, account, old, paths, path;
|
||||||
|
|
||||||
if (!utils.isName(name))
|
if (!common.isName(name))
|
||||||
throw new Error('Bad account name.');
|
throw new Error('Bad account name.');
|
||||||
|
|
||||||
account = yield this.getAccount(acct);
|
account = yield this.getAccount(acct);
|
||||||
@ -628,7 +630,7 @@ Wallet.prototype.getID = function getID() {
|
|||||||
p.writeBytes(hash);
|
p.writeBytes(hash);
|
||||||
p.writeChecksum();
|
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)
|
if (txs.length > 0)
|
||||||
this.logger.info('Rebroadcasting %d transactions.', txs.length);
|
this.logger.info('Rebroadcasting %d transactions.', txs.length);
|
||||||
|
|
||||||
txs = TX.sort(txs);
|
txs = btcutils.sortTX(txs);
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++)
|
for (i = 0; i < txs.length; i++)
|
||||||
yield this.db.send(txs[i]);
|
yield this.db.send(txs[i]);
|
||||||
|
|||||||
@ -7,16 +7,19 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var assert = require('assert');
|
||||||
var AsyncObject = require('../utils/async');
|
var AsyncObject = require('../utils/async');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var co = require('../utils/co');
|
var co = require('../utils/co');
|
||||||
var Locker = require('../utils/locker');
|
var Locker = require('../utils/locker');
|
||||||
var LRU = require('../utils/lru');
|
var LRU = require('../utils/lru');
|
||||||
|
var encoding = require('../utils/encoding');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = require('assert');
|
var btcutils = require('../utils/btcutils');
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var Network = require('../protocol/network');
|
var Network = require('../protocol/network');
|
||||||
var Path = require('./path');
|
var Path = require('./path');
|
||||||
|
var common = require('./common');
|
||||||
var Wallet = require('./wallet');
|
var Wallet = require('./wallet');
|
||||||
var Account = require('./account');
|
var Account = require('./account');
|
||||||
var LDB = require('../db/ldb');
|
var LDB = require('../db/ldb');
|
||||||
@ -32,7 +35,7 @@ var BlockMapRecord = records.BlockMapRecord;
|
|||||||
var BlockMeta = records.BlockMeta;
|
var BlockMeta = records.BlockMeta;
|
||||||
var PathMapRecord = records.PathMapRecord;
|
var PathMapRecord = records.PathMapRecord;
|
||||||
var OutpointMapRecord = records.OutpointMapRecord;
|
var OutpointMapRecord = records.OutpointMapRecord;
|
||||||
var U32 = utils.U32;
|
var U32 = encoding.U32;
|
||||||
var DUMMY = new Buffer([0]);
|
var DUMMY = new Buffer([0]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -694,7 +697,7 @@ WalletDB.prototype._rename = co(function* _rename(wallet, id) {
|
|||||||
var old = wallet.id;
|
var old = wallet.id;
|
||||||
var i, paths, path, batch;
|
var i, paths, path, batch;
|
||||||
|
|
||||||
if (!utils.isName(id))
|
if (!common.isName(id))
|
||||||
throw new Error('WDB: Bad wallet ID.');
|
throw new Error('WDB: Bad wallet ID.');
|
||||||
|
|
||||||
if (yield this.has(id))
|
if (yield this.has(id))
|
||||||
@ -1300,7 +1303,7 @@ WalletDB.prototype.resend = co(function* resend() {
|
|||||||
txs.push(tx);
|
txs.push(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
txs = TX.sort(txs);
|
txs = btcutils.sortTX(txs);
|
||||||
|
|
||||||
for (i = 0; i < txs.length; i++)
|
for (i = 0; i < txs.length; i++)
|
||||||
yield this.send(txs[i]);
|
yield this.send(txs[i]);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
var BN = require('bn.js');
|
var BN = require('bn.js');
|
||||||
var bcoin = require('../').set('main');
|
var bcoin = require('../').set('main');
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
|
var btcutils = require('../lib/utils/btcutils');
|
||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var network = bcoin.networks;
|
var network = bcoin.networks;
|
||||||
@ -106,7 +107,7 @@ describe('Block', function() {
|
|||||||
var reward;
|
var reward;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
reward = bcoin.block.reward(height);
|
reward = btcutils.getReward(height, 210000);
|
||||||
assert(reward <= constants.COIN * 50);
|
assert(reward <= constants.COIN * 50);
|
||||||
total += reward;
|
total += reward;
|
||||||
if (reward === 0)
|
if (reward === 0)
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
var BN = require('bn.js');
|
var BN = require('bn.js');
|
||||||
var bcoin = require('../').set('main');
|
var bcoin = require('../').set('main');
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
|
var base58 = require('../lib/utils/base58');
|
||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
@ -159,7 +160,7 @@ describe('HD', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function ub58(data) {
|
function ub58(data) {
|
||||||
return utils.fromBase58(data).toString('hex');
|
return base58.decode(data).toString('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
function equal(a, b) {
|
function equal(a, b) {
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var BN = require('bn.js');
|
|
||||||
var bcoin = require('../').set('main');
|
|
||||||
var assert = require('assert');
|
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 crypto = require('../lib/crypto/crypto');
|
||||||
var schnorr = require('../lib/crypto/schnorr');
|
var schnorr = require('../lib/crypto/schnorr');
|
||||||
|
|
||||||
@ -25,64 +28,63 @@ describe('Utils', function() {
|
|||||||
|
|
||||||
it('should encode/decode base58', function() {
|
it('should encode/decode base58', function() {
|
||||||
var arr = new Buffer([ 0, 0, 0, 0xde, 0xad, 0xbe, 0xef ]);
|
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.equal(b, '1116h8cQN');
|
||||||
assert.deepEqual(utils.fromBase58(b), arr);
|
assert.deepEqual(base58.decode(b), arr);
|
||||||
for (var i = 0; i < vectors.length; i++) {
|
for (var i = 0; i < vectors.length; i++) {
|
||||||
var r = new Buffer(vectors[i][0], 'hex');
|
var r = new Buffer(vectors[i][0], 'hex');
|
||||||
var b = vectors[i][1];
|
var b = vectors[i][1];
|
||||||
assert.equal(utils.toBase58(r), b);
|
assert.equal(base58.encode(r), b);
|
||||||
assert.deepEqual(utils.fromBase58(b), r);
|
assert.deepEqual(base58.decode(b), r);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should translate bits to target', function() {
|
it('should verify proof-of-work', function() {
|
||||||
var bits = 0x1900896c;
|
|
||||||
var hash = new Buffer(
|
var hash = new Buffer(
|
||||||
'672b3f1bb11a994267ea4171069ba0aa4448a840f38e8f340000000000000000',
|
'672b3f1bb11a994267ea4171069ba0aa4448a840f38e8f340000000000000000',
|
||||||
'hex'
|
'hex'
|
||||||
);
|
);
|
||||||
var target = utils.fromCompact(bits);
|
var bits = 0x1900896c;
|
||||||
assert(utils.testTarget(hash, target));
|
assert(btcutils.verifyPOW(hash, bits));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should convert satoshi to btc', function() {
|
it('should convert satoshi to btc', function() {
|
||||||
var btc = utils.btc(5460);
|
var btc = btcutils.btc(5460);
|
||||||
assert.equal(btc, '0.0000546');
|
assert.equal(btc, '0.0000546');
|
||||||
btc = utils.btc(54678 * 1000000);
|
btc = btcutils.btc(54678 * 1000000);
|
||||||
assert.equal(btc, '546.78');
|
assert.equal(btc, '546.78');
|
||||||
btc = utils.btc(5460 * 10000000);
|
btc = btcutils.btc(5460 * 10000000);
|
||||||
assert.equal(btc, '546.0');
|
assert.equal(btc, '546.0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should convert btc to satoshi', function() {
|
it('should convert btc to satoshi', function() {
|
||||||
var btc = utils.satoshi('0.0000546');
|
var btc = btcutils.satoshi('0.0000546');
|
||||||
assert(btc === 5460);
|
assert(btc === 5460);
|
||||||
btc = utils.satoshi('546.78');
|
btc = btcutils.satoshi('546.78');
|
||||||
assert(btc === 54678 * 1000000);
|
assert(btc === 54678 * 1000000);
|
||||||
btc = utils.satoshi('546');
|
btc = btcutils.satoshi('546');
|
||||||
assert(btc === 5460 * 10000000);
|
assert(btc === 5460 * 10000000);
|
||||||
btc = utils.satoshi('546.0');
|
btc = btcutils.satoshi('546.0');
|
||||||
assert(btc === 5460 * 10000000);
|
assert(btc === 5460 * 10000000);
|
||||||
btc = utils.satoshi('546.0000');
|
btc = btcutils.satoshi('546.0000');
|
||||||
assert(btc === 5460 * 10000000);
|
assert(btc === 5460 * 10000000);
|
||||||
assert.doesNotThrow(function() {
|
assert.doesNotThrow(function() {
|
||||||
utils.satoshi('546.00000000000000000');
|
btcutils.satoshi('546.00000000000000000');
|
||||||
});
|
});
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
utils.satoshi('546.00000000000000001');
|
btcutils.satoshi('546.00000000000000001');
|
||||||
});
|
});
|
||||||
assert.doesNotThrow(function() {
|
assert.doesNotThrow(function() {
|
||||||
utils.satoshi('90071992.54740991');
|
btcutils.satoshi('90071992.54740991');
|
||||||
});
|
});
|
||||||
assert.doesNotThrow(function() {
|
assert.doesNotThrow(function() {
|
||||||
utils.satoshi('090071992.547409910');
|
btcutils.satoshi('090071992.547409910');
|
||||||
});
|
});
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
utils.satoshi('90071992.54740992');
|
btcutils.satoshi('90071992.54740992');
|
||||||
});
|
});
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
utils.satoshi('190071992.54740991');
|
btcutils.satoshi('190071992.54740991');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -99,64 +101,64 @@ describe('Utils', function() {
|
|||||||
var n = 0;
|
var n = 0;
|
||||||
var b = new Buffer(1);
|
var b = new Buffer(1);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 0, 0);
|
encoding.writeVarint2(b, 0, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 0);
|
assert.equal(encoding.readVarint2(b, 0).value, 0);
|
||||||
assert.deepEqual(b, [0]);
|
assert.deepEqual(b, [0]);
|
||||||
|
|
||||||
var b = new Buffer(1);
|
var b = new Buffer(1);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 1, 0);
|
encoding.writeVarint2(b, 1, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 1);
|
assert.equal(encoding.readVarint2(b, 0).value, 1);
|
||||||
assert.deepEqual(b, [1]);
|
assert.deepEqual(b, [1]);
|
||||||
|
|
||||||
var b = new Buffer(1);
|
var b = new Buffer(1);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 127, 0);
|
encoding.writeVarint2(b, 127, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 127);
|
assert.equal(encoding.readVarint2(b, 0).value, 127);
|
||||||
assert.deepEqual(b, [0x7f]);
|
assert.deepEqual(b, [0x7f]);
|
||||||
|
|
||||||
var b = new Buffer(2);
|
var b = new Buffer(2);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 128, 0);
|
encoding.writeVarint2(b, 128, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 128);
|
assert.equal(encoding.readVarint2(b, 0).value, 128);
|
||||||
assert.deepEqual(b, [0x80, 0x00]);
|
assert.deepEqual(b, [0x80, 0x00]);
|
||||||
|
|
||||||
var b = new Buffer(2);
|
var b = new Buffer(2);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 255, 0);
|
encoding.writeVarint2(b, 255, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 255);
|
assert.equal(encoding.readVarint2(b, 0).value, 255);
|
||||||
assert.deepEqual(b, [0x80, 0x7f]);
|
assert.deepEqual(b, [0x80, 0x7f]);
|
||||||
|
|
||||||
var b = new Buffer(2);
|
var b = new Buffer(2);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 16383, 0);
|
encoding.writeVarint2(b, 16383, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 16383);
|
assert.equal(encoding.readVarint2(b, 0).value, 16383);
|
||||||
assert.deepEqual(b, [0xfe, 0x7f]);
|
assert.deepEqual(b, [0xfe, 0x7f]);
|
||||||
|
|
||||||
var b = new Buffer(2);
|
var b = new Buffer(2);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 16384, 0);
|
encoding.writeVarint2(b, 16384, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 16384);
|
assert.equal(encoding.readVarint2(b, 0).value, 16384);
|
||||||
assert.deepEqual(b, [0xff, 0x00]);
|
assert.deepEqual(b, [0xff, 0x00]);
|
||||||
|
|
||||||
var b = new Buffer(3);
|
var b = new Buffer(3);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 16511, 0);
|
encoding.writeVarint2(b, 16511, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 16511);
|
assert.equal(encoding.readVarint2(b, 0).value, 16511);
|
||||||
// assert.deepEqual(b, [0x80, 0xff, 0x7f]);
|
// assert.deepEqual(b, [0x80, 0xff, 0x7f]);
|
||||||
assert.deepEqual(b, [0xff, 0x7f, 0x00]);
|
assert.deepEqual(b, [0xff, 0x7f, 0x00]);
|
||||||
|
|
||||||
var b = new Buffer(3);
|
var b = new Buffer(3);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, 65535, 0);
|
encoding.writeVarint2(b, 65535, 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, 65535);
|
assert.equal(encoding.readVarint2(b, 0).value, 65535);
|
||||||
// assert.deepEqual(b, [0x82, 0xfd, 0x7f]);
|
// assert.deepEqual(b, [0x82, 0xfd, 0x7f]);
|
||||||
assert.deepEqual(b, [0x82, 0xfe, 0x7f]);
|
assert.deepEqual(b, [0x82, 0xfe, 0x7f]);
|
||||||
|
|
||||||
var b = new Buffer(5);
|
var b = new Buffer(5);
|
||||||
b.fill(0x00);
|
b.fill(0x00);
|
||||||
utils.writeVarint2(b, Math.pow(2, 32), 0);
|
encoding.writeVarint2(b, Math.pow(2, 32), 0);
|
||||||
assert.equal(utils.readVarint2(b, 0).value, Math.pow(2, 32));
|
assert.equal(encoding.readVarint2(b, 0).value, Math.pow(2, 32));
|
||||||
assert.deepEqual(b, [0x8e, 0xfe, 0xfe, 0xff, 0x00]);
|
assert.deepEqual(b, [0x8e, 0xfe, 0xfe, 0xff, 0x00]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -189,11 +191,11 @@ describe('Utils', function() {
|
|||||||
var buf2 = new Buffer(8);
|
var buf2 = new Buffer(8);
|
||||||
var msg = 'should write+read a ' + num.bitLength() + ' bit unsigned int';
|
var msg = 'should write+read a ' + num.bitLength() + ' bit unsigned int';
|
||||||
it(msg, function() {
|
it(msg, function() {
|
||||||
utils.writeU64(buf1, num, 0);
|
encoding.writeU64(buf1, num, 0);
|
||||||
utils.writeU64N(buf2, num.toNumber(), 0);
|
encoding.writeU64N(buf2, num.toNumber(), 0);
|
||||||
assert.deepEqual(buf1, buf2);
|
assert.deepEqual(buf1, buf2);
|
||||||
var n1 = utils.readU64(buf1, 0);
|
var n1 = encoding.readU64(buf1, 0);
|
||||||
var n2 = utils.readU64N(buf2, 0);
|
var n2 = encoding.readU64N(buf2, 0);
|
||||||
assert.equal(n1.toNumber(), n2);
|
assert.equal(n1.toNumber(), n2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -204,26 +206,26 @@ describe('Utils', function() {
|
|||||||
var msg = 'should write+read a ' + num.bitLength()
|
var msg = 'should write+read a ' + num.bitLength()
|
||||||
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int';
|
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int';
|
||||||
it(msg, function() {
|
it(msg, function() {
|
||||||
utils.write64(buf1, num, 0);
|
encoding.write64(buf1, num, 0);
|
||||||
utils.write64N(buf2, num.toNumber(), 0);
|
encoding.write64N(buf2, num.toNumber(), 0);
|
||||||
assert.deepEqual(buf1, buf2);
|
assert.deepEqual(buf1, buf2);
|
||||||
var n1 = utils.read64(buf1, 0);
|
var n1 = encoding.read64(buf1, 0);
|
||||||
var n2 = utils.read64N(buf2, 0);
|
var n2 = encoding.read64N(buf2, 0);
|
||||||
assert.equal(n1.toNumber(), n2);
|
assert.equal(n1.toNumber(), n2);
|
||||||
});
|
});
|
||||||
var msg = 'should write+read a ' + num.bitLength()
|
var msg = 'should write+read a ' + num.bitLength()
|
||||||
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int as unsigned';
|
+ ' bit ' + (num.isNeg() ? 'negative' : 'positive') + ' int as unsigned';
|
||||||
it(msg, function() {
|
it(msg, function() {
|
||||||
utils.writeU64(buf1, num, 0);
|
encoding.writeU64(buf1, num, 0);
|
||||||
utils.writeU64N(buf2, num.toNumber(), 0);
|
encoding.writeU64N(buf2, num.toNumber(), 0);
|
||||||
assert.deepEqual(buf1, buf2);
|
assert.deepEqual(buf1, buf2);
|
||||||
var n1 = utils.readU64(buf1, 0);
|
var n1 = encoding.readU64(buf1, 0);
|
||||||
if (num.isNeg()) {
|
if (num.isNeg()) {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
utils.readU64N(buf2, 0);
|
encoding.readU64N(buf2, 0);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var n2 = utils.readU64N(buf2, 0);
|
var n2 = encoding.readU64N(buf2, 0);
|
||||||
assert.equal(n1.toNumber(), n2);
|
assert.equal(n1.toNumber(), n2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -294,8 +296,8 @@ describe('Utils', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should do proper schnorr', function() {
|
it('should do proper schnorr', function() {
|
||||||
var key = bcoin.ec.generatePrivateKey();
|
var key = ec.generatePrivateKey();
|
||||||
var pub = bcoin.ec.publicKeyCreate(key, true);
|
var pub = ec.publicKeyCreate(key, true);
|
||||||
var msg = crypto.hash256(new Buffer('foo', 'ascii'));
|
var msg = crypto.hash256(new Buffer('foo', 'ascii'));
|
||||||
var sig = schnorr.sign(msg, key);
|
var sig = schnorr.sign(msg, key);
|
||||||
assert(schnorr.verify(msg, sig, pub));
|
assert(schnorr.verify(msg, sig, pub));
|
||||||
|
|||||||
@ -5,6 +5,7 @@ var bcoin = require('../').set('main');
|
|||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var network = bcoin.networks;
|
var network = bcoin.networks;
|
||||||
var utils = bcoin.utils;
|
var utils = bcoin.utils;
|
||||||
|
var encoding = require('../lib/utils/encoding');
|
||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var scriptTypes = constants.scriptTypes;
|
var scriptTypes = constants.scriptTypes;
|
||||||
@ -26,8 +27,8 @@ function nextBlock(height) {
|
|||||||
if (height == null)
|
if (height == null)
|
||||||
height = globalHeight++;
|
height = globalHeight++;
|
||||||
|
|
||||||
hash = crypto.hash256(utils.U32(height)).toString('hex');
|
hash = crypto.hash256(encoding.U32(height)).toString('hex');
|
||||||
prev = crypto.hash256(utils.U32(height - 1)).toString('hex');
|
prev = crypto.hash256(encoding.U32(height - 1)).toString('hex');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hash: hash,
|
hash: hash,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user