new to/from Obj. WIP
This commit is contained in:
parent
3d828df063
commit
397fc8607f
@ -65,6 +65,7 @@ var log = require('../util/log');
|
|||||||
var Transaction = require('./Transaction');
|
var Transaction = require('./Transaction');
|
||||||
|
|
||||||
var FEE_PER_1000B_SAT = parseInt(0.0001 * util.COIN);
|
var FEE_PER_1000B_SAT = parseInt(0.0001 * util.COIN);
|
||||||
|
var TOOBJ_VERSION = 1;
|
||||||
|
|
||||||
// Methods
|
// Methods
|
||||||
// -------
|
// -------
|
||||||
@ -97,6 +98,14 @@ var FEE_PER_1000B_SAT = parseInt(0.0001 * util.COIN);
|
|||||||
|
|
||||||
function TransactionBuilder(opts) {
|
function TransactionBuilder(opts) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
|
||||||
|
this.vanilla = {};
|
||||||
|
this.vanilla.scriptSig = [];
|
||||||
|
this.vanilla.opts = JSON.stringify(opts);
|
||||||
|
|
||||||
|
// If any default opts is changed, TOOBJ_VERSION should be changed as
|
||||||
|
// a caution measure.
|
||||||
|
|
||||||
this.lockTime = opts.lockTime || 0;
|
this.lockTime = opts.lockTime || 0;
|
||||||
this.spendUnconfirmed = opts.spendUnconfirmed || false;
|
this.spendUnconfirmed = opts.spendUnconfirmed || false;
|
||||||
|
|
||||||
@ -108,7 +117,6 @@ function TransactionBuilder(opts) {
|
|||||||
|
|
||||||
this.tx = {};
|
this.tx = {};
|
||||||
this.inputsSigned = 0;
|
this.inputsSigned = 0;
|
||||||
this.signaturesAdded = 0;
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -177,6 +185,7 @@ TransactionBuilder.infoForP2sh = function(opts, networkName) {
|
|||||||
// That amount is in BTCs (as returned in insight and bitcoind).
|
// That amount is in BTCs (as returned in insight and bitcoind).
|
||||||
// amountSat (instead of amount) can be given to provide amount in satochis.
|
// amountSat (instead of amount) can be given to provide amount in satochis.
|
||||||
TransactionBuilder.prototype.setUnspent = function(unspent) {
|
TransactionBuilder.prototype.setUnspent = function(unspent) {
|
||||||
|
this.vanilla.utxos = JSON.stringify(unspent);
|
||||||
this.utxos = unspent;
|
this.utxos = unspent;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -381,8 +390,9 @@ TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
TransactionBuilder.prototype.setOutputs = function(outs) {
|
TransactionBuilder.prototype.setOutputs = function(outs) {
|
||||||
var valueOutSat = bignum(0);
|
this.vanilla.outs = JSON.stringify(outs);
|
||||||
|
|
||||||
|
var valueOutSat = bignum(0);
|
||||||
var txobj = {};
|
var txobj = {};
|
||||||
txobj.version = 1;
|
txobj.version = 1;
|
||||||
txobj.lock_time = this.lockTime || 0;
|
txobj.lock_time = this.lockTime || 0;
|
||||||
@ -454,7 +464,7 @@ TransactionBuilder._signHashAndVerify = function(wk, txSigHash) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TransactionBuilder.prototype._checkTx = function() {
|
TransactionBuilder.prototype._checkTx = function() {
|
||||||
if (!this.tx || !this.tx.ins.length || !this.tx.outs.length)
|
if (!this.tx || !this.tx.ins || !this.tx.ins.length || !this.tx.outs.length)
|
||||||
throw new Error('tx is not defined');
|
throw new Error('tx is not defined');
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -746,6 +756,9 @@ fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
TransactionBuilder.prototype.sign = function(keys) {
|
TransactionBuilder.prototype.sign = function(keys) {
|
||||||
|
if (! (keys instanceof Array))
|
||||||
|
throw new Error('parameter should be an array');
|
||||||
|
|
||||||
this._checkTx();
|
this._checkTx();
|
||||||
var tx = this.tx,
|
var tx = this.tx,
|
||||||
ins = tx.ins,
|
ins = tx.ins,
|
||||||
@ -760,9 +773,10 @@ TransactionBuilder.prototype.sign = function(keys) {
|
|||||||
|
|
||||||
var ret = fnToSign[input.scriptType].call(this, walletKeyMap, input, txSigHash);
|
var ret = fnToSign[input.scriptType].call(this, walletKeyMap, input, txSigHash);
|
||||||
if (ret && ret.script) {
|
if (ret && ret.script) {
|
||||||
|
this.vanilla.scriptSig[i] = ret.script.toString('hex');
|
||||||
|
|
||||||
tx.ins[i].s = ret.script;
|
tx.ins[i].s = ret.script;
|
||||||
if (ret.inputFullySigned) this.inputsSigned++;
|
if (ret.inputFullySigned) this.inputsSigned++;
|
||||||
if (ret.signaturesAdded) this.signaturesAdded += ret.signaturesAdded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
@ -775,6 +789,8 @@ TransactionBuilder.prototype.sign = function(keys) {
|
|||||||
// for generate the input for this call.
|
// for generate the input for this call.
|
||||||
//
|
//
|
||||||
TransactionBuilder.prototype.setHashToScriptMap = function(hashToScriptMap) {
|
TransactionBuilder.prototype.setHashToScriptMap = function(hashToScriptMap) {
|
||||||
|
this.vanilla.hashToScriptMap = JSON.stringify(hashToScriptMap);
|
||||||
|
|
||||||
this.hashToScriptMap = hashToScriptMap;
|
this.hashToScriptMap = hashToScriptMap;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@ -783,8 +799,6 @@ TransactionBuilder.prototype.setHashToScriptMap = function(hashToScriptMap) {
|
|||||||
// isFullySigned
|
// isFullySigned
|
||||||
// -------------
|
// -------------
|
||||||
// Checks if the transaction have all the necesary signatures.
|
// Checks if the transaction have all the necesary signatures.
|
||||||
// Also, `.signaturesAdded` and `.inputsSigned` can be queried
|
|
||||||
// for more information about the transaction signature status.
|
|
||||||
//
|
//
|
||||||
TransactionBuilder.prototype.isFullySigned = function() {
|
TransactionBuilder.prototype.isFullySigned = function() {
|
||||||
return this.inputsSigned === this.tx.ins.length;
|
return this.inputsSigned === this.tx.ins.length;
|
||||||
@ -803,25 +817,18 @@ TransactionBuilder.prototype.build = function() {
|
|||||||
// See `.fromObj`
|
// See `.fromObj`
|
||||||
//
|
//
|
||||||
TransactionBuilder.prototype.toObj = function() {
|
TransactionBuilder.prototype.toObj = function() {
|
||||||
var data = {
|
|
||||||
valueInSat: this.valueInSat.toString(),
|
|
||||||
valueOutSat: this.valueOutSat.toString(),
|
|
||||||
feeSat: this.feeSat.toString(),
|
|
||||||
remainderSat: this.remainderSat.toString(),
|
|
||||||
|
|
||||||
hashToScriptMap: this.hashToScriptMap,
|
var ret = {
|
||||||
selectedUtxos: this.selectedUtxos,
|
version: TOOBJ_VERSION,
|
||||||
|
outs: JSON.parse(this.vanilla.outs),
|
||||||
inputsSigned: this.inputsSigned,
|
utxos: JSON.parse(this.vanilla.utxos),
|
||||||
signaturesAdded: this.signaturesAdded,
|
opts: JSON.parse(this.vanilla.opts),
|
||||||
|
scriptSig: this.vanilla.scriptSig,
|
||||||
signhash: this.signhash,
|
|
||||||
spendUnconfirmed: this.spendUnconfirmed,
|
|
||||||
};
|
};
|
||||||
if (this.tx) {
|
if (this.vanilla.hashToScriptMap)
|
||||||
data.tx = this.tx.serialize().toString('hex');
|
ret.hashToScriptMap = JSON.parse(this.vanilla.hashToScriptMap);
|
||||||
}
|
|
||||||
return data;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
// fromObj
|
// fromObj
|
||||||
@ -831,90 +838,36 @@ TransactionBuilder.prototype.toObj = function() {
|
|||||||
// with `.toObj`. See `.toObj`.
|
// with `.toObj`. See `.toObj`.
|
||||||
|
|
||||||
TransactionBuilder.fromObj = function(data) {
|
TransactionBuilder.fromObj = function(data) {
|
||||||
var b = new TransactionBuilder();
|
|
||||||
b.valueInSat = data.valueInSat.toString();
|
|
||||||
b.valueOutSat = data.valueOutSat.toString();
|
|
||||||
b.feeSat = data.feeSat.toString();
|
|
||||||
b.remainderSat = data.remainderSat.toString();
|
|
||||||
|
|
||||||
b.hashToScriptMap = data.hashToScriptMap;
|
if (data.version !== TOOBJ_VERSION)
|
||||||
b.selectedUtxos = data.selectedUtxos;
|
throw new Error('Incompatible version at TransactionBuilder fromObj');
|
||||||
|
|
||||||
b.inputsSigned = data.inputsSigned;
|
var b = new TransactionBuilder(data.opts);
|
||||||
b.signaturesAdded = data.signaturesAdded;
|
if (data.utxos) {
|
||||||
|
b.setUnspent(data.utxos);
|
||||||
|
|
||||||
b.signhash = data.signhash;
|
if (data.hashToScriptMap)
|
||||||
b.spendUnconfirmed = data.spendUnconfirmed;
|
b.setHashToScriptMap(data.hashToScriptMap);
|
||||||
|
|
||||||
b._setInputMap();
|
if (data.outs) {
|
||||||
|
b.setOutputs(data.outs);
|
||||||
|
|
||||||
if (data.tx) {
|
for (var i in data.scriptSig) {
|
||||||
// Tx may have signatures, that are not on txobj
|
b.tx.ins[i].s = new Buffer(data.scriptSig[i], 'hex');
|
||||||
var t = new Transaction();
|
|
||||||
t.parse(new Buffer(data.tx, 'hex'));
|
var scriptSig = new Script(b.tx.ins[i].s);
|
||||||
b.tx = t;
|
if ( scriptSig.finishedMultiSig() !== false )
|
||||||
|
b.inputsSigned++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
TransactionBuilder.prototype._checkMergeability = function(b) {
|
TransactionBuilder.prototype._checkMergeability = function(b) {
|
||||||
var self = this;
|
if ( JSON.stringify(this.vanilla) !== JSON.stringify(this.vanilla))
|
||||||
|
throw new Error('cannot merge: incompatible builders')
|
||||||
// Builder should have the same params
|
|
||||||
['valueInSat', 'valueOutSat', 'feeSat', 'remainderSat', 'signhash', 'spendUnconfirmed']
|
|
||||||
.forEach(function(k) {
|
|
||||||
|
|
||||||
if (self[k].toString() !== b[k].toString()) {
|
|
||||||
throw new Error('mismatch at TransactionBuilder match: ' + k + ': ' + self[k] + ' vs. ' + b[k]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (self.hashToScriptMap) {
|
|
||||||
var err = 0;
|
|
||||||
if (!b.hashToScriptMap) err = 1;
|
|
||||||
Object.keys(self.hashToScriptMap).forEach(function(k) {
|
|
||||||
if (!b.hashToScriptMap[k]) err = 1;
|
|
||||||
if (self.hashToScriptMap[k] !== b.hashToScriptMap[k]) err = 1;
|
|
||||||
});
|
|
||||||
if (err)
|
|
||||||
throw new Error('mismatch at TransactionBuilder hashToScriptMap');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var err = 0,
|
|
||||||
i = 0;;
|
|
||||||
self.selectedUtxos.forEach(function(u) {
|
|
||||||
if (!err) {
|
|
||||||
var v = b.selectedUtxos[i++];
|
|
||||||
if (!v) err = 1;
|
|
||||||
// confirmations could differ
|
|
||||||
['address', 'hash', 'scriptPubKey', 'vout', 'amount'].forEach(function(k) {
|
|
||||||
if (u[k] !== v[k])
|
|
||||||
err = k;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (err)
|
|
||||||
throw new Error('mismatch at TransactionBuilder selectedUtxos #' + i - 1 + ' Key:' + err);
|
|
||||||
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
i = 0;;
|
|
||||||
self.inputMap.forEach(function(u) {
|
|
||||||
if (!err) {
|
|
||||||
var v = b.inputMap[i++];
|
|
||||||
if (!v) err = 1;
|
|
||||||
// confirmations could differ
|
|
||||||
['address', 'scriptType', 'scriptPubKey', 'i'].forEach(function(k) {
|
|
||||||
if (u[k].toString() !== v[k].toString())
|
|
||||||
err = k;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (err)
|
|
||||||
throw new Error('mismatch at TransactionBuilder inputMap #' + i - 1 + ' Key:' + err);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO this could be on Script class
|
// TODO this could be on Script class
|
||||||
@ -944,22 +897,33 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input, s0, s1) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.887:diff:]',diff); //TODO
|
||||||
// Add signatures
|
// Add signatures
|
||||||
for (var j in diff) {
|
for (var j in diff) {
|
||||||
var newSig = diff[j];
|
var newSig = diff[j];
|
||||||
var order = this._getNewSignatureOrder(newSig.prio, s0, p2sh.txSigHash, pubkeys);
|
var order = this._getNewSignatureOrder(newSig.prio, s0, p2sh.txSigHash, pubkeys);
|
||||||
|
|
||||||
|
if (this._getSighashType(newSig.chunk) !== this.signhash)
|
||||||
|
throw new Error('signhash type mismatch at merge');
|
||||||
|
|
||||||
s0.chunks.splice(order + 1, 0, newSig.chunk);
|
s0.chunks.splice(order + 1, 0, newSig.chunk);
|
||||||
this.signaturesAdded++;
|
|
||||||
}
|
}
|
||||||
s0.updateBuffer();
|
s0.updateBuffer();
|
||||||
return s0.getBuffer();
|
return s0.getBuffer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: move this to script
|
||||||
|
TransactionBuilder.prototype._getSighashType = function(sig) {
|
||||||
|
return sig[sig.length-1];
|
||||||
|
};
|
||||||
|
|
||||||
// TODO this could be on Script class
|
// TODO this could be on Script class
|
||||||
TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
|
TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
|
||||||
if (buffertools.compare(s0buf, s1buf) === 0)
|
if (buffertools.compare(s0buf, s1buf) === 0)
|
||||||
return s0buf;
|
return s0buf;
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.925]'); //TODO
|
||||||
var s0 = new Script(s0buf);
|
var s0 = new Script(s0buf);
|
||||||
var s1 = new Script(s1buf);
|
var s1 = new Script(s1buf);
|
||||||
var l0 = s0.chunks.length;
|
var l0 = s0.chunks.length;
|
||||||
@ -969,15 +933,25 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
|
|||||||
if (l0 && l1 && ((l0 < 2 && l1 > 2) || (l1 < 2 && l0 > 2)))
|
if (l0 && l1 && ((l0 < 2 && l1 > 2) || (l1 < 2 && l0 > 2)))
|
||||||
throw new Error('TX sig types mismatch in merge');
|
throw new Error('TX sig types mismatch in merge');
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.935]', l0, l1); //TODO
|
||||||
if ((!l0 && !l1) || (l0 && !l1) || (!l0 && l1))
|
if ((!l0 && !l1) || (l0 && !l1) || (!l0 && l1))
|
||||||
return s1buf;
|
return s1buf;
|
||||||
|
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.940]'); //TODO
|
||||||
|
|
||||||
// Get the pubkeys
|
// Get the pubkeys
|
||||||
var input = this.inputMap[index];
|
var input = this.inputMap[index];
|
||||||
var type = input.scriptPubKey.classify();
|
var type = input.scriptPubKey.classify();
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.941]'); //TODO
|
||||||
//p2pubkey or p2pubkeyhash
|
//p2pubkey or p2pubkeyhash
|
||||||
if (type === Script.TX_PUBKEYHASH || type === Script.TX_PUBKEY) {
|
if (type === Script.TX_PUBKEYHASH || type === Script.TX_PUBKEY) {
|
||||||
|
var s = new Script(s1buf);
|
||||||
|
|
||||||
|
if (this._getSighashType(s.chunks[0]) !== this.signhash)
|
||||||
|
throw new Error('signhash type mismatch at merge');
|
||||||
|
|
||||||
log.debug('Merging two signed inputs type:' +
|
log.debug('Merging two signed inputs type:' +
|
||||||
input.scriptPubKey.getRawOutType() + '. Signatures differs. Using the first version.');
|
input.scriptPubKey.getRawOutType() + '. Signatures differs. Using the first version.');
|
||||||
return s0buf;
|
return s0buf;
|
||||||
@ -985,6 +959,9 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
|
|||||||
// No support for normal multisig or strange txs.
|
// No support for normal multisig or strange txs.
|
||||||
throw new Error('Script type:' + input.scriptPubKey.getRawOutType() + 'not supported at #merge');
|
throw new Error('Script type:' + input.scriptPubKey.getRawOutType() + 'not supported at #merge');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.957]'); //TODO
|
||||||
|
|
||||||
return this._mergeInputSigP2sh(input, s0, s1);
|
return this._mergeInputSigP2sh(input, s0, s1);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -992,6 +969,7 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
|
|||||||
TransactionBuilder.prototype._mergeTx = function(tx) {
|
TransactionBuilder.prototype._mergeTx = function(tx) {
|
||||||
var v0 = this.tx;
|
var v0 = this.tx;
|
||||||
var v1 = tx;
|
var v1 = tx;
|
||||||
|
console.log('[TransactionBuilder.js.966:var:]'); //TODO
|
||||||
|
|
||||||
var l = v0.ins.length;
|
var l = v0.ins.length;
|
||||||
if (l !== v1.ins.length)
|
if (l !== v1.ins.length)
|
||||||
@ -999,6 +977,7 @@ TransactionBuilder.prototype._mergeTx = function(tx) {
|
|||||||
|
|
||||||
this.inputsSigned = 0;
|
this.inputsSigned = 0;
|
||||||
for (var i = 0; i < l; i++) {
|
for (var i = 0; i < l; i++) {
|
||||||
|
console.log('[TransactionBuilder.js.974:for:]',i); //TODO
|
||||||
var i0 = v0.ins[i];
|
var i0 = v0.ins[i];
|
||||||
var i1 = v1.ins[i];
|
var i1 = v1.ins[i];
|
||||||
|
|
||||||
@ -1008,18 +987,31 @@ TransactionBuilder.prototype._mergeTx = function(tx) {
|
|||||||
if (buffertools.compare(i0.o, i1.o) !== 0)
|
if (buffertools.compare(i0.o, i1.o) !== 0)
|
||||||
throw new Error('TX .o in mismatch in merge. Input:', i);
|
throw new Error('TX .o in mismatch in merge. Input:', i);
|
||||||
|
|
||||||
|
console.log('[TransactionBuilder.js.984]'); //TODO
|
||||||
i0.s = this._mergeInputSig(i, i0.s, i1.s);
|
i0.s = this._mergeInputSig(i, i0.s, i1.s);
|
||||||
|
this.vanilla.scriptSig[i]= i0.s.toString('hex');
|
||||||
|
|
||||||
if (v0.isInputComplete(i)) this.inputsSigned++;
|
if (v0.isInputComplete(i)) this.inputsSigned++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// clone
|
||||||
|
// -----
|
||||||
|
// Clone current TransactionBuilder, regenerate derived fields.
|
||||||
|
//
|
||||||
|
TransactionBuilder.prototype.clone = function() {
|
||||||
|
return new TransactionBuilder.fromObj(this.toObj());
|
||||||
|
};
|
||||||
|
|
||||||
// merge
|
// merge
|
||||||
// -----
|
// -----
|
||||||
// Merge to TransactionBuilder objects, merging inputs signatures.
|
// Merge to TransactionBuilder objects, merging inputs signatures.
|
||||||
// This function supports multisig p2sh inputs.
|
// This function supports multisig p2sh inputs.
|
||||||
|
|
||||||
TransactionBuilder.prototype.merge = function(b) {
|
TransactionBuilder.prototype.merge = function(inB) {
|
||||||
|
//
|
||||||
|
var b = inB.clone();
|
||||||
|
|
||||||
this._checkMergeability(b);
|
this._checkMergeability(b);
|
||||||
|
|
||||||
// Does this tX have any signature already?
|
// Does this tX have any signature already?
|
||||||
|
|||||||
@ -218,11 +218,12 @@ describe('TransactionBuilder', function() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var getBuilder3 = function (outs) {
|
var getBuilder3 = function (outs, signhash) {
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
||||||
spendUnconfirmed: true,
|
spendUnconfirmed: true,
|
||||||
|
signhash: signhash,
|
||||||
};
|
};
|
||||||
|
|
||||||
var outs = outs || [{
|
var outs = outs || [{
|
||||||
@ -693,11 +694,11 @@ describe('TransactionBuilder', function() {
|
|||||||
// "redeemScript" : "532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae"
|
// "redeemScript" : "532103197599f6e209cefef07da2fddc6fe47715a70162c531ffff8e611cef23dfb70d210380a29968851f93af55e581c43d9ef9294577a439a3ca9fc2bc47d1ca2b3e9127210392dccb2ed470a45984811d6402fdca613c175f8f3e4eb8e2306e8ccd7d0aed032103a94351fecc4328bb683bf93a1aa67378374904eac5980c7966723a51897c56e32103e085eb6fa1f20b2722c16161144314070a2c316a9cae2489fd52ce5f63fff6e455ae"
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
var getP2shBuilder = function(setMap) {
|
var getP2shBuilder = function(setMap, opts) {
|
||||||
var network = 'testnet';
|
var network = 'testnet';
|
||||||
var opts = {
|
opts = opts || {};
|
||||||
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
|
opts.remainderOut = opts.remainderOut || {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'};
|
||||||
};
|
|
||||||
var data = getInfoForP2sh();
|
var data = getInfoForP2sh();
|
||||||
// multisig p2sh
|
// multisig p2sh
|
||||||
var p2shOpts = {nreq:3, pubkeys:data.pubkeys};
|
var p2shOpts = {nreq:3, pubkeys:data.pubkeys};
|
||||||
@ -760,43 +761,36 @@ describe('TransactionBuilder', function() {
|
|||||||
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
||||||
var k5 = testdata.dataUnspentSign.keyStringsP2sh.slice(4,5);
|
var k5 = testdata.dataUnspentSign.keyStringsP2sh.slice(4,5);
|
||||||
b.isFullySigned().should.equal(false);
|
b.isFullySigned().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(0);
|
|
||||||
|
|
||||||
b.sign(k1);
|
b.sign(k1);
|
||||||
b.isFullySigned().should.equal(false);
|
b.isFullySigned().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
var tx = b.build();
|
var tx = b.build();
|
||||||
tx.ins.length.should.equal(1);
|
tx.ins.length.should.equal(1);
|
||||||
tx.outs.length.should.equal(2);
|
tx.outs.length.should.equal(2);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
// Sign with the same
|
// Sign with the same
|
||||||
b.sign(k1);
|
b.sign(k1);
|
||||||
b.isFullySigned().should.equal(false);
|
b.isFullySigned().should.equal(false);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
// Sign with k5
|
// Sign with k5
|
||||||
b.sign(k5);
|
b.sign(k5);
|
||||||
///
|
///
|
||||||
b.isFullySigned().should.equal(false);
|
b.isFullySigned().should.equal(false);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(2);
|
|
||||||
|
|
||||||
// Sign with same
|
// Sign with same
|
||||||
b.sign(k5);
|
b.sign(k5);
|
||||||
b.isFullySigned().should.equal(false);
|
b.isFullySigned().should.equal(false);
|
||||||
tx.isComplete().should.equal(false);
|
tx.isComplete().should.equal(false);
|
||||||
b.signaturesAdded.should.equal(2);
|
|
||||||
|
|
||||||
|
|
||||||
// Sign k2
|
// Sign k2
|
||||||
b.sign(k2);
|
b.sign(k2);
|
||||||
b.isFullySigned().should.equal(true);
|
b.isFullySigned().should.equal(true);
|
||||||
tx.isComplete().should.equal(true);
|
tx.isComplete().should.equal(true);
|
||||||
b.signaturesAdded.should.equal(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should sign a p2sh/p2pubkeyhash tx', function() {
|
it('should sign a p2sh/p2pubkeyhash tx', function() {
|
||||||
@ -844,190 +838,311 @@ describe('TransactionBuilder', function() {
|
|||||||
tx.isComplete().should.equal(true);
|
tx.isComplete().should.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#toObj #fromObj roundtrip', function() {
|
|
||||||
var b = getBuilder2();
|
|
||||||
|
|
||||||
b.isFullySigned().should.equal(false);
|
it('should check sign parameters', function() {
|
||||||
b.getSelectedUnspent().length.should.equal(2);
|
|
||||||
|
|
||||||
var data =b.toObj();
|
|
||||||
|
|
||||||
var b2 = TransactionBuilder.fromObj(data);
|
|
||||||
var tx = b2.build();
|
|
||||||
should.exist(tx);
|
|
||||||
tx.version.should.equal(1);
|
|
||||||
tx.ins.length.should.equal(2);
|
|
||||||
tx.outs.length.should.equal(2);
|
|
||||||
|
|
||||||
util.valueToBigInt(tx.outs[0].v).cmp(8000000).should.equal(0);
|
|
||||||
|
|
||||||
// remainder is 0.0299 here because unspent select utxos in order
|
|
||||||
util.valueToBigInt(tx.outs[1].v).cmp(2990000).should.equal(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('#toObj #fromObj roundtrip, step signatures p2sh/p2pubkeyhash', function() {
|
|
||||||
var b = getP2shBuilder(1);
|
var b = getP2shBuilder(1);
|
||||||
|
(function() { b.sign(testdata.dataUnspentSign.keyStringsP2sh[0]) }).should.throw('array');
|
||||||
var k1 = testdata.dataUnspentSign.keyStringsP2sh.slice(0,1);
|
|
||||||
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
|
||||||
var k5 = testdata.dataUnspentSign.keyStringsP2sh.slice(4,5);
|
|
||||||
b.isFullySigned().should.equal(false);
|
|
||||||
b.signaturesAdded.should.equal(0);
|
|
||||||
|
|
||||||
var b2 = TransactionBuilder.fromObj(b.toObj());
|
|
||||||
|
|
||||||
b2.sign(k1);
|
|
||||||
|
|
||||||
b2.isFullySigned().should.equal(false);
|
|
||||||
b2.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
var tx = b2.build();
|
|
||||||
tx.ins.length.should.equal(1);
|
|
||||||
tx.outs.length.should.equal(2);
|
|
||||||
tx.isComplete().should.equal(false);
|
|
||||||
b2.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
// Sign with the same
|
|
||||||
var b3 = TransactionBuilder.fromObj(b2.toObj());
|
|
||||||
|
|
||||||
b3.sign(k1);
|
|
||||||
b3.isFullySigned().should.equal(false);
|
|
||||||
b3.signaturesAdded.should.equal(1);
|
|
||||||
|
|
||||||
// Sign with k5
|
|
||||||
var b4 = TransactionBuilder.fromObj(b3.toObj());
|
|
||||||
b4.sign(k5);
|
|
||||||
b4.isFullySigned().should.equal(false);
|
|
||||||
b4.signaturesAdded.should.equal(2);
|
|
||||||
|
|
||||||
var b5 = TransactionBuilder.fromObj(b4.toObj());
|
|
||||||
// Sign k2
|
|
||||||
b5.sign(k2);
|
|
||||||
b5.isFullySigned().should.equal(true);
|
|
||||||
var tx2 = b5.build();
|
|
||||||
tx2.isComplete().should.equal(true);
|
|
||||||
b5.signaturesAdded.should.equal(3);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('#merge self', function() {
|
|
||||||
var b = getBuilder3([{
|
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 16
|
|
||||||
}])
|
|
||||||
.sign(testdata.dataUnspentSign.keyStrings);
|
|
||||||
b.merge(b);
|
|
||||||
|
|
||||||
b.isFullySigned().should.equal(true);
|
describe('serizalization', function(){
|
||||||
var tx = b.build();
|
|
||||||
tx.isComplete().should.equal(true);
|
|
||||||
tx.ins.length.should.equal(3);
|
|
||||||
tx.outs.length.should.equal(2);
|
|
||||||
});
|
|
||||||
it('#merge simple', function() {
|
|
||||||
var b = getBuilder3([{
|
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 16
|
|
||||||
}])
|
|
||||||
.sign(testdata.dataUnspentSign.keyStrings);
|
|
||||||
|
|
||||||
// merge simple
|
it('#toObj #fromObj roundtrip', function() {
|
||||||
var b2 = getBuilder3([{
|
var b = getBuilder2();
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 16
|
|
||||||
}]);
|
|
||||||
b2.isFullySigned().should.equal(false);
|
|
||||||
b2.merge(b);
|
|
||||||
|
|
||||||
b2.isFullySigned().should.equal(true);
|
b.isFullySigned().should.equal(false);
|
||||||
var tx = b.build();
|
b.getSelectedUnspent().length.should.equal(2);
|
||||||
tx.isComplete().should.equal(true);
|
|
||||||
tx.ins.length.should.equal(3);
|
|
||||||
tx.outs.length.should.equal(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('#merge checks', function() {
|
var data =b.toObj();
|
||||||
var b = getBuilder3([{
|
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 16
|
|
||||||
}]);
|
|
||||||
// bad amount
|
|
||||||
var b2 = getBuilder3([{
|
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 15
|
|
||||||
}]);
|
|
||||||
(function() {b2.merge(b);}).should.throw();
|
|
||||||
// bad out
|
|
||||||
b2 = getBuilder3([{
|
|
||||||
address: 'muHct3YZ9Nd5Pq7uLYYhXRAxeW4EnpcaLz',
|
|
||||||
amount: 16
|
|
||||||
}]);
|
|
||||||
(function() {b2.merge(b);}).should.throw();
|
|
||||||
|
|
||||||
// same signature
|
var b2 = TransactionBuilder.fromObj(data);
|
||||||
// -> this fails: no way to check signatures, since PRIV Keys are not stored
|
var tx = b2.build();
|
||||||
b = getBuilder3([{
|
should.exist(tx);
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
tx.version.should.equal(1);
|
||||||
amount: 16
|
tx.ins.length.should.equal(2);
|
||||||
}])
|
tx.outs.length.should.equal(2);
|
||||||
.sign(testdata.dataUnspentSign.keyStrings);
|
|
||||||
// merge simple
|
|
||||||
b2 = getBuilder3([{
|
|
||||||
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
|
||||||
amount: 16
|
|
||||||
}])
|
|
||||||
.sign(testdata.dataUnspentSign.keyStrings);
|
|
||||||
b2.isFullySigned().should.equal(true);
|
|
||||||
b2.merge(b);
|
|
||||||
b2.isFullySigned().should.equal(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('#merge p2sh/steps', function(done) {
|
util.valueToBigInt(tx.outs[0].v).cmp(8000000).should.equal(0);
|
||||||
var b = getP2shBuilder(1);
|
|
||||||
var k1 = testdata.dataUnspentSign.keyStringsP2sh.slice(0,1);
|
|
||||||
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
|
||||||
var k3 = testdata.dataUnspentSign.keyStringsP2sh.slice(2,3);
|
|
||||||
b.isFullySigned().should.equal(false);
|
|
||||||
b.signaturesAdded.should.equal(0);
|
|
||||||
b.sign(k1);
|
|
||||||
b.signaturesAdded.should.equal(1);
|
|
||||||
b.isFullySigned().should.equal(false);
|
|
||||||
var tx = b.build();
|
|
||||||
tx.isComplete().should.equal(false);
|
|
||||||
|
|
||||||
b = TransactionBuilder.fromObj(b.toObj());
|
// remainder is 0.0299 here because unspent select utxos in order
|
||||||
|
util.valueToBigInt(tx.outs[1].v).cmp(2990000).should.equal(0);
|
||||||
// TODO TO OBJ!
|
|
||||||
var b2 = getP2shBuilder(1);
|
|
||||||
b2.sign(k2);
|
|
||||||
b2.signaturesAdded.should.equal(1);
|
|
||||||
b2.merge(b);
|
|
||||||
b2.signaturesAdded.should.equal(2);
|
|
||||||
tx = b2.build();
|
|
||||||
tx.isComplete().should.equal(false);
|
|
||||||
|
|
||||||
b2 = TransactionBuilder.fromObj(b2.toObj());
|
|
||||||
var b3 = getP2shBuilder(1);
|
|
||||||
b3.sign(k3);
|
|
||||||
b3.signaturesAdded.should.equal(1);
|
|
||||||
b3.merge(b2);
|
|
||||||
b3.signaturesAdded.should.equal(3);
|
|
||||||
tx = b3.build();
|
|
||||||
tx.isComplete().should.equal(true);
|
|
||||||
|
|
||||||
b3 = TransactionBuilder.fromObj(b3.toObj());
|
|
||||||
b2.merge(b3);
|
|
||||||
b2.signaturesAdded.should.equal(3);
|
|
||||||
tx = b2.build();
|
|
||||||
tx.isComplete().should.equal(true);
|
|
||||||
|
|
||||||
var shex = testdata.dataUnspentSign.unspentP2sh[0].scriptPubKey;
|
|
||||||
var s = new Script(new Buffer(shex,'hex'));
|
|
||||||
tx.verifyInput(0,s, vopts, function(err, results){
|
|
||||||
should.exist(results);
|
|
||||||
results.should.equal(true);
|
|
||||||
should.not.exist(err);
|
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('#toObj #fromObj roundtrip, step signatures p2sh/p2pubkeyhash', function() {
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
|
||||||
|
var keys = JSON.parse(JSON.stringify(testdata.dataUnspentSign.keyStringsP2sh));
|
||||||
|
|
||||||
|
var k1 = keys.slice(0,1);
|
||||||
|
var k2 = keys.slice(1,2);
|
||||||
|
var k5 = keys.slice(4,5);
|
||||||
|
b.isFullySigned().should.equal(false);
|
||||||
|
|
||||||
|
var b2 = TransactionBuilder.fromObj(b.toObj());
|
||||||
|
|
||||||
|
b2.sign(k1);
|
||||||
|
b2.isFullySigned().should.equal(false);
|
||||||
|
|
||||||
|
var tx = b2.build();
|
||||||
|
tx.ins.length.should.equal(1);
|
||||||
|
tx.outs.length.should.equal(2);
|
||||||
|
tx.isComplete().should.equal(false);
|
||||||
|
|
||||||
|
// Sign with the same
|
||||||
|
var b3 = TransactionBuilder.fromObj(b2.toObj());
|
||||||
|
|
||||||
|
b3.sign(k1);
|
||||||
|
b3.isFullySigned().should.equal(false);
|
||||||
|
|
||||||
|
// Sign with k5
|
||||||
|
var b4 = TransactionBuilder.fromObj(b3.toObj());
|
||||||
|
b4.sign(k5);
|
||||||
|
b4.isFullySigned().should.equal(false);
|
||||||
|
|
||||||
|
var b5 = TransactionBuilder.fromObj(b4.toObj());
|
||||||
|
// Sign k2
|
||||||
|
b5.sign(k2);
|
||||||
|
b5.isFullySigned().should.equal(true);
|
||||||
|
var tx2 = b5.build();
|
||||||
|
tx2.isComplete().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should keep signatures after clone', function() {
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
|
||||||
|
b.sign([k1]);
|
||||||
|
b2.sign([k2]);
|
||||||
|
b2.merge(b);
|
||||||
|
var tx2 = b2.build();
|
||||||
|
tx2.countInputSignatures(0).should.equal(2, 'before clone');
|
||||||
|
tx2 = b2.clone().build();
|
||||||
|
tx2.countInputSignatures(0).should.equal(2, 'after clone');
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('#merge', function() {
|
||||||
|
it('with self', function() {
|
||||||
|
var b = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}])
|
||||||
|
.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
b.merge(b);
|
||||||
|
|
||||||
|
b.isFullySigned().should.equal(true);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.isComplete().should.equal(true);
|
||||||
|
tx.ins.length.should.equal(3);
|
||||||
|
tx.outs.length.should.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#merge simple', function() {
|
||||||
|
var b = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}])
|
||||||
|
.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
|
||||||
|
// merge simple
|
||||||
|
var b2 = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}]);
|
||||||
|
b2.isFullySigned().should.equal(false);
|
||||||
|
b2.merge(b);
|
||||||
|
|
||||||
|
b2.isFullySigned().should.equal(true);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.isComplete().should.equal(true);
|
||||||
|
tx.ins.length.should.equal(3);
|
||||||
|
tx.outs.length.should.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var b = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}]);
|
||||||
|
|
||||||
|
it('should check amount', function() {
|
||||||
|
// bad amount
|
||||||
|
var b2 = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 15
|
||||||
|
}]);
|
||||||
|
(function() {b2.merge(b);}).should.throw('NTXID');
|
||||||
|
});
|
||||||
|
it('should check addresses', function() {
|
||||||
|
// bad out
|
||||||
|
var b2 = getBuilder3([{
|
||||||
|
address: 'muHct3YZ9Nd5Pq7uLYYhXRAxeW4EnpcaLz',
|
||||||
|
amount: 16
|
||||||
|
}]);
|
||||||
|
(function() {b2.merge(b);}).should.throw('NTXID');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should check signhash in p2pubkeyhash', function() {
|
||||||
|
// bad amount
|
||||||
|
var b = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 15
|
||||||
|
}]);
|
||||||
|
b.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
|
||||||
|
var b2 = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 15
|
||||||
|
}], bitcore.Transaction.SIGHASH_NONE);
|
||||||
|
b2.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
|
||||||
|
(function() {b2.merge(b);}).should.throw('signhash');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should merge signed signed txs', function() {
|
||||||
|
// same signature
|
||||||
|
// -> keep first signature
|
||||||
|
var b = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}])
|
||||||
|
.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
// merge simple
|
||||||
|
var b2 = getBuilder3([{
|
||||||
|
address: 'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE',
|
||||||
|
amount: 16
|
||||||
|
}])
|
||||||
|
.sign(testdata.dataUnspentSign.keyStrings);
|
||||||
|
b2.isFullySigned().should.equal(true);
|
||||||
|
b2.merge(b);
|
||||||
|
b2.isFullySigned().should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('#merge p2sh in 2 steps', function() {
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
b.sign([k1]);
|
||||||
|
b2.sign([k2]);
|
||||||
|
b.merge(b2);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.countInputSignatures(0).should.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#merge p2sh in 2 steps, case 2', function() {
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
var k3 = testdata.dataUnspentSign.keyStringsP2sh[2];
|
||||||
|
b.sign([k1,k2]);
|
||||||
|
b2.sign([k3]);
|
||||||
|
b.merge(b2);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.countInputSignatures(0).should.equal(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('#merge p2sh sign twice', function() {
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
|
||||||
|
b.sign([k1]);
|
||||||
|
b2.sign([k1,k2]);
|
||||||
|
b2.merge(b);
|
||||||
|
var tx = b2.build();
|
||||||
|
tx.countInputSignatures(0).should.equal(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('#merge p2sh sign twice, case2', function() {
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
|
||||||
|
b.sign([k1]);
|
||||||
|
b2.sign([k1]);
|
||||||
|
b2.merge(b);
|
||||||
|
var tx = b2.build();
|
||||||
|
tx.countInputSignatures(0).should.equal(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
it('#merge p2sh in 3 steps', function() {
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh[0];
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh[1];
|
||||||
|
var k3 = testdata.dataUnspentSign.keyStringsP2sh[2];
|
||||||
|
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var b2 = getP2shBuilder(1);
|
||||||
|
var b3 = getP2shBuilder(1);
|
||||||
|
|
||||||
|
b.sign([k1]);
|
||||||
|
b2.sign([k2]);
|
||||||
|
b2.merge(b);
|
||||||
|
var tx = b2.clone().build();
|
||||||
|
tx.countInputSignatures(0).should.equal(2);
|
||||||
|
|
||||||
|
b3.sign([k3]);
|
||||||
|
b3.merge(b2);
|
||||||
|
tx = b3.build();
|
||||||
|
tx.countInputSignatures(0).should.equal(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it.only('should check signhash in p2sh/merge', function() {
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh.slice(0,1);
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
||||||
|
var k3 = testdata.dataUnspentSign.keyStringsP2sh.slice(2,3);
|
||||||
|
b.isFullySigned().should.equal(false);
|
||||||
|
b.sign(k1);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.isComplete().should.equal(false);
|
||||||
|
b = TransactionBuilder.fromObj(b.toObj());
|
||||||
|
|
||||||
|
var b2 = getP2shBuilder(1, {signhash: bitcore.Transaction.SIGHASH_NONE });
|
||||||
|
b2.sign(k2);
|
||||||
|
|
||||||
|
console.log('[test.TransactionBuilder.js.1124]'); //TODO
|
||||||
|
(function() { b2.merge(b)}).should.throw();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#merge p2sh/steps change return address', function() {
|
||||||
|
var b = getP2shBuilder(1);
|
||||||
|
var k1 = testdata.dataUnspentSign.keyStringsP2sh.slice(0,1);
|
||||||
|
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
|
||||||
|
var k3 = testdata.dataUnspentSign.keyStringsP2sh.slice(2,3);
|
||||||
|
b.isFullySigned().should.equal(false);
|
||||||
|
b.sign(k1);
|
||||||
|
var tx = b.build();
|
||||||
|
tx.isComplete().should.equal(false);
|
||||||
|
b = TransactionBuilder.fromObj(b.toObj());
|
||||||
|
|
||||||
|
var b2 = getP2shBuilder(1, {remainderOut: {address:'mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE' }});
|
||||||
|
b2.sign(k2);
|
||||||
|
(function() { b2.merge(b)}).should.throw('asdds');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user