Skip to content

Commit

Permalink
store rescan height + refactor node/wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
rithvikvibhu committed Mar 25, 2022
1 parent 7842f03 commit 7af427a
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 55 deletions.
28 changes: 17 additions & 11 deletions app/background/node/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fs from 'fs';
import crypto from 'crypto';
import tcpPortUsed from 'tcp-port-used';
import EventEmitter from 'events';
import throttle from 'lodash.throttle';
import { NodeClient } from 'hs-client';
import { BigNumber } from 'bignumber.js';
import { ConnectionTypes, getConnection, getCustomRPC } from '../connections/service';
Expand Down Expand Up @@ -239,7 +240,7 @@ export class NodeService extends EventEmitter {
await put(migrateFlag, true);
}

this.hsd.on('connect', async () => this.refreshNodeInfo());
this.hsd.on('connect', async (entry) => this.refreshNodeInfo(entry));
}

async setHSDLocalClient() {
Expand Down Expand Up @@ -351,35 +352,40 @@ export class NodeService extends EventEmitter {
}
}

async refreshNodeInfo() {
async refreshNodeInfo(entry) {
if (!this.client)
return;

try {
const info = await this.getInfo();
this.emit('refreshNodeInfo', info);
this.emit('refreshNodeInfo', entry?.height ?? info.chain.height);

dispatchToMainWindow({
type: SET_NODE_INFO,
payload: info.chain,
});

if (info.chain.progress > 0.99) {
const fees = await this.getFees();

if (fees) {
dispatchToMainWindow({
type: SET_FEE_INFO,
payload: fees,
});
}
// TODO: Make sure this works
throttledSetFeeInfo()
}

this.height = info.chain.height;
} catch (e) {
}
};

throttledSetFeeInfo = throttle(async () => {
const fees = await this.getFees();

if (fees) {
dispatchToMainWindow({
type: SET_FEE_INFO,
payload: fees,
});
}
}, 5000, {leading: true})

async generateToAddress(numblocks, address) {
return this._execRPC('generatetoaddress', [numblocks, address]);
}
Expand Down
91 changes: 73 additions & 18 deletions app/background/wallet/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
STOP_SYNC_WALLET,
SYNC_WALLET_PROGRESS,
SET_WALLET_NETWORK,
SET_RESCAN_HEIGHT,
} from '../../ducks/walletReducer';
import {STOP, SET_CUSTOM_RPC_STATUS} from '../../ducks/nodeReducer';
import createRegisterAll from "./create-register-all";
Expand Down Expand Up @@ -62,6 +63,7 @@ class WalletService {
this.nodeHeight = 0;
this.lastProgressUpdate = 0;
this.lastKnownChainHeight = 0;
this.heightBeforeRescan = null; // null = not rescanning
this.conn = {type: null};
}

Expand Down Expand Up @@ -118,6 +120,8 @@ class WalletService {
type: SET_WALLETS,
payload: createPayloadForSetWallets(wallets),
});

this.lastKnownChainHeight = this.node.wdb.height;
};

