Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wallet Sync Updates #883

Merged
merged 13 commits into from
Aug 20, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
test: Change nodes-context seed ports.
Add stack traces to common test helper timeouts.
Change default timeout to 2000.
  • Loading branch information
nodech committed Aug 20, 2024
commit f46192d3a6201f76cdcfa1f63c3b16e8ce3773e0
2 changes: 1 addition & 1 deletion test/node-spv-sync-test.js
Original file line number Diff line number Diff line change
@@ -158,7 +158,7 @@ describe('SPV Node Sync', function() {
});

it('should send a tx from chain 1 to SPV node', async () => {
const balanceEvent = forEvent(spvwallet, 'balance');
const balanceEvent = forEvent(spvwallet, 'balance', 1, 9000);
await wallet.send({
outputs: [{
value: 1012345678,
30 changes: 23 additions & 7 deletions test/util/common.js
Original file line number Diff line number Diff line change
@@ -103,13 +103,14 @@ common.rimraf = async function(p) {
return await fs.rimraf(p);
};

common.forValue = async function forValue(obj, key, val, timeout = 5000) {
common.forValue = async function forValue(obj, key, val, timeout = 2000) {
assert(typeof obj === 'object');
assert(typeof key === 'string');

const ms = 10;
let interval = null;
let count = 0;
const stack = getStack();

return new Promise((resolve, reject) => {
interval = setInterval(() => {
@@ -118,14 +119,16 @@ common.forValue = async function forValue(obj, key, val, timeout = 5000) {
resolve();
} else if (count * ms >= timeout) {
clearInterval(interval);
reject(new Error('Timeout waiting for value.'));
const error = new Error('Timeout waiting for value.');
error.stack = error.stack + '\n' + stack;
reject(error);
}
count += 1;
}, ms);
});
};

common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000) {
common.forEvent = async function forEvent(obj, name, count = 1, timeout = 2000) {
assert(typeof obj === 'object');
assert(typeof name === 'string');
assert(typeof count === 'number');
@@ -134,6 +137,8 @@ common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000)
let countdown = count;
const events = [];

const stack = getStack();

return new Promise((resolve, reject) => {
let timeoutHandler, listener;

@@ -159,22 +164,26 @@ common.forEvent = async function forEvent(obj, name, count = 1, timeout = 5000)
timeoutHandler = setTimeout(() => {
cleanup();
const msg = `Timeout waiting for event ${name} `
+ `(received ${count - countdown}/${count})`;
+ `(received ${count - countdown}/${count})\n${stack}`;

reject(new Error(msg));
const error = new Error(msg);
error.stack = error.stack + '\n' + stack;
reject(error);
return;
}, timeout);

obj.on(name, listener);
});
};

common.forEventCondition = async function forEventCondition(obj, name, fn, timeout = 5000) {
common.forEventCondition = async function forEventCondition(obj, name, fn, timeout = 2000) {
assert(typeof obj === 'object');
assert(typeof name === 'string');
assert(typeof fn === 'function');
assert(typeof timeout === 'number');

const stack = getStack();

return new Promise((resolve, reject) => {
let timeoutHandler, listener;

@@ -190,6 +199,7 @@ common.forEventCondition = async function forEventCondition(obj, name, fn, timeo
res = await fn(...args);
} catch (e) {
cleanup();
e.stack = e.stack + '\n' + stack;
reject(e);
return;
}
@@ -203,7 +213,9 @@ common.forEventCondition = async function forEventCondition(obj, name, fn, timeo
timeoutHandler = setTimeout(() => {
cleanup();
const msg = `Timeout waiting for event ${name} with condition`;
reject(new Error(msg));
const error = new Error(msg);
error.stack = error.stack + '\n' + stack;
reject(error);
return;
}, timeout);

@@ -357,3 +369,7 @@ class TXContext {
return [tx, view];
}
}

function getStack() {
return new Error().stack.split('\n').slice(2).join('\n');
}
22 changes: 15 additions & 7 deletions test/util/nodes-context.js
Original file line number Diff line number Diff line change
@@ -19,12 +19,12 @@ class NodesContext {
}

addNode(options = {}) {
const index = this.nodeCtxs.length + 1;
const index = this.nodeCtxs.length;

let seedPort = this.network.port + index - 1;
let seedPort = getPort(this.network, index - 1);

if (seedPort < this.network.port)
seedPort = this.network.port;
if (options.seedNodeIndex != null)
seedPort = getPort(this.network, options.seedNodeIndex);

const port = this.network.port + index;
const brontidePort = this.network.brontidePort + index;
@@ -33,6 +33,11 @@ class NodesContext {
const nsPort = this.network.nsPort + index;
const rsPort = this.network.rsPort + index + 100;

const seeds = [];

if (options.seedNodeIndex != null || index > 0)
seeds.push(`127.0.0.1:${seedPort}`);

const nodeCtx = new NodeContext({
listen: true,

@@ -47,9 +52,8 @@ class NodesContext {
nsPort: nsPort,
httpPort: httpPort,
walletHttpPort: walletHttpPort,
seeds: [
`127.0.0.1:${seedPort}`
]

seeds: seeds
});

this.nodeCtxs.push(nodeCtx);
@@ -191,4 +195,8 @@ class NodesContext {
}
}

function getPort(network, index) {
return Math.max(network.port + index, network.port);
}

module.exports = NodesContext;
20 changes: 12 additions & 8 deletions test/wallet-rescan-test.js
Original file line number Diff line number Diff line change
@@ -41,9 +41,9 @@ const noSPVcombinations = combinations.filter(c => !c.SPV);
const regtest = Network.get('regtest');

describe('Wallet rescan/addBlock', function() {
// TODO: Add SPV tests.
for (const {SPV, STANDALONE, name} of noSPVcombinations) {
describe(`rescan/addBlock gapped addresses (${name} Integration)`, function() {
this.timeout(5000);
const TEST_LOOKAHEAD = 20;

const MAIN = 0;
@@ -144,6 +144,7 @@ describe('Wallet rescan/addBlock', function() {
// Prepare for the rescan and addBlock tests.
it('should send gapped txs on each block', async () => {
const expectedRescanBalance = await getBalance(main.client, ACCOUNT);
const height = nodes.height(MAIN);
const blocks = 5;

// 1 address per block, all of them gapped.
@@ -154,9 +155,10 @@ describe('Wallet rescan/addBlock', function() {
// give addBlock first address.
await deriveAddresses(addBlock.client, addresses[0].depth - TEST_LOOKAHEAD);

const mainWalletBlocks = forEvent(main.wdb, 'block connect', blocks);
const addBlockWalletBlocks = forEvent(addBlock.wdb, 'block connect', blocks);
const rescanWalletBlocks = forEvent(rescan.wdb, 'block connect', blocks);
const condFn = entry => entry.height === blocks + height;
const mainWalletBlocks = forEventCondition(main.wdb, 'block connect', condFn);
const addBlockWalletBlocks = forEventCondition(addBlock.wdb, 'block connect', condFn);
const rescanWalletBlocks = forEventCondition(rescan.wdb, 'block connect', condFn);

for (let i = 0; i < blocks; i++) {
await minerWallet.send({
@@ -704,15 +706,17 @@ describe('Wallet rescan/addBlock', function() {
const BLOCKS = 20;
const chainBlocks = forEventCondition(node.chain, 'connect', (entry) => {
return entry.height === BLOCKS;
});
}, 5000);

const wdbBlocks = forEventCondition(wdb, 'block connect', (entry) => {
return entry.height === BLOCKS;
});
}, 5000);

await minerCtx.mineBlocks(BLOCKS, address);
await chainBlocks;
await wdbBlocks;
await Promise.all([
chainBlocks,
wdbBlocks
]);
});

it('should rescan when receiving a block', async () => {