Skip to content

Commit

Permalink
Catch corrupt Wagerr database on launch and ask user to resync
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryptarchist committed Dec 18, 2020
1 parent 9a5e9e4 commit 687cae9
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 73 deletions.
41 changes: 22 additions & 19 deletions src/main/blockchain/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,18 @@ import os from 'os';
import fs from 'fs';
import path from 'path';
import { spawn } from 'child_process';
import decompress from 'decompress';
import findProcess from 'find-process';
import { app, BrowserWindow, dialog } from 'electron';
import errDialog from '../alerts/errors';
import constants from '../constants/constants';
import * as blockchain from './blockchain';

const request = require('request');
const packageJSON = require('../../../package.json');

export default class Daemon {
wagerrdProcess;

constructor() {}

/**
* Launch the wagerrd process with the given list of command line args.
*/
runCommand(cmd) {
return new Promise(async resolve => {
return new Promise(async (resolve) => {
const cliPath = this.getExecutablePath('wagerr-cli');
console.log(
'Confirm the cli params',
Expand Down Expand Up @@ -55,29 +47,40 @@ export default class Daemon {
});
}

launch(args) {
launch(window, args) {
const wagerrdPath = this.getExecutablePath('wagerrd');
const wagerrdArgs = this.getWagerrdArgs(args);

console.log(`\x1b[32m Launching daemon: ${wagerrdPath}\x1b[32m`);
console.log(`\x1b[32m Following args used: ${wagerrdArgs}\x1b[32m`);

// Change file permissions so we can run the wagerrd.
fs.chmod(wagerrdPath, '0777', err => {
fs.chmod(wagerrdPath, '0777', (err) => {
if (err) {
console.error(err);
}

// Spawn the wagerrd and attach event callbacks.
this.wagerrdProcess = spawn(wagerrdPath, wagerrdArgs);
this.wagerrdProcess.stdout.on('data', data =>
console.log(`Daemon: ${data}`)
);
this.wagerrdProcess.stderr.on('data', data =>
console.error(`Daemon: ${data}`)
);
this.wagerrdProcess.on('error', data => errDialog.wagerrdError(data));
this.wagerrdProcess.on('exit', data => errDialog.wagerrdStopped());

this.wagerrdProcess.stdout.on('data', (data) => {
console.log(`Daemon: ${data}`);
});

this.wagerrdProcess.stderr.on('data', (data) => {
if (data.includes('Error loading block database')) {
// this.wagerrdProcess.stop();
window.webContents.send('wagerr-corrupt-database');
} else {
console.error(`Daemon: ${data}`);
}
});

this.wagerrdProcess.on('error', (data) => {
errDialog.wagerrdError(data);
});

this.wagerrdProcess.on('exit', (data) => errDialog.wagerrdStopped());
});
}

Expand Down
8 changes: 4 additions & 4 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ async function createMainWindow() {
* @returns {Promise<void>}
*/
export async function init(args) {
// Start main window first so if we catch certain errors on wagerrd launch we show them on the UI.
await createMainWindow();

logger.info('Initialising Wagerr Electron App');
daemon = new Daemon();

Expand Down Expand Up @@ -211,15 +214,12 @@ export async function init(args) {

// If not then start it.
if (!isRunning) {
daemon.launch(args);
daemon.launch(mainWindow, args);
} else {
// Show popup warning the users a wagerrd instance is all ready running.
forcelyQuit = true;
errors.deamonRunningError();
}

// Render the main window.
await createMainWindow();
}

app.on('ready', async () => {
Expand Down
107 changes: 57 additions & 50 deletions src/renderer/components/splashscreen/SplashScreen.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@

<div class="col s12">
<transition name="slide-fade" mode="out-in">
<div :key="initText">
<div v-if="!wagerrCorruptDatabase" :key="initText">
<h5>{{ initText }}</h5>
</div>
<div v-else :key="'Corrupt database'">
<h5>
⚠️ Error loading block database. This can occur when upgrading, please resync below.️
</h5>
</div>
</transition>
</div>

<div class="col s12 splash-loading-container">
<div v-if="!wagerrCorruptDatabase" class="col s12 splash-loading-container">
<div class="slider">
<div class="line"></div>
<div class="break dot1"></div>
Expand All @@ -30,23 +35,23 @@
/>

<div class="splash-wallet-repair text-center">
<div>
<div v-if="!wagerrCorruptDatabase">
<a href="#" @click="restartWallet">Restart Wallet</a>
</div>

<div>
<div v-if="!wagerrCorruptDatabase">
<a href="#" @click="rescanBlockchain">Rescan Blockchain Files</a>
</div>

<div>
<div v-if="!wagerrCorruptDatabase">
<a href="#" @click="reindexBlockchain">Reindex Blockchain</a>
</div>

<div>
<a href="#" @click="resyncBlockchain">Resync Blockchain</a>
</div>

<div>
<div v-if="!wagerrCorruptDatabase">
<a href="#" @click="onOpenConf">Wagerr.Conf</a>
</div>
</div>
Expand All @@ -55,20 +60,15 @@
</template>

<script>
import { remote, shell } from 'electron';
import { ipcRenderer, shell } from 'electron';
import moment from 'moment';
import { path } from 'path';
import fs from 'fs';
import { mapActions, mapGetters } from 'vuex';
import blockchainRPC from '../../services/api/blockchain_rpc';
import networkRPC from '../../services/api/network_rpc';
import ipcRenderer from '../../../common/ipc/ipcRenderer';
import ipcRendererHandler from '../../../common/ipc/ipcRenderer';
import { getWagerrConfPath } from '../../../main/blockchain/blockchain';
import DownloadSnapshot from './DownloadSnapshot.vue';
import {
blockchainSnapshot,
syncMethods
} from '../../../main/constants/constants';
import { syncMethods } from '../../../main/constants/constants';
export default {
name: 'SplashScreen',
Expand All @@ -79,7 +79,8 @@ export default {
confPath: getWagerrConfPath(),
syncMethod: syncMethods.SCAN_BLOCKS,
timeBehindText: '',
mayDownloadSnapshot: false
mayDownloadSnapshot: false,
wagerrCorruptDatabase: false
};
},
Expand All @@ -103,23 +104,23 @@ export default {
]),
rescanBlockchain: function() {
ipcRenderer.rescanBlockchain();
ipcRendererHandler.rescanBlockchain();
},
reindexBlockchain: function() {
ipcRenderer.reindexBlockchain();
ipcRendererHandler.reindexBlockchain();
},
resyncBlockchain: function() {
ipcRenderer.resyncBlockchain();
ipcRendererHandler.resyncBlockchain();
},
restartWallet: function() {
ipcRenderer.restartWallet();
ipcRendererHandler.restartWallet();
},
closeWallet: function() {
ipcRenderer.closeWallet();
ipcRendererHandler.closeWallet();
},
updateSyncMethod: function(syncMethod) {
Expand Down Expand Up @@ -157,7 +158,7 @@ export default {
let peersFound = false;
this.updateInitText('Connecting to peers... this may take some time!');
ipcRenderer.log('info', 'Waiting for daemon to find peers');
ipcRendererHandler.log('info', 'Waiting for daemon to find peers');
// While no peers have connected to the daemon keep looping.
while (!peersFound) {
Expand All @@ -174,11 +175,11 @@ export default {
// Give the daemon an arbitrary 101 loops to find peers. If not show an error to the user.
if (count === 100) {
ipcRenderer.log(
ipcRendererHandler.log(
'warn',
'No peers could be found, please review your Wagerr Core logs'
);
ipcRenderer.noPeers();
ipcRendererHandler.noPeers();
return 1;
}
Expand All @@ -188,15 +189,15 @@ export default {
// Once peers have been found resolve the Promise.
if (peersFound) {
ipcRenderer.log('info', 'Connected to network');
ipcRendererHandler.log('info', 'Connected to network');
return 1;
}
},
// Check for daemon initialized
checkDaemonInitialized: async function() {
this.updateInitText('Initializing daemon... this may take some time!');
ipcRenderer.log('info', 'Waiting for daemon to initialize');
ipcRendererHandler.log('info', 'Waiting for daemon to initialize');
// wait 50 seconds + 10 previous seconds => 1 minute so daemon can initialize
await this.sleep(50000);
Expand All @@ -207,7 +208,7 @@ export default {
// If we have successfully connected to peers break out of the loop.
if (netInfo.blocks !== -1) {
ipcRenderer.log('info', 'Daemon initialized');
ipcRendererHandler.log('info', 'Daemon initialized');
break;
}
Expand All @@ -219,7 +220,7 @@ export default {
// Show the blockchain sync status information.
syncBlockchainStatus: async function() {
let blockchainInfo, durationBehind, synced = false;
ipcRenderer.log('info', 'Syncing blockchain');
ipcRendererHandler.log('info', 'Syncing blockchain');
while (!synced) {
if (this.syncMethod === syncMethods.SCAN_BLOCKS) {
Expand Down Expand Up @@ -255,13 +256,13 @@ export default {
// Once peers have been found resolve the Promise.
if (synced) {
ipcRenderer.log('info', 'Blockchain is now synced with network');
ipcRendererHandler.log('info', 'Blockchain is now synced with network');
return 1;
}
},
onOpenConf: function() {
ipcRenderer.log('debug', 'Opening wagerr.conf file');
ipcRendererHandler.log('debug', 'Opening wagerr.conf file');
shell.openItem(this.confPath);
},
Expand All @@ -277,27 +278,33 @@ export default {
},
async mounted() {
// On some computers (especially Windows) the daemon is taking a while to
// launch. If we start hitting it with RPC calls too early the app might
// fail to launch in some instances. Dirty workaround to allow 10 seconds
// before moving to the RPC calls.
await this.sleep(10000);
// Wait for the daemon to be initialized
await this.checkDaemonInitialized();
// Check if connected to the Wagerr network and if we have peers.
await this.checkPeerStatus();
// Set the network.
let blockchainInfo = await blockchainRPC.getBlockchainInfo();
let network = blockchainInfo.chain === 'test' ? 'Testnet' : 'Mainnet';
// load User Config - could use methods access, instead of store.dispatch
await this.loadUserSettings(network);
await this.updateNetworkType(network);
// If Wallet not synced show time behind text.
await this.syncBlockchainStatus();
ipcRenderer.on('wagerr-corrupt-database', () => {
this.wagerrCorruptDatabase = true;
});
if (!this.wagerrCorruptDatabase) {
// On some computers (especially Windows) the daemon is taking a while to
// launch. If we start hitting it with RPC calls too early the app might
// fail to launch in some instances. Dirty workaround to allow 10 seconds
// before moving to the RPC calls.
await this.sleep(10000);
// Wait for the daemon to be initialized
await this.checkDaemonInitialized();
// Check if connected to the Wagerr network and if we have peers.
await this.checkPeerStatus();
// Set the network.
let blockchainInfo = await blockchainRPC.getBlockchainInfo();
let network = blockchainInfo.chain === 'test' ? 'Testnet' : 'Mainnet';
// load User Config - could use methods access, instead of store.dispatch
await this.loadUserSettings(network);
await this.updateNetworkType(network);
// If Wallet not synced show time behind text.
await this.syncBlockchainStatus();
}
}
};
</script>

0 comments on commit 687cae9

Please sign in to comment.