From 84505e49a74ba43a28ea632e0e27bd1df653ba48 Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Tue, 21 Feb 2017 11:23:44 +0100 Subject: [PATCH] Checking that locktime works --- test/integration/crosschain-test.js | 65 ++++++++++++++++++++--------- test/integration/tools/unit.js | 5 ++- 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/test/integration/crosschain-test.js b/test/integration/crosschain-test.js index 2f0861781..c7d419702 100644 --- a/test/integration/crosschain-test.js +++ b/test/integration/crosschain-test.js @@ -12,9 +12,13 @@ const user = require('./tools/user'); const unit = require('./tools/unit'); const httpTest = require('./tools/http'); +/** + * Test Crosschain algorithm described at https://en.bitcoin.it/wiki/Atomic_cross-chain_trading + */ + describe("Crosschain transactions", function() { - const now = Math.round(Date.now() / 1000); + const now = 1487000000; const MEMORY_MODE = true; const commonConf = { @@ -91,7 +95,7 @@ describe("Crosschain transactions", function() { // We submit it to the network yield ticM.sendTX(mtx0); // Written - yield commit(sM)(); + yield commit(sM)({ time: now + 10 }); }) ); @@ -116,27 +120,35 @@ describe("Crosschain transactions", function() { // 1. toc secretely chooses X password let btx1 = yield tocB.prepareUTX(btx0, ['SIG(0)'], [{ qty: 120, base: 0, lock: '(XHX(8AFC8DF633FC158F9DB4864ABED696C1AA0FE5D617A7B5F7AB8DE7CA2EFCD4CB) && SIG(' + ticB.pub + ')) || (SIG(' + tocB.pub + ') && SIG(' + ticB.pub + '))' }], { comment: 'BETA toc to tic', blockstamp: blockstampB }); // 2. toc makes a rollback transaction from tx1, signed by both parties (through internet): toc and tic - let btx2 = yield tocB.prepareMTX(btx1, ticB, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB in 48h', locktime: 0, blockstamp: blockstampB }); // N.B.: locktime should be like 48h in real world + let btx2 = yield tocB.prepareMTX(btx1, ticB, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB in 48h', locktime: 3600*48, blockstamp: blockstampB }); // N.B.: locktime should be like 48h in real world // TICM side (META) // 3. tic generates a transaction based on H(X) given by toc (through internet) let mtx3 = yield ticM.prepareUTX(mtx0, ['SIG(0)'], [{ qty: 120, base: 0, lock: '(XHX(8AFC8DF633FC158F9DB4864ABED696C1AA0FE5D617A7B5F7AB8DE7CA2EFCD4CB) && SIG(' + tocM.pub + ')) || (SIG(' + ticM.pub + ') && SIG(' + tocM.pub + '))' }], { comment: 'META tic to toc', blockstamp: blockstampM }); // 4. tic makes a rollback transaction from tx1, signed by both parties: toc and tic - let mtx4 = yield ticM.prepareMTX(mtx3, tocM, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB', locktime: 0, blockstamp: blockstampM }); // N.B.: locktime should be like 24h in real world + let mtx4 = yield ticM.prepareMTX(mtx3, tocM, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB', locktime: 3600*24, blockstamp: blockstampM }); // N.B.: locktime should be like 24h in real world // We submit TX1 to the network & write it yield tocB.sendTX(btx1); // Written - yield commit(sB)(); + yield commit(sB)({ time: now + 10 }); // We submit TX3 to the network & write it yield ticM.sendTX(mtx3); // Written - yield commit(sM)(); + yield commit(sM)({ time: now + 10 }); /** * So now ... parties can either COMMIT or ROLLBACK. It's UP to the initiator: TOC. - * + */ + + /** + * Note: the ROLLBACK transactions have a locktime, and cannot be used before that delay. + */ + yield unit.shouldFail(ticM.sendTX(mtx4), 'Locktime not elapsed yet'); + yield unit.shouldFail(tocB.sendTX(btx2), 'Locktime not elapsed yet'); + + /** * Let's say TOC agrees & and start COMMIT. */ @@ -249,7 +261,7 @@ describe("Crosschain transactions", function() { // We submit it to the network yield tocB.sendTX(btx0); // Written - yield commit(sB)(); + yield commit(sB)({ time: now + 10 }); // Initialize META yield ticM.createIdentity(); @@ -266,7 +278,7 @@ describe("Crosschain transactions", function() { // We submit it to the network yield ticM.sendTX(mtx0); // Written - yield commit(sM)(); + yield commit(sM)({ time: now + 10 }); }); }); @@ -291,23 +303,23 @@ describe("Crosschain transactions", function() { // 1. toc secretely chooses X password let btx1 = yield tocB.prepareUTX(btx0, ['SIG(0)'], [{ qty: 120, base: 0, lock: '(XHX(8AFC8DF633FC158F9DB4864ABED696C1AA0FE5D617A7B5F7AB8DE7CA2EFCD4CB) && SIG(' + ticB.pub + ')) || (SIG(' + tocB.pub + ') && SIG(' + ticB.pub + '))' }], { comment: 'BETA toc to tic', blockstamp: blockstampB }); // 2. toc makes a rollback transaction from tx1, signed by both parties (through internet): toc and tic - let btx2 = yield tocB.prepareMTX(btx1, ticB, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB in 48h', locktime: 0, blockstamp: blockstampB }); // N.B.: locktime should be like 48h in real world + let btx2 = yield tocB.prepareMTX(btx1, ticB, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + tocB.pub + ')' }], { comment: 'money back to tocB in 48h', locktime: 3, blockstamp: blockstampB }); // N.B.: locktime should be like 48h in real world // TICM side (META) // 3. tic generates a transaction based on H(X) given by toc (through internet) let mtx3 = yield ticM.prepareUTX(mtx0, ['SIG(0)'], [{ qty: 120, base: 0, lock: '(XHX(8AFC8DF633FC158F9DB4864ABED696C1AA0FE5D617A7B5F7AB8DE7CA2EFCD4CB) && SIG(' + tocM.pub + ')) || (SIG(' + ticM.pub + ') && SIG(' + tocM.pub + '))' }], { comment: 'META tic to toc', blockstamp: blockstampM }); // 4. tic makes a rollback transaction from tx1, signed by both parties: toc and tic - let mtx4 = yield ticM.prepareMTX(mtx3, tocM, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + ticM.pub + ')' }], { comment: 'money back to ticM', locktime: 0, blockstamp: blockstampM }); // N.B.: locktime should be like 24h in real world + let mtx4 = yield ticM.prepareMTX(mtx3, tocM, ['XHX(0) SIG(1) SIG(0) SIG(1)'], [{ qty: 120, base: 0, lock: 'SIG(' + ticM.pub + ')' }], { comment: 'money back to ticM', locktime: 2, blockstamp: blockstampM }); // N.B.: locktime should be like 24h in real world // We submit TX1 to the network & write it yield tocB.sendTX(btx1); // Written - yield commit(sB)(); + yield commit(sB)({ time: now + 12 }); // We submit TX3 to the network & write it yield ticM.sendTX(mtx3); // Written - yield commit(sM)(); + yield commit(sM)({ time: now + 12 }); /** * So now ... parties can either COMMIT or ROLLBACK. It's UP to the initiator: TOC. @@ -315,12 +327,27 @@ describe("Crosschain transactions", function() { * Let's say TOC wants to stop and ROLLBACK. */ - yield unit.shouldNotFail(tocB.sendTX(btx2)); - // Written - yield commit(sB)(); - yield unit.shouldNotFail(ticM.sendTX(mtx4)); - // Written - yield commit(sM)(); + /** + * Note: the ROLLBACK transactions have a locktime, and cannot be used before that delay. + */ + yield unit.shouldFail(ticM.sendTX(mtx4), 'Locktime not elapsed yet'); + yield unit.shouldFail(tocB.sendTX(btx2), 'Locktime not elapsed yet'); + + // Increment the medianTime by 1 + yield commit(sM)({ time: now + 12 }); + yield commit(sB)({ time: now + 14 }); + + yield unit.shouldNotFail(ticM.sendTX(mtx4)); // tic can rollback early (24h in real case) if toc does not reveal X + yield unit.shouldFail(tocB.sendTX(btx2), 'Locktime not elapsed yet'); // This one has a longer locktime (48h in real case) + + // Rollback for TIC(M) should be done + yield commit(sM)({ time: now + 12 }); + + // Make the medianTime increment by 1 + yield commit(sB)({ time: now + 14 }); + + yield unit.shouldNotFail(tocB.sendTX(btx2)); // toc can rollback now (48h has passed). He has not revealed X, so he is safe. + yield commit(sB)({ time: now + 14 }); /** * Now the transaction is fully COMMITTED! Look at rollback transactions: they will fail. diff --git a/test/integration/tools/unit.js b/test/integration/tools/unit.js index fe12c111b..55b9db297 100644 --- a/test/integration/tools/unit.js +++ b/test/integration/tools/unit.js @@ -18,7 +18,10 @@ module.exports = { try { yield promise; } catch(e) { - let err = JSON.parse(e.message); + let err = e; + if (typeof e === 'string') { + err = JSON.parse(e.message); + } should.not.exist(err); } }) -- GitLab