utils refactor.

This commit is contained in:
Christopher Jeffrey 2016-04-30 16:20:40 -07:00
parent aa3579c8cd
commit afee09a935
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
16 changed files with 132 additions and 159 deletions

View File

@ -122,7 +122,7 @@ function getTX(callback) {
function getBlock(callback) {
var hash = argv.args[0];
if (utils.isInt(hash))
if (hash.length !== 64)
hash = +hash;
else
hash = utils.revHex(hash);

View File

@ -152,7 +152,7 @@ ChainBlock.prototype.getAncestors = function getAncestors(max, callback) {
if (ancestors.length)
entry = ancestors.pop();
assert(utils.isFinite(max));
assert(utils.isNumber(max));
// Try to do this iteratively and synchronously
// so we don't have to wait on nextTicks.

View File

@ -65,7 +65,7 @@ function Coin(tx, index) {
}
assert(typeof this.version === 'number');
assert(utils.isFinite(this.height));
assert(utils.isNumber(this.height));
assert(bn.isBN(this.value));
assert(this.script instanceof bcoin.script);
assert(typeof this.coinbase === 'boolean');

View File

@ -508,8 +508,8 @@ HDPrivateKey.prototype.deriveAccount44 = function deriveAccount44(options) {
if (coinType == null)
coinType = this.network === 'main' ? 0 : 1;
assert(utils.isFinite(coinType));
assert(utils.isFinite(accountIndex));
assert(utils.isNumber(coinType));
assert(utils.isNumber(accountIndex));
child = this
.derive(44, true)

View File

@ -809,8 +809,8 @@ HTTPClient.prototype.zapWallet = function zapWallet(id, now, age, callback) {
age: age
};
assert(utils.isFinite(now));
assert(utils.isFinite(age));
assert(utils.isNumber(now));
assert(utils.isNumber(age));
assert(now >= age);
callback = utils.ensure(callback);

View File

@ -85,7 +85,7 @@ HTTPServer.prototype._init = function _init() {
}
if (params.hash) {
if (utils.isInt(params.hash))
if (params.hash.length !== 64)
options.height = params.hash >>> 0;
else
options.hash = utils.revHex(params.hash);

View File

@ -175,7 +175,7 @@ MerkleBlock.prototype.verifyPartial = function verifyPartial() {
return null;
right = visit(depth + 1);
if (right && utils.equals(right, left))
if (right && utils.equal(right, left))
return null;
if (!right)

View File

@ -305,7 +305,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
// with segwit: figuring out where the redeem script and witness
// redeem scripts go.
if (prev.isScripthash()) {
if (addr.program && utils.equals(prev.code[1], addr.programHash)) {
if (addr.program && utils.equal(prev.code[1], addr.programHash)) {
// Witness program nested in regular P2SH.
redeemScript = addr.program.encode();
vector = input.witness.items;
@ -321,7 +321,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
} else {
assert(false, 'Unknown program.');
}
} else if (addr.script && utils.equals(prev.code[1], addr.scriptHash160)) {
} else if (addr.script && utils.equal(prev.code[1], addr.scriptHash160)) {
// Regular P2SH.
redeemScript = addr.script.encode();
vector = input.script.code;
@ -337,14 +337,14 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
if (prev.isWitnessScripthash()) {
// Bare P2WSH.
if (!addr.script || !utils.equals(prev.code[1], addr.scriptHash256))
if (!addr.script || !utils.equal(prev.code[1], addr.scriptHash256))
return false;
witnessScript = addr.script.encode();
prev = addr.script;
} else if (prev.isWitnessPubkeyhash()) {
// Bare P2WPKH.
if (!utils.equals(prev.code[1], addr.keyHash))
if (!utils.equal(prev.code[1], addr.keyHash))
return false;
prev = Script.createPubkeyhash(prev.code[1]);
@ -360,7 +360,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
if (prev.isPubkey()) {
// P2PK
if (!utils.equals(prev.code[0], addr.publicKey))
if (!utils.equal(prev.code[0], addr.publicKey))
return false;
// Already has a script template (at least)
@ -370,7 +370,7 @@ MTX.prototype.scriptInput = function scriptInput(index, addr) {
vector[0] = dummy;
} else if (prev.isPubkeyhash()) {
// P2PKH
if (!utils.equals(prev.code[2], addr.keyHash))
if (!utils.equal(prev.code[2], addr.keyHash))
return false;
// Already has a script template (at least)
@ -535,7 +535,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true;
// Make sure the pubkey is ours.
if (!utils.equals(addr.publicKey, prev.code[0]))
if (!utils.equal(addr.publicKey, prev.code[0]))
return false;
vector[0] = signature;
@ -550,7 +550,7 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
return true;
// Make sure the pubkey hash is ours.
if (!utils.equals(addr.keyHash, prev.code[2]))
if (!utils.equal(addr.keyHash, prev.code[2]))
return false;
vector[0] = signature;

View File

@ -39,11 +39,14 @@ function Output(options, mutable) {
value = new bn(value);
}
this.mutable = !!mutable;
this.value = utils.satoshi(value || new bn(0));
this.script = bcoin.script(options.script, false);
if (!value)
value = new bn(0);
assert(typeof value !== 'number');
this.mutable = !!mutable;
this.value = value;
this.script = bcoin.script(options.script, this.mutable);
assert(bn.isBN(this.value));
assert(!this.mutable || !this.value.isNeg());
}

View File

@ -1321,7 +1321,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) {
case opcodes.OP_EQUALVERIFY: {
if (stack.length < 2)
throw new ScriptError('INVALID_STACK_OPERATION', op, ip);
res = utils.equals(stack.pop(), stack.pop());
res = utils.equal(stack.pop(), stack.pop());
if (op === opcodes.OP_EQUALVERIFY) {
if (!res)
throw new ScriptError('EQUALVERIFY', op, ip);
@ -1922,7 +1922,7 @@ Script.array = function(value) {
if (Buffer.isBuffer(value))
return value;
if (utils.isFinite(value))
if (utils.isNumber(value))
value = new bn(value);
assert(bn.isBN(value));
@ -3935,7 +3935,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) {
hadWitness = true;
// Input script must be exactly one push of the redeem script.
if (!(input.code.length === 1 && utils.equals(input.code[0], raw)))
if (!(input.code.length === 1 && utils.equal(input.code[0], raw)))
throw new ScriptError('WITNESS_MALLEATED');
// Verify the program in the redeem script
@ -3991,7 +3991,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) {
witnessScript = stack.pop();
if (!utils.equals(utils.sha256(witnessScript), program.data))
if (!utils.equal(utils.sha256(witnessScript), program.data))
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
redeem = new Script(witnessScript);

View File

@ -1929,8 +1929,8 @@ TXDB.prototype.zap = function zap(address, now, age, callback, force) {
callback = utils.wrap(callback, unlock);
assert(utils.isFinite(now));
assert(utils.isFinite(age));
assert(utils.isNumber(now));
assert(utils.isNumber(age));
assert(now >= age);
return this.getRange(address, {

View File

@ -357,24 +357,15 @@ utils.pbkdf2 = function pbkdf2(key, salt, iterations, dkLen) {
return DK;
};
/**
* Encryption salt.
* @type String
* @const
*/
utils.salt = new Buffer('bcoin:', 'ascii');
/**
* Encrypt with aes-256-cbc.
* @param {Buffer|String} data
* @param {String} passphrase
* @returns {Buffer} Hex string.
* @throws on no passphrase
* @param {Buffer|String} passphrase
* @returns {Buffer}
*/
utils.encrypt = function encrypt(data, passphrase) {
var cipher, out;
var key, cipher;
assert(crypto, 'No crypto module available.');
assert(passphrase, 'No passphrase.');
@ -382,27 +373,27 @@ utils.encrypt = function encrypt(data, passphrase) {
if (typeof data === 'string')
data = new Buffer(data, 'utf8');
cipher = crypto.createCipher('aes-256-cbc', passphrase);
if (typeof passphrase === 'string')
passphrase = new Buffer(passphrase, 'utf8');
out = Buffer.concat([
cipher.update(utils.salt),
key = utils.pbkdf2key(passphrase, null, 2048, 256, 16);
cipher = crypto.createCipheriv('aes-256-cbc', key.key, key.iv);
return Buffer.concat([
cipher.update(data),
cipher.final()
]);
return out;
};
/**
* Decrypt from aes-256-cbc.
* @param {Buffer|String} data
* @param {String} passphrase
* @param {Buffer|String} passphrase
* @returns {Buffer}
* @throws on bad decrypt.
*/
utils.decrypt = function decrypt(data, passphrase) {
var decipher, out;
var key, decipher;
assert(crypto, 'No crypto module available.');
assert(passphrase, 'No passphrase.');
@ -410,19 +401,39 @@ utils.decrypt = function decrypt(data, passphrase) {
if (typeof data === 'string')
data = new Buffer(data, 'hex');
decipher = crypto.createDecipher('aes-256-cbc', passphrase);
if (typeof passphrase === 'string')
passphrase = new Buffer(passphrase, 'utf8');
out = Buffer.concat([
key = utils.pbkdf2key(passphrase, null, 2048, 256, 16);
decipher = crypto.createDecipheriv('aes-256-cbc', key.key, key.iv);
return Buffer.concat([
decipher.update(data),
decipher.final()
]);
};
if (utils.icmp(out, utils.salt, 0) !== 0)
throw new Error('Decrypt failed.');
/**
* Generate a key and IV using pbkdf2.
* @param {Buffer|String} passphrase
* @param {(Buffer|String)?} salt
* @param {Number} iterations
* @param {Number} nkey - Key size in bits.
* @param {Number} niv - IV size in bytes.
* @returns {Buffer}
*/
out = out.slice(utils.salt.length);
utils.pbkdf2key = function pbkdf2key(passphrase, salt, iterations, nkey, niv) {
var key;
return out;
nkey /= 8;
key = utils.pbkdf2(passphrase, salt || '', iterations, nkey + niv);
return {
key: key.slice(0, nkey),
iv: key.slice(nkey)
};
};
/**
@ -443,7 +454,7 @@ utils.isHex = function isHex(msg) {
* @returns {Boolean}
*/
utils.equals = function equals(a, b) {
utils.equal = function equal(a, b) {
var i;
if (!Buffer.isBuffer(a))
@ -592,40 +603,38 @@ utils.assert.fatal = function fatal(value, message) {
}
};
/**
* One bitcoin in satoshis.
* @const {BN}
* @default
*/
utils.COIN = new bn(10000000).muln(10);
/**
* Convert satoshis to a BTC string. Note that
* BTC strings _always_ have a decimal point.
* @name btc
* @function
* @param {BN|Number} satoshi
* @param {Boolean?} strict - Throw if `satoshi`
* is not a {@link BN}.
* @returns {String} BTC string.
*/
utils.btc =
utils.toBTC = function toBTC(satoshi, strict) {
var m = new bn(10000000).mul(new bn(10));
utils.btc = function btc(satoshi) {
var neg = false;
var lo;
var btc, hi, lo;
if (utils.isBTC(satoshi))
return utils.isBTC(satoshi);
return satoshi;
if (!strict && utils.isFinite(satoshi))
satoshi = new bn(Math.floor(satoshi) + '', 10);
satoshi = utils.isSatoshi(satoshi);
if (!satoshi)
throw new Error('Could not calculate BTC');
assert(utils.isSatoshi(satoshi), 'Non-satoshi value for conversion.');
if (satoshi.isNeg()) {
satoshi = satoshi.neg();
neg = true;
}
lo = satoshi.mod(m);
hi = satoshi.div(utils.COIN).toString(10);
lo = satoshi.mod(utils.COIN);
if (lo.cmpn(0) !== 0) {
lo = lo.toString(10);
@ -640,38 +649,34 @@ utils.toBTC = function toBTC(satoshi, strict) {
if (lo === '.')
lo += '0';
return (neg ? '-' : '') + satoshi.div(m).toString(10) + lo;
btc = hi + lo;
if (neg)
btc = '-' + btc;
return btc;
};
/**
* Convert BTC string to satoshis.
* @name satoshi
* @function
* @param {String|Number} btc
* @param {Boolean?} strict - Throw if `btc`
* is not a string.
* @returns {BN} Satoshis.
*/
utils.satoshi =
utils.toSatoshi =
utils.fromBTC = function fromBTC(btc, strict) {
utils.satoshi = function satoshi(btc) {
var neg = false;
var satoshi, parts, hi, lo;
if (utils.isSatoshi(btc))
return utils.isSatoshi(btc);
return btc;
if (!strict && utils.isFinite(btc)) {
btc = btc + '';
if (utils.isInt(btc))
btc += '.0';
assert(utils.isBTC(btc), 'Non-BTC value for conversion.');
if (btc[0] === '-') {
neg = true;
btc = btc.substring(1);
}
btc = utils.isBTC(btc);
if (!btc)
throw new Error('Could not calculate satoshis');
parts = btc.split('.');
hi = parts[0] || '0';
lo = parts[1] || '0';
@ -681,27 +686,12 @@ utils.fromBTC = function fromBTC(btc, strict) {
satoshi = (hi + lo).replace(/^0+/, '');
return new bn(satoshi, 10);
};
satoshi = new bn(satoshi, 10);
/**
* Test whether a string is an int (no decimal point).
* @param {String?} val
* @returns {Boolean}
*/
if (neg)
satoshi.ineg();
utils.isInt = function isInt(val) {
return typeof val === 'string' && /^\d+$/.test(val);
};
/**
* Test whether a string is a float (decimal point).
* @param {String?} val
* @returns {Boolean}
*/
utils.isFloat = function isFloat(val) {
return typeof val === 'string' && /^-?\d+\.\d+$/.test(val);
return satoshi;
};
/**
@ -710,7 +700,7 @@ utils.isFloat = function isFloat(val) {
* @returns {Boolean}
*/
utils.isFinite = function _isFinite(val) {
utils.isNumber = function isNumber(val) {
return typeof val === 'number' && isFinite(val);
};
@ -721,13 +711,7 @@ utils.isFinite = function _isFinite(val) {
*/
utils.isSatoshi = function isSatoshi(val) {
if (bn.isBN(val))
return val;
if (utils.isInt(val))
return new bn(val, 10);
if (Buffer.isBuffer(val))
return new bn(val);
return false;
return bn.isBN(val);
};
/**
@ -737,25 +721,7 @@ utils.isSatoshi = function isSatoshi(val) {
*/
utils.isBTC = function isBTC(val) {
if (utils.isFloat(val))
return val;
return false;
};
/**
* Ensure number string is a float
* string (with a decimal point).
* @param {String} val
* @returns {String}
* @throws on non-number string
*/
utils.toFloat = function toFloat(val) {
if (utils.isFloat(val))
return val;
if (utils.isInt(val))
return val + '.0';
throw new Error('Could not convert ' + val + ' to float');
return typeof val === 'string' && /^-?\d+\.\d+$/.test(val);
};
/**
@ -2492,7 +2458,7 @@ utils.buildMerkleTree = function buildMerkleTree(leaves) {
for (i = 0; i < size; i += 2) {
i2 = Math.min(i + 1, size - 1);
if (i2 === i + 1 && i2 + 1 === size
&& utils.equals(tree[j + i], tree[j + i2])) {
&& utils.equal(tree[j + i], tree[j + i2])) {
return;
}
hash = Buffer.concat([tree[j + i], tree[j + i2]]);
@ -2593,7 +2559,7 @@ utils.indexOf = function indexOf(arr, buf) {
for (i = 0; i < arr.length; i++) {
if (!Buffer.isBuffer(arr[i]))
continue;
if (utils.equals(arr[i], buf))
if (utils.equal(arr[i], buf))
return i;
}

View File

@ -1018,7 +1018,7 @@ Wallet.prototype.getRedeem = function getRedeem(hash, prefix) {
return;
if (address.program && hash.length === 20) {
if (utils.equals(hash, address.programHash))
if (utils.equal(hash, address.programHash))
return address.program;
}

View File

@ -9,7 +9,15 @@ var utils = require('./utils');
var assert = utils.assert;
/**
* An object that allows writing of buffers in a sane manner.
* An object that allows writing of buffers in a
* sane manner. This buffer writer is extremely
* optimized since it does not actually write
* anything until `render` is called. It makes
* one allocation: at the end, once it knows the
* size of the buffer to be allocated. Because
* of this, it can also act as a size calculator
* which is useful for guaging block size
* without actually serializing any data.
* @exports BufferWriter
* @constructor
* @param {(BufferWriter|Object)?} options

View File

@ -146,9 +146,9 @@ describe('Script', function() {
var s = bcoin.script.fromString(
'OP_1 OP_DUP OP_PUSHDATA1'
);
assert(utils.equals(s.raw, new Buffer('51764c', 'hex')));
assert(utils.equal(s.raw, new Buffer('51764c', 'hex')));
delete s.raw;
assert(utils.equals(s.encode(), new Buffer('51764c', 'hex')));
assert(utils.equal(s.encode(), new Buffer('51764c', 'hex')));
try {
s.execute(stack);
} catch (e) {
@ -159,9 +159,9 @@ describe('Script', function() {
var s = bcoin.script.fromString(
'OP_1 OP_DUP OP_PUSHDATA2 0x01'
);
assert(utils.equals(s.raw, new Buffer('51764d01', 'hex')));
assert(utils.equal(s.raw, new Buffer('51764d01', 'hex')));
delete s.raw;
assert(utils.equals(s.encode(), new Buffer('51764d01', 'hex')));
assert(utils.equal(s.encode(), new Buffer('51764d01', 'hex')));
err = null;
try {
s.execute(stack);
@ -173,9 +173,9 @@ describe('Script', function() {
var s = bcoin.script.fromString(
'OP_1 OP_DUP OP_PUSHDATA4 0x0001'
);
assert(utils.equals(s.raw, new Buffer('51764e0001', 'hex')));
assert(utils.equal(s.raw, new Buffer('51764e0001', 'hex')));
delete s.raw;
assert(utils.equals(s.encode(), new Buffer('51764e0001', 'hex')));
assert(utils.equal(s.encode(), new Buffer('51764e0001', 'hex')));
err = null;
try {
s.execute(stack);
@ -187,9 +187,9 @@ describe('Script', function() {
var s = bcoin.script.fromString(
'OP_1 OP_DUP OP_PUSHDATA1 0x02 0x01'
);
assert(utils.equals(s.raw, new Buffer('51764c0201', 'hex')));
assert(utils.equal(s.raw, new Buffer('51764c0201', 'hex')));
delete s.raw;
assert(utils.equals(s.encode(), new Buffer('51764c0201', 'hex')));
assert(utils.equal(s.encode(), new Buffer('51764c0201', 'hex')));
err = null;
try {
s.execute(stack);
@ -201,9 +201,9 @@ describe('Script', function() {
var s = bcoin.script.fromString(
'OP_1 OP_DUP OP_PUSHDATA2 0x0200 0x01'
);
assert(utils.equals(s.raw, new Buffer('51764d020001', 'hex')));
assert(utils.equal(s.raw, new Buffer('51764d020001', 'hex')));
delete s.raw;
assert(utils.equals(s.encode(), new Buffer('51764d020001', 'hex')));
assert(utils.equal(s.encode(), new Buffer('51764d020001', 'hex')));
err = null;
try {
s.execute(stack);

View File

@ -22,24 +22,20 @@ describe('Utils', function() {
});
it('should convert satoshi to btc', function() {
var btc = utils.toBTC(new bn(5460));
var btc = utils.btc(new bn(5460));
assert.equal(btc, '0.0000546');
btc = utils.toBTC(new bn(54678).mul(new bn(1000000)));
btc = utils.btc(new bn(54678).mul(new bn(1000000)));
assert.equal(btc, '546.78');
btc = utils.toBTC(new bn(5460).mul(new bn(10000000)));
btc = utils.btc(new bn(5460).mul(new bn(10000000)));
assert.equal(btc, '546.0');
btc = utils.toBTC(new Buffer(new bn(5460).mul(new bn(10000000)).toArray()));
assert.equal(btc, '546.0');
// btc = utils.toBTC(new bn(5460).mul(new bn(10000000)).toString('hex'));
// assert.equal(btc, '546.0');
});
it('should convert btc to satoshi', function() {
var btc = utils.fromBTC('0.0000546');
var btc = utils.satoshi('0.0000546');
assert(btc.cmp(new bn(5460)) === 0);
btc = utils.fromBTC('546.78');
btc = utils.satoshi('546.78');
assert(btc.cmp(new bn(54678).mul(new bn(1000000))) === 0);
btc = utils.fromBTC('546.0');
btc = utils.satoshi('546.0');
assert(btc.cmp(new bn(5460).mul(new bn(10000000))) === 0);
});
});