Merge pull request #764 from braydonf/checkpoint
blockchain: do not accept forked chain older than last checkpoint
This commit is contained in:
commit
812dc1a6f3
@ -1104,6 +1104,16 @@ class Chain extends AsyncEmitter {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async saveAlternate(entry, block, prev, flags) {
|
async saveAlternate(entry, block, prev, flags) {
|
||||||
|
// Do not accept forked chain older than the
|
||||||
|
// last checkpoint.
|
||||||
|
if (this.options.checkpoints) {
|
||||||
|
if (prev.height + 1 < this.network.lastCheckpoint)
|
||||||
|
throw new VerifyError(block,
|
||||||
|
'checkpoint',
|
||||||
|
'bad-fork-prior-to-checkpoint',
|
||||||
|
100);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Do as much verification
|
// Do as much verification
|
||||||
// as we can before saving.
|
// as we can before saving.
|
||||||
|
|||||||
@ -121,17 +121,21 @@ chain.on('disconnect', (entry, block) => {
|
|||||||
describe('Chain', function() {
|
describe('Chain', function() {
|
||||||
this.timeout(process.browser ? 1200000 : 60000);
|
this.timeout(process.browser ? 1200000 : 60000);
|
||||||
|
|
||||||
it('should open chain and miner', async () => {
|
before(async () => {
|
||||||
await blocks.open();
|
await blocks.open();
|
||||||
await chain.open();
|
await chain.open();
|
||||||
await miner.open();
|
await miner.open();
|
||||||
});
|
|
||||||
|
|
||||||
it('should add addrs to miner', async () => {
|
|
||||||
miner.addresses.length = 0;
|
miner.addresses.length = 0;
|
||||||
miner.addAddress(wallet.getReceive());
|
miner.addAddress(wallet.getReceive());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await miner.close();
|
||||||
|
await chain.close();
|
||||||
|
await blocks.close();
|
||||||
|
});
|
||||||
|
|
||||||
it('should mine 200 blocks', async () => {
|
it('should mine 200 blocks', async () => {
|
||||||
for (let i = 0; i < 200; i++) {
|
for (let i = 0; i < 200; i++) {
|
||||||
const block = await cpu.mineBlock();
|
const block = await cpu.mineBlock();
|
||||||
@ -900,9 +904,44 @@ describe('Chain', function() {
|
|||||||
assert(fmt.includes('chainwork'));
|
assert(fmt.includes('chainwork'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should cleanup', async () => {
|
describe('Checkpoints', function() {
|
||||||
await miner.close();
|
before(async () => {
|
||||||
await chain.close();
|
const entry = await chain.getEntry(chain.tip.height - 5);
|
||||||
await blocks.close();
|
assert(Buffer.isBuffer(entry.hash));
|
||||||
|
assert(Number.isInteger(entry.height));
|
||||||
|
|
||||||
|
network.checkpointMap[entry.height] = entry.hash;
|
||||||
|
network.lastCheckpoint = entry.height;
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
network.checkpointMap = {};
|
||||||
|
network.lastCheckpoint = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will reject blocks before last checkpoint', async () => {
|
||||||
|
const entry = await chain.getEntry(chain.tip.height - 10);
|
||||||
|
const block = await cpu.mineBlock(entry);
|
||||||
|
|
||||||
|
let err = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await chain.add(block);
|
||||||
|
} catch (e) {
|
||||||
|
err = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(err);
|
||||||
|
assert.equal(err.type, 'VerifyError');
|
||||||
|
assert.equal(err.reason, 'bad-fork-prior-to-checkpoint');
|
||||||
|
assert.equal(err.score, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('will accept blocks after last checkpoint', async () => {
|
||||||
|
const entry = await chain.getEntry(chain.tip.height - 4);
|
||||||
|
const block = await cpu.mineBlock(entry);
|
||||||
|
|
||||||
|
assert(await chain.add(block));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user