// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // // SPDX-License-Identifier: BSD-3-Clause import { app } from 'electron'; import axios from 'axios'; import cs from 'checksum'; import { download } from 'electron-dl'; import fs from 'fs'; import { promisify } from 'util'; import retry from 'async-retry'; import debug from './utils/debug'; import { defaultParityPath, getParityPath } from './getParityPath'; import parityChannel from './utils/parityChannel'; const checksum = promisify(cs.file); const fsChmod = promisify(fs.chmod); const fsStat = promisify(fs.stat); const fsUnlink = promisify(fs.unlink); const VANITY_URL = 'https://vanity-service.parity.io/parity-binaries'; const getArch = () => { switch (process.platform) { case 'darwin': case 'win32': return 'x86_64'; default: { switch (process.arch) { case 'arm': return 'arm'; case 'arm64': return 'aarch64'; case 'x32': return 'i686'; default: return 'x86_64'; } } } }; const getOs = () => { switch (process.platform) { case 'darwin': return 'darwin'; case 'win32': return 'windows'; default: return 'linux'; } }; /** * Remove parity binary in the userData folder */ export const deleteParity = async () => { try { const parityPath = await defaultParityPath(); await fsStat(parityPath); await fsUnlink(parityPath); } catch (e) {} }; // Fetch parity from https://vanity-service.parity.io/parity-binaries export const fetchParity = (mainWindow, onProgress) => { try { return retry( async (_, attempt) => { if (attempt > 1) { debug('main')('Retrying.'); } // Delete any old Parity if it exists await deleteParity(); // Fetch the metadata of the correct version of parity const metadataUrl = `${VANITY_URL}?version=${parityChannel()}&os=${getOs()}&architecture=${getArch()}`; debug('main')(`Downloading from ${metadataUrl}.`); const { data } = await axios.get(metadataUrl); // Get the binary's url const { downloadUrl, checksum: expectedChecksum } = data[0].files.find( ({ name }) => name === 'parity' || name === 'parity.exe' ); // Start downloading. This will install parity into defaultParityPath. const downloadItem = await download(mainWindow, downloadUrl, { directory: app.getPath('userData'), onProgress }); const downloadPath = downloadItem.getSavePath(); // Equal to defaultParityPath // Once downloaded, we check the sha256 checksum // Calculate the actual checksum const actualChecksum = await checksum(downloadPath, { algorithm: 'sha256' }); // The 2 checksums should of course match if (expectedChecksum !== actualChecksum) { throw new Error( `Checksum mismatch, expecting ${expectedChecksum}, got ${actualChecksum}.` ); } // Set a+x permissions on the downloaded binary await fsChmod(downloadPath, '755'); // Double-check that Parity exists now. const parityPath = await getParityPath(); return parityPath; }, { retries: 3 } ); } catch (err) { return deleteParity().then(() => { Promise.reject(err); }); } };