Skip to content

Commit

Permalink
fix<node> Headers-Sync (maybeSync)
Browse files Browse the repository at this point in the history
  • Loading branch information
manavdesai27 committed Jul 22, 2023
1 parent 059acb4 commit 9750e82
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 67 deletions.
12 changes: 2 additions & 10 deletions lib/blockchain/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -2021,22 +2021,14 @@ class Chain extends AsyncEmitter {
if (this.synced)
return;

if (this.options.neutrino && this.getProgress() < 1)
return;
if (this.options.checkpoints) {
if (this.options.checkpoints)
if (this.height < this.network.lastCheckpoint)
return;
} else if (!this.options.neutrino &&
this.tip.time < util.now() - this.network.block.maxTipAge)
return;

if (!this.hasChainwork())
return;
this.synced = true;
if (this.options.neutrino)
this.emit('headersFull');
else
this.emit('full');
this.emit('full');
}

/**
Expand Down
6 changes: 2 additions & 4 deletions lib/net/pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,7 @@ class Pool extends EventEmitter {
return false;

// Ask for the mempool if we're synced.
if (this.network.requestMempool) {
if (this.network.requestMempool && !this.options.neutrino) {
if (peer.loader && this.chain.synced)
peer.sendMempool();
}
Expand Down Expand Up @@ -1807,8 +1807,6 @@ class Pool extends EventEmitter {
*/

async handleTXInv(peer, hashes) {
if (this.options.neutrino)
return;
assert(hashes.length > 0);

if (this.syncing && !this.chain.synced)
Expand Down Expand Up @@ -2273,7 +2271,7 @@ class Pool extends EventEmitter {
return;
}
} else if (cFilterHeight === this.chain.height) {
this.chain.emit('full');
this.emit('cfilters');
}
}

Expand Down
7 changes: 6 additions & 1 deletion lib/node/neutrino.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class Neutrino extends Node {
this.emit('reset', tip);
});

