Add functionality to randomize outputs

This commit is contained in:
eordano 2015-03-11 15:38:14 -03:00
parent 23ba46f476
commit a37e7b140c
3 changed files with 83 additions and 1 deletions

View File

@ -805,6 +805,40 @@ Transaction.prototype.removeOutput = function(index) {
this._updateChangeOutput();
};
/**
* Randomize this transaction's outputs ordering. The shuffling algorithm is a
* version of the Fisher-Yates shuffle, provided by lodash's _.shuffle().
*
* @return {Transaction} this
*/
Transaction.prototype.shuffleOutputs = function() {
return this.sortOutputs(_.shuffle);
};
/**
* Sort this transaction's outputs, according to a given sorting function that
* takes an array as argument and returns a new array, with the same elements
* but with a different order. The argument function MUST NOT modify the order
* of the original array
*
* @param {Function} sortingFunction
* @return {Transaction} this
*/
Transaction.prototype.sortOutputs = function(sortingFunction) {
var outs = sortingFunction(this.outputs);
return this._newOutputOrder(outs);
};
Transaction.prototype._newOutputOrder = function(newOutputs) {
var changeIndex = 0;
while (this.outputs[this._changeIndex] !== newOutputs[changeIndex]) {
changeIndex++;
}
this.outputs = newOutputs;
this._changeIndex = changeIndex;
return this;
};
Transaction.prototype.removeInput = function(txId, outputIndex) {
var index;
if (!outputIndex && _.isNumber(txId)) {

View File

@ -91,7 +91,8 @@
"bitcore-build": "bitpay/bitcore-build",
"brfs": "^1.2.0",
"chai": "^1.10.0",
"gulp": "^3.8.10"
"gulp": "^3.8.10",
"sinon": "^1.13.0"
},
"license": "MIT"
}

View File

@ -5,6 +5,7 @@
var should = require('chai').should();
var expect = require('chai').expect;
var _ = require('lodash');
var sinon = require('sinon');
var bitcore = require('../..');
var Transaction = bitcore.Transaction;
@ -619,6 +620,52 @@ describe('Transaction', function() {
});
});
describe('output ordering', function() {
var tenth = 1e7;
var fourth = 25e6;
var half = 5e7;
var transaction, out1, out2, out3, out4;
beforeEach(function() {
transaction = new Transaction()
.from(simpleUtxoWith1BTC)
.to(toAddress, tenth)
.to(toAddress, fourth)
.to(toAddress, half)
.change(changeAddress);
out1 = transaction.outputs[0];
out2 = transaction.outputs[1];
out3 = transaction.outputs[2];
out4 = transaction.outputs[3];
});
it('allows the user to sort outputs according to a criteria', function() {
var sorting = function(array) {
return [array[3], array[2], array[1], array[0]];
};
transaction.sortOutputs(sorting);
transaction.outputs[0].should.equal(out4);
transaction.outputs[1].should.equal(out3);
transaction.outputs[2].should.equal(out2);
transaction.outputs[3].should.equal(out1);
});
it('allows the user to randomize the output order', function() {
var shuffle = sinon.stub(_, 'shuffle');
shuffle.onFirstCall().returns([out2, out1, out4, out3]);
transaction._changeIndex.should.equal(3);
transaction.shuffleOutputs();
transaction.outputs[0].should.equal(out2);
transaction.outputs[1].should.equal(out1);
transaction.outputs[2].should.equal(out4);
transaction.outputs[3].should.equal(out3);
transaction._changeIndex.should.equal(2);
_.shuffle.restore();
});
});
});
var tx_empty_hex = '01000000000000000000';