Merge pull request #1028 from eordano/transaction/changeupdate

Improvements to Transaction
This commit is contained in:
Manuel Aráoz 2015-02-04 16:19:02 -03:00
commit cd7e5d5a1e
2 changed files with 56 additions and 18 deletions

View File

@ -240,6 +240,7 @@ Transaction.prototype.toObject = function toObject() {
});
return {
change: this._change ? this._change.toString() : undefined,
fee: this._fee ? this._fee : undefined,
version: this.version,
inputs: inputs,
outputs: outputs,
@ -270,6 +271,9 @@ Transaction.prototype.fromObject = function(transaction) {
if (transaction.change) {
this.change(transaction.change);
}
if (transaction.fee) {
this.fee(transaction.fee);
}
this.nLockTime = transaction.nLockTime;
this.version = transaction.version;
};
@ -354,8 +358,14 @@ Transaction.prototype.from = function(utxo, pubkeys, threshold) {
};
Transaction.prototype._fromNonP2SH = function(utxo) {
var clazz;
utxo = new UnspentOutput(utxo);
this.inputs.push(new PublicKeyHashInput({
if (utxo.script.isPublicKeyHashOut()) {
clazz = PublicKeyHashInput;
} else {
clazz = Input;
}
this.addInput(new clazz({
output: new Output({
script: utxo.script,
satoshis: utxo.satoshis
@ -365,7 +375,6 @@ Transaction.prototype._fromNonP2SH = function(utxo) {
sequenceNumber: DEFAULT_SEQNUMBER,
script: Script.empty()
}));
this._inputAmount += utxo.satoshis;
};
Transaction.prototype._fromMultisigUtxo = function(utxo, pubkeys, threshold) {
@ -394,10 +403,10 @@ Transaction.prototype._fromMultisigUtxo = function(utxo, pubkeys, threshold) {
*/
Transaction.prototype.addInput = function(input, outputScript, satoshis) {
$.checkArgumentType(input, Input, 'input');
if (!input.output || !(input.output instanceof Output) && !outputScript && !satoshis) {
if (!input.output && (_.isUndefined(outputScript) || _.isUndefined(satoshis))) {
throw new errors.Transaction.NeedMoreInfo('Need information about the UTXO script and satoshis');
}
if (!input.output && outputScript && satoshis) {
if (!input.output && outputScript && !_.isUndefined(satoshis)) {
outputScript = outputScript instanceof Script ? outputScript : new Script(outputScript);
$.checkArgumentType(satoshis, 'number', 'satoshis');
input.output = new Output({
@ -417,11 +426,11 @@ Transaction.prototype.addInput = function(input, outputScript, satoshis) {
*/
Transaction.prototype.uncheckedAddInput = function(input) {
$.checkArgumentType(input, Input, 'input');
this._changeSetup = false;
this.inputs.push(input);
if (input.output) {
this._inputAmount += input.output.satoshis;
}
this._updateChangeOutput();
return this;
};
@ -446,7 +455,7 @@ Transaction.prototype.hasAllUtxoInfo = function() {
*/
Transaction.prototype.fee = function(amount) {
this._fee = amount;
this._changeSetup = false;
this._updateChangeOutput();
return this;
};
@ -463,7 +472,7 @@ Transaction.prototype.fee = function(amount) {
*/
Transaction.prototype.change = function(address) {
this._change = new Address(address);
this._changeSetup = false;
this._updateChangeOutput();
return this;
};
@ -505,8 +514,12 @@ Transaction.prototype.addData = function(value) {
Transaction.prototype.addOutput = function(output) {
$.checkArgumentType(output, Output, 'output');
this._addOutput(output);
this._updateChangeOutput();
};
Transaction.prototype._addOutput = function(output) {
this.outputs.push(output);
this._changeSetup = false;
this._outputAmount += output.satoshis;
};
@ -514,12 +527,7 @@ Transaction.prototype._updateChangeOutput = function() {
if (!this._change) {
return;
}
if (this._changeSetup) {
return;
}
if (!_.isUndefined(this._changeSetup)) {
this._clearSignatures();
}
this._clearSignatures();
if (!_.isUndefined(this._changeOutput)) {
this.removeOutput(this._changeOutput);
}
@ -527,14 +535,13 @@ Transaction.prototype._updateChangeOutput = function() {
var fee = this.getFee();
if (available - fee > 0) {
this._changeOutput = this.outputs.length;
this.addOutput(new Output({
this._addOutput(new Output({
script: Script.fromAddress(this._change),
satoshis: available - fee
}));
} else {
this._changeOutput = undefined;
}
this._changeSetup = true;
};
Transaction.prototype.getFee = function() {
@ -602,7 +609,6 @@ Transaction.prototype.removeOutput = function(index) {
*/
Transaction.prototype.sign = function(privateKey, sigtype) {
$.checkState(this.hasAllUtxoInfo());
this._updateChangeOutput();
var self = this;
if (_.isArray(privateKey)) {
_.each(privateKey, function(privateKey) {

View File

@ -250,6 +250,14 @@ describe('Transaction', function() {
return transaction.serialize(true);
}).to.not.throw();
});
it('stores the fee set by the user', function() {
var fee = 1000000;
var serialized = new Transaction()
.fee(fee)
.toObject();
var deserialized = new Transaction(serialized);
expect(deserialized._fee).to.equal(fee);
});
});
describe('checked serialize', function() {
@ -265,7 +273,8 @@ describe('Transaction', function() {
var transaction = new Transaction()
.from(simpleUtxoWith1BTC)
.change(changeAddress)
.to(toAddress, 1);
.fee(50000000)
.to(toAddress, 40000000);
expect(function() {
return transaction.serialize();
}).to.throw(errors.Transaction.FeeError);
@ -325,6 +334,29 @@ describe('Transaction', function() {
expect(deserialized.inputs[0] instanceof Transaction.Input.MultiSigScriptHash).to.equal(true);
});
});
describe('checks on adding inputs', function() {
var transaction = new Transaction();
it('fails if no output script is provided', function() {
expect(function() {
transaction.addInput(new Transaction.Input());
}).to.throw(errors.Transaction.NeedMoreInfo);
});
it('fails if no satoshi amount is provided', function() {
var input = new Transaction.Input();
expect(function() {
transaction.addInput(input);
}).to.throw(errors.Transaction.NeedMoreInfo);
expect(function() {
transaction.addInput(new Transaction.Input(), Script.empty());
}).to.throw(errors.Transaction.NeedMoreInfo);
});
it('allows output and transaction to be feed as arguments', function() {
expect(function() {
transaction.addInput(new Transaction.Input(), Script.empty(), 0);
}).to.not.throw();
});
});
});
var tx_empty_hex = '01000000000000000000';