Skip to content

Commit

Permalink
[DDW-918] Display block sync progress
Browse files Browse the repository at this point in the history
  • Loading branch information
renanvalentin committed Jan 26, 2022
1 parent 34e3198 commit 737e999
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 85 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,10 @@

- Updated CWB and Cardano Node ([PR 2822](https://github.com/input-output-hk/daedalus/pull/2822))

### Fixes

- Fixed blockain verification progress text ([PR 2830](https://github.com/input-output-hk/daedalus/pull/2830))

## 4.7.0

### Features
Expand Down
11 changes: 8 additions & 3 deletions source/common/ipc/api.js
Expand Up @@ -19,6 +19,7 @@ import type {
CardanoStatus,
FaultInjectionIpcRequest,
TlsConfig,
BlockSyncType,
} from '../types/cardano-node.types';
import type { CheckDiskSpaceResponse } from '../types/no-disk-space.types';
import type { LogFiles } from '../../renderer/app/types/LogTypes';
Expand Down Expand Up @@ -453,9 +454,13 @@ export type IntrospectAddressMainResponse = IntrospectAddressResponse;
/**
* Channel for checking block replay progress
*/
export const GET_BLOCK_REPLAY_STATUS_CHANNEL = 'GetBlockReplayProgressChannel';
export type GetBlockReplayProgressRendererRequest = void;
export type GetBlockReplayProgressMainResponse = number;
export const GET_BLOCK_SYNC_STATUS_CHANNEL = 'GetBlockSyncProgressChannel';
export type GetBlockSyncProgressType = BlockSyncType;
export type GetBlockSyncProgressRendererRequest = void;
export type GetBlockSyncProgressMainResponse = {
progress: number,
type: GetBlockSyncProgressType,
};

/**
* Channels for connecting / interacting with Hardware Wallet devices
Expand Down
5 changes: 5 additions & 0 deletions source/common/types/cardano-node.types.js
Expand Up @@ -174,3 +174,8 @@ export const NetworkMagics: {
// Cardano Selfnode network magic
[SELFNODE]: [1, null],
};

export type BlockSyncType =
| 'validatingChunk'
| 'pushingLedger'
| 'replayedBlock';
3 changes: 2 additions & 1 deletion source/main/index.js
Expand Up @@ -233,6 +233,8 @@ const onAppReady = async () => {

getSystemLocaleChannel.onRequest(() => Promise.resolve(systemLocale));

await handleCheckBlockReplayProgress(mainWindow, launcherConfig.logsPrefix);

const handleCheckDiskSpace = handleDiskSpace(mainWindow, cardanoNode);
const onMainError = (error: string) => {
if (error.indexOf('ENOSPC') > -1) {
Expand All @@ -242,7 +244,6 @@ const onAppReady = async () => {
};
mainErrorHandler(onMainError);
await handleCheckDiskSpace();
await handleCheckBlockReplayProgress(mainWindow, launcherConfig.logsPrefix);

if (isWatchMode) {
// Connect to electron-connect server which restarts / reloads windows on file changes
Expand Down
14 changes: 0 additions & 14 deletions source/main/ipc/get-block-replay-progress.js

This file was deleted.

14 changes: 14 additions & 0 deletions source/main/ipc/get-block-sync-progress.js
@@ -0,0 +1,14 @@
// @flow
import { MainIpcChannel } from './lib/MainIpcChannel';
import { GET_BLOCK_SYNC_STATUS_CHANNEL } from '../../common/ipc/api';
import type {
GetBlockSyncProgressRendererRequest,
GetBlockSyncProgressMainResponse,
} from '../../common/ipc/api';

// IpcChannel<Incoming, Outgoing>

export const getBlockReplayProgressChannel: MainIpcChannel<
GetBlockSyncProgressRendererRequest,
GetBlockSyncProgressMainResponse
> = new MainIpcChannel(GET_BLOCK_SYNC_STATUS_CHANNEL);
50 changes: 46 additions & 4 deletions source/main/utils/handleCheckBlockReplayProgress.js
Expand Up @@ -3,9 +3,47 @@ import { BrowserWindow } from 'electron';
import fs from 'fs';
import readline from 'readline';
import path from 'path';
import { getBlockReplayProgressChannel } from '../ipc/get-block-replay-progress';
import { getBlockReplayProgressChannel } from '../ipc/get-block-sync-progress';
import type { GetBlockSyncProgressType } from '../../common/ipc/api';
import { BLOCK_REPLAY_PROGRESS_CHECK_INTERVAL } from '../config';

const blockKeyword = 'Replayed block';
const validatingChunkKeyword = 'Validating chunk';
const validatedChunkKeyword = 'Validated chunk';
const ledgerKeyword = 'Pushing ledger state';

const progressKeywords = [
blockKeyword,
validatingChunkKeyword,
validatedChunkKeyword,
ledgerKeyword,
];

type KeywordTypeMap = {
[name: string]: GetBlockSyncProgressType,
};

const keywordTypeMap: KeywordTypeMap = {
[blockKeyword]: 'replayedBlock',
[validatingChunkKeyword]: 'validatingChunk',
[validatedChunkKeyword]: 'validatingChunk',
[ledgerKeyword]: 'pushingLedger',
};

function containProgressKeywords(line: string) {
return progressKeywords.some((keyword) => line.includes(keyword));
}

function getProgressType(line: string): ?GetBlockSyncProgressType {
const key = progressKeywords.find((k) => line.includes(k));

if (!key) {
return null;
}

return keywordTypeMap[key];
}

export const handleCheckBlockReplayProgress = (
mainWindow: BrowserWindow,
logsDirectoryPath: string
Expand All @@ -20,19 +58,23 @@ export const handleCheckBlockReplayProgress = (
const rl = readline.createInterface({ input: fileStream });
const progress = [];
for await (const line of rl) {
if (line.includes('block replay')) {
if (containProgressKeywords(line)) {
progress.push(line);
}
}
if (!progress.length) return;

const finalProgress = progress.slice(-1).pop();
const percentage = finalProgress.split('block replay progress (%) =').pop();
const percentage = finalProgress.match(/Progress:([\s\d.,]+)%/)?.[1];
const progressType = getProgressType(finalProgress);
if (!percentage || !progressType) {
return;
}
const finalProgressPercentage = parseFloat(percentage);

// Send result to renderer process (NetworkStatusStore)
getBlockReplayProgressChannel.send(
finalProgressPercentage,
{ progress: finalProgressPercentage, type: progressType },
mainWindow.webContents
);
};
Expand Down
3 changes: 2 additions & 1 deletion source/main/utils/handleDiskSpace.js
Expand Up @@ -181,7 +181,8 @@ export const handleDiskSpace = (
logger.error('[DISK-SPACE-DEBUG] Unknown error', error);
resetInterval(DISK_SPACE_CHECK_MEDIUM_INTERVAL);
}
await getDiskSpaceStatusChannel.send(response, mainWindow.webContents);
const diskReport = await getDiskCheckReport(stateDirectoryPath);
getDiskSpaceStatusChannel.send(diskReport, mainWindow.webContents);
return response;
};

Expand Down
Expand Up @@ -9,7 +9,10 @@ import SyncingConnectingBackground from './SyncingConnectingBackground';
import SyncingConnectingStatus from './SyncingConnectingStatus';
import { CardanoNodeStates } from '../../../../../common/types/cardano-node.types';
import styles from './SyncingConnecting.scss';
import type { CardanoNodeState } from '../../../../../common/types/cardano-node.types';
import type {
CardanoNodeState,
BlockSyncType,
} from '../../../../../common/types/cardano-node.types';
import { REPORT_ISSUE_TIME_TRIGGER } from '../../../config/timingConfig';
import NewsFeedIcon from '../../widgets/NewsFeedIcon';

Expand All @@ -21,7 +24,7 @@ type State = {

type Props = {
cardanoNodeState: ?CardanoNodeState,
verificationProgress: number,
blockSync: { type: BlockSyncType, progress: number },
hasBeenConnected: boolean,
forceConnectivityIssue?: boolean,
isConnected: boolean,
Expand Down Expand Up @@ -163,7 +166,7 @@ export default class SyncingConnecting extends Component<Props, State> {
onToggleNewsFeedIconClick,
showNewsFeedIcon,
isVerifyingBlockchain,
verificationProgress,
blockSync,
} = this.props;

const newsFeedIconStyles = classNames([
Expand Down Expand Up @@ -206,7 +209,7 @@ export default class SyncingConnecting extends Component<Props, State> {
isNodeStopping={isNodeStopping}
isNodeStopped={isNodeStopped}
isVerifyingBlockchain={isVerifyingBlockchain}
verificationProgress={verificationProgress}
blockSync={blockSync}
/>
<StatusIcons
onIconClick={onStatusIconClick}
Expand Down
Expand Up @@ -4,7 +4,10 @@ import { defineMessages, intlShape, FormattedHTMLMessage } from 'react-intl';
import classNames from 'classnames';
import styles from './SyncingConnectingStatus.scss';
import { CardanoNodeStates } from '../../../../../common/types/cardano-node.types';
import type { CardanoNodeState } from '../../../../../common/types/cardano-node.types';
import type {
CardanoNodeState,
BlockSyncType,
} from '../../../../../common/types/cardano-node.types';

const messages = defineMessages({
starting: {
Expand Down Expand Up @@ -80,15 +83,28 @@ const messages = defineMessages({
verifyingBlockchain: {
id: 'loading.screen.verifyingBlockchainMessage',
defaultMessage:
'!!!Cardano node is currently syncing. This process can take several hours',
'!!!Verifying the blockchain ({verificationProgress}% complete)',
description:
'Message on the loading screen informing that sync process could be very long',
'Message "Verifying the blockchain (65% complete) ..." on the loading screen.',
},
validatingChunk: {
id: 'loading.screen.validatingChunk',
defaultMessage: '!!!Validating blocks ({verificationProgress}% complete)',
description:
'Message "Validating blocks (65% complete) ..." on the loading screen.',
},
pushingLedgerState: {
id: 'loading.screen.pushingLedgerState',
defaultMessage:
'!!!Applying a block to ledger ({verificationProgress}% complete)',
description:
'Message "Applying a block to ledger (65% complete) ..." on the loading screen.',
},
});

type Props = {
cardanoNodeState: ?CardanoNodeState,
verificationProgress: number,
blockSync: { type: BlockSyncType, progress: number },
hasLoadedCurrentLocale: boolean,
hasBeenConnected: boolean,
isTlsCertInvalid: boolean,
Expand Down Expand Up @@ -159,12 +175,24 @@ export default class SyncingConnectingStatus extends Component<Props> {
if (isTlsCertInvalid && isConnectingMessage) {
connectingMessage = messages.tlsCertificateNotValidError;
} else if (isVerifyingBlockchain && isConnectingMessage) {
connectingMessage = messages.verifyingBlockchain;
connectingMessage = this.getBlockSyncMessage();
connectingDescription = messages.startingDescription;
}
return { connectingMessage, connectingDescription };
};

getBlockSyncMessage = () => {
switch (this.props.blockSync.type) {
case 'replayedBlock':
return messages.verifyingBlockchain;
case 'pushingLedger':
return messages.pushingLedgerState;
case 'validatingChunk':
default:
return messages.validatingChunk;
}
};

render() {
const { intl } = this.context;
const {
Expand All @@ -173,7 +201,7 @@ export default class SyncingConnectingStatus extends Component<Props> {
isNodeStopped,
isTlsCertInvalid,
hasLoadedCurrentLocale,
verificationProgress,
blockSync,
} = this.props;

if (!hasLoadedCurrentLocale) return null;
Expand All @@ -200,7 +228,7 @@ export default class SyncingConnectingStatus extends Component<Props> {
<div className={componentStyles}>
<h1 className={headlineStyles}>
{intl.formatMessage(connectingMessage, {
verificationProgress,
verificationProgress: blockSync.progress,
})}
</h1>
<div className={styles.description}>
Expand Down
Expand Up @@ -35,7 +35,7 @@ export default class LoadingSyncingConnectingPage extends Component<Props> {
isNotEnoughDiskSpace,
isTlsCertInvalid,
isVerifyingBlockchain,
verificationProgress,
blockSync,
} = networkStatus;
const { displayAppUpdateNewsItem } = appUpdate;
const { hasLoadedCurrentLocale, hasLoadedCurrentTheme } = profile;
Expand Down Expand Up @@ -74,7 +74,7 @@ export default class LoadingSyncingConnectingPage extends Component<Props> {
disableDownloadLogs={app.isDownloadNotificationVisible}
showNewsFeedIcon={!isNodeStopping && !isNodeStopped}
isVerifyingBlockchain={isVerifyingBlockchain}
verificationProgress={verificationProgress}
blockSync={blockSync}
/>
);
}
Expand Down

0 comments on commit 737e999

Please sign in to comment.