restore legacy txproposal model
This commit is contained in:
parent
61ffe309f8
commit
827bb03d0c
|
@ -13,6 +13,7 @@ var Common = require('../common');
|
|||
var Constants = Common.Constants;
|
||||
var Defaults = Common.Defaults;
|
||||
|
||||
var TxProposalLegacy = require('./txproposal_legacy');
|
||||
var TxProposalAction = require('./txproposalaction');
|
||||
|
||||
function TxProposal() {};
|
||||
|
@ -67,7 +68,7 @@ TxProposal.create = function(opts) {
|
|||
|
||||
TxProposal.fromObj = function(obj) {
|
||||
if (!(obj.version >= 3)) {
|
||||
throw new Error('TxProposal < v3 no longer supported.')
|
||||
return TxProposalLegacy.fromObj(obj);
|
||||
}
|
||||
|
||||
var x = new TxProposal();
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var $ = require('preconditions').singleton();
|
||||
var log = require('npmlog');
|
||||
log.debug = log.verbose;
|
||||
log.disableColor();
|
||||
|
||||
var Bitcore = require('bitcore-lib');
|
||||
|
||||
var Common = require('../common');
|
||||
var Constants = Common.Constants;
|
||||
var Defaults = Common.Defaults;
|
||||
|
||||
var TxProposalAction = require('./txproposalaction');
|
||||
|
||||
function TxProposal() {};
|
||||
|
||||
TxProposal.Types = {
|
||||
SIMPLE: 'simple',
|
||||
MULTIPLEOUTPUTS: 'multiple_outputs',
|
||||
EXTERNAL: 'external'
|
||||
};
|
||||
|
||||
TxProposal.fromObj = function(obj) {
|
||||
var x = new TxProposal();
|
||||
|
||||
x.version = obj.version;
|
||||
if (obj.version === '1.0.0') {
|
||||
x.type = TxProposal.Types.SIMPLE;
|
||||
} else {
|
||||
x.type = obj.type;
|
||||
}
|
||||
x.createdOn = obj.createdOn;
|
||||
x.id = obj.id;
|
||||
x.walletId = obj.walletId;
|
||||
x.creatorId = obj.creatorId;
|
||||
x.outputs = obj.outputs;
|
||||
x.toAddress = obj.toAddress;
|
||||
x.amount = obj.amount;
|
||||
x.message = obj.message;
|
||||
x.payProUrl = obj.payProUrl;
|
||||
x.proposalSignature = obj.proposalSignature;
|
||||
x.changeAddress = obj.changeAddress;
|
||||
x.inputs = obj.inputs;
|
||||
x.requiredSignatures = obj.requiredSignatures;
|
||||
x.requiredRejections = obj.requiredRejections;
|
||||
x.walletN = obj.walletN;
|
||||
x.status = obj.status;
|
||||
x.txid = obj.txid;
|
||||
x.broadcastedOn = obj.broadcastedOn;
|
||||
x.inputPaths = obj.inputPaths;
|
||||
x.actions = _.map(obj.actions, function(action) {
|
||||
return TxProposalAction.fromObj(action);
|
||||
});
|
||||
x.outputOrder = obj.outputOrder;
|
||||
x.network = obj.network;
|
||||
x.fee = obj.fee;
|
||||
x.feePerKb = obj.feePerKb;
|
||||
x.excludeUnconfirmedUtxos = obj.excludeUnconfirmedUtxos;
|
||||
x.proposalSignaturePubKey = obj.proposalSignaturePubKey;
|
||||
x.proposalSignaturePubKeySig = obj.proposalSignaturePubKeySig;
|
||||
x.addressType = obj.addressType || Constants.SCRIPT_TYPES.P2SH;
|
||||
x.derivationStrategy = obj.derivationStrategy || Constants.DERIVATION_STRATEGIES.BIP45;
|
||||
x.customData = obj.customData;
|
||||
|
||||
return x;
|
||||
};
|
||||
|
||||
function throwUnsupportedError() {
|
||||
var msg = 'Unsupported operation on this transaction proposal';
|
||||
log.warn('DEPRECATED: ' + msg);
|
||||
throw new Error(msg);
|
||||
};
|
||||
|
||||
TxProposal.prototype.toObject = function() {
|
||||
var x = _.cloneDeep(this);
|
||||
x.isPending = this.isPending();
|
||||
return x;
|
||||
};
|
||||
|
||||
TxProposal.prototype._updateStatus = function() {
|
||||
if (this.status != 'pending') return;
|
||||
|
||||
if (this.isRejected()) {
|
||||
this.status = 'rejected';
|
||||
} else if (this.isAccepted()) {
|
||||
this.status = 'accepted';
|
||||
}
|
||||
};
|
||||
|
||||
TxProposal.prototype.getBitcoreTx = function() {
|
||||
throwUnsupportedError();
|
||||
};
|
||||
|
||||
TxProposal.prototype.getNetworkName = function() {
|
||||
return Bitcore.Address(this.changeAddress.address).toObject().network;
|
||||
};
|
||||
|
||||
TxProposal.prototype.getRawTx = function() {
|
||||
throwUnsupportedError();
|
||||
};
|
||||
|
||||
TxProposal.prototype.getTotalAmount = function() {
|
||||
if (this.type == TxProposal.Types.MULTIPLEOUTPUTS || this.type == TxProposal.Types.EXTERNAL) {
|
||||
return _.pluck(this.outputs, 'amount')
|
||||
.reduce(function(total, n) {
|
||||
return total + n;
|
||||
}, 0);
|
||||
} else {
|
||||
return this.amount;
|
||||
}
|
||||
};
|
||||
|
||||
TxProposal.prototype.getActors = function() {
|
||||
return _.pluck(this.actions, 'copayerId');
|
||||
};
|
||||
|
||||
TxProposal.prototype.getApprovers = function() {
|
||||
return _.pluck(
|
||||
_.filter(this.actions, {
|
||||
type: 'accept'
|
||||
}), 'copayerId');
|
||||
};
|
||||
|
||||
TxProposal.prototype.getActionBy = function(copayerId) {
|
||||
return _.find(this.actions, {
|
||||
copayerId: copayerId
|
||||
});
|
||||
};
|
||||
|
||||
TxProposal.prototype.addAction = function(copayerId, type, comment, signatures, xpub) {
|
||||
var action = TxProposalAction.create({
|
||||
copayerId: copayerId,
|
||||
type: type,
|
||||
signatures: signatures,
|
||||
xpub: xpub,
|
||||
comment: comment,
|
||||
});
|
||||
this.actions.push(action);
|
||||
this._updateStatus();
|
||||
};
|
||||
|
||||
TxProposal.prototype.sign = function() {
|
||||
throwUnsupportedError();
|
||||
};
|
||||
|
||||
TxProposal.prototype.reject = function(copayerId, reason) {
|
||||
this.addAction(copayerId, 'reject', reason);
|
||||
};
|
||||
|
||||
TxProposal.prototype.isPending = function() {
|
||||
return !_.contains(['broadcasted', 'rejected'], this.status);
|
||||
};
|
||||
|
||||
TxProposal.prototype.isAccepted = function() {
|
||||
var votes = _.countBy(this.actions, 'type');
|
||||
return votes['accept'] >= this.requiredSignatures;
|
||||
};
|
||||
|
||||
TxProposal.prototype.isRejected = function() {
|
||||
var votes = _.countBy(this.actions, 'type');
|
||||
return votes['reject'] >= this.requiredRejections;
|
||||
};
|
||||
|
||||
TxProposal.prototype.isBroadcasted = function() {
|
||||
return this.status == 'broadcasted';
|
||||
};
|
||||
|
||||
TxProposal.prototype.setBroadcasted = function() {
|
||||
$.checkState(this.txid);
|
||||
this.status = 'broadcasted';
|
||||
this.broadcastedOn = Math.floor(Date.now() / 1000);
|
||||
};
|
||||
|
||||
module.exports = TxProposal;
|
|
@ -1330,12 +1330,10 @@ WalletService.prototype._checkTx = function(txp) {
|
|||
var bitcoreError;
|
||||
|
||||
var serializationOpts = {
|
||||
disableIsFullySigned: true
|
||||
disableIsFullySigned: true,
|
||||
disableSmallFees: true,
|
||||
disableLargeFees: true,
|
||||
};
|
||||
if (!_.startsWith(txp.version, '1.')) {
|
||||
serializationOpts.disableSmallFees = true;
|
||||
serializationOpts.disableLargeFees = true;
|
||||
}
|
||||
|
||||
if (txp.getEstimatedSize() / 1000 > Defaults.MAX_TX_SIZE_IN_KB)
|
||||
return Errors.TX_MAX_SIZE_EXCEEDED;
|
||||
|
@ -1886,7 +1884,12 @@ WalletService.prototype.publishTx = function(opts, cb) {
|
|||
|
||||
var copayer = wallet.getCopayer(self.copayerId);
|
||||
|
||||
var raw = txp.getRawTx();
|
||||
var raw;
|
||||
try {
|
||||
raw = txp.getRawTx();
|
||||
} catch (ex) {
|
||||
return cb(ex);
|
||||
}
|
||||
var signingKey = self._getSigningKey(raw, opts.proposalSignature, copayer.requestPubKeys);
|
||||
if (!signingKey) {
|
||||
return cb(new ClientError('Invalid proposal signature'));
|
||||
|
@ -2135,6 +2138,7 @@ WalletService.prototype.signTx = function(opts, cb) {
|
|||
|
||||
var copayer = wallet.getCopayer(self.copayerId);
|
||||
|
||||
try {
|
||||
if (!txp.sign(self.copayerId, opts.signatures, copayer.xPubKey)) {
|
||||
log.warn('Error signing transaction (BAD_SIGNATURES)');
|
||||
log.warn('Wallet id:', self.walletId);
|
||||
|
@ -2146,6 +2150,10 @@ WalletService.prototype.signTx = function(opts, cb) {
|
|||
log.warn('Raw tx:', raw);
|
||||
return cb(Errors.BAD_SIGNATURES);
|
||||
}
|
||||
} catch (ex) {
|
||||
log.error('Error signing transaction proposal', ex);
|
||||
return cb(ex);
|
||||
}
|
||||
|
||||
self.storage.storeTx(self.walletId, txp, function(err) {
|
||||
if (err) return cb(err);
|
||||
|
|
Loading…
Reference in New Issue