|
|
@ -11,6 +11,7 @@ var Bitcore = require('bitcore-lib'); |
|
|
|
|
|
|
|
var Common = require('../common'); |
|
|
|
var Constants = Common.Constants; |
|
|
|
var Defaults = Common.Defaults; |
|
|
|
|
|
|
|
var TxProposalAction = require('./txproposalaction'); |
|
|
|
|
|
|
@ -148,6 +149,76 @@ TxProposal.prototype._updateStatus = function() { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
TxProposal.newBitcoreTransaction = function() { |
|
|
|
return new Bitcore.Transaction(); |
|
|
|
}; |
|
|
|
|
|
|
|
TxProposal.prototype._buildTx = function() { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
var t = TxProposal.newBitcoreTransaction(); |
|
|
|
|
|
|
|
$.checkState(_.contains(_.values(Constants.SCRIPT_TYPES), self.addressType)); |
|
|
|
|
|
|
|
switch (self.addressType) { |
|
|
|
case Constants.SCRIPT_TYPES.P2SH: |
|
|
|
_.each(self.inputs, function(i) { |
|
|
|
t.from(i, i.publicKeys, self.requiredSignatures); |
|
|
|
}); |
|
|
|
break; |
|
|
|
case Constants.SCRIPT_TYPES.P2PKH: |
|
|
|
t.from(self.inputs); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
if (self.toAddress && self.amount && !self.outputs) { |
|
|
|
t.to(self.toAddress, self.amount); |
|
|
|
} else if (self.outputs) { |
|
|
|
_.each(self.outputs, function(o) { |
|
|
|
$.checkState(!o.script != !o.toAddress, 'Output should have either toAddress or script specified'); |
|
|
|
if (o.script) { |
|
|
|
t.addOutput(new Bitcore.Transaction.Output({ |
|
|
|
script: o.script, |
|
|
|
satoshis: o.amount |
|
|
|
})); |
|
|
|
} else { |
|
|
|
t.to(o.toAddress, o.amount); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
if (_.startsWith(self.version, '1.')) { |
|
|
|
Bitcore.Transaction.FEE_SECURITY_MARGIN = 1; |
|
|
|
t.feePerKb(self.feePerKb); |
|
|
|
} else { |
|
|
|
t.fee(self.fee); |
|
|
|
} |
|
|
|
|
|
|
|
t.change(self.changeAddress.address); |
|
|
|
|
|
|
|
// Shuffle outputs for improved privacy
|
|
|
|
if (t.outputs.length > 1) { |
|
|
|
$.checkState(t.outputs.length == self.outputOrder.length); |
|
|
|
t.sortOutputs(function(outputs) { |
|
|
|
return _.map(self.outputOrder, function(i) { |
|
|
|
return outputs[i]; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// Validate inputs vs outputs independently of Bitcore
|
|
|
|
var totalInputs = _.reduce(self.inputs, function(memo, i) { |
|
|
|
return +i.satoshis + memo; |
|
|
|
}, 0); |
|
|
|
var totalOutputs = _.reduce(t.outputs, function(memo, o) { |
|
|
|
return +o.satoshis + memo; |
|
|
|
}, 0); |
|
|
|
|
|
|
|
$.checkState(totalInputs - totalOutputs <= Defaults.MAX_TX_FEE); |
|
|
|
|
|
|
|
return t; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
TxProposal.prototype._getCurrentSignatures = function() { |
|
|
|
var acceptedActions = _.filter(this.actions, { |
|
|
@ -165,7 +236,7 @@ TxProposal.prototype._getCurrentSignatures = function() { |
|
|
|
TxProposal.prototype.getBitcoreTx = function() { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
var t = Common.Utils.buildTx(this); |
|
|
|
var t = this._buildTx(); |
|
|
|
|
|
|
|
var sigs = this._getCurrentSignatures(); |
|
|
|
_.each(sigs, function(x) { |
|
|
|