this.chain.on('headersFull', async () => {
this.chain.on('full', async () => {
if (this.chain.height === 0)
return;
this.logger.info('Block Headers are fully synced');
Expand All @@ -175,6 +175,11 @@ class Neutrino extends Node {
await this.pool.startFilterSync();
});

this.pool.on('cfilters', async () => {
this.logger.info('Compact Filters are fully synced');
this.startSync();
});

this.loadPlugins();
}

Expand Down
155 changes: 103 additions & 52 deletions test/neutrino-test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
'use strict';

const Network = require('../lib/protocol/network');
const FullNode = require('../lib/node/fullnode');
const NeutrinoNode = require('../lib/node/neutrino');
const {forValue} = require('./util/common');
const assert = require('bsert');
describe('neutrino', function () {
this.timeout(100000);

const node1 = new NeutrinoNode({
network: 'regtest',
memory: true,
port: 10000,
httpPort: 20000,
neutrino: true,
logConsole: true,
logLevel: 'debug',
only: '127.0.0.1'
});
const network = Network.get('regtest');

const node2 = new FullNode({
describe('Neutrino', function () {
this.timeout(10000);

const fullNode = new FullNode({
network: 'regtest',
memory: true,
listen: true,
Expand All @@ -28,64 +21,70 @@ describe('neutrino', function () {

async function mineBlocks(n) {
while (n) {
const block = await node2.miner.mineBlock();
await node2.chain.add(block);
await new Promise(resolve => setTimeout(resolve, 20));
const block = await fullNode.miner.mineBlock();
await fullNode.chain.add(block);
n--;
}
await forValue(node1.chain, 'height', node2.chain.height);
}

before(async function () {
const waitForConnection = new Promise((resolve, reject) => {
node1.pool.once('peer open', async (peer) => {
resolve(peer);
});
});

await node1.open();
await node2.open();
await node1.connect();
await node2.connect();
node1.startSync();
node2.startSync();
await waitForConnection;
await mineBlocks(1000);
before(async () => {
await fullNode.open();
await fullNode.connect();
await mineBlocks(200);
});

after(async () => {
await node1.close();
await node2.close();
await fullNode.close();
});

describe('getheaders', () => {
it('should getheaders', async () => {
describe('No Checkpoints', function () {
const neutrinoNode = new NeutrinoNode({
network: 'regtest',
memory: true,
port: 10000,
httpPort: 20000,
neutrino: true,
only: '127.0.0.1'
});

before(async () => {
await neutrinoNode.open();
await neutrinoNode.connect();
assert.strictEqual(neutrinoNode.chain.height, 0);
assert(neutrinoNode.chain.synced);
});

after(async () => {
await neutrinoNode.close();
});

it('should initial sync', async () => {
neutrinoNode.startSync();
await forValue(neutrinoNode.chain, 'height', fullNode.chain.height);
});

it('should get new blocks headers-only', async () => {
await mineBlocks(10);
assert.equal(node1.chain.height, node2.chain.height);
await new Promise(resolve => setTimeout(resolve, 400));
assert.equal(neutrinoNode.chain.height, fullNode.chain.height);
});
});

describe('getcfheaders', () => {
it('should getcfheaders', async () => {
await new Promise(resolve => setTimeout(resolve, 400));
const headerHeight = await node1.chain.getCFHeaderHeight();
assert.equal(headerHeight, node1.chain.height);
await new Promise(resolve => setTimeout(resolve, 400));
const headerHeight = await neutrinoNode.chain.getCFHeaderHeight();
assert.equal(headerHeight, neutrinoNode.chain.height);
});
});

describe('getcfilters', () => {
it('should getcfilters', async () => {
await new Promise(resolve => setTimeout(resolve, 400));
const filterHeight = await node1.chain.getCFilterHeight();
assert.equal(filterHeight, node1.chain.height);
await new Promise(resolve => setTimeout(resolve, 400));
const filterHeight = await neutrinoNode.chain.getCFilterHeight();
assert.equal(filterHeight, neutrinoNode.chain.height);
});
});

describe('save filters', () => {
it('should save filters correctly', async () => {
const filterIndexer = node1.filterIndexers.get('BASIC');
for (let i = 0; i < node1.chain.height; i++) {
const hash = await node1.chain.getHash(i);
const filterIndexer = neutrinoNode.filterIndexers.get('BASIC');
for (let i = 0; i < neutrinoNode.chain.height; i++) {
const hash = await neutrinoNode.chain.getHash(i);
const filterHeader = await filterIndexer.getFilterHeader(hash);
assert(filterHeader);
const filter = await filterIndexer.getFilter(hash);
Expand All @@ -94,4 +93,56 @@ describe('neutrino', function () {
}
});
});

describe('With Checkpoints', function () {
const neutrinoNode = new NeutrinoNode({
network: 'regtest',
memory: true,
port: 10000,
httpPort: 20000,
logConsole: true,
logLevel: 'debug',
neutrino: true,
only: '127.0.0.1'
});

before(async () => {
// Set a new checkpoint from live regtrest chain
const entry = await fullNode.chain.getEntry(fullNode.chain.tip.height - 20);
network.checkpointMap[entry.height] = entry.hash;
network.lastCheckpoint = entry.height;
network.init();

await neutrinoNode.open();
await neutrinoNode.connect();
assert.strictEqual(neutrinoNode.chain.height, 0);
assert(!neutrinoNode.chain.synced);
});

after(async () => {
await neutrinoNode.close();

// Restore defaults
network.checkpointMap = {};
network.lastCheckpoint = 0;
});

it('should initial sync', async () => {
let full = false;
neutrinoNode.chain.on('full', () => {
full = true;
});

neutrinoNode.startSync();
await forValue(neutrinoNode.chain, 'height', fullNode.chain.height);
assert(full);
assert(neutrinoNode.chain.synced);
});

it('should get new blocks headers-only', async () => {
await mineBlocks(10);
await new Promise(resolve => setTimeout(resolve, 400));
assert.equal(neutrinoNode.chain.height, fullNode.chain.height);
});
});
});

0 comments on commit 9750e82

Please sign in to comment.