2014-04-09 13:28:35 -07:00
|
|
|
'use strict';
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var chai = chai || require('chai');
|
|
|
|
var should = chai.should();
|
|
|
|
var bitcore = bitcore || require('bitcore');
|
|
|
|
var Transaction = bitcore.Transaction;
|
|
|
|
var buffertools = bitcore.buffertools;
|
|
|
|
var WalletKey = bitcore.WalletKey;
|
|
|
|
var Key = bitcore.Key;
|
2014-06-17 09:39:41 -07:00
|
|
|
var bignum = bitcore.Bignum;
|
2014-06-10 06:39:57 -07:00
|
|
|
var Script = bitcore.Script;
|
|
|
|
var Builder = bitcore.TransactionBuilder;
|
|
|
|
var util = bitcore.util;
|
|
|
|
var networks = bitcore.networks;
|
2014-06-15 20:55:23 -07:00
|
|
|
try {
|
|
|
|
var copay = require('copay'); //browser
|
|
|
|
} catch (e) {
|
|
|
|
var copay = require('../copay'); //node
|
|
|
|
}
|
2014-06-10 06:39:57 -07:00
|
|
|
var fakeStorage = copay.FakeStorage;
|
|
|
|
var PrivateKey = copay.PrivateKey || require('../js/models/PrivateKey');
|
|
|
|
var TxProposals = copay.TxProposals || require('../js/models/TxProposal');
|
2014-06-17 09:39:41 -07:00
|
|
|
var is_browser = (typeof process == 'undefined' || typeof process.versions === 'undefined')
|
2014-06-10 06:39:57 -07:00
|
|
|
var PublicKeyRing = is_browser ? copay.PublicKeyRing :
|
|
|
|
require('soop').load('../js/models/core/PublicKeyRing', {
|
|
|
|
Storage: fakeStorage
|
|
|
|
});
|
2014-04-09 13:28:35 -07:00
|
|
|
|
|
|
|
var config = {
|
2014-06-11 07:22:48 -07:00
|
|
|
networkName: 'testnet',
|
2014-04-09 13:28:35 -07:00
|
|
|
};
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var unspentTest = [{
|
|
|
|
"address": "dummy",
|
|
|
|
"scriptPubKey": "dummy",
|
|
|
|
"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1",
|
|
|
|
"vout": 1,
|
|
|
|
"amount": 10,
|
|
|
|
"confirmations": 7
|
|
|
|
}];
|
2014-04-09 13:28:35 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var createPKR = function(bip32s) {
|
2014-04-09 13:28:35 -07:00
|
|
|
var w = new PublicKeyRing(config);
|
|
|
|
should.exist(w);
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
for (var i = 0; i < 5; i++) {
|
2014-06-11 07:22:48 -07:00
|
|
|
if (bip32s && i < bip32s.length) {
|
2014-06-10 06:39:57 -07:00
|
|
|
var b = bip32s[i];
|
2014-06-11 07:22:48 -07:00
|
|
|
w.addCopayer(b.deriveBIP45Branch().extendedPublicKeyString());
|
|
|
|
} else {
|
2014-04-09 13:28:35 -07:00
|
|
|
w.addCopayer();
|
2014-06-11 07:22:48 -07:00
|
|
|
}
|
2014-04-09 13:28:35 -07:00
|
|
|
}
|
2014-07-03 07:18:01 -07:00
|
|
|
|
|
|
|
var pubkey = bip32s[0].publicHex;
|
|
|
|
|
|
|
|
w.generateAddress(false, pubkey);
|
|
|
|
w.generateAddress(false, pubkey);
|
|
|
|
w.generateAddress(false, pubkey);
|
|
|
|
w.generateAddress(true, pubkey);
|
|
|
|
w.generateAddress(true, pubkey);
|
|
|
|
w.generateAddress(true, pubkey);
|
2014-06-12 10:34:32 -07:00
|
|
|
|
2014-04-09 13:28:35 -07:00
|
|
|
return w;
|
|
|
|
};
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var vopts = {
|
2014-04-21 16:28:57 -07:00
|
|
|
verifyP2SH: true,
|
|
|
|
dontVerifyStrictEnc: true
|
|
|
|
};
|
|
|
|
|
2014-04-09 13:28:35 -07:00
|
|
|
|
|
|
|
describe('TxProposals model', function() {
|
|
|
|
|
2014-06-24 10:40:03 -07:00
|
|
|
var isChange = false;
|
|
|
|
var index = 0;
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('verify TXs', function(done) {
|
2014-04-21 16:28:57 -07:00
|
|
|
|
|
|
|
var priv = new PrivateKey(config);
|
|
|
|
var priv2 = new PrivateKey(config);
|
|
|
|
var priv3 = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
2014-05-29 12:17:17 -07:00
|
|
|
var ts = Date.now();
|
2014-06-10 06:39:57 -07:00
|
|
|
var pkr = createPKR([priv, priv2, priv3]);
|
|
|
|
var opts = {
|
|
|
|
remainderOut: {
|
2014-07-03 07:18:01 -07:00
|
|
|
address: pkr.generateAddress(true, pub).toString()
|
2014-06-10 06:39:57 -07:00
|
|
|
}
|
|
|
|
};
|
2014-04-21 16:28:57 -07:00
|
|
|
|
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
|
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-21 16:28:57 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-21 16:28:57 -07:00
|
|
|
unspentTest,
|
|
|
|
opts,
|
|
|
|
priv,
|
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var b = w.txps[ntxid].builder;
|
2014-04-21 16:28:57 -07:00
|
|
|
var tx = b.build();
|
|
|
|
tx.isComplete().should.equal(false);
|
2014-07-03 07:18:01 -07:00
|
|
|
|
|
|
|
var ringIndex = pkr.getIndex(pub);
|
|
|
|
b.sign(priv2.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner));
|
|
|
|
b.sign(priv3.getAll(ringIndex.getReceiveIndex(), ringIndex.getChangeIndex(), ringIndex.cosigner));
|
2014-04-21 16:28:57 -07:00
|
|
|
tx = b.build();
|
|
|
|
tx.isComplete().should.equal(true);
|
|
|
|
|
2014-06-17 09:39:41 -07:00
|
|
|
var s = new Script(new bitcore.Buffer(unspentTest[0].scriptPubKey, 'hex'));
|
2014-04-21 16:28:57 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
tx.verifyInput(0, s, {
|
2014-04-21 16:28:57 -07:00
|
|
|
verifyP2SH: true,
|
|
|
|
dontVerifyStrictEnc: true
|
2014-06-10 06:39:57 -07:00
|
|
|
}, function(err, results) {
|
|
|
|
should.not.exist(err);
|
|
|
|
results.should.equal(true);
|
2014-04-21 16:28:57 -07:00
|
|
|
done();
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
|
|
|
|
it('should create an instance', function() {
|
2014-04-09 13:28:35 -07:00
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName
|
|
|
|
});
|
|
|
|
should.exist(w);
|
2014-06-12 10:34:32 -07:00
|
|
|
w.network.name.should.equal(config.networkName);
|
2014-04-09 13:28:35 -07:00
|
|
|
});
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var createTx = function(toAddress, amountSatStr, utxos, opts, priv, pkr) {
|
2014-04-15 14:23:35 -07:00
|
|
|
opts = opts || {};
|
2014-04-09 13:28:35 -07:00
|
|
|
|
2014-06-15 20:55:23 -07:00
|
|
|
var amountSat = bitcore.Bignum(amountSatStr);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
2014-04-09 13:28:35 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
if (!pkr.isComplete()) {
|
2014-04-15 14:23:35 -07:00
|
|
|
throw new Error('publicKeyRing is not complete');
|
|
|
|
}
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-04-15 14:23:35 -07:00
|
|
|
if (!opts.remainderOut) {
|
2014-06-10 06:39:57 -07:00
|
|
|
opts.remainderOut = {
|
2014-07-03 07:18:01 -07:00
|
|
|
address: pkr.generateAddress(true, pub).toString()
|
2014-06-10 06:39:57 -07:00
|
|
|
};
|
2014-04-15 14:23:35 -07:00
|
|
|
};
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-04-15 14:23:35 -07:00
|
|
|
var b = new Builder(opts)
|
2014-06-10 06:39:57 -07:00
|
|
|
.setUnspent(utxos)
|
|
|
|
.setOutputs([{
|
|
|
|
address: toAddress,
|
|
|
|
amountSat: amountSat
|
|
|
|
}]);
|
2014-06-18 14:39:29 -07:00
|
|
|
var selectedUtxos = b.getSelectedUnspent();
|
|
|
|
var inputChainPaths = selectedUtxos.map(function(utxo) {
|
|
|
|
return pkr.pathForAddress(utxo.address);
|
|
|
|
});
|
2014-06-10 06:39:57 -07:00
|
|
|
|
2014-06-24 09:17:22 -07:00
|
|
|
var selectedUtxos = b.getSelectedUnspent();
|
|
|
|
var inputChainPaths = selectedUtxos.map(function(utxo) {
|
|
|
|
return pkr.pathForAddress(utxo.address);
|
|
|
|
});
|
|
|
|
b.setHashToScriptMap(pkr.getRedeemScriptMap(inputChainPaths));
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var signRet;
|
2014-04-15 14:23:35 -07:00
|
|
|
if (priv) {
|
2014-06-18 14:39:29 -07:00
|
|
|
var pkeys = priv.getForPaths(inputChainPaths);
|
2014-06-12 10:27:53 -07:00
|
|
|
b.sign(pkeys);
|
2014-04-15 14:23:35 -07:00
|
|
|
}
|
|
|
|
var me = {};
|
2014-06-18 14:39:29 -07:00
|
|
|
if (priv) me[priv.getId()] = Date.now();
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-04-15 14:23:35 -07:00
|
|
|
return {
|
2014-06-18 14:39:29 -07:00
|
|
|
inputChainPaths: inputChainPaths,
|
|
|
|
creator: priv.getId(),
|
|
|
|
createdTs: new Date(),
|
2014-04-15 14:23:35 -07:00
|
|
|
signedBy: priv && b.signaturesAdded ? me : {},
|
2014-06-10 06:39:57 -07:00
|
|
|
seenBy: priv ? me : {},
|
2014-04-15 14:23:35 -07:00
|
|
|
builder: b,
|
|
|
|
};
|
|
|
|
};
|
2014-04-09 13:28:35 -07:00
|
|
|
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('#getUsedUnspend', function() {
|
2014-04-21 08:00:14 -07:00
|
|
|
var priv = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
2014-04-21 08:00:14 -07:00
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
|
|
|
var start = new Date().getTime();
|
2014-06-10 06:39:57 -07:00
|
|
|
var pkr = createPKR([priv]);
|
2014-04-21 08:00:14 -07:00
|
|
|
var ts = Date.now();
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-21 08:00:14 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
|
|
|
unspentTest, {},
|
2014-04-21 08:00:14 -07:00
|
|
|
priv,
|
|
|
|
pkr
|
|
|
|
));
|
2014-06-05 11:43:43 -07:00
|
|
|
var uu = w.getUsedUnspent();
|
|
|
|
var uuk = Object.keys(uu);
|
|
|
|
uuk.length.should.equal(1);
|
|
|
|
uuk[0].split(',')[0].should.equal(unspentTest[0].txid);
|
2014-04-21 08:00:14 -07:00
|
|
|
});
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('#merge with self', function() {
|
2014-04-10 21:09:42 -07:00
|
|
|
var priv = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
2014-04-10 21:09:42 -07:00
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-04-17 11:04:39 -07:00
|
|
|
var start = new Date().getTime();
|
2014-06-10 06:39:57 -07:00
|
|
|
var pkr = createPKR([priv]);
|
2014-04-10 21:09:42 -07:00
|
|
|
var ts = Date.now();
|
|
|
|
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
|
|
|
unspentTest, {},
|
2014-04-15 14:23:35 -07:00
|
|
|
priv,
|
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-10 21:09:42 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
|
|
|
|
2014-06-18 14:39:29 -07:00
|
|
|
var x = priv.getId();
|
|
|
|
(w.txps[ntxid].signedBy[priv.getId()] - ts > 0).should.equal(true);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 14:39:29 -07:00
|
|
|
var info = w.merge(w.txps[ntxid], pkr.getCopayerId(0));
|
2014-06-13 13:24:44 -07:00
|
|
|
info.events.length.should.equal(0);
|
|
|
|
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w.txps).length.should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('#merge, merge signatures case 1', function() {
|
2014-04-10 21:09:42 -07:00
|
|
|
var priv2 = new PrivateKey(config);
|
|
|
|
var priv = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
2014-04-10 21:09:42 -07:00
|
|
|
var ts = Date.now();
|
2014-04-17 13:01:31 -07:00
|
|
|
var pkr = createPKR([priv]);
|
2014-06-10 06:39:57 -07:00
|
|
|
var opts = {
|
|
|
|
remainderOut: {
|
2014-07-03 07:18:01 -07:00
|
|
|
address: pkr.generateAddress(true, pub).toString()
|
2014-06-10 06:39:57 -07:00
|
|
|
}
|
|
|
|
};
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv2,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
Object.keys(w.txps[ntxid].signedBy).length.should.equal(0);
|
|
|
|
Object.keys(w.txps[ntxid].seenBy).length.should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
var w2 = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
publicKeyRing: w.publicKeyRing,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w2.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var tx = w2.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
(w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 14:39:29 -07:00
|
|
|
var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0));
|
2014-06-19 07:28:50 -07:00
|
|
|
info.events.length.should.equal(2);
|
|
|
|
info.events[0].type.should.equal('seen');
|
|
|
|
info.events[1].type.should.equal('signed');
|
2014-06-13 13:24:44 -07:00
|
|
|
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w.txps).length.should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-06-10 06:39:57 -07:00
|
|
|
|
2014-04-10 21:09:42 -07:00
|
|
|
});
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var _dumpChunks = function(scriptSig, label) {
|
|
|
|
console.log('## DUMP: ' + label + ' ##');
|
|
|
|
for (var i = 0; i < scriptSig.chunks.length; i++) {
|
|
|
|
console.log('\tCHUNK ', i, scriptSig.chunks[i]);
|
|
|
|
}
|
|
|
|
};
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
it('#merge, merge signatures case 2', function() {
|
|
|
|
|
2014-06-16 08:44:18 -07:00
|
|
|
var o1 = {
|
|
|
|
extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdSF1avR6mXyDj5Uv1XY2UyUHSDpAXQ5TvPN7prGeDppjy4562rBB9gMMAhRfFdJrNDpQ4t69kkqHNEEen3PX1zBJqSehJDH',
|
|
|
|
networkName: 'testnet',
|
|
|
|
privateKeyCache: {}
|
|
|
|
};
|
|
|
|
var o2 = {
|
|
|
|
extendedPrivateKeyString: 'tprv8ZgxMBicQKsPdVeB5RzuxS9JQcACueZYgUaM5eWzaEBkHjW5Pg6Mqez1APSqoUP1jUdbT8WVG7ZJYTXvUL7XtPzFYBXjmdKuwSor1dcNQ8j',
|
|
|
|
networkName: 'testnet',
|
|
|
|
privateKeyCache: {}
|
|
|
|
};
|
|
|
|
var o3 = {
|
|
|
|
extendedPrivateKeyString: 'tprv8ZgxMBicQKsPeHWNrPVZtQVgcCtXBr5TACNbDQ56rwqNJce9MEc64US6DJKxpWsrebEomxxWZFDtkvkZGkzA43uLvdF4XHiWqoNaL6Dq2Gd',
|
|
|
|
networkName: 'testnet',
|
|
|
|
privateKeyCache: {}
|
|
|
|
};
|
2014-06-12 10:27:53 -07:00
|
|
|
|
|
|
|
|
|
|
|
var priv = PrivateKey.fromObj(o1);
|
|
|
|
var priv2 = PrivateKey.fromObj(o2);
|
|
|
|
var priv3 = PrivateKey.fromObj(o3);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var ts = Date.now();
|
2014-04-17 13:01:31 -07:00
|
|
|
var pkr = createPKR([priv, priv2]);
|
2014-06-10 06:39:57 -07:00
|
|
|
var opts = {
|
|
|
|
remainderOut: {
|
2014-06-11 07:22:48 -07:00
|
|
|
address: '2MxK2m7cPtEwjZBB8Ksq7ppjkgJyFPJGemr'
|
2014-06-10 06:39:57 -07:00
|
|
|
}
|
|
|
|
};
|
2014-07-03 07:18:01 -07:00
|
|
|
var addressToSign = pkr.generateAddress(false, pub);
|
2014-06-11 07:22:48 -07:00
|
|
|
unspentTest[0].address = addressToSign.toString();
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-06-11 07:22:48 -07:00
|
|
|
var tx, txb;
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-04-15 14:23:35 -07:00
|
|
|
|
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv3,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
2014-06-11 07:22:48 -07:00
|
|
|
txb = w.txps[ntxid].builder;
|
|
|
|
txb.signaturesAdded.should.equal(0);
|
|
|
|
tx = txb.build();
|
|
|
|
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
Object.keys(w.txps[ntxid].signedBy).length.should.equal(0);
|
|
|
|
Object.keys(w.txps[ntxid].seenBy).length.should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
var w2 = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-04-15 14:23:35 -07:00
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
|
|
|
|
|
2014-04-15 14:23:35 -07:00
|
|
|
w2.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-06-11 07:22:48 -07:00
|
|
|
var ntxid = Object.keys(w2.txps)[0];
|
|
|
|
txb = w2.txps[ntxid].builder;
|
|
|
|
tx = txb.build();
|
|
|
|
|
|
|
|
txb.signaturesAdded.should.equal(1);
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-11 07:22:48 -07:00
|
|
|
(w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-18 14:39:29 -07:00
|
|
|
var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(0));
|
2014-06-19 07:28:50 -07:00
|
|
|
info.events.length.should.equal(2);
|
|
|
|
info.events[0].type.should.equal('seen');
|
|
|
|
info.events[1].type.should.equal('signed');
|
2014-04-13 07:00:58 -07:00
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-12 10:27:53 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
var w3 = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
publicKeyRing: pkr,
|
|
|
|
});
|
2014-04-15 14:23:35 -07:00
|
|
|
w3.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv2,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-06-12 10:27:53 -07:00
|
|
|
tx = w3.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
(w3.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w3.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-19 07:28:50 -07:00
|
|
|
var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(1));
|
2014-06-13 13:24:44 -07:00
|
|
|
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w.txps).length.should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-12 10:27:53 -07:00
|
|
|
tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(1);
|
2014-04-10 21:09:42 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('#merge, merge signatures case 3', function() {
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
var priv = new PrivateKey(config);
|
|
|
|
var priv2 = new PrivateKey(config);
|
|
|
|
var priv3 = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
var ts = Date.now();
|
|
|
|
var pkr = createPKR([priv, priv2, priv3]);
|
|
|
|
var opts = {
|
|
|
|
remainderOut: {
|
2014-07-03 07:18:01 -07:00
|
|
|
address: pkr.generateAddress(true, pub).toString()
|
2014-06-10 06:39:57 -07:00
|
|
|
}
|
|
|
|
};
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
var w = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
var w2 = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w2.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv2,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx = w2.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w2.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w2.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
var w3 = new TxProposals({
|
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w3.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
2014-04-10 21:09:42 -07:00
|
|
|
unspentTest,
|
2014-04-15 14:23:35 -07:00
|
|
|
opts,
|
2014-04-10 21:09:42 -07:00
|
|
|
priv3,
|
2014-04-15 14:23:35 -07:00
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx = w3.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w3.txps[ntxid].signedBy[priv3.id] - ts > 0).should.equal(true);
|
|
|
|
(w3.txps[ntxid].seenBy[priv3.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
2014-06-19 07:28:50 -07:00
|
|
|
var info = w.merge(w2.txps[ntxid], pkr.getCopayerId(1));
|
2014-06-13 13:24:44 -07:00
|
|
|
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w.txps).length.should.equal(1);
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(1);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
|
|
|
|
|
2014-06-19 07:28:50 -07:00
|
|
|
var info = w.merge(w3.txps[ntxid], pkr.getCopayerId(2));
|
2014-06-13 13:24:44 -07:00
|
|
|
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-13 07:00:58 -07:00
|
|
|
tx.isComplete().should.equal(true);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(0);
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w.txps).length.should.equal(1);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv3.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv2.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].signedBy[priv3.id] - ts > 0).should.equal(true);
|
2014-04-10 21:09:42 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-10 06:39:57 -07:00
|
|
|
it('#toObj #fromObj roundtrip', function() {
|
2014-04-09 19:04:22 -07:00
|
|
|
|
|
|
|
var priv = new PrivateKey(config);
|
2014-07-03 07:18:01 -07:00
|
|
|
var pub = priv.publicHex;
|
|
|
|
|
2014-04-17 13:01:31 -07:00
|
|
|
var pkr = createPKR([priv]);
|
2014-04-09 19:04:22 -07:00
|
|
|
var w = new TxProposals({
|
2014-04-11 09:26:36 -07:00
|
|
|
walletId: 'qwerty',
|
2014-04-09 19:04:22 -07:00
|
|
|
networkName: config.networkName,
|
|
|
|
});
|
2014-04-09 22:16:57 -07:00
|
|
|
var ts = Date.now();
|
2014-04-09 13:28:35 -07:00
|
|
|
|
2014-07-03 07:18:01 -07:00
|
|
|
unspentTest[0].address = pkr.getAddress(index, isChange, pub).toString();
|
|
|
|
unspentTest[0].scriptPubKey = pkr.getScriptPubKeyHex(index, isChange, pub);
|
2014-04-15 14:23:35 -07:00
|
|
|
w.add(createTx(
|
2014-06-10 06:39:57 -07:00
|
|
|
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
|
|
|
'123456789',
|
|
|
|
unspentTest, {},
|
2014-04-15 14:23:35 -07:00
|
|
|
priv,
|
|
|
|
pkr
|
|
|
|
));
|
2014-06-18 05:07:32 -07:00
|
|
|
var ntxid = Object.keys(w.txps)[0];
|
|
|
|
var tx = w.txps[ntxid].builder.build();
|
2014-04-09 22:16:57 -07:00
|
|
|
tx.isComplete().should.equal(false);
|
|
|
|
tx.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
2014-04-09 22:16:57 -07:00
|
|
|
|
|
|
|
var o = w.toObj();
|
|
|
|
should.exist(o);
|
2014-04-10 21:09:42 -07:00
|
|
|
o.txps.length.should.equal(1);
|
2014-04-13 07:00:58 -07:00
|
|
|
should.exist(o.txps[0]);
|
2014-04-10 21:09:42 -07:00
|
|
|
should.exist(o.txps[0].signedBy);
|
|
|
|
should.exist(o.txps[0].seenBy);
|
2014-04-13 07:00:58 -07:00
|
|
|
should.exist(o.txps[0].builderObj);
|
|
|
|
should.exist(o.txps[0].builderObj.valueInSat);
|
2014-04-10 21:09:42 -07:00
|
|
|
should.exist(o.txps[0].signedBy[priv.id]);
|
2014-04-09 22:16:57 -07:00
|
|
|
|
2014-04-18 15:28:28 -07:00
|
|
|
var o2 = JSON.parse(JSON.stringify(o));
|
|
|
|
var w2 = TxProposals.fromObj(o2);
|
2014-04-11 09:26:36 -07:00
|
|
|
w2.walletId.should.equal(w.walletId);
|
2014-06-18 05:07:32 -07:00
|
|
|
var tx2 = w2.txps[ntxid].builder.build();
|
2014-04-09 22:16:57 -07:00
|
|
|
tx2.isComplete().should.equal(false);
|
|
|
|
tx2.countInputMissingSignatures(0).should.equal(2);
|
2014-06-18 05:07:32 -07:00
|
|
|
(w2.txps[ntxid].signedBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
(w2.txps[ntxid].seenBy[priv.id] - ts > 0).should.equal(true);
|
|
|
|
should.exist(w2.txps[ntxid].builder);
|
|
|
|
should.exist(w2.txps[ntxid].builder.valueInSat);
|
2014-06-10 06:39:57 -07:00
|
|
|
|
2014-06-18 14:39:29 -07:00
|
|
|
w2.merge(w.txps[ntxid], pkr.getCopayerId(0));
|
2014-04-18 15:28:28 -07:00
|
|
|
Object.keys(w2.txps).length.should.equal(1);
|
2014-04-09 13:28:35 -07:00
|
|
|
});
|
2014-04-21 16:28:57 -07:00
|
|
|
|
|
|
|
|
2014-04-09 13:28:35 -07:00
|
|
|
});
|