use js numbers for values.

This commit is contained in:
Christopher Jeffrey 2016-05-14 20:57:52 -07:00
parent f38350ec14
commit dd5c9096a7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
19 changed files with 235 additions and 200 deletions

View File

@ -434,7 +434,7 @@ Block.prototype.getReward = function getReward(network) {
var i;
for (i = 1; i < this.txs.length; i++)
reward.iadd(this.txs[i].getFee());
reward += this.txs[i].getFee();
return reward;
};
@ -463,13 +463,18 @@ Block.reward = function reward(height, network) {
halvings = height / network.halvingInterval | 0;
if (height < 0)
return new bn(0);
return 0;
if (halvings >= 64)
return new bn(0);
return 0;
reward = new bn(5000000000);
reward.iushrn(halvings);
if (halvings === 0)
return 5000000000;
reward = 2500000000 >>> (halvings - 1);
// reward = 5000000000;
// reward = Math.floor(reward / Math.pow(2, halvings));
return reward;
};

View File

@ -909,7 +909,7 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, state, callbac
}
// Make sure the miner isn't trying to conjure more coins.
if (block.getClaimed().cmp(block.getReward(self.network)) > 0) {
if (block.getClaimed() > block.getReward(self.network)) {
return callback(new VerifyError(block,
'invalid',
'bad-cb-amount',

View File

@ -45,8 +45,6 @@ function Coin(tx, index) {
this.version = tx.version;
this.height = tx.height;
this.value = tx.outputs[index].value;
if (tx.mutable)
this.value = this.value.clone();
this.script = bcoin.script(tx.outputs[index].script, false);
this.coinbase = tx.isCoinbase();
this.hash = tx.hash('hex');
@ -64,7 +62,7 @@ function Coin(tx, index) {
assert(typeof this.version === 'number');
assert(utils.isNumber(this.height));
assert(bn.isBN(this.value));
assert(typeof this.value === 'number');
assert(this.script instanceof bcoin.script);
assert(typeof this.coinbase === 'boolean');
assert(!this.hash || typeof this.hash === 'string');

View File

@ -843,7 +843,7 @@ Mempool.prototype.removeUnchecked = function removeUnchecked(entry, limit, callb
self.total--;
if (limit) {
rate = entry.fees.muln(1000).divn(entry.size).toNumber();
rate = Math.floor(entry.fees * 1000 / entry.size);
rate += self.minReasonableFee;
if (rate > self.minFeeRate) {
self.minFeeRate = rate;
@ -952,14 +952,14 @@ Mempool.prototype.verify = function verify(entry, callback) {
rejectFee = tx.getMinFee(size, minRate);
minRelayFee = tx.getMinFee(size, self.minRelayFee);
if (rejectFee.cmpn(0) > 0 && modFee.cmp(rejectFee) < 0) {
if (rejectFee > 0 && modFee < rejectFee) {
return callback(new VerifyError(tx,
'insufficientfee',
'mempool min fee not met',
0));
}
if (self.relayPriority && modFee.cmp(minRelayFee) < 0) {
if (self.relayPriority && modFee < minRelayFee) {
if (!entry.isFree(height)) {
return callback(new VerifyError(tx,
'insufficientfee',
@ -973,7 +973,7 @@ Mempool.prototype.verify = function verify(entry, callback) {
// sending thousands of free transactions just to be
// annoying or make others' transactions take longer
// to confirm.
if (self.limitFree && modFee.cmp(minRelayFee) < 0) {
if (self.limitFree && modFee < minRelayFee) {
now = utils.now();
if (!self.lastTime)
@ -995,7 +995,7 @@ Mempool.prototype.verify = function verify(entry, callback) {
self.freeCount += size;
}
if (self.rejectAbsurdFees && fee.cmp(minRelayFee.muln(10000)) > 0)
if (self.rejectAbsurdFees && fee > minRelayFee * 10000)
return callback(new VerifyError(tx, 'highfee', 'absurdly-high-fee', 0));
if (!tx.checkInputs(height, ret))
@ -1136,7 +1136,7 @@ Mempool.prototype.storeOrphan = function storeOrphan(tx, callback, force) {
*/
Mempool.prototype.getBalance = function getBalance(callback) {
var total = new bn(0);
var total = 0;
var i;
return this.db.iterate({
@ -1151,10 +1151,10 @@ Mempool.prototype.getBalance = function getBalance(callback) {
return callback(err);
for (i = 0; i < coins.length; i++)
total.iadd(coins[i].value);
total += coins[i].value;
return callback(null, {
confirmed: new bn(0),
confirmed: 0,
unconfirmed: total,
total: total
});
@ -1876,12 +1876,12 @@ MempoolEntry.fromRaw = function fromRaw(data) {
return new MempoolEntry({
tx: bcoin.tx.fromRaw(p),
height: p.readU32(),
priority: p.readVarint(true),
chainValue: p.readVarint(true),
priority: p.readVarint(),
chainValue: p.readVarint(),
ts: p.readU32(),
count: p.readU32(),
size: p.readU32(),
fees: p.readVarint(true)
fees: p.readVarint()
});
};
@ -1894,12 +1894,12 @@ MempoolEntry.fromRaw = function fromRaw(data) {
*/
MempoolEntry.prototype.getPriority = function getPriority(height) {
var heightDelta = Math.max(0, height - this.height);
var heightDelta = height - this.height;
var modSize = this.tx.getModifiedSize(this.size);
var deltaPriority = new bn(heightDelta).mul(this.chainValue).divn(modSize);
var result = this.priority.add(deltaPriority);
if (result.cmpn(0) < 0)
result = new bn(0);
var deltaPriority = heightDelta * this.chainValue / modSize;
var result = this.priority * deltaPriority;
if (result < 0)
result = 0;
return result;
};
@ -1913,7 +1913,7 @@ MempoolEntry.prototype.getPriority = function getPriority(height) {
MempoolEntry.prototype.isFree = function isFree(height) {
var priority = this.getPriority(height);
return priority.cmp(constants.tx.FREE_THRESHOLD) > 0;
return priority > constants.tx.FREE_THRESHOLD;
};
/*

View File

@ -392,7 +392,7 @@ function MinerBlock(options) {
this.coinbase.addOutput({
address: options.address,
value: new bn(0)
value: 0
});
// Create our block
@ -416,7 +416,7 @@ function MinerBlock(options) {
this.coinbase.inputs[0].witness.items[0] = this.witnessNonce;
this.coinbase.addOutput({
script: new bcoin.script(),
value: new bn(0)
value: 0
});
}

View File

@ -1082,11 +1082,11 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
function total() {
if (options.subtractFee != null)
return outputValue;
return outputValue.add(fee);
return outputValue + fee;
}
function isFull() {
return tx.getInputValue().cmp(total()) >= 0;
return tx.getInputValue() >= total();
}
function addCoins() {
@ -1124,7 +1124,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
// Transfer `total` funds maximum.
addCoins();
} else {
fee = new bn(constants.tx.MIN_FEE);
fee = constants.tx.MIN_FEE;
// Transfer `total` funds maximum.
addCoins();
@ -1136,7 +1136,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
// In case we don't have a change address,
// use a fake p2pkh output to gauge size.
keyHash: constants.ZERO_HASH.slice(0, 20),
value: new bn(0)
value: 0
});
// Change fee value if it is more than 1024
@ -1151,7 +1151,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
// fee is zero (i.e. the mempool is
// not full).
if (tx.isFree(options.height + 1, size)) {
fee = new bn(0);
fee = 0;
break;
}
tryFree = false;
@ -1175,11 +1175,11 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
throw err;
}
if (fee.cmp(constants.tx.MAX_FEE) > 0)
fee = constants.tx.MAX_FEE.clone();
if (fee > constants.tx.MAX_FEE)
fee = constants.tx.MAX_FEE;
// How much money is left after filling outputs.
change = tx.getInputValue().sub(total());
change = tx.getInputValue() - total();
// Attempt to subtract fee.
if (options.subtractFee != null) {
@ -1190,18 +1190,18 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
if (!output)
throw new Error('Subtraction index does not exist.');
min = fee.add(output.getDustThreshold());
min = fee + output.getDustThreshold();
if (output.value.cmp(min) < 0)
if (output.value < 0)
throw new Error('Could not subtract fee.');
output.value.isub(fee);
output.value -= fee;
} else {
for (i = 0; i < tx.outputs.length; i++) {
output = tx.outputs[i];
min = fee.add(output.getDustThreshold());
if (output.value.cmp(min) >= 0) {
output.value.isub(fee);
min = fee + output.getDustThreshold();
if (output.value >= min) {
output.value -= fee;
break;
}
}
@ -1253,10 +1253,10 @@ MTX.prototype.fill = function fill(coins, options) {
// Do nothing. Change is added to fee.
this.outputs.pop();
this.changeIndex = -1;
assert(this.getFee().cmp(result.fee.add(result.change)) === 0);
assert(this.getFee() === result.fee + result.change);
} else {
this.changeIndex = this.outputs.length - 1;
assert(this.getFee().cmp(result.fee) === 0);
assert(this.getFee() === result.fee);
}
return result;
@ -1287,7 +1287,7 @@ MTX.prototype.sortMembers = function sortMembers() {
});
this.outputs = this.outputs.slice().sort(function(a, b) {
var res = a.value.cmp(b.value);
var res = a.value - b.value;
if (res !== 0)
return res;
return utils.cmp(a.encode(), b.encode());

View File

@ -35,20 +35,15 @@ function Output(options, mutable) {
value = options.value;
if (typeof value === 'number') {
assert(value % 1 === 0, 'Output value cannot be a float.');
value = new bn(value);
}
if (!value)
value = new bn(0);
value = 0;
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());
assert(typeof this.value === 'number');
assert(!this.mutable || this.value > 0);
}
/**
@ -167,12 +162,12 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
rate = constants.tx.MIN_RELAY;
if (this.script.isUnspendable())
return new bn(0);
return 0;
size = Framer.output(this, new BufferWriter()).written;
size += 148;
return bcoin.tx.getMinFee(size, rate).muln(3);
return 3 * bcoin.tx.getMinFee(size, rate);
};
/**
@ -182,7 +177,7 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
*/
Output.prototype.isDust = function isDust(rate) {
return this.value.cmp(this.getDustThreshold(rate)) < 0;
return this.value < this.getDustThreshold(rate);
};
/**

View File

@ -306,7 +306,7 @@ exports.opcodesByVal = utils.revMap(exports.opcodes);
* @default
*/
exports.COIN = new bn(10000000).muln(10);
exports.COIN = 100000000;
/**
* One bitcoin / 100.
@ -314,7 +314,7 @@ exports.COIN = new bn(10000000).muln(10);
* @default
*/
exports.CENT = new bn(1000000);
exports.CENT = 1000000;
/**
* Maximum amount of money in satoshis (1btc * 21million)
@ -322,7 +322,7 @@ exports.CENT = new bn(1000000);
* @default
*/
exports.MAX_MONEY = new bn(21000000).mul(exports.COIN);
exports.MAX_MONEY = 21000000 * exports.COIN;
/**
* Sighash Types.
@ -410,10 +410,10 @@ exports.tx = {
MAX_SIZE: 100000,
MAX_COST: 400000,
MIN_FEE: 10000,
MAX_FEE: exports.COIN.divn(10),
MAX_FEE: exports.COIN / 10,
MIN_RELAY: 10000,
BARE_MULTISIG: true,
FREE_THRESHOLD: exports.COIN.muln(144).divn(250),
FREE_THRESHOLD: Math.floor(exports.COIN * 144 / 250),
MAX_SIGOPS: exports.block.MAX_SIGOPS / 5,
MAX_SIGOPS_COST: exports.block.MAX_SIGOPS_COST / 5,
COINBASE_MATURITY: 100

View File

@ -652,8 +652,6 @@ Framer.coin = function _coin(coin, extended, writer) {
if (height === -1)
height = 0x7fffffff;
assert(coin.value.byteLength() <= 8);
p.writeU32(coin.version);
p.writeU32(height);
p.write64(coin.value);
@ -753,8 +751,6 @@ Framer.input = function _input(input, writer) {
Framer.output = function _output(output, writer) {
var p = new BufferWriter(writer);
assert(output.value.byteLength() <= 8);
p.write64(output.value);
Framer.script(output.script, p);

View File

@ -875,7 +875,7 @@ Parser.parseOutput = function parseOutput(p) {
p = new BufferReader(p);
value = p.read64();
value = p.read64N();
script = Parser.parseScript(p);
return {
@ -898,7 +898,7 @@ Parser.parseCoin = function parseCoin(p, extended) {
version = p.readU32();
height = p.readU32();
value = p.read64();
value = p.read64N();
script = Parser.parseScript(p);
coinbase = p.readU8() === 1;

View File

@ -2700,35 +2700,26 @@ Script.isUnknownInput = function isUnknownInput(code, isWitness) {
* @example
* Script.createOutputScript({ address: '1HT7xU2Ngenf7D4yocz2SAcnNLW7rK8d4E' });
* @param {Object} options
* @param {Base58Address?} options.address - Base58 address to send to.
* @param {(Address|Base58Address)?} options.address - Address to send to.
* @param {Buffer?} options.flags - Nulldata flags.
* @param {Buffer?} options.key - Key for pay-to-pubkey.
* @param {Buffer?} options.keyHash - Key has for pay-to-pubkeyhash.
* @param {Buffer[]?} options.keys - Keys for pay-to-multisig.
* @param {Boolean|Buffer[]} options.scriptHash - Whether to create a scripthash
* @param {Buffer} options.scriptHash - Whether to create a scripthash
* @returns {Script}
*/
Script.createOutputScript = function createOutputScript(options) {
var script, m, n, hash, flags, address, redeem;
var m, n, flags, address;
if (!options)
options = {};
if (options.address) {
if (typeof options.address === 'string')
address = bcoin.address.parseBase58(options.address);
if (address.type === 'pubkeyhash')
script = Script.createPubkeyhash(address.hash);
else if (address.type === 'scripthash')
script = Script.createScripthash(address.hash);
else if (address.version !== -1)
script = Script.createWitnessProgram(address.version, address.hash);
else
assert(false, 'Unknown address type.');
return script;
address = options.address;
if (typeof address === 'string')
address = bcoin.address.fromBase58(address);
return address.toScript();
}
if (options.flags) {
@ -2738,19 +2729,23 @@ Script.createOutputScript = function createOutputScript(options) {
return Script.createNulldata(flags);
}
if (options.key) {
script = Script.createPubkey(options.key);
} else if (options.keyHash) {
if (options.key)
return Script.createPubkey(options.key);
if (options.keyHash) {
assert(options.keyHash.length === 20);
if (options.version != null)
script = Script.createWitnessProgram(options.version, options.keyHash);
else
script = Script.createPubkeyhash(options.keyHash);
} else if (options.keys) {
return Script.createWitnessProgram(options.version, options.keyHash);
return Script.createPubkeyhash(options.keyHash);
}
if (options.keys) {
m = options.m;
n = options.n || options.keys.length;
script = Script.createMultisig(options.keys, m, n);
} else if (Buffer.isBuffer(options.scriptHash)) {
return Script.createMultisig(options.keys, m, n);
}
if (options.scriptHash) {
if (options.version != null) {
assert(options.scriptHash.length === 32);
return Script.createWitnessProgram(options.version, options.scriptHash);
@ -2759,28 +2754,7 @@ Script.createOutputScript = function createOutputScript(options) {
return Script.createScripthash(options.scriptHash);
}
if (!script)
return new Script([]);
if (options.locktime != null) {
script.code.unshift(opcodes.OP_DROP);
script.code.unshift(opcodes.OP_CHECKLOCKTIMEVERIFY);
script.code.unshift(Script.array(options.locktime));
}
if (options.scriptHash) {
redeem = script;
if (options.version != null) {
hash = utils.sha256(redeem.encode());
script = Script.createWitnessProgram(options.version, hash);
} else {
hash = utils.ripesha(redeem.encode());
script = Script.createScripthash(hash);
}
script.redeem = redeem;
}
return script;
return new Script();
};
/**

View File

@ -428,7 +428,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
for (i = 0; i < copy.outputs.length; i++) {
if (i !== index) {
copy.outputs[i].script = new Script([]);
copy.outputs[i].value = utils.U64;
copy.outputs[i].value = -1;
}
}
@ -651,9 +651,9 @@ TX.prototype.isCoinbase = function isCoinbase() {
TX.prototype.getFee = function getFee() {
if (!this.hasCoins())
return new bn(0);
return 0;
return this.getInputValue().sub(this.getOutputValue());
return this.getInputValue() - this.getOutputValue();
};
/**
@ -662,14 +662,14 @@ TX.prototype.getFee = function getFee() {
*/
TX.prototype.getInputValue = function getInputValue() {
var total = new bn(0);
var total = 0;
var i;
if (!this.hasCoins())
return total;
for (i = 0; i < this.inputs.length; i++)
total.iadd(this.inputs[i].coin.value);
total += this.inputs[i].coin.value;
return total;
};
@ -680,11 +680,11 @@ TX.prototype.getInputValue = function getInputValue() {
*/
TX.prototype.getOutputValue = function getOutputValue() {
var total = new bn(0);
var total = 0;
var i;
for (i = 0; i < this.outputs.length; i++)
total.iadd(this.outputs[i].value);
total += this.outputs[i].value;
return total;
};
@ -1056,7 +1056,7 @@ TX.prototype.getSigops = function getSigops(flags) {
TX.prototype.isSane = function isSane(ret) {
var prevout = {};
var total = new bn(0);
var total = 0;
var i, input, output, size, key;
if (!ret)
@ -1083,21 +1083,21 @@ TX.prototype.isSane = function isSane(ret) {
for (i = 0; i < this.outputs.length; i++) {
output = this.outputs[i];
if (output.value.cmpn(0) < 0) {
if (output.value < 0) {
ret.reason = 'bad-txns-vout-negative';
ret.score = 100;
return false;
}
if (output.value.cmp(constants.MAX_MONEY) > 0) {
if (output.value > constants.MAX_MONEY) {
ret.reason = 'bad-txns-vout-toolarge';
ret.score = 100;
return false;
}
total.iadd(output.value);
total += output.value;
if (total.cmpn(0) < 0 || total.cmp(constants.MAX_MONEY) > 0) {
if (total < 0 || total > constants.MAX_MONEY) {
ret.reason = 'bad-txns-txouttotal-toolarge';
ret.score = 100;
return false;
@ -1286,7 +1286,7 @@ TX.prototype.hasStandardInputs = function hasStandardInputs(flags) {
*/
TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
var total = new bn(0);
var total = 0;
var i, input, coin, fee, value;
if (!ret)
@ -1304,16 +1304,16 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
}
}
if (coin.value.cmpn(0) < 0 || coin.value.cmp(constants.MAX_MONEY) > 0) {
if (coin.value < 0 || coin.value > constants.MAX_MONEY) {
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
}
total.iadd(coin.value);
total += coin.value;
}
if (total.cmpn(0) < 0 || total.cmp(constants.MAX_MONEY) > 0) {
if (total < 0 || total > constants.MAX_MONEY) {
ret.reason = 'bad-txns-inputvalues-outofrange';
ret.score = 100;
return false;
@ -1321,21 +1321,21 @@ TX.prototype.checkInputs = function checkInputs(spendHeight, ret) {
value = this.getOutputValue();
if (value.cmp(total) > 0) {
if (value > total) {
ret.reason = 'bad-txns-in-belowout'
ret.score = 100;
return false;
}
fee = total.sub(value);
fee = total - value;
if (fee.cmpn(0) < 0) {
if (fee < 0) {
ret.reason = 'bad-txns-fee-negative';
ret.score = 100;
return false;
}
if (fee.cmp(constants.MAX_MONEY) > 0) {
if (fee > constants.MAX_MONEY) {
ret.reason = 'bad-txns-fee-outofrange';
ret.score = 100;
return false;
@ -1392,7 +1392,7 @@ TX.prototype.getPriority = function getPriority(height, size) {
var sum, i, input, age, value;
if (this.isCoinbase())
return new bn(0);
return 0;
if (height == null) {
height = this.height;
@ -1403,8 +1403,8 @@ TX.prototype.getPriority = function getPriority(height, size) {
if (size == null)
size = this.maxSize();
sum = new bn(0);
value = new bn(0);
sum = 0;
value = 0;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
@ -1417,14 +1417,14 @@ TX.prototype.getPriority = function getPriority(height, size) {
if (input.coin.height <= height) {
age = height - input.coin.height;
value.iadd(input.coin.value);
sum.iadd(input.coin.value.muln(age));
value += input.coin.value;
sum += input.coin.value * age;
}
}
return {
value: value,
priority: sum.divn(size)
priority: sum / size
};
};
@ -1451,7 +1451,7 @@ TX.prototype.isFree = function isFree(height, size) {
priority = this.getPriority(height, size).priority;
return priority.cmp(constants.tx.FREE_THRESHOLD) > 0;
return priority > constants.tx.FREE_THRESHOLD;
};
/**
@ -1483,10 +1483,10 @@ TX.getMinFee = function getMinFee(size, rate) {
if (rate == null)
rate = constants.tx.MIN_RELAY;
fee = new bn(rate).muln(size).divn(1000);
fee = Math.floor(rate * size / 1000);
if (fee.cmpn(0) === 0 && rate > 0)
fee = new bn(rate);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};
@ -1510,10 +1510,10 @@ TX.prototype.getMaxFee = function getMaxFee(size, rate) {
if (rate == null)
rate = constants.tx.MIN_RELAY;
fee = new bn(rate).muln(Math.ceil(size / 1000));
fee = rate * Math.ceil(size / 1000);
if (fee.cmpn(0) === 0 && rate > 0)
fee = new bn(rate);
if (fee === 0 && rate > 0)
fee = rate;
return fee;
};

View File

@ -1609,8 +1609,8 @@ TXDB.prototype.hasCoin = function hasCoin(hash, index, callback) {
*/
TXDB.prototype.getBalance = function getBalance(address, callback) {
var confirmed = new bn(0);
var unconfirmed = new bn(0);
var confirmed = 0;
var unconfirmed = 0;
var i;
if (typeof address === 'function') {
@ -1624,15 +1624,15 @@ TXDB.prototype.getBalance = function getBalance(address, callback) {
for (i = 0; i < coins.length; i++) {
if (coins[i].height === -1)
unconfirmed.iadd(coins[i].value);
unconfirmed += coins[i].value;
else
confirmed.iadd(coins[i].value);
confirmed += coins[i].value;
}
return callback(null, {
confirmed: confirmed,
unconfirmed: unconfirmed,
total: confirmed.add(unconfirmed)
total: confirmed + unconfirmed
});
});
};

View File

@ -638,7 +638,7 @@ utils.assert.fatal = function fatal(value, message) {
* @default
*/
utils.COIN = new bn(10000000).muln(10);
utils.COIN = 100000000;
/**
* Convert satoshis to a BTC string. Note that
@ -656,16 +656,13 @@ utils.btc = function btc(satoshi) {
assert(utils.isSatoshi(satoshi), 'Non-satoshi value for conversion.');
if (satoshi.isNeg()) {
satoshi = satoshi.neg();
if (satoshi < 0) {
satoshi = -satoshi;
neg = true;
}
hi = satoshi.div(utils.COIN).toString(10);
lo = satoshi.mod(utils.COIN);
lo = lo.toString(10);
hi = Math.floor(satoshi / utils.COIN).toString(10);
lo = (satoshi % utils.COIN).toString(10);
while (lo.length < 8)
lo = '0' + lo;
@ -711,12 +708,14 @@ utils.satoshi = function satoshi(btc) {
while (lo.length < 8)
lo += '0';
assert(lo.length === 8);
satoshi = (hi + lo).replace(/^0+/, '');
satoshi = new bn(satoshi, 10);
satoshi = parseInt(satoshi, 10);
if (neg)
satoshi.ineg();
satoshi = -satoshi;
return satoshi;
};
@ -738,7 +737,7 @@ utils.isNumber = function isNumber(val) {
*/
utils.isSatoshi = function isSatoshi(val) {
return bn.isBN(val);
return utils.isNumber(val) && val % 1 === 0;
};
/**
@ -1733,20 +1732,54 @@ utils.readU64NBE = function readU64NBE(data, off, force53) {
*/
utils.read64N = function read64N(data, off, force53) {
var hi, lo, result, one, b, v;
off = off >>> 0;
var hi = utils.readU32(data, off + 4);
var lo = utils.readU32(data, off);
if (hi & 0x80000000) {
hi = ~hi + 1;
lo = ~lo + 1;
if (force53)
hi &= utils.MAX_SAFE_HI;
assert(hi <= utils.MAX_SAFE_HI, 'Number exceeds 2^53-1');
return -(hi * 0x100000000 + lo);
if (data[off + 7] & 0x80) {
result = 0;
one = 1;
for (i = 0; i < 8; i++) {
b = (data[i + off] ^ 0xff) + one;
v = b & 0xff;
// We can't have any bits in the msb.
if (i === 7 && v !== 0) {
assert(force53, 'Number exceeds 2^53-1');
v = 0;
}
// We can only have 5 bits in the second msb.
if (i === 6 && v > 0x1f) {
assert(force53, 'Number exceeds 2^53-1');
v &= 0x1f;
}
// We need to shift left by `i` bytes,
// but we can't because this will
// exceed 32 bits. So we multiply by
// `Math.pow(2, shiftBits)` instead.
// Equivalent to `v <<= 8 * i`.
v *= Math.pow(2, 8 * i);
// We can't OR so we add.
result += v;
one = b >>> 8;
}
return -result;
}
hi = utils.readU32(data, off + 4);
lo = utils.readU32(data, off);
if (force53)
hi &= utils.MAX_SAFE_HI;
assert(hi <= utils.MAX_SAFE_HI, 'Number exceeds 2^53-1');
return (hi * 0x100000000) + lo;
};
@ -1760,20 +1793,54 @@ utils.read64N = function read64N(data, off, force53) {
*/
utils.read64NBE = function read64NBE(data, off, force53) {
var hi, lo, result, one, b, v;
off = off >>> 0;
var hi = utils.readU32BE(data, off);
var lo = utils.readU32BE(data, off + 4);
if (hi & 0x80000000) {
hi = ~hi + 1;
lo = ~lo + 1;
if (force53)
hi &= utils.MAX_SAFE_HI;
assert(hi <= utils.MAX_SAFE_HI, 'Number exceeds 2^53-1');
return -(hi * 0x100000000 + lo);
if (data[off] & 0x80) {
result = 0;
one = 1;
for (i = 7; i >= 0; i--) {
b = (data[i + off] ^ 0xff) + one;
v = b & 0xff;
// We can't have any bits on the msb.
if (i === 0 && v !== 0) {
assert(force53, 'Number exceeds 2^53-1');
v = 0;
}
// We can only have 5 bits on the second msb.
if (i === 1 && v > 0x1f) {
assert(force53, 'Number exceeds 2^53-1');
v &= 0x1f;
}
// We need to shift left by `7 - i` bytes,
// but we can't because this will exceed
// 32 bits. So we multiply by
// `Math.pow(2, shiftBits)` instead.
// Equivalent to `v <<= 8 * (7 - i)`.
v *= Math.pow(2, 8 * (7 - i));
// We can't OR so we add.
result += v;
one = b >>> 8;
}
return -result;
}
hi = utils.readU32(data, off);
lo = utils.readU32(data, off + 4);
if (force53)
hi &= utils.MAX_SAFE_HI;
assert(hi <= utils.MAX_SAFE_HI, 'Number exceeds 2^53-1');
return (hi * 0x100000000) + lo;
};

View File

@ -39,7 +39,7 @@ describe('Mempool', function() {
coin: {
version: 1,
height: 0,
value: new bn(70000),
value: 70000,
script: prev,
coinbase: false,
hash: constants.ONE_HASH.toString('hex'),

View File

@ -302,7 +302,7 @@ describe('Script', function() {
}],
outputs: [{
script: output,
value: new bn(0)
value: 0
}],
locktime: 0
});
@ -320,7 +320,7 @@ describe('Script', function() {
}],
outputs: [{
script: new bcoin.script(),
value: new bn(0)
value: 0
}],
locktime: 0
});

View File

@ -161,7 +161,7 @@ describe('TX', function() {
hash: utils.revHex(hash),
index: index,
script: script,
value: value != null ? new bn(value) : new bn(0)
value: value != null ? parseInt(value, 10) : 0
});
tx.fillCoins(coin);
});

View File

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

View File

@ -13,7 +13,7 @@ var dummyInput = {
coin: {
version: 1,
height: 0,
value: constants.MAX_MONEY.clone(),
value: constants.MAX_MONEY,
script: new bcoin.script([]),
coinbase: false,
hash: constants.NULL_HASH,
@ -342,7 +342,7 @@ describe('Wallet', function() {
tx.addOutput(to, 5460);
var cost = tx.getOutputValue();
var total = cost.add(new bn(constants.tx.MIN_FEE));
var total = cost * constants.tx.MIN_FEE;
w1.getCoins(function(err, coins1) {
assert.ifError(err);
@ -350,19 +350,19 @@ describe('Wallet', function() {
assert.ifError(err);
// Add dummy output (for `left`) to calculate maximum TX size
tx.addOutput(w1, new bn(0));
tx.addOutput(w1, 0);
// Add our unspent inputs to sign
tx.addInput(coins1[0]);
tx.addInput(coins1[1]);
tx.addInput(coins2[0]);
var left = tx.getInputValue().sub(total);
if (left.cmpn(constants.tx.DUST_THRESHOLD) < 0) {
tx.outputs[tx.outputs.length - 2].value.iadd(left);
left = new bn(0);
var left = tx.getInputValue() - total;
if (left < constants.tx.DUST_THRESHOLD) {
tx.outputs[tx.outputs.length - 2].value += left;
left = 0;
}
if (left.cmpn(0) === 0)
if (left === 0)
tx.outputs.pop();
else
tx.outputs[tx.outputs.length - 1].value = left;
@ -527,7 +527,7 @@ describe('Wallet', function() {
send.inputs[0].script.code[2] = 0;
assert(!send.verify(null, true, flags));
assert.equal(send.getFee().toNumber(), 10000);
assert.equal(send.getFee(), 10000);
w3 = bcoin.wallet.fromJSON(w3.toJSON());
assert.equal(w3.receiveDepth, 2);