Browse Source

Merge pull request #1028 from eordano/transaction/changeupdate

Improvements to Transaction
patch-2
Manuel Aráoz 10 years ago
parent
commit
cd7e5d5a1e
  1. 38
      lib/transaction/transaction.js
  2. 34
      test/transaction/transaction.js

38
lib/transaction/transaction.js

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

34
test/transaction/transaction.js

@ -250,6 +250,14 @@ describe('Transaction', function() {
return transaction.serialize(true); return transaction.serialize(true);
}).to.not.throw(); }).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() { describe('checked serialize', function() {
@ -265,7 +273,8 @@ describe('Transaction', function() {
var transaction = new Transaction() var transaction = new Transaction()
.from(simpleUtxoWith1BTC) .from(simpleUtxoWith1BTC)
.change(changeAddress) .change(changeAddress)
.to(toAddress, 1); .fee(50000000)
.to(toAddress, 40000000);
expect(function() { expect(function() {
return transaction.serialize(); return transaction.serialize();
}).to.throw(errors.Transaction.FeeError); }).to.throw(errors.Transaction.FeeError);
@ -325,6 +334,29 @@ describe('Transaction', function() {
expect(deserialized.inputs[0] instanceof Transaction.Input.MultiSigScriptHash).to.equal(true); 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'; var tx_empty_hex = '01000000000000000000';

Loading…
Cancel
Save