more refactoring.
This commit is contained in:
parent
d423e33e03
commit
86312d9241
112
lib/bcoin/mtx.js
112
lib/bcoin/mtx.js
@ -539,8 +539,8 @@ MTX.prototype.signInput = function signInput(index, addr, type) {
|
||||
return signatures === m;
|
||||
};
|
||||
|
||||
MTX.prototype.isSigned = function isSigned(m) {
|
||||
var i, input, prev, vector, len, j;
|
||||
MTX.prototype.isSigned = function isSigned() {
|
||||
var i, input, prev, vector, m, len, j;
|
||||
var total = 0;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
@ -567,10 +567,7 @@ MTX.prototype.isSigned = function isSigned(m) {
|
||||
|
||||
// If the output script is a witness program,
|
||||
// we have to switch the vector to the witness
|
||||
// and potentially alter the length. Note that
|
||||
// witnesses are stack items, so the `dummy`
|
||||
// _has_ to be an empty buffer (what OP_0
|
||||
// pushes onto the stack).
|
||||
// and potentially alter the length.
|
||||
if (prev.isWitnessScripthash()) {
|
||||
prev = input.witness.getRedeem();
|
||||
vector = input.witness.items;
|
||||
@ -602,13 +599,7 @@ MTX.prototype.isSigned = function isSigned(m) {
|
||||
if (len - 1 !== m)
|
||||
return false;
|
||||
} else {
|
||||
for (j = 0; j < vector.length; j++) {
|
||||
if (Script.isSignatureEncoding(vector[j]))
|
||||
total++;
|
||||
}
|
||||
|
||||
if (total !== m)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -684,15 +675,25 @@ MTX.prototype.scriptOutput = function scriptOutput(index, options) {
|
||||
};
|
||||
|
||||
MTX.prototype.isScripted = function isScripted() {
|
||||
if (this.inputs.length === 0)
|
||||
return false;
|
||||
var i, input;
|
||||
|
||||
if (this.outputs.length === 0)
|
||||
return false;
|
||||
|
||||
return this.inputs.every(function(input) {
|
||||
return input.script.code.length > 0 || input.witness.items.length > 0;
|
||||
});
|
||||
if (this.inputs.length === 0)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
|
||||
if (input.script.code.length === 0)
|
||||
return false;
|
||||
|
||||
if (input.witness.items.length === 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
@ -855,25 +856,20 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
||||
};
|
||||
|
||||
MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
var chosen, lastAdded, tx, outputValue;
|
||||
var i, size, change, fee, tryFree, minValue;
|
||||
var chosen = [];
|
||||
var index = 0;
|
||||
var tx = this.clone();
|
||||
var outputValue = tx.getOutputValue();
|
||||
var tryFree, i, size, change, fee, minValue;
|
||||
|
||||
if (!options || typeof options !== 'object') {
|
||||
options = {
|
||||
changeAddress: arguments[1],
|
||||
fee: arguments[2]
|
||||
};
|
||||
}
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
tx = this.clone();
|
||||
tx.inputs.length = 0;
|
||||
|
||||
chosen = [];
|
||||
lastAdded = 0;
|
||||
|
||||
outputValue = tx.getOutputValue();
|
||||
tryFree = options.free;
|
||||
|
||||
// Null the inputs if there are any.
|
||||
tx.inputs.length = 0;
|
||||
|
||||
if (options.confirmed) {
|
||||
coins = coins.filter(function(coin) {
|
||||
return coin.height !== -1;
|
||||
@ -895,7 +891,7 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
}
|
||||
|
||||
function total() {
|
||||
if (options.subtractFee)
|
||||
if (options.subtractFee != null)
|
||||
return outputValue;
|
||||
return outputValue.add(fee);
|
||||
}
|
||||
@ -905,15 +901,13 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
}
|
||||
|
||||
function addCoins() {
|
||||
var i, index;
|
||||
|
||||
for (i = lastAdded; i < coins.length; i++) {
|
||||
while (index < coins.length) {
|
||||
// Add new inputs until TX will have enough
|
||||
// funds to cover both minimum post cost
|
||||
// and fee.
|
||||
tx.addInput(coins[i]);
|
||||
chosen.push(coins[i]);
|
||||
lastAdded++;
|
||||
tx.addInput(coins[index]);
|
||||
chosen.push(coins[index]);
|
||||
index++;
|
||||
|
||||
if (options.selection === 'all')
|
||||
continue;
|
||||
@ -939,6 +933,9 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
// calculate maximum TX size.
|
||||
tx.addOutput({
|
||||
address: options.changeAddress,
|
||||
// In case we don't have a change address,
|
||||
// use a fake p2pkh output to gauge size.
|
||||
keyHash: constants.zeroHash.slice(0, 20),
|
||||
value: new bn(0)
|
||||
});
|
||||
|
||||
@ -961,10 +958,10 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
else
|
||||
fee = tx.getMaxFee(size);
|
||||
|
||||
// Failed to get enough funds, add more inputs.
|
||||
// Failed to get enough funds, add more coins.
|
||||
if (!isFull())
|
||||
addCoins();
|
||||
} while (!isFull() && lastAdded < coins.length);
|
||||
} while (!isFull() && index < coins.length);
|
||||
}
|
||||
|
||||
if (!isFull()) {
|
||||
@ -1012,50 +1009,37 @@ MTX.prototype.selectCoins = function selectCoins(coins, options) {
|
||||
};
|
||||
|
||||
MTX.prototype.fill = function fill(coins, options) {
|
||||
var self = this;
|
||||
var result, err;
|
||||
var result, i;
|
||||
|
||||
assert(this.ts === 0, 'Cannot modify a confirmed tx.');
|
||||
assert(this.inputs.length === 0, 'TX is already filled.');
|
||||
|
||||
if (!options || typeof options !== 'object') {
|
||||
options = {
|
||||
changeAddress: arguments[1],
|
||||
fee: arguments[2]
|
||||
};
|
||||
}
|
||||
|
||||
assert(coins);
|
||||
assert(options, '`options` are required.');
|
||||
assert(options.changeAddress, '`changeAddress` is required.');
|
||||
|
||||
// Select necessary coins.
|
||||
result = this.selectCoins(coins, options);
|
||||
|
||||
result.coins.forEach(function(coin) {
|
||||
self.addInput(coin);
|
||||
});
|
||||
// Add coins to transaction.
|
||||
for (i = 0; i < result.coins.length; i++)
|
||||
this.addInput(result.coins[i]);
|
||||
|
||||
if (result.change.cmpn(constants.tx.dustThreshold) < 0) {
|
||||
// Do nothing. Change is added to fee.
|
||||
assert.equal(
|
||||
this.getFee().toNumber(),
|
||||
result.fee.add(result.change).toNumber()
|
||||
);
|
||||
assert(this.getFee().cmp(result.fee.add(result.change)) === 0);
|
||||
this.changeIndex = -1;
|
||||
} else {
|
||||
// Add a change output.
|
||||
this.addOutput({
|
||||
address: options.changeAddress,
|
||||
value: result.change
|
||||
});
|
||||
|
||||
this.changeIndex = this.outputs.length - 1;
|
||||
|
||||
assert.equal(this.getFee().toNumber(), result.fee.toNumber());
|
||||
assert(this.getFee().cmp(result.fee) === 0);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki
|
||||
MTX.prototype.sortMembers = function sortMembers() {
|
||||
var changeOutput;
|
||||
|
||||
|
||||
@ -202,6 +202,8 @@ Wallet.prototype.addKey = function addKey(key) {
|
||||
if (key instanceof bcoin.hd.privateKey)
|
||||
key = key.hdPublicKey;
|
||||
|
||||
assert(key instanceof bcoin.hd, 'Must add HD keys to wallet.');
|
||||
|
||||
if (this.derivation === 'bip44') {
|
||||
if (!key || !key.isAccount44())
|
||||
throw new Error('Must add HD account keys to BIP44 wallet.');
|
||||
@ -246,6 +248,8 @@ Wallet.prototype.removeKey = function removeKey(key) {
|
||||
if (key instanceof bcoin.hd.privateKey)
|
||||
key = key.hdPublicKey;
|
||||
|
||||
assert(key instanceof bcoin.hd, 'Must add HD keys to wallet.');
|
||||
|
||||
if (this.derivation === 'bip44') {
|
||||
if (!key || !key.isAccount44())
|
||||
throw new Error('Must add HD account keys to BIP44 wallet.');
|
||||
@ -616,6 +620,10 @@ Wallet.prototype.createTX = function createTX(options, outputs, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.deriveInput = function deriveInput(tx, i) {
|
||||
return this.deriveInputs(tx.inputs[i])[0];
|
||||
};
|
||||
|
||||
Wallet.prototype.deriveInputs = function deriveInputs(tx) {
|
||||
var paths = this.getInputPaths(tx);
|
||||
var addresses = [];
|
||||
@ -731,7 +739,7 @@ Wallet.prototype.getRedeem = function getRedeem(hash, prefix) {
|
||||
else if (hash.length === 32)
|
||||
prefix = 'witnessscripthash';
|
||||
else
|
||||
assert(false, 'Unknown hash length.');
|
||||
return;
|
||||
}
|
||||
|
||||
addr = bcoin.address.compileHash(hash, prefix);
|
||||
@ -759,8 +767,9 @@ Wallet.prototype.zap = function zap(now, age, callback) {
|
||||
Wallet.prototype.scan = function scan(txByAddress, callback) {
|
||||
var self = this;
|
||||
var res = false;
|
||||
var i;
|
||||
|
||||
return this._scan({}, txByAddress, function(err, depth) {
|
||||
return this._scan({}, txByAddress, function(err, depth, txs) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
|
||||
@ -770,25 +779,50 @@ Wallet.prototype.scan = function scan(txByAddress, callback) {
|
||||
if (self.setReceiveDepth(depth.receiveDepth + 1))
|
||||
res = true;
|
||||
|
||||
return callback(null, res);
|
||||
if (self.provider && self.provider.addTX) {
|
||||
utils.forEachSerial(txs, function(tx, next) {
|
||||
self.addTX(tx, next);
|
||||
}, function(err) {
|
||||
if (err)
|
||||
return callback(err);
|
||||
return callback(null, res, txs);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
return callback(null, res, txs);
|
||||
});
|
||||
};
|
||||
|
||||
Wallet.prototype.clone = function clone() {
|
||||
var passphrase = this.options.passphrase;
|
||||
var wallet;
|
||||
|
||||
delete this.options.passphrase;
|
||||
|
||||
wallet = Wallet.fromJSON(this.toJSON());
|
||||
|
||||
this.options.passphrase = passphrase;
|
||||
|
||||
return wallet;
|
||||
};
|
||||
|
||||
Wallet.prototype._scan = function _scan(options, txByAddress, callback) {
|
||||
var self = this;
|
||||
var depth = { changeDepth: 0, receiveDepth: 0 };
|
||||
var wallet = this.clone();
|
||||
var all = [];
|
||||
|
||||
assert(this._initialized);
|
||||
|
||||
return (function chainCheck(change) {
|
||||
(function chainCheck(change) {
|
||||
var addressIndex = 0;
|
||||
var total = 0;
|
||||
var gap = 0;
|
||||
|
||||
return (function next() {
|
||||
var address = self.deriveAddress(change, addressIndex++);
|
||||
(function next() {
|
||||
var address = wallet.deriveAddress(change, addressIndex++);
|
||||
|
||||
return txByAddress(address.getAddress(), function(err, txs) {
|
||||
txByAddress(address.getAddress(), function(err, txs) {
|
||||
var result;
|
||||
|
||||
if (err)
|
||||
@ -805,7 +839,7 @@ Wallet.prototype._scan = function _scan(options, txByAddress, callback) {
|
||||
result = false;
|
||||
|
||||
if (Array.isArray(txs) && (txs[0] instanceof bcoin.tx))
|
||||
txs.forEach(function(tx) { self.addTX(tx); });
|
||||
all = all.concat(txs);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
@ -827,7 +861,7 @@ Wallet.prototype._scan = function _scan(options, txByAddress, callback) {
|
||||
if (change === false)
|
||||
return chainCheck(true);
|
||||
|
||||
return callback(null, depth);
|
||||
return callback(null, depth, all);
|
||||
});
|
||||
})();
|
||||
})(false);
|
||||
@ -835,26 +869,35 @@ Wallet.prototype._scan = function _scan(options, txByAddress, callback) {
|
||||
|
||||
Wallet.prototype.scriptInputs = function scriptInputs(tx, index) {
|
||||
var addresses = this.deriveInputs(tx);
|
||||
var total = 0;
|
||||
var i;
|
||||
|
||||
return addresses.reduce(function(total, address) {
|
||||
return total + address.scriptInputs(tx, index);
|
||||
}, 0);
|
||||
for (i = 0; i < addresses.length; i++)
|
||||
total += addresses[i].scriptInputs(tx, index);
|
||||
|
||||
return total;
|
||||
};
|
||||
|
||||
Wallet.prototype.signInputs = function signInputs(tx, type, index) {
|
||||
var addresses = this.deriveInputs(tx);
|
||||
var total = 0;
|
||||
var i;
|
||||
|
||||
return addresses.reduce(function(total, address) {
|
||||
return total + address.signInputs(tx, type, index);
|
||||
}, 0);
|
||||
for (i = 0; i < addresses.length; i++)
|
||||
total += addresses[i].signInputs(tx, type, index);
|
||||
|
||||
return total;
|
||||
};
|
||||
|
||||
Wallet.prototype.sign = function sign(tx, type, index) {
|
||||
var addresses = this.deriveInputs(tx);
|
||||
var total = 0;
|
||||
var i;
|
||||
|
||||
return addresses.reduce(function(total, address) {
|
||||
return total + address.sign(tx, type, index);
|
||||
}, 0);
|
||||
for (i = 0; i < addresses.length; i++)
|
||||
total += addresses[i].sign(tx, type, index);
|
||||
|
||||
return total;
|
||||
};
|
||||
|
||||
Wallet.prototype.addTX = function addTX(tx, callback) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user