multisign test for signing twice with same sig
This commit is contained in:
parent
2af6ab7650
commit
8acf093339
|
@ -58,7 +58,7 @@
|
||||||
*
|
*
|
||||||
* @opts
|
* @opts
|
||||||
* {
|
* {
|
||||||
* remainderAddress: null,
|
* remainderOut: null,
|
||||||
* fee: 0.001,
|
* fee: 0.001,
|
||||||
* lockTime: null,
|
* lockTime: null,
|
||||||
* spendUnconfirmed: false,
|
* spendUnconfirmed: false,
|
||||||
|
@ -67,8 +67,12 @@
|
||||||
* Amounts are in BTC. instead of fee and amount; feeSat and amountSat can be given,
|
* Amounts are in BTC. instead of fee and amount; feeSat and amountSat can be given,
|
||||||
* repectively, to provide amounts in satoshis.
|
* repectively, to provide amounts in satoshis.
|
||||||
*
|
*
|
||||||
* If no remainderAddress is given, and there are remainder coins, the
|
* If no remainderOut is given, and there are remainder coins, the
|
||||||
* first IN address will be used to return the coins. (TODO: is this is reasonable?)
|
* first IN out will be used to return the coins. remainderOut has the form:
|
||||||
|
* remainderOut = { address: 1xxxxx}
|
||||||
|
* or
|
||||||
|
* remainderOut = { pubkeys: ['hex1','hex2',...} for multisig
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -101,7 +105,7 @@ function TransactionBuilder(opts) {
|
||||||
if (opts.fee || opts.feeSat) {
|
if (opts.fee || opts.feeSat) {
|
||||||
this.givenFeeSat = opts.fee ? opts.fee * util.COIN : 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.signhash = opts.signhash || Transaction.SIGHASH_ALL;
|
||||||
|
|
||||||
this.tx = {};
|
this.tx = {};
|
||||||
|
@ -134,6 +138,31 @@ TransactionBuilder._scriptForAddress = function(addressString) {
|
||||||
return script;
|
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) {
|
TransactionBuilder.prototype.setUnspent = function(utxos) {
|
||||||
this.utxos = utxos;
|
this.utxos = utxos;
|
||||||
return this;
|
return this;
|
||||||
|
@ -279,9 +308,9 @@ TransactionBuilder.prototype._setRemainder = function(remainderIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remainderSat.cmp(0) > 0) {
|
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 value = util.bigIntToValue(remainderSat);
|
||||||
var script = TransactionBuilder._scriptForAddress(remainderAddress);
|
var script = TransactionBuilder._scriptForOut(remainderOut);
|
||||||
var txout = {
|
var txout = {
|
||||||
v: value,
|
v: value,
|
||||||
s: script.getBuffer(),
|
s: script.getBuffer(),
|
||||||
|
@ -327,7 +356,7 @@ TransactionBuilder.prototype.setOutputs = function(outs) {
|
||||||
for (var i = 0; i < l; i++) {
|
for (var i = 0; i < l; i++) {
|
||||||
var amountSat = outs[i].amountSat || util.parseValue(outs[i].amount);
|
var amountSat = outs[i].amountSat || util.parseValue(outs[i].amount);
|
||||||
var value = util.bigIntToValue(amountSat);
|
var value = util.bigIntToValue(amountSat);
|
||||||
var script = TransactionBuilder._scriptForAddress(outs[i].address);
|
var script = TransactionBuilder._scriptForOut(outs[i]);
|
||||||
var txout = {
|
var txout = {
|
||||||
v: value,
|
v: value,
|
||||||
s: script.getBuffer(),
|
s: script.getBuffer(),
|
||||||
|
@ -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 = {};
|
var fnToSign = {};
|
||||||
fnToSign[Script.TX_PUBKEYHASH] = TransactionBuilder.prototype._signPubKeyHash;
|
fnToSign[Script.TX_PUBKEYHASH] = TransactionBuilder.prototype._signPubKeyHash;
|
||||||
fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
|
fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
|
||||||
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
|
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
|
||||||
fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
|
fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
|
||||||
//if (!this.hashToScriptMap) throw new Error('hashToScriptMap not set');
|
|
||||||
|
|
||||||
TransactionBuilder.prototype.sign = function(keys) {
|
TransactionBuilder.prototype.sign = function(keys) {
|
||||||
this._checkTx();
|
this._checkTx();
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
|
|
||||||
var run = function() {
|
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 bitcore = require('../bitcore');
|
||||||
var networks = require('../networks');
|
var networks = require('../networks');
|
||||||
var WalletKey = bitcore.WalletKey;
|
var WalletKey = bitcore.WalletKey;
|
||||||
|
|
||||||
var opts = {network: networks.livenet};
|
var opts = {network: networks.testnet};
|
||||||
|
|
||||||
function print(wk) {
|
function print(wk) {
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ describe('TransactionBuilder', function() {
|
||||||
|
|
||||||
var getBuilder2 = function (fee) {
|
var getBuilder2 = function (fee) {
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
spendUnconfirmed: true,
|
spendUnconfirmed: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ describe('TransactionBuilder', function() {
|
||||||
var utxos = testdata.dataUnspent;
|
var utxos = testdata.dataUnspent;
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
spendUnconfirmed: true,
|
spendUnconfirmed: true,
|
||||||
};
|
};
|
||||||
var outs = [{
|
var outs = [{
|
||||||
|
@ -211,7 +211,7 @@ describe('TransactionBuilder', function() {
|
||||||
var getBuilder3 = function (outs) {
|
var getBuilder3 = function (outs) {
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
spendUnconfirmed: true,
|
spendUnconfirmed: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ describe('TransactionBuilder', function() {
|
||||||
|
|
||||||
it('should sign a p2pubkey tx', function() {
|
it('should sign a p2pubkey tx', function() {
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
};
|
};
|
||||||
var outs = outs || [{
|
var outs = outs || [{
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
@ -419,7 +419,7 @@ describe('TransactionBuilder', function() {
|
||||||
|
|
||||||
it('should sign a multisig tx', function() {
|
it('should sign a multisig tx', function() {
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
};
|
};
|
||||||
var outs = outs || [{
|
var outs = outs || [{
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
@ -440,7 +440,7 @@ describe('TransactionBuilder', function() {
|
||||||
|
|
||||||
it('should sign a multisig tx in steps (3-5)', function() {
|
it('should sign a multisig tx in steps (3-5)', function() {
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
};
|
};
|
||||||
var outs = outs || [{
|
var outs = outs || [{
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
@ -470,7 +470,7 @@ describe('TransactionBuilder', function() {
|
||||||
|
|
||||||
it('should count multisig signs (3-5)', function() {
|
it('should count multisig signs (3-5)', function() {
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderAddress: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd',
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
};
|
};
|
||||||
var outs = outs || [{
|
var outs = outs || [{
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
@ -494,7 +494,40 @@ describe('TransactionBuilder', function() {
|
||||||
b.sign(k3);
|
b.sign(k3);
|
||||||
b.isFullySigned().should.equal(true);
|
b.isFullySigned().should.equal(true);
|
||||||
b.countInputMultiSig(0).should.equal(3);
|
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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue