Added more reorg tests.

This commit is contained in:
Chris Kleeschulte 2017-10-04 18:01:03 -04:00
parent b6b730ea2a
commit adffdd5401
No known key found for this signature in database
GPG Key ID: 33195D27EF6BDB7F
3 changed files with 329 additions and 135 deletions

View File

@ -548,9 +548,9 @@ describe('Address', function() {
} }
//console.log(data); //console.log(data);
expect(data.items.length).to.equal(3); expect(data.items.length).to.equal(2);
expect(data.from).to.equal(0); expect(data.from).to.equal(0);
expect(data.to).to.equal(3); expect(data.to).to.equal(2);
done(); done();
}); });
@ -581,9 +581,9 @@ describe('Address', function() {
} }
//console.log(data); //console.log(data);
expect(data.items.length).to.equal(3); expect(data.items.length).to.equal(2);
expect(data.from).to.equal(0); expect(data.from).to.equal(0);
expect(data.to).to.equal(3); expect(data.to).to.equal(2);
done(); done();
}); });

View File

@ -0,0 +1,5 @@
[
"000000208830396b41c347d355046304af9953798ce868fe1fd1d7c00b16000000000000dc9ea7dc644678e64215fbe4e99ad92dcdf83dcdcb1d24fd2c3989bf6e0d88427d28d5598064231a5e2a8f680101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4c03fe5b12047d28d55908fabe6d6d0000000000000000000000000000000000000000000000000000000000000000010000000000000040000001413013030d2f6e6f64655374726174756d2f00000000030000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90c583809000000001976a914f9d5148cf7cb6489ccfad417fe3cf940a1d5b1dc88ac84d71700000000001976a914268e890b133bbe0de1830edf8d581966da2847cb88ac00000000"
]

View File

@ -8,7 +8,7 @@
2. block service not sync'ed, reorg common ancestor height greater than current block service tip height (reorg while sync, not affected) 2. block service not sync'ed, reorg common ancestor height greater than current block service tip height (reorg while sync, not affected)
3. block service not sync'ed, reorg common ancestor height less than current block service tip height (reorg while sync, affected) 3. block service not sync'ed, reorg common ancestor height less than current block service tip height (reorg while sync, affected)
4. system shutdown, reorg wipes out header and block tip (reorg while shutdown, affected) 4. system shutdown, reorg wipes out header and block tip (reorg while shutdown, affected)
5. system shutdown, reorg common ancestor height greater than the current header tip (reorg while shutdown, not affected) 5. reorg from a block that was mined from an already-orphaned block
*/ */
@ -31,7 +31,6 @@ var Block = bitcore.Block;
var bcoin = require('bcoin'); var bcoin = require('bcoin');
var BcoinBlock = bcoin.block; var BcoinBlock = bcoin.block;
var BcoinTx = bcoin.tx; var BcoinTx = bcoin.tx;
var _ = require('lodash');
var tx = BcoinTx.fromRaw('0200000001d7cf6999aa1eeee5bf954071d974bff51aa7126494a071ec0ba7820d98fc3106010000006a473044022072a784b07c68abde667a27587eb3979ee1f3ca5dc78e665801150492268c1307022054fdd4aafdcb15fc4cb7555c3a38a9ade8bb8af57c95be974b06ed16a713355d012103d3b1e94531d8b7ed3eb54751abe79786c1aa9adc1b5bc35cfced49693095b68dfeffffff0245519103000000001976a914beac8701ec4a6970ed239a47671c967b50da43d588ac80969800000000001976a914c98d54f2eb6c8970d50f7e90c9b3f4b71af9493088ac00000000', 'hex'); var tx = BcoinTx.fromRaw('0200000001d7cf6999aa1eeee5bf954071d974bff51aa7126494a071ec0ba7820d98fc3106010000006a473044022072a784b07c68abde667a27587eb3979ee1f3ca5dc78e665801150492268c1307022054fdd4aafdcb15fc4cb7555c3a38a9ade8bb8af57c95be974b06ed16a713355d012103d3b1e94531d8b7ed3eb54751abe79786c1aa9adc1b5bc35cfced49693095b68dfeffffff0245519103000000001976a914beac8701ec4a6970ed239a47671c967b50da43d588ac80969800000000001976a914c98d54f2eb6c8970d50f7e90c9b3f4b71af9493088ac00000000', 'hex');
@ -87,11 +86,20 @@ var getReorgBlock = function() {
return BcoinBlock.fromRaw(require('./data/blocks_reorg.json')[0], 'hex'); return BcoinBlock.fromRaw(require('./data/blocks_reorg.json')[0], 'hex');
}; };
var getOrphanedBlock = function() {
return BcoinBlock.fromRaw(require('./data/blocks_orphaned.json')[0], 'hex');
};
var TestBitcoind = function TestBitcoind() { var TestBitcoind = function TestBitcoind() {
var self = this; var self = this;
self.blocks = []; self._orphans = {};
self.currentBlockIndex = 0;
self.reorientData = function(block) {
var lastHash = self.blocks.getLastIndex().rhash();
self.blocks.remove(lastHash);
self.blocks.set(block.rhash(), block);
};
self._getHeaders = function() { self._getHeaders = function() {
var ret = []; var ret = [];
@ -160,7 +168,11 @@ var TestBitcoind = function TestBitcoind() {
if (hash === tx.txid()) { if (hash === tx.txid()) {
return msg.push(messages.Transaction(tx, { Transaction: BcoinTx })); return msg.push(messages.Transaction(tx, { Transaction: BcoinTx }));
} }
msg.push(messages.Block(self.blocks.get(hash), { Block: BcoinBlock })); var block = self.blocks.get(hash);
if (!block) {
block = self._orphans[hash];
}
msg.push(messages.Block(block, { Block: BcoinBlock }));
} }
if (msg.length > 0) { if (msg.length > 0) {
@ -175,10 +187,14 @@ var TestBitcoind = function TestBitcoind() {
// this will kick out an unsolicited inventory message to the peer // this will kick out an unsolicited inventory message to the peer
// prompting them to send a getdata message back to us with the hash // prompting them to send a getdata message back to us with the hash
// of the resource. // of the resource.
self.sendBlock = function(block) { self.sendBlock = function(block, doNotChangeHeaders) {
if (!doNotChangeHeaders) {
var lastHash = self.blocks.getLastIndex().rhash(); var lastHash = self.blocks.getLastIndex().rhash();
self.blocks.remove(lastHash); self.blocks.remove(lastHash);
self.blocks.set(block.rhash(), block); self.blocks.set(block.rhash(), block);
} else {
self._orphans[block.rhash()] = block;
}
var inv = p2p.Inventory.forBlock(block.rhash()); var inv = p2p.Inventory.forBlock(block.rhash());
var message = messages.Inventory([inv]); var message = messages.Inventory([inv]);
self._socket.write(message.toBuffer()); self._socket.write(message.toBuffer());
@ -761,13 +777,101 @@ var performTest3 = function(fakeServer, callback) {
/* /*
4. system shutdown, reorg wipes out header and block tip (reorg while shutdown, affected) 4. system shutdown, reorg wipes out header and block tip (reorg while shutdown, affected)
*/ */
var performTest4 = function() { var performTest4 = function(fakeServer, callback) {
async.series([
// 0. reset the test directories
function(next) {
console.log('step 0: setting up directories.');
var dirs = bitcoinDataDirs.concat([bitcoreDataDir]);
resetDirs(dirs, function(err) {
if (err) {
return next(err);
}
writeBitcoreConf();
next();
});
},
// 1. start fake server
function(next) {
console.log('step 1: starting fake server.');
fakeServer.start();
next();
},
// 2. start bitcore
function(next) {
console.log('step 2: start bitcore and let sync.');
blocksGenerated = 7;
startBitcore(next);
},
// 3. shutdown bitcore
function(next) {
console.log('step 3: shut down bitcore.');
shutdownBitcore(next);
},
// 4. setup the fake server to send a reorg'ed set of headers
function(next) {
console.log('step 4: setup fake server to send reorg set of headers.');
var reorgBlock = getReorgBlock();
fakeServer.reorientData(reorgBlock);
next();
},
// 5. start up bitcore once again
function(next) {
console.log('step 5: start up bitcore.');
blocksGenerated = 7;
startBitcore(next);
}
], function(err) {
if (err) {
return callback(err);
}
callback();
});
}; };
/* /*
5. system shutdown, reorg common ancestor height greater than the current header tip (reorg while shutdown, not affected) 5. reorg from a block that was mined from an already-orphaned block
*/ */
var performTest5 = function() { var performTest5 = function(fakeServer, callback) {
async.series([
// 0. reset the test directories
function(next) {
console.log('step 0: setting up directories.');
var dirs = bitcoinDataDirs.concat([bitcoreDataDir]);
resetDirs(dirs, function(err) {
if (err) {
return next(err);
}
writeBitcoreConf();
next();
});
},
// 1. start fake server
function(next) {
console.log('step 1: starting fake server.');
fakeServer.start();
next();
},
// 2. start bitcore
function(next) {
console.log('step 2: start bitcore and let sync.');
blocksGenerated = 7;
startBitcore(next);
},
// 3. send in a block that has nothing to do with anything in my chain.
function(next) {
console.log('step 3: send in an orphaned block.');
var orphanedBlock = getOrphanedBlock();
fakeServer.sendBlock(orphanedBlock, true);
next();
}
], function(err) {
if (err) {
return callback(err);
}
callback();
});
}; };
describe('Reorg', function() { describe('Reorg', function() {
@ -959,4 +1063,89 @@ describe('Reorg', function() {
}); });
}); });
describe('Case 4: system shutdown, reorg wipes out header and block tip (reorg while shutdown, affected)', function() {
var fakeServer;
before(function(done) {
fakeServer = new TestBitcoind();
done();
});
after(function(done) {
shutdownBitcore(function() {
fakeServer.stop();
done();
});
});
it('should reorg when, while the node is shut down, our header tip is reorged out of existence.', function(done) {
performTest4(fakeServer, function(err) {
if (err) {
return done(err);
}
setTimeout(function() {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: 'http://localhost:53001/api/block/' + getReorgBlock().rhash(),
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
request(httpOpts, function(err, data) {
if(err) {
return done(err);
}
console.log(data);
expect(data.height).to.equal(7);
done();
});
}, 2000);
});
});
});
describe('Case 5: reorg from a block that was mined from an already-orphaned block', function() {
var fakeServer;
before(function(done) {
fakeServer = new TestBitcoind();
done();
});
after(function(done) {
shutdownBitcore(function() {
fakeServer.stop();
done();
});
});
it('should launch a reorg, yet no mainchain blocks will be affected when a new block comes in that is not mainchain to begin with', function(done) {
performTest5(fakeServer, function(err) {
if (err) {
return done(err);
}
setTimeout(function() {
var httpOpts = {
hostname: 'localhost',
port: 53001,
path: 'http://localhost:53001/api/block/' + fakeServer.blocks.getLastIndex().rhash(),
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
request(httpOpts, function(err, data) {
if(err) {
return done(err);
}
console.log(data);
expect(data.height).to.equal(7);
done();
});
}, 2000);
});
});
});
}); });