-
-
Notifications
You must be signed in to change notification settings - Fork 650
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
Web Worker Decrypt #680
Web Worker Decrypt #680
Changes from 2 commits
1079f46
d07428c
c669ee3
f6877ea
5c7f2b5
269d79a
47f7732
5e43fa1
1479e58
596bfe3
69e9799
21cf809
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import { isKeystorePassRequired } from 'libs/wallet'; | ||
import React, { Component } from 'react'; | ||
import translate, { translateRaw } from 'translations'; | ||
import Spinner from 'components/ui/Spinner'; | ||
|
||
export interface KeystoreValue { | ||
file: string; | ||
|
@@ -21,12 +22,14 @@ function isPassRequired(file: string): boolean { | |
export default class KeystoreDecrypt extends Component { | ||
public props: { | ||
value: KeystoreValue; | ||
isWalletLoading: boolean; | ||
onChange(value: KeystoreValue): void; | ||
onUnlock(): void; | ||
}; | ||
|
||
public render() { | ||
const { file, password } = this.props.value; | ||
const isWalletLoading = this.props.isWalletLoading; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not de-structure? |
||
const passReq = isPassRequired(file); | ||
|
||
return ( | ||
|
@@ -46,7 +49,7 @@ export default class KeystoreDecrypt extends Component { | |
{translate('ADD_Radio_2_short')} | ||
</a> | ||
</label> | ||
<div className={file.length && passReq ? '' : 'hidden'}> | ||
<div className={file.length && passReq && !isWalletLoading ? '' : 'hidden'}> | ||
<p>{translate('ADD_Label_3')}</p> | ||
<input | ||
className={`form-control ${password.length > 0 ? 'is-valid' : 'is-invalid'}`} | ||
|
@@ -57,6 +60,7 @@ export default class KeystoreDecrypt extends Component { | |
type="password" | ||
/> | ||
</div> | ||
{isWalletLoading ? <Spinner /> : ''} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor, but you can simplify these boolean checks to |
||
</div> | ||
</div> | ||
</section> | ||
|
@@ -92,8 +96,12 @@ export default class KeystoreDecrypt extends Component { | |
this.props.onChange({ | ||
...this.props.value, | ||
file: keystore, | ||
valid: keystore.length && !passReq | ||
valid: keystore.length && !passReq, | ||
password: '' | ||
}); | ||
if (isPassRequired(keystore)) { | ||
this.props.onUnlock(); | ||
} | ||
}; | ||
|
||
fileReader.readAsText(inputFile, 'utf-8'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { IFullWallet, fromPrivateKey } from 'ethereumjs-wallet'; | ||
import { toBuffer } from 'ethereumjs-util'; | ||
const Worker = require('worker-loader!./workers/scrypt-worker.worker.ts'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should setup typing for this, as outlined here: https://github.com/webpack-contrib/worker-loader#integrating-with-typescript. Right now it's an implicit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still typed as any, but
seems to fix it! |
||
|
||
export const fromV3 = ( | ||
keystore: string, | ||
password: string, | ||
nonStrict: boolean | ||
): Promise<IFullWallet> => { | ||
return new Promise((resolve, reject) => { | ||
const scryptWorker = new Worker(); | ||
scryptWorker.postMessage({ keystore, password, nonStrict }); | ||
scryptWorker.onmessage = event => { | ||
try { | ||
const wallet = fromPrivateKey(toBuffer(event.data)); | ||
resolve(wallet); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { fromV3, IFullWallet } from 'ethereumjs-wallet'; | ||
|
||
declare var postMessage: any; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From https://github.com/webpack-contrib/worker-loader#integrating-with-typescript:
for typing |
||
interface DecryptionParameters { | ||
keystore: string; | ||
password: string; | ||
nonStrict: boolean; | ||
} | ||
|
||
onmessage = event => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. event could use typing |
||
const info: DecryptionParameters = event.data; | ||
try { | ||
const rawKeystore: IFullWallet = fromV3(info.keystore, info.password, info.nonStrict); | ||
postMessage(rawKeystore.getPrivateKeyString()); | ||
} catch (e) { | ||
postMessage(e.message); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ import { | |
setTokenBalancesFulfilled, | ||
setTokenBalancesRejected, | ||
setWallet, | ||
setWalletLoading, | ||
setWalletConfig, | ||
UnlockKeystoreAction, | ||
UnlockMnemonicAction, | ||
|
@@ -24,12 +25,16 @@ import { | |
MnemonicWallet, | ||
getPrivKeyWallet, | ||
getKeystoreWallet, | ||
determineKeystoreType, | ||
KeystoreTypes, | ||
getUtcWallet, | ||
signWrapper, | ||
Web3Wallet, | ||
WalletConfig | ||
} from 'libs/wallet'; | ||
import { NODES, initWeb3Node } from 'config/data'; | ||
import { SagaIterator } from 'redux-saga'; | ||
import { apply, call, fork, put, select, takeEvery, take } from 'redux-saga/effects'; | ||
import { SagaIterator, delay, Task } from 'redux-saga'; | ||
import { apply, call, fork, put, select, takeEvery, take, cancel } from 'redux-saga/effects'; | ||
import { getNodeLib } from 'selectors/config'; | ||
import { | ||
getTokens, | ||
|
@@ -141,18 +146,43 @@ export function* unlockPrivateKey(action: UnlockPrivateKeyAction): SagaIterator | |
yield put(setWallet(wallet)); | ||
} | ||
|
||
export function* startLoadingSpinner(): SagaIterator { | ||
yield call(delay, 1000); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd probably shorten this to 300-500, a full second before having the site respond is a little long. |
||
yield put(setWalletLoading(true)); | ||
} | ||
|
||
export function* stopLoadingSpinner(loadingFork: Task | null): SagaIterator { | ||
if (loadingFork !== null) { | ||
yield cancel(loadingFork); | ||
} | ||
yield put(setWalletLoading(false)); | ||
} | ||
|
||
export function* unlockKeystore(action: UnlockKeystoreAction): SagaIterator { | ||
const { file, password } = action.payload; | ||
let wallet: null | IWallet = null; | ||
|
||
let spinnerTask: null | Task = null; | ||
try { | ||
wallet = getKeystoreWallet(file, password); | ||
if (determineKeystoreType(file) === KeystoreTypes.utc) { | ||
spinnerTask = yield fork(startLoadingSpinner); | ||
wallet = signWrapper(yield call(getUtcWallet, file, password)); | ||
} else { | ||
yield call(stopLoadingSpinner, spinnerTask); | ||
wallet = getKeystoreWallet(file, password); | ||
} | ||
} catch (e) { | ||
yield put(showNotification('danger', translate('ERROR_6'))); | ||
yield call(stopLoadingSpinner, spinnerTask); | ||
if ( | ||
password !== '' || | ||
e.message !== 'Private key does not satisfy the curve requirements (ie. it is invalid)' | ||
) { | ||
yield put(showNotification('danger', translate('ERROR_6'))); | ||
} | ||
return; | ||
} | ||
|
||
// TODO: provide a more descriptive error than the two 'ERROR_6' (invalid pass) messages above | ||
yield put(setWalletLoading(false)); | ||
yield put(setWallet(wallet)); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,7 +110,8 @@ | |
"webpack": "3.10.0", | ||
"webpack-dev-middleware": "2.0.3", | ||
"webpack-hot-middleware": "2.21.0", | ||
"webpack-sources": "1.0.1" | ||
"webpack-sources": "1.0.1", | ||
"worker-loader": "^1.1.0" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lock down version # (We try to avoid |
||
}, | ||
"scripts": { | ||
"freezer": "webpack --config=./webpack_config/webpack.freezer.js && node ./dist/freezer.js", | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing nomenclature would be
setWalletPending