// Wallet as a separate process only runs in Custom RPC mode
Expand Down Expand Up @@ -241,19 +245,8 @@ class WalletService {

// Called when node emits refreshNodeInfo
// Required to get node height once node is connected
_onRefreshNodeInfo = async (nodeInfo) => {
this.nodeHeight = nodeInfo.chain.height;

// If wallet is synced up with node,
// stop wallet sync (similar to onRescanBlock)
if (this.lastKnownChainHeight === this.nodeHeight) {
dispatchToMainWindow({type: STOP_SYNC_WALLET});
dispatchToMainWindow({
type: SYNC_WALLET_PROGRESS,
payload: this.nodeHeight,
});
await this.refreshWalletInfo();
}
_onRefreshNodeInfo = async (nodeHeight) => {
// TODO: Remove?
}

isReady = async () => {
Expand Down Expand Up @@ -395,11 +388,18 @@ class WalletService {
};

rescan = async (height = 0) => {
this.heightBeforeRescan = this.lastKnownChainHeight;
this.lastKnownChainHeight = height;

dispatchToMainWindow({type: START_SYNC_WALLET});
dispatchToMainWindow({
type: SYNC_WALLET_PROGRESS,
payload: height,
});
dispatchToMainWindow({
type: SET_RESCAN_HEIGHT,
payload: this.heightBeforeRescan,
});

return this.node.wdb.rescan(height);
};
Expand Down Expand Up @@ -789,6 +789,12 @@ class WalletService {
};

importName = (name, start) => {
this.heightBeforeRescan = this.lastKnownChainHeight;
this.lastKnownChainHeight = start;
dispatchToMainWindow({
type: SET_RESCAN_HEIGHT,
payload: this.heightBeforeRescan,
});
return this._executeRPC('importname', [name, start]);
};

Expand Down Expand Up @@ -1063,14 +1069,55 @@ class WalletService {

onNewBlock = async (entry) => {
await this._ensureClient();
await this.refreshWalletInfo();

console.log('LOG onNewBlock - SyncWalletProgress:', entry.height);
this.lastKnownChainHeight = entry.height;

let stopWalletSync = false;
if (this.heightBeforeRescan !== null && this.heightBeforeRescan <= entry.height) {
console.log('LOG onNewBlock: stopping wallet sync because reached heightBeforeRescan - v')
stopWalletSync = true;
}

console.log('LOG onNewBlock:', {
newWalletHeight: entry.height,
lastKnownChainHeight: this.lastKnownChainHeight,
heightBeforeRescan: this.heightBeforeRescan,
stopWalletSync: stopWalletSync,
});

// If wallet is synced up with node,
// stop wallet sync (similar to onRescanBlock)
if (stopWalletSync) {
this.heightBeforeRescan = null;
dispatchToMainWindow({type: STOP_SYNC_WALLET});
// dispatchToMainWindow({
// type: SYNC_WALLET_PROGRESS,
// payload: this.nodeHeight,
// });
dispatchToMainWindow({
type: SET_RESCAN_HEIGHT,
payload: null,
});
await this.refreshWalletInfo();
}

// debounce wallet info refresh
const now = Date.now();
if (now - this.lastProgressUpdate > 500) {
// dispatchToMainWindow({
// type: SYNC_WALLET_PROGRESS,
// payload: entry.height,
// });
await this.refreshWalletInfo();
this.lastProgressUpdate = now;
}

// TODO: debounce this also
dispatchToMainWindow({
type: SYNC_WALLET_PROGRESS,
payload: entry.height,
});

this.lastKnownChainHeight = entry.height;
};

/**
Expand All @@ -1082,9 +1129,12 @@ class WalletService {
*/

onRescanBlock = async (entry) => {
// TODO: Verify this works?
this.lastKnownChainHeight = entry.height;

if (entry.height === this.nodeHeight) {
if (this.heightBeforeRescan <= entry.height) {
console.log('LOG onRescanBlock: stopping wallet sync because reached heightBeforeRescan', this.heightBeforeRescan, entry.height);
this.heightBeforeRescan = null;
dispatchToMainWindow({type: STOP_SYNC_WALLET});
dispatchToMainWindow({
type: SYNC_WALLET_PROGRESS,
Expand All @@ -1094,9 +1144,14 @@ class WalletService {
return;
}

const now = Date.now();
console.log('LOG onRescanBlock:', {
rescannedBlock: entry.height,
lastKnownChainHeight: this.lastKnownChainHeight,
heightBeforeRescan: this.heightBeforeRescan,
});

// debounce wallet sync update
const now = Date.now();
if (now - this.lastProgressUpdate > 500) {
dispatchToMainWindow({type: START_SYNC_WALLET});
dispatchToMainWindow({
Expand Down
5 changes: 4 additions & 1 deletion app/components/Sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const nodeClient = clientStub(() => require('electron').ipcRenderer);
walletWatchOnly: state.wallet.watchOnly,
walletSync: state.wallet.walletSync,
walletHeight: state.wallet.walletHeight,
rescanHeight: state.wallet.rescanHeight,
address: state.wallet.address,
}),
dispatch => ({
Expand All @@ -44,6 +45,7 @@ class Sidebar extends Component {
walletWatchOnly: PropTypes.bool.isRequired,
walletSync: PropTypes.bool.isRequired,
walletHeight: PropTypes.number.isRequired,
rescanHeight: PropTypes.number,
network: PropTypes.string.isRequired,
address: PropTypes.string.isRequired,
};
Expand Down Expand Up @@ -202,6 +204,7 @@ class Sidebar extends Component {
const {
walletSync,
walletHeight,
rescanHeight,
newBlockStatus,
chainHeight,
tip,
Expand All @@ -215,7 +218,7 @@ class Sidebar extends Component {
<div className="sidebar__footer__row">
<div className="sidebar__footer__title">{t('currentHeight')}</div>
<div className="sidebar__footer__text">
{walletSync ? `${walletHeight}/${chainHeight}` : `${chainHeight}` || '--'}
{walletSync ? `${walletHeight}/${rescanHeight}` : `${chainHeight}` || '--'}
</div>
<div className="sidebar__footer__simnet-controls">
{this.renderGenerateBlockButton(1)}
Expand Down
19 changes: 10 additions & 9 deletions app/components/SyncStatus/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {I18nContext} from "../../utils/i18n";
progress,
walletSync: state.wallet.walletSync,
walletHeight: state.wallet.walletHeight,
rescanHeight: state.wallet.rescanHeight,
chainHeight: state.node.chain.height,
};
})
Expand All @@ -40,6 +41,7 @@ class SyncStatus extends Component {
isTestingCustomRPC: PropTypes.bool.isRequired,
walletSync: PropTypes.bool.isRequired,
walletHeight: PropTypes.number.isRequired,
rescanHeight: PropTypes.number,
chainHeight: PropTypes.number.isRequired,
};

Expand All @@ -52,7 +54,6 @@ class SyncStatus extends Component {
isChangingNodeStatus,
isTestingCustomRPC,
isRunning,
isCustomRPCConnected,
walletSync,
progress,
} = this.props;
Expand Down Expand Up @@ -82,31 +83,31 @@ class SyncStatus extends Component {
isSynchronized,
isSynchronizing,
progress,
isRunning,
isCustomRPCConnected,
isChangingNodeStatus,
isTestingCustomRPC,
walletSync,
walletHeight,
rescanHeight,
chainHeight,
} = this.props;

const {t} = this.context;

if (walletSync) {
const percentText = Math.floor((walletHeight * 100) / rescanHeight);
return isCustomRPCConnected
? `${t('rescanningFromRPC')}... (${percentText}%)`
: `${t('rescanning')}... (${percentText}%)`;
}

if (isSynchronizing) {
const progressText = progress ? "(" + (progress * 100).toFixed(2) + "%)" : "";
return isCustomRPCConnected
? `${t('synchronizingFromRPC')}... ${progressText}`
: `${t('synchronizing')}... ${progressText}`;
}

if (walletSync) {
const percentText = Math.floor((walletHeight * 100) / chainHeight);
return isCustomRPCConnected
? `${t('rescanningFromRPC')}... (${percentText}%)`
: `${t('rescanning')}... (${percentText}%)`;
}

if (isSynchronized) {
return isCustomRPCConnected
? t('synchronizedFromRPC')
Expand Down
35 changes: 21 additions & 14 deletions app/ducks/walletActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,38 +179,45 @@ export const waitForWalletSync = () => async (dispatch, getState) => {
let lastProgress = 0;
let stall = 0;

console.log('LOG waitForWalletSync: START')

for (; ;) {
const nodeInfo = await nodeClient.getInfo();
const wdbInfo = await walletClient.rpcGetWalletInfo();
const state = getState();
const nodeHeight = state.node.chain.height;
const {walletHeight, rescanHeight, walletSync} = state.wallet;

if (nodeInfo.chain.height === 0) {
dispatch({type: STOP_SYNC_WALLET});
break;
let progress;
if (walletSync) {
progress = walletHeight / rescanHeight * 100;
} else {
progress = walletHeight / nodeHeight * 100;
}

const progress = parseInt(wdbInfo.height / nodeInfo.chain.height * 100);
console.log('LOG waitForWalletSync:', {
nodeHeight, walletHeight, rescanHeight, walletSync, progress
})

// If we go 5 seconds without any progress, throw an error
// If we go 50 seconds without any progress, throw an error
if (lastProgress === progress) {
stall++;
console.log('LOG waitForWalletSync: STALL', stall)
} else {
lastProgress = progress;
stall = 0;
}

if (stall >= 5) {
dispatch({type: STOP_SYNC_WALLET});
if (stall >= 50) {
console.log('LOG waitForWalletSync: STALL too much', stall)
throw new Error('Wallet sync progress has stalled.');
}

if (progress === 100) {
dispatch({type: STOP_SYNC_WALLET});
if (walletSync ? (rescanHeight === null) : (progress === 100)) {
console.log('LOG waitForWalletSync: END')
break;
} else {
dispatch({type: SYNC_WALLET_PROGRESS, payload: progress});
}

await new Promise((r) => setTimeout(r, 10000));
console.log('LOG waitForWalletSync: wait 1 sec...')
await new Promise((r) => setTimeout(r, 1000));
}
};

Expand Down
Loading

0 comments on commit 7af427a

Please sign in to comment.