567 lines
16 KiB
JavaScript
567 lines
16 KiB
JavaScript
#!/usr/bin/env node
|
|
'use strict';
|
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
|
|
|
var should = require('chai');
|
|
|
|
var
|
|
assert = require('assert'),
|
|
async = require('async'),
|
|
HistoricSync = require('../../lib/HistoricSync');
|
|
|
|
var s;
|
|
var b = [
|
|
'00000000c4cbd75af741f3a2b2ff72d9ed4d83a048462c1efe331be31ccf006b', //0 B#16
|
|
'00000000fe198cce4c8abf9dca0fee1182cb130df966cc428ad2a230df8da743', //1
|
|
'000000008d55c3e978639f70af1d2bf1fe6f09cb3143e104405a599215c89a48', //2
|
|
'000000009b3bca4909f38313f2746120129cce4a699a1f552390955da470c5a9', //3
|
|
'00000000ede57f31cc598dc241d129ccb4d8168ef112afbdc870dc60a85f5dd3', //4 B#20
|
|
'000000001a29aff8154de6230a4909a3a971c52ae590006e00fddff33f9e3773', //5 B#21
|
|
];
|
|
var t = [
|
|
'd08582d3711f75d085c618874fb0d049ae09d5ec95ec6f5abd289f4b54712c54', // TX from B#16
|
|
'1729001087e0cebea8d14de1653d5cf59628d9746bc1ae65f776f1cbaff7ebad', //1
|
|
'cf53d7ccd83a099acfbc319ee10c1e3b10e3d42ba675b569fdd6b69cb8d2db4e', //2
|
|
'73a4988adf462b6540cfa59097804174b298cfa439f73c1a072c2c6fbdbe57c7', //3
|
|
'd45f9da73619799e9d7bd03cc290e70875ea4cbad56b8bffa15135fbbb3df9ea', //4 Tx from B20
|
|
];
|
|
|
|
var initialTest = function(cb) {
|
|
async.each([2,3,4], function(i,c) {
|
|
s.sync.bDb.getPrev(b[i], function(err, p) {
|
|
assert.equal(p,b[i-1]);
|
|
return c();
|
|
});
|
|
}, function() {
|
|
async.each([0,1,2,3,4], function(i,c) {
|
|
s.sync.bDb.has(b[i], function(err, p) {
|
|
assert(p);
|
|
return c();
|
|
});
|
|
}, function() {
|
|
async.each([0,1,2,3], function(i,c) {
|
|
s.sync.bDb.getNext(b[i], function(err, p) {
|
|
assert.equal(p,b[i+1]);
|
|
return c();
|
|
});
|
|
}, function() {
|
|
async.each([0,1,2,3], function(i,c) {
|
|
s.sync.bDb.getHeight(b[i], function(err, h) {
|
|
assert.equal(h,16+i);
|
|
return c();
|
|
});
|
|
}, function() {
|
|
async.each([0,1,2,3], function(i,c) {
|
|
s.sync.bDb.getDepth(b[i], function(err, d) {
|
|
assert.equal(d,4-i);
|
|
return c();
|
|
});
|
|
}, cb);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* TEST CASES
|
|
*
|
|
* b0 height = 16;
|
|
*
|
|
* Blocks: 0-1-2-3-4
|
|
* case 1)
|
|
* 0-1-2-3-4
|
|
* \
|
|
* C1* (height should be 19)
|
|
*
|
|
* case 2)
|
|
* 0-1-2---3-4
|
|
* \ \
|
|
* C1 C2*
|
|
*
|
|
* case 2b)
|
|
* 0-1-2---3-4
|
|
* \ \
|
|
* C1 C2-C2b(TX=C1.TX)*
|
|
* case 2c)
|
|
* 0-1-2---3-4
|
|
* \ \
|
|
* C1 C2-C2b(TX=C1.TX)
|
|
* \
|
|
* C2c(TX=C2.TX)*
|
|
*
|
|
*/
|
|
|
|
var checkTxs = function(txs,heights){
|
|
var i=0;
|
|
txs.forEach(function(tx){
|
|
var v=heights[i++];
|
|
it('tx height:'+tx+' #'+v,function(done){
|
|
s.sync.bDb.getBlockForTx(tx, function(err,hash,height) {
|
|
assert(!err,err);
|
|
if (v>=0) {
|
|
assert(hash);
|
|
height.should.equal(v);
|
|
} else {
|
|
assert(!hash);
|
|
assert(!height);
|
|
}
|
|
|
|
return done();
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
//heights is optional
|
|
var checkBlocks = function(hashes,heights){
|
|
var i=0;
|
|
hashes.forEach(function(hash){
|
|
var v = heights[i++];
|
|
it('block height:'+hash+' #'+v,function(done){
|
|
s.sync.bDb.getHeight(hash, function(err,height) {
|
|
assert(!err,err);
|
|
height.should.equal(v);
|
|
return done();
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
|
|
describe('Sync Reorgs', function(){
|
|
var opts = {
|
|
forceRPC: true,
|
|
stopAt: b[5],
|
|
};
|
|
|
|
before(function(done) {
|
|
s = new HistoricSync();
|
|
s.sync.destroy(done);
|
|
});
|
|
|
|
it('simple RPC forward syncing', function(done) {
|
|
s.start(opts, function(err) {
|
|
if (err) return done(err);
|
|
initialTest(done);
|
|
});
|
|
});
|
|
|
|
var case1 = {
|
|
hash: '0000000042d3db6c529dd8f1b085367cb6d907b534f5b1a5dfdd3a34a3459886',
|
|
tx: [ '2dc27c8d4b98f5e2ed009cfc164ac4990f18e03c4d5b71e780f9c8b7b2c5f151' ],
|
|
time: 1296690099,
|
|
previousblockhash: b[2],
|
|
};
|
|
|
|
|
|
describe('reorg, case 1', function(done) {
|
|
checkTxs([t[0], t[1], t[2], t[3], t[4]],[16,17,18,19,20]);
|
|
checkBlocks([b[0], b[1], b[2], b[3], b[4]],[16,17,18,19,20]);
|
|
it('trigger reorg case 1', function(done1){
|
|
s.sync.storeTipBlock(case1, function(err) {
|
|
assert(!err, 'shouldnt return error' + err);
|
|
done1();
|
|
});
|
|
});
|
|
checkTxs([t[0], t[1], t[2], t[3], t[4],case1.tx],[16,17,18,-1,-1,19]);
|
|
checkBlocks([b[0], b[1], b[2],b[3],b[4],case1.hash],[16,17,18,-1,-1,19]);
|
|
});
|
|
//
|
|
// it('reorg, case 1 (repeat)', function(done) {
|
|
// s.sync.storeTipBlock(case1, function(err) {
|
|
// assert(!err, 'shouldnt return error' + err);
|
|
// return done();
|
|
// });
|
|
// });
|
|
//
|
|
// var case2 = {
|
|
// hash: '00000000c262f9428bb84407780bb0bd008b74941d651111ab2500cf649fa45d',
|
|
// tx: [ '3fa6fce216e91c9dc9a6267168e9d8bfb4ae57aec0d26590442cfec6e8233682' ],
|
|
// time: 1296690099,
|
|
// previousblockhash: b[3],
|
|
// };
|
|
//
|
|
//
|
|
// it('reorg, case 2', function(done) {
|
|
// async.series([
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case1.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[4], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// // BEFORE
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(b[3], function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is,-1);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.storeTipBlock(case2, function(err) {
|
|
// assert(!err, 'shouldnt return error' + err);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// // AFTER
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(b[3], function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is,19);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(b[4], function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal( is,-1, b[3] + 'should not be on main chain: #'+is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(case1.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is,-1);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(case2.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is, 20);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[3], function(err,is) {
|
|
// console.log('[99-sync.js.descructive-test.300:is:]',is); //TODO
|
|
// assert(!err);
|
|
// assert(is, 'transaction t[3] should be valid:' + t[3]);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case1.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[4], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getNext(b[2], function(err, val) {
|
|
// assert(!err);
|
|
// assert.equal(val,b[3]);
|
|
// return c();
|
|
// });
|
|
// },
|
|
//
|
|
//
|
|
//
|
|
// ], done );
|
|
// });
|
|
//
|
|
//
|
|
// var case2b = {
|
|
// hash: '0000000022bb34bc09f8d8d0ae26b86c87f8483e54b9c3addfe6f30b12bc656a',
|
|
// tx: case1.tx,
|
|
// time: 1296690099,
|
|
// previousblockhash: case2.hash,
|
|
// };
|
|
//
|
|
// it('reorg, case 2b', function(done) {
|
|
// async.series([
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2b.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.storeTipBlock(case2b, function(err) {
|
|
// assert(!err, 'shouldnt return error' + err);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[3], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is, 'transaction t[3] should be valid:' + t[3]);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2b.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// ], done );
|
|
// });
|
|
//
|
|
//
|
|
//
|
|
// var case2c = {
|
|
// hash: '0000000000000000000000000000000000000000000000000000000000000004',
|
|
// tx: case2.tx,
|
|
// time: 1296690099,
|
|
// previousblockhash: case1.hash,
|
|
// };
|
|
//
|
|
// it('reorg, case 2c', function(done) {
|
|
// async.series([
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case1.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(case1.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is, -1, 'case1 block shouldnt be main:' + case1.hash);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is); //It was there before (from case2)
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.storeTipBlock(case2c, function(err) {
|
|
// assert(!err, 'shouldnt return error' + err);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case1.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.has(case1.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.has(case2c.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(case1.hash, function(err,h) {
|
|
// assert(!err);
|
|
// assert.equal(h,19);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(case2c.hash, function(err,h) {
|
|
// assert(!err);
|
|
// assert.equal(h,20);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[3], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[4], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
//
|
|
// ], done );
|
|
// });
|
|
//
|
|
// var case3 = {
|
|
// hash: '0000000000000000000000000000000000000000000000000000000000000005',
|
|
// tx: case2.tx,
|
|
// time: 1296690099,
|
|
// previousblockhash: '666',
|
|
// };
|
|
//
|
|
// it('reorg, case 3)', function(done) {
|
|
// async.series([
|
|
// function (c) {
|
|
// s.sync.storeTipBlock(case3, function(err) {
|
|
// assert(err, 'should return error' + err);
|
|
// return c();
|
|
// });
|
|
// },
|
|
//
|
|
// //shoudnt change anything
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case1.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.has(case1.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.has(case2c.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2c.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[3], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is, 'TX t[3]: shouldnt be confirmed:' + t[3] +':'+ is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(t[4], function(err,is) {
|
|
// assert(!err);
|
|
// assert(!is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(case2.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
//
|
|
// ], done );
|
|
// });
|
|
//
|
|
// var p2p = {
|
|
// hash: '0000000000000000000000000000000000000000000000000000000000000006',
|
|
// tx: ['f6c2901f39fd07f2f2e503183d76f73ecc1aee9ac9216fde58e867bc29ce674e'],
|
|
// time: 1296690099,
|
|
// previousblockhash: '111',
|
|
// };
|
|
//
|
|
// it('p2p, no reorg allowed', function(done) {
|
|
// async.series([
|
|
// function (c) {
|
|
// s.sync.storeTipBlock(p2p, false, function(err) {
|
|
// assert(!err, 'shouldnt return error' + err);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.has(p2p.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.txDb.getBlock(p2p.tx[0], function(err,is) {
|
|
// assert(!err);
|
|
// assert(is);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getNext(p2p.hash, function(err,v) {
|
|
// assert(!err);
|
|
// assert.equal(v,p2p.nextblockhash);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getNext(p2p.previousblockhash, function(err,v) {
|
|
// assert(!err);
|
|
// assert.equal(v,p2p.hash);
|
|
// return c();
|
|
// });
|
|
// },
|
|
// function (c) {
|
|
// s.sync.bDb.getHeight(p2p.hash, function(err,is) {
|
|
// assert(!err);
|
|
// assert.equal(is,-1);
|
|
// return c();
|
|
// });
|
|
// },
|
|
//
|
|
// ], done );
|
|
// });
|
|
});
|
|
|
|
|