restore legacy txproposal model

This commit is contained in:
Ivan Socolsky 2016-08-04 11:35:40 -03:00
parent 61ffe309f8
commit 827bb03d0c
No known key found for this signature in database
GPG Key ID: FAECE6A05FAA4F56
3 changed files with 202 additions and 17 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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,16 +2138,21 @@ WalletService.prototype.signTx = function(opts, cb) {
var copayer = wallet.getCopayer(self.copayerId);
if (!txp.sign(self.copayerId, opts.signatures, copayer.xPubKey)) {
log.warn('Error signing transaction (BAD_SIGNATURES)');
log.warn('Wallet id:', self.walletId);
log.warn('Copayer id:', self.copayerId);
log.warn('Client version:', self.clientVersion);
log.warn('Arguments:', JSON.stringify(opts));
log.warn('Transaction proposal:', JSON.stringify(txp));
var raw = txp.getBitcoreTx().uncheckedSerialize();
log.warn('Raw tx:', raw);
return cb(Errors.BAD_SIGNATURES);
try {
if (!txp.sign(self.copayerId, opts.signatures, copayer.xPubKey)) {
log.warn('Error signing transaction (BAD_SIGNATURES)');
log.warn('Wallet id:', self.walletId);
log.warn('Copayer id:', self.copayerId);
log.warn('Client version:', self.clientVersion);
log.warn('Arguments:', JSON.stringify(opts));
log.warn('Transaction proposal:', JSON.stringify(txp));
var raw = txp.getBitcoreTx().uncheckedSerialize();
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) {