Skip to content

Commit

Permalink
multisign test for signing twice with same sig
Browse files Browse the repository at this point in the history
  • Loading branch information
matiu committed Mar 31, 2014
1 parent 2af6ab7 commit 8acf093
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 17 deletions.
50 changes: 42 additions & 8 deletions TransactionBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
*
* @opts
* {
* remainderAddress: null,
* remainderOut: null,
* fee: 0.001,
* lockTime: null,
* spendUnconfirmed: false,
Expand All @@ -67,8 +67,12 @@
* Amounts are in BTC. instead of fee and amount; feeSat and amountSat can be given,
* repectively, to provide amounts in satoshis.
*
* If no remainderAddress is given, and there are remainder coins, the
* first IN address will be used to return the coins. (TODO: is this is reasonable?)
* If no remainderOut is given, and there are remainder coins, the
* first IN out will be used to return the coins. remainderOut has the form:
* remainderOut = { address: 1xxxxx}
* or
* remainderOut = { pubkeys: ['hex1','hex2',...} for multisig
*
*
*/

Expand Down Expand Up @@ -101,7 +105,7 @@ function TransactionBuilder(opts) {
if (opts.fee || opts.feeSat) {
this.givenFeeSat = opts.fee ? opts.fee * util.COIN : opts.feeSat;
}
this.remainderAddress = opts.remainderAddress;
this.remainderOut = opts.remainderOut;
this.signhash = opts.signhash || Transaction.SIGHASH_ALL;

this.tx = {};
Expand Down Expand Up @@ -134,6 +138,31 @@ TransactionBuilder._scriptForAddress = function(addressString) {
return script;
};


TransactionBuilder._scriptForPubkeys = function(out) {

var l = out.pubkeys.length;
var pubKeyBuf=[];

for (var i=0; i<l; i++) {
pubKeyBuf.push(new Buffer(out.pubkeys[i],'hex'));
}

return Script.createMultisig(out.nreq, pubKeyBuf);
};

TransactionBuilder._scriptForOut = function(out) {
var ret;
if (out.address)
ret = this._scriptForAddress(out.address)
else if (out.pubkeys || out.nreq || out.nreq > 1)
ret = this._scriptForPubkeys(out);
else
throw new Error('unknow out type');

return ret;
};

TransactionBuilder.prototype.setUnspent = function(utxos) {
this.utxos = utxos;
return this;
Expand Down Expand Up @@ -279,9 +308,9 @@ TransactionBuilder.prototype._setRemainder = function(remainderIndex) {
}

if (remainderSat.cmp(0) > 0) {
var remainderAddress = this.remainderAddress || this.selectedUtxos[0].address;
var remainderOut = this.remainderOut || this.selectedUtxos[0];
var value = util.bigIntToValue(remainderSat);
var script = TransactionBuilder._scriptForAddress(remainderAddress);
var script = TransactionBuilder._scriptForOut(remainderOut);
var txout = {
v: value,
s: script.getBuffer(),
Expand Down Expand Up @@ -327,7 +356,7 @@ TransactionBuilder.prototype.setOutputs = function(outs) {
for (var i = 0; i < l; i++) {
var amountSat = outs[i].amountSat || util.parseValue(outs[i].amount);
var value = util.bigIntToValue(amountSat);
var script = TransactionBuilder._scriptForAddress(outs[i].address);
var script = TransactionBuilder._scriptForOut(outs[i]);
var txout = {
v: value,
s: script.getBuffer(),
Expand Down Expand Up @@ -552,15 +581,20 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
};
};

TransactionBuilder.prototype._signScriptHash = function(walletKeyMap, input, txSigHash) {
if (!this.hashToScriptMap)
throw new Error('hashToScriptMap not set');


throw new Error('TX_SCRIPTHASH not supported yet');
};


var fnToSign = {};
fnToSign[Script.TX_PUBKEYHASH] = TransactionBuilder.prototype._signPubKeyHash;
fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
//if (!this.hashToScriptMap) throw new Error('hashToScriptMap not set');

TransactionBuilder.prototype.sign = function(keys) {
this._checkTx();
Expand Down
4 changes: 2 additions & 2 deletions examples/CreateKey.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@


var run = function() {
// Replace '../bitcore' with 'bitcore' if you use this code elsewhere.
// replace '../bitcore' with 'bitcore' if you use this code elsewhere.
var bitcore = require('../bitcore');
var networks = require('../networks');
var WalletKey = bitcore.WalletKey;

var opts = {network: networks.livenet};
var opts = {network: networks.testnet};

function print(wk) {

Expand Down
47 changes: 40 additions & 7 deletions test/test.TransactionBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('TransactionBuilder', function() {

var getBuilder2 = function (fee) {
var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
spendUnconfirmed: true,
};

Expand Down Expand Up @@ -134,7 +134,7 @@ describe('TransactionBuilder', function() {
var utxos = testdata.dataUnspent;

var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
spendUnconfirmed: true,
};
var outs = [{
Expand Down Expand Up @@ -211,7 +211,7 @@ describe('TransactionBuilder', function() {
var getBuilder3 = function (outs) {

var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
spendUnconfirmed: true,
};

Expand Down Expand Up @@ -397,7 +397,7 @@ describe('TransactionBuilder', function() {

it('should sign a p2pubkey tx', function() {
var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
var outs = outs || [{
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
Expand All @@ -419,7 +419,7 @@ describe('TransactionBuilder', function() {

it('should sign a multisig tx', function() {
var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
var outs = outs || [{
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
Expand All @@ -440,7 +440,7 @@ describe('TransactionBuilder', function() {

it('should sign a multisig tx in steps (3-5)', function() {
var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
var outs = outs || [{
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
Expand Down Expand Up @@ -470,7 +470,7 @@ describe('TransactionBuilder', function() {

it('should count multisig signs (3-5)', function() {
var opts = {
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
var outs = outs || [{
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
Expand All @@ -494,7 +494,40 @@ describe('TransactionBuilder', function() {
b.sign(k3);
b.isFullySigned().should.equal(true);
b.countInputMultiSig(0).should.equal(3);
});


it('should avoid siging with the same key twice multisig signs (3-5)', function() {
var opts = {
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
var outs = outs || [{
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
amount: 0.08
}];
var b = new TransactionBuilder(opts)
.setUnspent(testdata.dataUnspentSign.unspentMulti)
.setOutputs(outs);

var k1 = testdata.dataUnspentSign.keyStringsMulti.slice(0,1);
var k23 = testdata.dataUnspentSign.keyStringsMulti.slice(1,3);

b.countInputMultiSig(0).should.equal(0);
b.sign(k1);
b.isFullySigned().should.equal(false);
b.countInputMultiSig(0).should.equal(1);
b.sign(k1);
b.isFullySigned().should.equal(false);
b.countInputMultiSig(0).should.equal(1);
b.sign(k1);
b.isFullySigned().should.equal(false);
b.countInputMultiSig(0).should.equal(1);




b.sign(k23);
b.isFullySigned().should.equal(true);
b.countInputMultiSig(0).should.equal(3);
});
});

0 comments on commit 8acf093

Please sign in to comment.