mirror of https://github.com/BTCPrivate/copay.git
tx proposal test working with new bitcore Builder
This commit is contained in:
parent
7693f0a7ff
commit
85d02a6977
|
@ -13,7 +13,6 @@ function PrivateKey(opts) {
|
|||
this.network = opts.networkName === 'testnet' ?
|
||||
networks.testnet : networks.livenet;
|
||||
var init = opts.extendedPrivateKeyString || this.network.name;
|
||||
console.log('[PrivateKey.js.15:init:]',init); //TODO
|
||||
this.BIP32 = opts.BIP32 || new BIP32(init);
|
||||
this._calcId();
|
||||
};
|
||||
|
|
|
@ -14,9 +14,9 @@ var Storage = imports.Storage || require('./Storage');
|
|||
var storage = Storage.default();
|
||||
|
||||
function TxProposal(opts) {
|
||||
this.tx = opts.tx;
|
||||
this.seenBy = opts.seenBy || {};
|
||||
this.signedBy = opts.signedBy || {};
|
||||
this.builder = opts.builder;
|
||||
};
|
||||
module.exports = require('soop')(TxProposal);
|
||||
|
||||
|
@ -36,12 +36,10 @@ TxProposals.fromObj = function(o) {
|
|||
walletId: o.walletId,
|
||||
});
|
||||
o.txps.forEach(function(t) {
|
||||
var tx = new Transaction;
|
||||
tx.parse(new Buffer(t.txHex,'hex'));
|
||||
ret.txps.push({
|
||||
seenBy: t.seenBy,
|
||||
signedBy: t.signedBy,
|
||||
tx: tx,
|
||||
builder: new Builder.fromObj(t.builderObj),
|
||||
});
|
||||
});
|
||||
return ret;
|
||||
|
@ -54,7 +52,7 @@ TxProposals.prototype.toObj = function() {
|
|||
ret.push({
|
||||
seenBy: t.seenBy,
|
||||
signedBy: t.signedBy,
|
||||
txHex: t.tx.serialize(),
|
||||
builderObj: t.builder.toObj(),
|
||||
});
|
||||
});
|
||||
return {
|
||||
|
@ -68,7 +66,7 @@ TxProposals.prototype.toObj = function() {
|
|||
TxProposals.prototype._getNormHash = function(txps) {
|
||||
var ret = {};
|
||||
txps.forEach(function(txp) {
|
||||
var hash = txp.tx.getNormalizedHash().toString('hex');
|
||||
var hash = txp.builder.build().getNormalizedHash().toString('hex');
|
||||
ret[hash]=txp;
|
||||
});
|
||||
return ret;
|
||||
|
@ -126,107 +124,18 @@ TxProposals.prototype._mergeMetadata = function(myTxps, theirTxps, mergeInfo) {
|
|||
};
|
||||
|
||||
|
||||
TxProposals.prototype._chunkIsEmpty = function(chunk) {
|
||||
return chunk === 0 || // when serializing and back, EMPTY_BUFFER becomes 0
|
||||
buffertools.compare(chunk, util.EMPTY_BUFFER) === 0;
|
||||
};
|
||||
//
|
||||
// function d(s,l) {
|
||||
// console.log('DUMP'); //TODO
|
||||
// for (var i=0; i<l; i++) {
|
||||
// var k = s.chunks[i];
|
||||
// console.log("0:", i, Buffer.isBuffer(k)? k.toString('hex'):k);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
// this assumes that the same signature can not be v0 / v1 (which shouldnt be!)
|
||||
TxProposals.prototype._mergeInputSig = function(s0buf, s1buf) {
|
||||
if (buffertools.compare(s0buf,s1buf) === 0) {
|
||||
// console.log('BUFFERS .s MATCH'); //TODO
|
||||
return s0buf;
|
||||
}
|
||||
// Is multisig?
|
||||
var s0 = new Script(s0buf);
|
||||
var s1 = new Script(s1buf);
|
||||
var l0 = s0.chunks.length;
|
||||
var l1 = s1.chunks.length;
|
||||
var s0map = {};
|
||||
|
||||
if (l0 && l1 && l0 !== l1)
|
||||
throw new Error('TX sig types mismatch in merge');
|
||||
|
||||
if (l0) {
|
||||
for (var i=0; i<l0; i++) {
|
||||
if (!this._chunkIsEmpty(s0.chunks[i]))
|
||||
s0map[s0.chunks[i]] = 1;
|
||||
};
|
||||
|
||||
var diff = [];
|
||||
for (var i=0; i<l1; i++) {
|
||||
if ( !this._chunkIsEmpty(s1.chunks[i]) && !s0map[s1.chunks[i]]) {
|
||||
diff.push(s1.chunks[i]);
|
||||
}
|
||||
};
|
||||
|
||||
if (!diff) {
|
||||
console.log('[TxProposals.js.155] NO DIFF FOUND'); //TODO
|
||||
return s0.getBuffer();
|
||||
}
|
||||
|
||||
var emptySlots = [];
|
||||
for (var i=1; i<l0; i++) {
|
||||
if (this._chunkIsEmpty(s0.chunks[i])) {
|
||||
emptySlots.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (emptySlots.length<diff.length)
|
||||
throw new Error('no enough empty slots to merge Txs');
|
||||
|
||||
for (var i=0; i<diff.length; i++) {
|
||||
s0.chunks[emptySlots[i]] = diff[i];
|
||||
}
|
||||
s0.updateBuffer();
|
||||
return s0.getBuffer();
|
||||
}
|
||||
else {
|
||||
return s1.getBuffer();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TxProposals.prototype._mergeSignatures = function(myTxps, theirTxps, mergeInfo) {
|
||||
TxProposals.prototype._mergeBuilder = function(myTxps, theirTxps, mergeInfo) {
|
||||
var self = this;
|
||||
var toMerge = mergeInfo.toMerge;
|
||||
|
||||
Object.keys(toMerge).forEach(function(hash) {
|
||||
var v0 = myTxps[hash].tx;
|
||||
var v1 = toMerge[hash].tx;
|
||||
var v0 = myTxps[hash].builder;
|
||||
var v1 = toMerge[hash].builder;
|
||||
|
||||
var l = v0.ins.length;
|
||||
if (l !== v1.ins.length)
|
||||
throw new Error('TX in length mismatch in merge');
|
||||
|
||||
for(var i=0; i<l; i++) {
|
||||
var i0 = v0.ins[i];
|
||||
var i1 = v1.ins[i];
|
||||
|
||||
if (i0.q !== i1.q)
|
||||
throw new Error('TX sequence ins mismatch in merge. Input:',i);
|
||||
|
||||
if (buffertools.compare(i0.o,i1.o) !== 0)
|
||||
throw new Error('TX .o in mismatch in merge. Input:',i);
|
||||
|
||||
|
||||
i0.s=self._mergeInputSig(i0.s,i1.s);
|
||||
}
|
||||
v0.merge(v1);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
TxProposals.prototype.merge = function(t) {
|
||||
if (this.network.name !== t.network.name)
|
||||
throw new Error('network mismatch in:', t);
|
||||
|
@ -238,7 +147,7 @@ TxProposals.prototype.merge = function(t) {
|
|||
|
||||
var mergeInfo = this._startMerge(myTxps, theirTxps);
|
||||
this._mergeMetadata(myTxps, theirTxps, mergeInfo);
|
||||
this._mergeSignatures(myTxps, theirTxps, mergeInfo);
|
||||
this._mergeBuilder(myTxps, theirTxps, mergeInfo);
|
||||
|
||||
Object.keys(mergeInfo.toMerge).forEach(function(hash) {
|
||||
mergeInfo.ready.push(myTxps[hash]);
|
||||
|
@ -272,21 +181,17 @@ TxProposals.prototype.create = function(toAddress, amountSatStr, utxos, priv, op
|
|||
if (priv) {
|
||||
b.sign( priv.getAll(pkr.addressIndex, pkr.changeAddressIndex) );
|
||||
}
|
||||
|
||||
var tx = b.build();
|
||||
|
||||
var me = {};
|
||||
|
||||
if (priv) me[priv.id] = Date.now();
|
||||
|
||||
this.txps.push(
|
||||
new TxProposal({
|
||||
signedBy: priv && b.signaturesAdded ? me : {},
|
||||
seenBy: priv ? me : {},
|
||||
tx: tx,
|
||||
builder: b,
|
||||
})
|
||||
);
|
||||
return tx;
|
||||
return 1;
|
||||
};
|
||||
|
||||
TxProposals.prototype.sign = function(index) {
|
||||
|
|
|
@ -79,11 +79,12 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].address = w.publicKeyRing.getAddress(1, true).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
||||
|
||||
var tx = w.create(
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest
|
||||
);
|
||||
var tx = w.txps[0].builder.build();
|
||||
should.exist(tx);
|
||||
tx.isComplete().should.equal(false);
|
||||
Object.keys(w.txps[0].signedBy).length.should.equal(0);
|
||||
|
@ -103,12 +104,13 @@ describe('TxProposals model', function() {
|
|||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(1, true);
|
||||
|
||||
var priv = new PrivateKey(config);
|
||||
var tx = w.create(
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
var tx = w.txps[0].builder.build();
|
||||
should.exist(tx);
|
||||
tx.isComplete().should.equal(false);
|
||||
Object.keys(w.txps[0].signedBy).length.should.equal(0);
|
||||
|
@ -129,12 +131,13 @@ describe('TxProposals model', function() {
|
|||
for (var index=0; index<3; index++) {
|
||||
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
var tx = w.txps[0].builder.build();
|
||||
should.exist(tx);
|
||||
tx.isComplete().should.equal(false);
|
||||
|
||||
|
@ -159,13 +162,13 @@ describe('TxProposals model', function() {
|
|||
|
||||
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
|
||||
|
@ -210,8 +213,9 @@ describe('TxProposals model', function() {
|
|||
opts
|
||||
);
|
||||
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(1);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(1);
|
||||
|
||||
Object.keys(w.txps[0].signedBy).length.should.equal(0);
|
||||
Object.keys(w.txps[0].seenBy).length.should.equal(1);
|
||||
|
@ -231,8 +235,9 @@ describe('TxProposals model', function() {
|
|||
opts
|
||||
);
|
||||
|
||||
w2.txps[0].tx.isComplete().should.equal(false);
|
||||
w2.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
var tx = w2.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
|
||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
@ -240,8 +245,9 @@ describe('TxProposals model', function() {
|
|||
w.merge(w2);
|
||||
w.txps.length.should.equal(1);
|
||||
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
|
@ -280,8 +286,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
opts
|
||||
);
|
||||
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(1);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(1);
|
||||
|
||||
Object.keys(w.txps[0].signedBy).length.should.equal(0);
|
||||
Object.keys(w.txps[0].seenBy).length.should.equal(1);
|
||||
|
@ -300,16 +307,19 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
priv,
|
||||
opts
|
||||
);
|
||||
w2.txps[0].tx.isComplete().should.equal(false);
|
||||
w2.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
tx = w2.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
|
||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
w.merge(w2);
|
||||
w.txps.length.should.equal(1);
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
|
||||
tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
|
@ -327,8 +337,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
priv2,
|
||||
opts
|
||||
);
|
||||
w3.txps[0].tx.isComplete().should.equal(false);
|
||||
w3.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
tx = w3.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
|
||||
(w3.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||
(w3.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||
|
@ -341,8 +352,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
(w.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(1);
|
||||
tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(1);
|
||||
});
|
||||
|
||||
|
||||
|
@ -370,8 +382,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
priv,
|
||||
opts
|
||||
);
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
|
@ -389,8 +402,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
priv2,
|
||||
opts
|
||||
);
|
||||
w2.txps[0].tx.isComplete().should.equal(false);
|
||||
w2.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
var tx = w2.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w2.txps[0].signedBy[priv2.id] - ts > 0).should.equal(true);
|
||||
(w2.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||
|
||||
|
@ -408,15 +422,17 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
priv3,
|
||||
opts
|
||||
);
|
||||
w3.txps[0].tx.isComplete().should.equal(false);
|
||||
w3.txps[0].tx.countInputMissingSignatures(0).should.equal(2);
|
||||
var tx = w3.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w3.txps[0].signedBy[priv3.id] - ts > 0).should.equal(true);
|
||||
(w3.txps[0].seenBy[priv3.id] - ts > 0).should.equal(true);
|
||||
|
||||
w.merge(w2);
|
||||
w.txps.length.should.equal(1);
|
||||
w.txps[0].tx.isComplete().should.equal(false);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(1);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(1);
|
||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
@ -424,8 +440,9 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
|
||||
|
||||
w.merge(w3);
|
||||
w.txps[0].tx.isComplete().should.equal(true);
|
||||
w.txps[0].tx.countInputMissingSignatures(0).should.equal(0);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(true);
|
||||
tx.countInputMissingSignatures(0).should.equal(0);
|
||||
w.txps.length.should.equal(1);
|
||||
(w.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w.txps[0].seenBy[priv2.id] - ts > 0).should.equal(true);
|
||||
|
@ -451,12 +468,13 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
|
||||
unspentTest[0].address = w.publicKeyRing.getAddress(index, isChange).toString();
|
||||
unspentTest[0].scriptPubKey = w.publicKeyRing.getScriptPubKeyHex(index, isChange);
|
||||
var tx = w.create(
|
||||
w.create(
|
||||
'15q6HKjWHAksHcH91JW23BJEuzZgFwydBt',
|
||||
'123456789',
|
||||
unspentTest,
|
||||
priv
|
||||
);
|
||||
var tx = w.txps[0].builder.build();
|
||||
tx.isComplete().should.equal(false);
|
||||
tx.countInputMissingSignatures(0).should.equal(2);
|
||||
(w.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
@ -465,19 +483,23 @@ var _dumpChunks = function (scriptSig, label) {
|
|||
var o = w.toObj();
|
||||
should.exist(o);
|
||||
o.txps.length.should.equal(1);
|
||||
should.exist(o.txps[0].txHex);
|
||||
should.exist(o.txps[0]);
|
||||
should.exist(o.txps[0].signedBy);
|
||||
should.exist(o.txps[0].seenBy);
|
||||
should.exist(o.txps[0].builderObj);
|
||||
should.exist(o.txps[0].builderObj.valueInSat);
|
||||
should.exist(o.txps[0].signedBy[priv.id]);
|
||||
|
||||
var w2 = TxProposals.fromObj(o);
|
||||
w2.walletId.should.equal(w.walletId);
|
||||
var tx2 = w2.txps[0].tx;
|
||||
var tx2 = w2.txps[0].builder.build();
|
||||
tx2.isComplete().should.equal(false);
|
||||
tx2.countInputMissingSignatures(0).should.equal(2);
|
||||
(w2.txps[0].signedBy[priv.id] - ts > 0).should.equal(true);
|
||||
(w2.txps[0].seenBy[priv.id] - ts > 0).should.equal(true);
|
||||
|
||||
should.exist(w2.txps[0].builder);
|
||||
should.exist(w2.txps[0].builder.valueInSat);
|
||||
|
||||
w2.merge(w);
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue