|
|
|
|
@ -36,9 +36,7 @@ var opcodes = Script.opcodes;
|
|
|
|
|
* @param {Number?} options.changeIndex
|
|
|
|
|
* @param {Input[]?} options.inputs
|
|
|
|
|
* @param {Output[]?} options.outputs
|
|
|
|
|
* @property {Number} version - Transaction version. Note that BCoin reads
|
|
|
|
|
* versions as unsigned even though they are signed at the protocol level.
|
|
|
|
|
* This value will never be negative.
|
|
|
|
|
* @property {Number} version - Transaction version.
|
|
|
|
|
* @property {Number} flag - Flag field for segregated witness.
|
|
|
|
|
* Always non-zero (1 if not present).
|
|
|
|
|
* @property {Input[]} inputs
|
|
|
|
|
@ -63,24 +61,6 @@ function MTX(options) {
|
|
|
|
|
|
|
|
|
|
util.inherits(MTX, TX);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Minimum fee to start with
|
|
|
|
|
* during coin selection.
|
|
|
|
|
* @const {Amount}
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.MIN_FEE = 10000;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Maximum fee to allow
|
|
|
|
|
* after coin selection.
|
|
|
|
|
* @const {Amount}
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.MAX_FEE = consensus.COIN / 10;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Inject properties from options object.
|
|
|
|
|
* @private
|
|
|
|
|
@ -147,20 +127,21 @@ MTX.prototype.clone = function clone() {
|
|
|
|
|
/**
|
|
|
|
|
* Add an input to the transaction.
|
|
|
|
|
* @example
|
|
|
|
|
* tx.addInput({ prevout: { hash: ... }, sequence: ... });
|
|
|
|
|
* tx.addInput(prev, prevIndex);
|
|
|
|
|
* tx.addInput(coin);
|
|
|
|
|
* tx.addInput(bcoin.coin.fromTX(prev, prevIndex));
|
|
|
|
|
* @param {Object|TX|Coin} options - Options object, transaction, or coin.
|
|
|
|
|
* @param {Number?} index - Input of output if `options` is a TX.
|
|
|
|
|
* tx.addInput({ prevout: { hash: ... }, script: ... });
|
|
|
|
|
* tx.addInput(tx, index);
|
|
|
|
|
* tx.addInput(new Outpoint(hash, index));
|
|
|
|
|
* tx.addInput(Coin.fromTX(prev, prevIndex, -1));
|
|
|
|
|
* @param {TX|Coin|Outpoint|Input|Object} coin
|
|
|
|
|
* @param {Number?} index - Input of output if `coin` is a TX.
|
|
|
|
|
* @param {Number?} height - Coin height if `coin` is a TX.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype.addInput = function addInput(coin, index) {
|
|
|
|
|
MTX.prototype.addInput = function addInput(coin, index, height) {
|
|
|
|
|
var input = new Input();
|
|
|
|
|
|
|
|
|
|
if (coin instanceof TX) {
|
|
|
|
|
input.fromTX(coin, index);
|
|
|
|
|
coin = Coin.fromTX(coin, index, -1);
|
|
|
|
|
coin = Coin.fromTX(coin, index, height || -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (coin instanceof Coin) {
|
|
|
|
|
@ -187,10 +168,9 @@ MTX.prototype.addInput = function addInput(coin, index) {
|
|
|
|
|
* @example
|
|
|
|
|
* tx.addOutput({ address: ..., value: 100000 });
|
|
|
|
|
* tx.addOutput({ address: ..., value: Amount.value('0.1') });
|
|
|
|
|
* tx.addOutput(receivingWallet, Amount.value('0.1'));
|
|
|
|
|
* @param {Wallet|KeyRing|Object} obj - Wallet, Address,
|
|
|
|
|
* or options (see {@link Script.createOutputScript} for options).
|
|
|
|
|
* @param {Amount?} value - Only needs to be present for non-options.
|
|
|
|
|
* tx.addOutput(address, Amount.value('0.1'));
|
|
|
|
|
* @param {KeyRing|Base58Address|Address|Script|Output|Object} options
|
|
|
|
|
* @param {Amount?} value - Only needs to be present for non-output options.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype.addOutput = function addOutput(options, value) {
|
|
|
|
|
@ -805,15 +785,11 @@ MTX.prototype.isInputSigned = function isInputSigned(index, coin) {
|
|
|
|
|
assert(input, 'Input does not exist.');
|
|
|
|
|
assert(coin, 'No coin passed.');
|
|
|
|
|
|
|
|
|
|
// Get the prevout's script
|
|
|
|
|
prev = coin.script;
|
|
|
|
|
|
|
|
|
|
// Script length, needed for multisig
|
|
|
|
|
vector = input.script;
|
|
|
|
|
redeem = false;
|
|
|
|
|
|
|
|
|
|
// We need to grab the redeem script when
|
|
|
|
|
// signing p2sh transactions.
|
|
|
|
|
// Grab redeem script if possible.
|
|
|
|
|
if (prev.isScripthash()) {
|
|
|
|
|
prev = input.script.getRedeem();
|
|
|
|
|
if (!prev)
|
|
|
|
|
@ -1072,6 +1048,7 @@ MTX.prototype.estimateSize = co(function* estimateSize(estimate) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Call out to the custom estimator.
|
|
|
|
|
if (estimate) {
|
|
|
|
|
size = yield estimate(prev);
|
|
|
|
|
if (size !== -1) {
|
|
|
|
|
@ -1083,18 +1060,18 @@ MTX.prototype.estimateSize = co(function* estimateSize(estimate) {
|
|
|
|
|
// P2SH
|
|
|
|
|
if (prev.isScripthash()) {
|
|
|
|
|
// varint size
|
|
|
|
|
total += 2;
|
|
|
|
|
total += 1;
|
|
|
|
|
// 2-of-3 multisig input
|
|
|
|
|
total += 257;
|
|
|
|
|
total += 149;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// P2WSH
|
|
|
|
|
if (prev.isWitnessScripthash()) {
|
|
|
|
|
// varint-len
|
|
|
|
|
// varint-items-len
|
|
|
|
|
size += 1;
|
|
|
|
|
// 2-of-3 multisig input
|
|
|
|
|
size += 257;
|
|
|
|
|
size += 149;
|
|
|
|
|
// vsize
|
|
|
|
|
size = (size + scale - 1) / scale | 0;
|
|
|
|
|
total += size;
|
|
|
|
|
@ -1140,19 +1117,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype.subtractFee = function subtractFee(fee, index) {
|
|
|
|
|
var i, min, output, hash, addrs;
|
|
|
|
|
|
|
|
|
|
if (Buffer.isBuffer(index) || typeof index === 'string')
|
|
|
|
|
index = [index];
|
|
|
|
|
|
|
|
|
|
if (Array.isArray(index)) {
|
|
|
|
|
addrs = [];
|
|
|
|
|
for (i = 0; i < index.length; i++) {
|
|
|
|
|
hash = Address.getHash(index[i]);
|
|
|
|
|
if (hash)
|
|
|
|
|
addrs.push(hash);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var i, min, output;
|
|
|
|
|
|
|
|
|
|
if (typeof index === 'number') {
|
|
|
|
|
output = this.outputs[index];
|
|
|
|
|
@ -1174,24 +1139,13 @@ MTX.prototype.subtractFee = function subtractFee(fee, index) {
|
|
|
|
|
output = this.outputs[i];
|
|
|
|
|
min = fee + output.getDustThreshold();
|
|
|
|
|
|
|
|
|
|
if (addrs) {
|
|
|
|
|
hash = output.getHash();
|
|
|
|
|
|
|
|
|
|
if (!hash)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (util.indexOf(addrs, hash) === -1)
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (output.value >= min) {
|
|
|
|
|
output.value -= fee;
|
|
|
|
|
break;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i === this.outputs.length)
|
|
|
|
|
throw new Error('Could not subtract fee.');
|
|
|
|
|
throw new Error('Could not subtract fee.');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -1202,7 +1156,7 @@ MTX.prototype.subtractFee = function subtractFee(fee, index) {
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype.fund = co(function* fund(coins, options) {
|
|
|
|
|
var i, select, change;
|
|
|
|
|
var i, select, coin, change;
|
|
|
|
|
|
|
|
|
|
assert(options, 'Options are required.');
|
|
|
|
|
assert(options.changeAddress, 'Change address is required.');
|
|
|
|
|
@ -1223,6 +1177,7 @@ MTX.prototype.fund = co(function* fund(coins, options) {
|
|
|
|
|
change = new Output();
|
|
|
|
|
change.value = select.change;
|
|
|
|
|
change.script.fromAddress(select.changeAddress);
|
|
|
|
|
change.mutable = true;
|
|
|
|
|
|
|
|
|
|
if (change.isDust(policy.MIN_RELAY)) {
|
|
|
|
|
// Do nothing. Change is added to fee.
|
|
|
|
|
@ -1261,15 +1216,19 @@ MTX.prototype.sortMembers = function sortMembers() {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Avoid fee sniping.
|
|
|
|
|
* @param {Number?} [height=network.height] - Current chain height.
|
|
|
|
|
* @param {Number} - Current chain height.
|
|
|
|
|
* @see bitcoin/src/wallet/wallet.cpp
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
|
|
|
|
assert(typeof height === 'number', 'Must pass in height.');
|
|
|
|
|
|
|
|
|
|
if ((Math.random() * 10 | 0) === 0)
|
|
|
|
|
height = Math.max(0, height - (Math.random() * 100 | 0));
|
|
|
|
|
if (util.random(0, 10) === 0) {
|
|
|
|
|
height -= util.random(0, 100);
|
|
|
|
|
|
|
|
|
|
if (height < 0)
|
|
|
|
|
height = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setLocktime(height);
|
|
|
|
|
};
|
|
|
|
|
@ -1282,10 +1241,13 @@ MTX.prototype.avoidFeeSniping = function avoidFeeSniping(height) {
|
|
|
|
|
MTX.prototype.setLocktime = function setLocktime(locktime) {
|
|
|
|
|
var i, input;
|
|
|
|
|
|
|
|
|
|
assert(util.isUInt32(locktime), 'Locktime must be a uint32.');
|
|
|
|
|
assert(this.inputs.length > 0, 'Cannot set sequence with no inputs.');
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < this.inputs.length; i++) {
|
|
|
|
|
input = this.inputs[i];
|
|
|
|
|
if (input.sequence === 0xffffffff)
|
|
|
|
|
input.sequence = 0xffffffff - 1;
|
|
|
|
|
input.sequence = 0xfffffffe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.locktime = locktime;
|
|
|
|
|
@ -1302,6 +1264,7 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) {
|
|
|
|
|
var input = this.inputs[index];
|
|
|
|
|
|
|
|
|
|
assert(input, 'Input does not exist.');
|
|
|
|
|
assert(util.isUInt32(locktime), 'Locktime must be a uint32.');
|
|
|
|
|
|
|
|
|
|
this.version = 2;
|
|
|
|
|
|
|
|
|
|
@ -1316,16 +1279,17 @@ MTX.prototype.setSequence = function setSequence(index, locktime, seconds) {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mark inputs and outputs as mutable.
|
|
|
|
|
* Mark outputs as mutable.
|
|
|
|
|
* @private
|
|
|
|
|
* @param {Boolean} flag
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
MTX.prototype._mutable = function _mutable(value) {
|
|
|
|
|
MTX.prototype._mutable = function _mutable(flag) {
|
|
|
|
|
var i, output;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < this.outputs.length; i++) {
|
|
|
|
|
output = this.outputs[i];
|
|
|
|
|
output.mutable = value;
|
|
|
|
|
output.mutable = flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
@ -1433,7 +1397,7 @@ function CoinSelector(tx, options) {
|
|
|
|
|
this.index = 0;
|
|
|
|
|
this.chosen = [];
|
|
|
|
|
this.change = 0;
|
|
|
|
|
this.fee = 0;
|
|
|
|
|
this.fee = CoinSelector.MIN_FEE;
|
|
|
|
|
|
|
|
|
|
this.selection = 'age';
|
|
|
|
|
this.shouldSubtract = false;
|
|
|
|
|
@ -1441,7 +1405,7 @@ function CoinSelector(tx, options) {
|
|
|
|
|
this.height = -1;
|
|
|
|
|
this.depth = -1;
|
|
|
|
|
this.hardFee = -1;
|
|
|
|
|
this.rate = MTX.MIN_FEE;
|
|
|
|
|
this.rate = CoinSelector.FEE_RATE;
|
|
|
|
|
this.maxFee = -1;
|
|
|
|
|
this.round = false;
|
|
|
|
|
this.changeAddress = null;
|
|
|
|
|
@ -1453,6 +1417,33 @@ function CoinSelector(tx, options) {
|
|
|
|
|
this.fromOptions(options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Default fee rate
|
|
|
|
|
* for coin selection.
|
|
|
|
|
* @const {Amount}
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.FEE_RATE = 10000;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Minimum fee to start with
|
|
|
|
|
* during coin selection.
|
|
|
|
|
* @const {Amount}
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.MIN_FEE = 10000;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Maximum fee to allow
|
|
|
|
|
* after coin selection.
|
|
|
|
|
* @const {Amount}
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.MAX_FEE = consensus.COIN / 10;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize selector options.
|
|
|
|
|
* @param {Object} options
|
|
|
|
|
@ -1542,7 +1533,7 @@ CoinSelector.prototype.init = function init(coins) {
|
|
|
|
|
this.index = 0;
|
|
|
|
|
this.chosen = [];
|
|
|
|
|
this.change = 0;
|
|
|
|
|
this.fee = 0;
|
|
|
|
|
this.fee = CoinSelector.MIN_FEE;
|
|
|
|
|
this.tx.inputs.length = 0;
|
|
|
|
|
|
|
|
|
|
switch (this.selection) {
|
|
|
|
|
@ -1587,7 +1578,7 @@ CoinSelector.prototype.isFull = function isFull() {
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.prototype.isSpendable = function isSpendable(coin) {
|
|
|
|
|
var conf;
|
|
|
|
|
var depth;
|
|
|
|
|
|
|
|
|
|
if (this.height === -1)
|
|
|
|
|
return true;
|
|
|
|
|
@ -1598,22 +1589,17 @@ CoinSelector.prototype.isSpendable = function isSpendable(coin) {
|
|
|
|
|
|
|
|
|
|
if (this.height + 1 < coin.height + consensus.COINBASE_MATURITY)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.depth > 0) {
|
|
|
|
|
if (coin.height === -1)
|
|
|
|
|
return this.depth <= 0;
|
|
|
|
|
if (this.depth === -1)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
conf = this.height - coin.height;
|
|
|
|
|
depth = coin.getDepth(this.height);
|
|
|
|
|
|
|
|
|
|
if (conf < 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
conf += 1;
|
|
|
|
|
|
|
|
|
|
if (conf < this.depth)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (depth < this.depth)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
@ -1627,20 +1613,22 @@ CoinSelector.prototype.isSpendable = function isSpendable(coin) {
|
|
|
|
|
CoinSelector.prototype.getFee = function getFee(size) {
|
|
|
|
|
var fee;
|
|
|
|
|
|
|
|
|
|
if (this.round)
|
|
|
|
|
if (this.round) {
|
|
|
|
|
// This is mostly here for testing.
|
|
|
|
|
// i.e. A fee rounded to the nearest
|
|
|
|
|
// kb is easier to predict ahead of time.
|
|
|
|
|
fee = policy.getRoundFee(size, this.rate);
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
fee = policy.getMinFee(size, this.rate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fee > MTX.MAX_FEE)
|
|
|
|
|
fee = MTX.MAX_FEE;
|
|
|
|
|
|
|
|
|
|
return fee;
|
|
|
|
|
return Math.min(fee, CoinSelector.MAX_FEE);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Fund the transaction with more
|
|
|
|
|
* coins if the `total` was updated.
|
|
|
|
|
* coins if the `output value + fee`
|
|
|
|
|
* total was updated.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.prototype.fund = function fund() {
|
|
|
|
|
@ -1652,16 +1640,12 @@ CoinSelector.prototype.fund = function fund() {
|
|
|
|
|
if (!this.isSpendable(coin))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Add new inputs until TX will have enough
|
|
|
|
|
// funds to cover both minimum post cost
|
|
|
|
|
// and fee.
|
|
|
|
|
this.tx.addInput(coin);
|
|
|
|
|
this.chosen.push(coin);
|
|
|
|
|
|
|
|
|
|
if (this.selection === 'all')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Stop once we're full.
|
|
|
|
|
if (this.isFull())
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -1676,10 +1660,16 @@ CoinSelector.prototype.fund = function fund() {
|
|
|
|
|
CoinSelector.prototype.select = co(function* select(coins) {
|
|
|
|
|
this.init(coins);
|
|
|
|
|
|
|
|
|
|
if (this.hardFee !== -1)
|
|
|
|
|
this.selectHard(this.hardFee);
|
|
|
|
|
else
|
|
|
|
|
if (this.hardFee !== -1) {
|
|
|
|
|
this.selectHard();
|
|
|
|
|
} else {
|
|
|
|
|
// This is potentially asynchronous:
|
|
|
|
|
// it may invoke the size estimator
|
|
|
|
|
// required for redeem scripts (we
|
|
|
|
|
// may be calling out to a wallet
|
|
|
|
|
// or something similar).
|
|
|
|
|
yield this.selectEstimate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!this.isFull()) {
|
|
|
|
|
// Still failing to get enough funds.
|
|
|
|
|
@ -1700,28 +1690,28 @@ CoinSelector.prototype.select = co(function* select(coins) {
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.prototype.selectEstimate = co(function* selectEstimate() {
|
|
|
|
|
var output = new Output();
|
|
|
|
|
var size;
|
|
|
|
|
var change, size;
|
|
|
|
|
|
|
|
|
|
// Initial fee.
|
|
|
|
|
this.fee = MTX.MIN_FEE;
|
|
|
|
|
|
|
|
|
|
// Transfer `total` funds maximum.
|
|
|
|
|
// Set minimum fee and do
|
|
|
|
|
// an initial round of funding.
|
|
|
|
|
this.fee = CoinSelector.MIN_FEE;
|
|
|
|
|
this.fund();
|
|
|
|
|
|
|
|
|
|
// Add dummy output (for `change`) to
|
|
|
|
|
// calculate maximum TX size.
|
|
|
|
|
// Add dummy output for change.
|
|
|
|
|
change = new Output();
|
|
|
|
|
change.mutable = true;
|
|
|
|
|
|
|
|
|
|
if (this.changeAddress) {
|
|
|
|
|
output.script.fromAddress(this.changeAddress);
|
|
|
|
|
change.script.fromAddress(this.changeAddress);
|
|
|
|
|
} else {
|
|
|
|
|
// In case we don't have a change address,
|
|
|
|
|
// we use a fake p2pkh output to gauge size.
|
|
|
|
|
output.script.fromPubkeyhash(encoding.ZERO_HASH160);
|
|
|
|
|
change.script.fromPubkeyhash(encoding.ZERO_HASH160);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tx.outputs.push(output);
|
|
|
|
|
this.tx.outputs.push(change);
|
|
|
|
|
|
|
|
|
|
// Keep recalculating fee and funding
|
|
|
|
|
// Keep recalculating the fee and funding
|
|
|
|
|
// until we reach some sort of equilibrium.
|
|
|
|
|
do {
|
|
|
|
|
size = yield this.tx.estimateSize(this.estimate);
|
|
|
|
|
@ -1739,17 +1729,10 @@ CoinSelector.prototype.selectEstimate = co(function* selectEstimate() {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initiate selection based on a hard fee.
|
|
|
|
|
* @param {Amount} fee
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
CoinSelector.prototype.selectHard = function selectHard(fee) {
|
|
|
|
|
// Initial fee.
|
|
|
|
|
this.fee = fee;
|
|
|
|
|
|
|
|
|
|
if (this.fee > MTX.MAX_FEE)
|
|
|
|
|
this.fee = MTX.MAX_FEE;
|
|
|
|
|
|
|
|
|
|
// Transfer `total` funds maximum.
|
|
|
|
|
CoinSelector.prototype.selectHard = function selectHard() {
|
|
|
|
|
this.fee = Math.min(this.hardFee, CoinSelector.MAX_FEE);
|
|
|
|
|
this.fund();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@ -1818,7 +1801,7 @@ function sortOutputs(a, b) {
|
|
|
|
|
if (res !== 0)
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
|
|
return util.cmp(a.script.toRaw(), b.script.toRaw());
|
|
|
|
|
return util.cmp(a.script.raw, b.script.raw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|