more tx refactoring.

This commit is contained in:
Christopher Jeffrey 2016-01-12 05:15:22 -08:00
parent b147951a83
commit c94457cf1f
2 changed files with 63 additions and 57 deletions

View File

@ -41,10 +41,6 @@ function TX(data, block) {
this._lock = this.lock;
this._fee = !(data instanceof bcoin.tx)
? data.fee
: data._fee;
if (data.inputs) {
data.inputs.forEach(function(input) {
this.input(input, null);
@ -64,8 +60,9 @@ function TX(data, block) {
}
}
this.hardFee = data.hardFee || null;
this.changeAddress = data.changeAddress || null;
this.changeOutput = data.changeOutput || null;
this.changeIndex = data.changeIndex || -1;
// ps = Pending Since
this.ps = this.ts === 0 ? utils.now() : 0;
@ -785,7 +782,7 @@ TX.prototype.maxSize = function maxSize() {
return total;
};
TX.prototype.getUnspent = function getUnspent(unspent, fee) {
TX.prototype.getUnspent = function getUnspent(unspent, address, fee) {
var tx = this.clone();
var cost = tx.funds('out');
var totalkb = 1;
@ -794,12 +791,9 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
var lastAdded = 0;
var size, newkb, change;
if (!fee)
fee = this._fee;
if (fee) {
total = cost.add(fee);
this._fee = fee;
this.hardFee = fee;
}
function addInput(unspent) {
@ -819,7 +813,7 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
// Add dummy output (for `change`) to
// calculate maximum TX size.
tx.output({
script: [],
address: address,
value: new bn(0)
});
@ -839,15 +833,13 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
} while (tx.funds('in').cmp(total) < 0 && lastAdded < unspent.length);
}
// Expose `total`. Useful for error messages.
this.total = total;
// Still failing to get enough funds.
if (tx.funds('in').cmp(total) < 0)
return;
// How much money is left after filling outputs.
change = tx.funds('in').sub(total);
if (tx.funds('in').cmp(total) < 0) {
// Still failing to get enough funds.
inputs = null;
} else {
// How much money is left after filling outputs.
change = tx.funds('in').sub(total);
}
// Return necessary inputs and change.
return {
@ -855,22 +847,26 @@ TX.prototype.getUnspent = function getUnspent(unspent, fee) {
change: change,
cost: cost,
fee: total.sub(cost),
total: total
total: total,
kb: totalkb
};
};
TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) {
var result = this.getUnspent(unspent, fee);
TX.prototype.fillUnspent = function fillUnspent(unspent, address, fee) {
var result;
if (address)
this.changeAddress = address;
if (fee)
this._fee = fee;
this.hardFee = fee;
if (!result)
return;
assert(this.changeAddress);
this.changeAddress = changeAddress
|| this.changeAddress
|| result.inputs[0].output.address;
result = this.getUnspent(unspent, this.changeAddress, this.hardFee);
if (!result.inputs)
return result;
result.inputs.forEach(function(input) {
this.input(input);
@ -882,27 +878,24 @@ TX.prototype.fillUnspent = function fillUnspent(unspent, changeAddress, fee) {
this.getFee().toNumber(),
result.fee.add(result.change).toNumber()
);
this.changeOutput = null;
this.changeIndex = -1;
} else {
if (!this.changeAddress)
throw new Error('No change address');
this.output({
address: this.changeAddress,
value: result.change
});
this.changeOutput = this.outputs[this.outputs.length - 1];
this.changeIndex = this.outputs.length - 1;
}
return result;
};
TX.prototype._recalculateFee = function recalculateFee() {
var output = this.changeOutput;
var output = this.outputs[this.changeIndex];
var size, real, fee;
if (this._fee)
if (this.hardFee)
return;
if (!output) {
@ -918,7 +911,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
fee = this.getFee().toNumber();
if (real === fee) {
if (!this.changeOutput)
if (this.changeIndex === -1)
this.outputs.pop();
return;
}
@ -926,7 +919,7 @@ TX.prototype._recalculateFee = function recalculateFee() {
if (real > fee) {
if (output.value.cmpn(real - fee) < 0) {
this.outputs.pop();
this.changeOutput = null;
this.changeIndex = -1;
return;
}
output.value.isubn(real - fee);
@ -936,11 +929,11 @@ TX.prototype._recalculateFee = function recalculateFee() {
if (output.value.cmpn(constants.tx.dust) < 0) {
this.outputs.pop();
this.changeOutput = null;
this.changeIndex = -1;
return;
}
this.changeOutput = output;
this.changeIndex = this.outputs.indexOf(output);
};
TX.prototype.getFee = function getFee() {
@ -1247,7 +1240,9 @@ TX.prototype.toJSON = function toJSON() {
block: this.block,
network: this.network,
relayedBy: this.relayedBy,
changeIndex: this.outputs.indexOf(this.changeOutput),
changeAddress: this.changeAddress,
changeIndex: this.changeIndex,
hardFee: this.hardFee ? utils.btc(this.hardFee) : null,
tx: utils.toHex(this.render())
};
};
@ -1264,6 +1259,12 @@ TX.fromJSON = function fromJSON(json) {
data.network = json.network;
data.relayedBy = json.relayedBy;
data.changeAddress = json.changeAddress;
data.changeIndex = json.changeIndex;
if (json.hardFee)
data.hardFee = utils.satoshi(json.hardFee);
data._raw = raw;
data._size = raw.length;
@ -1272,14 +1273,24 @@ TX.fromJSON = function fromJSON(json) {
tx.block = json.block || null;
tx.ps = json.ps;
if (data.changeIndex >= 0) {
tx.changeOutput = tx.outputs[data.changeIndex];
assert(tx.changeOutput);
}
return tx;
};
TX.prototype.toRaw = function toRaw(enc) {
var raw = this.render();
if (enc === 'hex')
return utils.toHex(raw);
return raw;
};
TX.fromRaw = function fromRaw(raw, enc) {
if (enc === 'hex')
raw = utils.toArray(raw, 'hex');
return new bcoin.protocol.parser().parseTX(raw);
};
/**
* Expose
*/

View File

@ -436,16 +436,11 @@ Wallet.prototype.ownInput = function ownInput(tx, index) {
return inputs;
};
Wallet.prototype.scriptOutputs = function scriptOutputs(tx, options) {
outputs.forEach(function(output) {
tx.scriptOutput(output, output);
});
return outputs.length;
};
Wallet.prototype.fillUnspent = function fillUnspent(tx, address, fee) {
if (!address)
address = this.changeAddress || this.getAddress();
Wallet.prototype.fillUnspent = function fillUnspent(tx, changeAddress) {
changeAddress = changeAddress || this.changeAddress || this.getAddress();
return tx.fillUnspent(this.unspent(), changeAddress);
return tx.fillUnspent(this.unspent(), address, fee);
};
Wallet.prototype.fillTX = function fillTX(tx) {
@ -546,9 +541,9 @@ Wallet.prototype.fill = function fill(tx, changeAddress, cb) {
result = this.fillUnspent(tx, changeAddress);
if (!result) {
if (!result.inputs) {
err = new Error('Not enough funds');
err.minBalance = tx.total;
err.minBalance = result.total;
cb(err);
return null;
}