forked from bitcoinjs/coinselect
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
5,008 additions
and
1,892 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
coverage | ||
.nyc_output | ||
node_modules | ||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,48 @@ | ||
var utils = require('./utils') | ||
var ext = require('./bn-extensions') | ||
|
||
// add inputs until we reach or surpass the target value (or deplete) | ||
// worst-case: O(n) | ||
module.exports = function accumulative (utxos, outputs, feeRate) { | ||
if (!isFinite(utils.uintOrNaN(feeRate))) return {} | ||
if (!isFinite(utils.bnOrNaN(feeRate))) return {} | ||
var bytesAccum = utils.transactionBytes([], outputs) | ||
|
||
var inAccum = 0 | ||
var inAccum = ext.BN_ZERO | ||
var inputs = [] | ||
var outAccum = utils.sumOrNaN(outputs) | ||
|
||
for (var i = 0; i < utxos.length; ++i) { | ||
var utxo = utxos[i] | ||
var utxoBytes = utils.inputBytes(utxo) | ||
var utxoFee = feeRate * utxoBytes | ||
var utxoValue = utils.uintOrNaN(utxo.value) | ||
var utxoFee = ext.mul(feeRate, utxoBytes) | ||
var utxoValue = utils.bnOrNaN(utxo.value) | ||
|
||
// skip detrimental input | ||
if (utxoFee > utxo.value) { | ||
if (i === utxos.length - 1) return { fee: feeRate * (bytesAccum + utxoBytes) } | ||
var feeIsMoreThanValue = ext.gt(utxoFee, utxoValue) | ||
// utxoFee > utxoValue | ||
if (feeIsMoreThanValue) { | ||
if (i === utxos.length - 1) { | ||
var bytesSum = ext.add(bytesAccum, utxoBytes) | ||
return { | ||
fee: ext.mul(feeRate, bytesSum) | ||
} | ||
} | ||
continue | ||
} | ||
|
||
bytesAccum += utxoBytes | ||
inAccum += utxoValue | ||
bytesAccum = ext.add(bytesAccum, utxoBytes) | ||
inAccum = ext.add(inAccum, utxoValue) | ||
inputs.push(utxo) | ||
|
||
var fee = feeRate * bytesAccum | ||
var fee = ext.mul(feeRate, bytesAccum) | ||
|
||
// go again? | ||
if (inAccum < outAccum + fee) continue | ||
if (ext.lt(inAccum, ext.add(outAccum, fee))) continue | ||
|
||
return utils.finalize(inputs, outputs, feeRate) | ||
} | ||
|
||
return { fee: feeRate * bytesAccum } | ||
return { | ||
fee: feeRate.mul(bytesAccum) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,42 @@ | ||
var utils = require('./utils') | ||
var ext = require('./bn-extensions') | ||
|
||
// only add inputs if they don't bust the target value (aka, exact match) | ||
// worst-case: O(n) | ||
module.exports = function blackjack (utxos, outputs, feeRate) { | ||
if (!isFinite(utils.uintOrNaN(feeRate))) return {} | ||
if (!isFinite(utils.bnOrNaN(feeRate))) return {} | ||
|
||
var bytesAccum = utils.transactionBytes([], outputs) | ||
|
||
var inAccum = 0 | ||
var inAccum = ext.BN_ZERO | ||
var inputs = [] | ||
var outAccum = utils.sumOrNaN(outputs) | ||
var threshold = utils.dustThreshold({}, feeRate) | ||
|
||
for (var i = 0; i < utxos.length; ++i) { | ||
var input = utxos[i] | ||
var inputBytes = utils.inputBytes(input) | ||
var fee = feeRate * (bytesAccum + inputBytes) | ||
var inputValue = utils.uintOrNaN(input.value) | ||
var fee = ext.mul(feeRate, ext.add(bytesAccum, inputBytes)) | ||
var inputValue = utils.bnOrNaN(input.value) | ||
|
||
// would it waste value? | ||
if ((inAccum + inputValue) > (outAccum + fee + threshold)) continue | ||
var totalInputs = ext.add(inAccum, inputValue) | ||
var outputsAndFee = ext.add(outAccum, fee) | ||
var totalOutputs = ext.add(outputsAndFee, threshold) | ||
var inputsAreGreaterThanOutputs = ext.gt(totalInputs, totalOutputs) | ||
|
||
bytesAccum += inputBytes | ||
inAccum += inputValue | ||
if (inputsAreGreaterThanOutputs) continue | ||
|
||
bytesAccum = ext.add(bytesAccum, inputBytes) | ||
inAccum = ext.add(inAccum, inputValue) | ||
inputs.push(input) | ||
|
||
// go again? | ||
if (inAccum < outAccum + fee) continue | ||
if (ext.lt(inAccum, outputsAndFee)) continue | ||
|
||
return utils.finalize(inputs, outputs, feeRate) | ||
} | ||
|
||
return { fee: feeRate * bytesAccum } | ||
return { | ||
fee: feeRate.mul(bytesAccum) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
var BN = require('bn.js') | ||
|
||
var BN_ZERO = new BN(0) | ||
var BN_ONE = new BN(1) | ||
|
||
function mul (multiplicand, multiplier) { | ||
if (!BN.isBN(multiplicand) || !BN.isBN(multiplier)) return NaN | ||
|
||
return multiplicand.mul(multiplier) | ||
} | ||
|
||
function div (dividend, divisor) { | ||
if (!BN.isBN(dividend) || !BN.isBN(divisor)) return NaN | ||
if (divisor.cmp(BN_ZERO) === 0) return Infinity | ||
|
||
return dividend.div(divisor) | ||
} | ||
|
||
function add (arg1, arg2, arg3) { | ||
// Add two items | ||
if (!BN.isBN(arg1) || !BN.isBN(arg2)) return NaN | ||
if (typeof arg3 === 'undefined') return arg1.add(arg2) | ||
|
||
// Add three items | ||
if (!BN.isBN(arg3)) return NaN | ||
return arg1.add(arg2).add(arg3) | ||
} | ||
|
||
function sub (arg1, arg2, arg3) { | ||
// Subtract two items | ||
if (!BN.isBN(arg1) || !BN.isBN(arg2)) return NaN | ||
if (typeof arg3 === 'undefined') return arg1.sub(arg2) | ||
|
||
// Subtract three items | ||
if (!BN.isBN(arg3)) return NaN | ||
return arg1.sub(arg2).sub(arg3) | ||
} | ||
|
||
function shrn (argument, shiftBy) { | ||
if (!BN.isBN(argument)) return NaN | ||
if (BN.isBN(shiftBy)) shiftBy = shiftBy.toNumber() | ||
if (typeof shiftBy !== 'number') return NaN | ||
|
||
return argument.shrn(shiftBy) | ||
} | ||
|
||
function isZero (argument) { | ||
if (!BN.isBN(argument)) return false | ||
if (argument.cmp(BN_ZERO) === 0) return true | ||
return false | ||
} | ||
|
||
function lt (subject, argument) { | ||
if (!BN.isBN(argument) || !BN.isBN(subject)) return false | ||
return subject.lt(argument) | ||
} | ||
|
||
function gt (subject, argument) { | ||
if (!BN.isBN(argument) || !BN.isBN(subject)) return false | ||
return subject.gt(argument) | ||
} | ||
|
||
module.exports = { | ||
mul: mul, | ||
div: div, | ||
add: add, | ||
sub: sub, | ||
shrn: shrn, | ||
isZero: isZero, | ||
lt: lt, | ||
gt: gt, | ||
BN_ZERO: BN_ZERO, | ||
BN_ONE: BN_ONE | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.