Decrypting for external accounts. (#5581)
This commit is contained in:
parent
4df1772078
commit
879195397e
@ -103,6 +103,12 @@ export default class SignerMiddleware {
|
|||||||
return this.confirmRawRequest(store, id, signature);
|
return this.confirmRawRequest(store, id, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
confirmDecryptedMsg (store, id, decrypted) {
|
||||||
|
const { msg } = decrypted;
|
||||||
|
|
||||||
|
return this.confirmRawRequest(store, id, msg);
|
||||||
|
}
|
||||||
|
|
||||||
confirmSignedTransaction (store, id, txSigned) {
|
confirmSignedTransaction (store, id, txSigned) {
|
||||||
const { netVersion } = store.getState().nodeStatus;
|
const { netVersion } = store.getState().nodeStatus;
|
||||||
const { signature, tx } = txSigned;
|
const { signature, tx } = txSigned;
|
||||||
@ -153,7 +159,7 @@ export default class SignerMiddleware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onConfirmStart = (store, action) => {
|
onConfirmStart = (store, action) => {
|
||||||
const { condition, gas = 0, gasPrice = 0, id, password, payload, txSigned, dataSigned, wallet } = action.payload;
|
const { condition, gas = 0, gasPrice = 0, id, password, payload, txSigned, dataSigned, decrypted, wallet } = action.payload;
|
||||||
const handlePromise = this._createConfirmPromiseHandler(store, id);
|
const handlePromise = this._createConfirmPromiseHandler(store, id);
|
||||||
const transaction = payload.sendTransaction || payload.signTransaction;
|
const transaction = payload.sendTransaction || payload.signTransaction;
|
||||||
|
|
||||||
@ -176,10 +182,14 @@ export default class SignerMiddleware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO [ToDr] Support eth_sign for external wallet (wallet && !transction)
|
// TODO [ToDr] Support eth_sign for external wallet (wallet && dataSigned)
|
||||||
if (dataSigned) {
|
if (dataSigned) {
|
||||||
return this.confirmSignedData(store, id, dataSigned);
|
return this.confirmSignedData(store, id, dataSigned);
|
||||||
}
|
}
|
||||||
|
// TODO [ToDr] Support parity_decrypt for external wallet (wallet && decrypted)
|
||||||
|
if (decrypted) {
|
||||||
|
return this.confirmDecryptedMsg(store, id, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
return handlePromise(this._api.signer.confirmRequest(id, { gas, gasPrice, condition }, password));
|
return handlePromise(this._api.signer.confirmRequest(id, { gas, gasPrice, condition }, password));
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,16 @@ export function generateDataQr (data) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateDecryptQr (data) {
|
||||||
|
return Promise.resolve({
|
||||||
|
decrypt: data,
|
||||||
|
value: JSON.stringify({
|
||||||
|
action: 'decrypt',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function generateTxQr (api, netVersion, transaction) {
|
export function generateTxQr (api, netVersion, transaction) {
|
||||||
return createUnsignedTx(api, netVersion, transaction)
|
return createUnsignedTx(api, netVersion, transaction)
|
||||||
.then((qr) => {
|
.then((qr) => {
|
||||||
|
@ -114,7 +114,7 @@ class DecryptRequest extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderActions () {
|
renderActions () {
|
||||||
const { accounts, address, focus, isFinished, status } = this.props;
|
const { accounts, address, focus, isFinished, status, data } = this.props;
|
||||||
const account = accounts[address];
|
const account = accounts[address];
|
||||||
|
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
@ -153,15 +153,16 @@ class DecryptRequest extends Component {
|
|||||||
onConfirm={ this.onConfirm }
|
onConfirm={ this.onConfirm }
|
||||||
onReject={ this.onReject }
|
onReject={ this.onReject }
|
||||||
className={ styles.actions }
|
className={ styles.actions }
|
||||||
|
dataToSign={ { decrypt: data } }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onConfirm = (data) => {
|
onConfirm = (data) => {
|
||||||
const { id } = this.props;
|
const { id } = this.props;
|
||||||
const { password } = data;
|
const { password, decrypted, wallet } = data;
|
||||||
|
|
||||||
this.props.onConfirm({ id, password });
|
this.props.onConfirm({ id, password, decrypted, wallet });
|
||||||
}
|
}
|
||||||
|
|
||||||
onReject = () => {
|
onReject = () => {
|
||||||
|
@ -40,6 +40,12 @@ const PAYLOAD_SIGN = {
|
|||||||
const PAYLOAD_SIGNTX = {
|
const PAYLOAD_SIGNTX = {
|
||||||
signTransaction: TRANSACTION
|
signTransaction: TRANSACTION
|
||||||
};
|
};
|
||||||
|
const PAYLOAD_DECRYPT = {
|
||||||
|
decrypt: {
|
||||||
|
address: ADDRESS,
|
||||||
|
msg: 'testing'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let component;
|
let component;
|
||||||
let onConfirm;
|
let onConfirm;
|
||||||
@ -109,4 +115,18 @@ describe('views/Signer/RequestPending', () => {
|
|||||||
expect(component.find('Connect(TransactionPending)')).to.have.length(1);
|
expect(component.find('Connect(TransactionPending)')).to.have.length(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('decrypt', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render(PAYLOAD_DECRYPT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders defaults', () => {
|
||||||
|
expect(component).to.be.ok;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders DecryptRequest component', () => {
|
||||||
|
expect(component.find('Connect(DecryptRequest)')).to.have.length(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
|
||||||
import { Form, Input, IdentityIcon, QrCode, QrScan } from '~/ui';
|
import { Form, Input, IdentityIcon, QrCode, QrScan } from '~/ui';
|
||||||
import { generateTxQr, generateDataQr } from '~/util/qrscan';
|
import { generateTxQr, generateDataQr, generateDecryptQr } from '~/util/qrscan';
|
||||||
|
|
||||||
import styles from './transactionPendingFormConfirm.css';
|
import styles from './transactionPendingFormConfirm.css';
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
return (
|
return (
|
||||||
<QrScan
|
<QrScan
|
||||||
className={ styles.camera }
|
className={ styles.camera }
|
||||||
onScan={ this.onScanTx }
|
onScan={ this.onScan }
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -404,8 +404,8 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onScanTx = (signature) => {
|
onScan = (signature) => {
|
||||||
const { chainId, rlp, tx, data } = this.state.qr;
|
const { chainId, rlp, tx, data, decrypt } = this.state.qr;
|
||||||
|
|
||||||
if (signature && signature.substr(0, 2) !== '0x') {
|
if (signature && signature.substr(0, 2) !== '0x') {
|
||||||
signature = `0x${signature}`;
|
signature = `0x${signature}`;
|
||||||
@ -425,6 +425,16 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (decrypt) {
|
||||||
|
this.props.onConfirm({
|
||||||
|
decrypted: {
|
||||||
|
decrypt,
|
||||||
|
msg: signature
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.props.onConfirm({
|
this.props.onConfirm({
|
||||||
dataSigned: {
|
dataSigned: {
|
||||||
data,
|
data,
|
||||||
@ -499,7 +509,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
generateQr = () => {
|
generateQr = () => {
|
||||||
const { api } = this.context;
|
const { api } = this.context;
|
||||||
const { netVersion, dataToSign } = this.props;
|
const { netVersion, dataToSign } = this.props;
|
||||||
const { transaction, data } = dataToSign;
|
const { transaction, data, decrypt } = dataToSign;
|
||||||
const setState = qr => {
|
const setState = qr => {
|
||||||
this.setState({ qr });
|
this.setState({ qr });
|
||||||
};
|
};
|
||||||
@ -509,6 +519,11 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (decrypt) {
|
||||||
|
generateDecryptQr(decrypt).then(setState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
generateDataQr(data).then(setState);
|
generateDataQr(data).then(setState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +562,7 @@ export default class TransactionPendingFormConfirm extends Component {
|
|||||||
const { account, dataToSign } = this.props;
|
const { account, dataToSign } = this.props;
|
||||||
const { qr } = this.state;
|
const { qr } = this.state;
|
||||||
|
|
||||||
if (dataToSign.data && qr && !qr.value) {
|
if ((dataToSign.data || dataToSign.decrypt) && qr && !qr.value) {
|
||||||
this.generateQr();
|
this.generateQr();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,9 @@ export default class TransactionPendingForm extends Component {
|
|||||||
}),
|
}),
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
data: PropTypes.string.isRequired
|
data: PropTypes.string.isRequired
|
||||||
|
}),
|
||||||
|
PropTypes.shape({
|
||||||
|
decrypt: PropTypes.string.isRequired
|
||||||
})
|
})
|
||||||
]).isRequired
|
]).isRequired
|
||||||
};
|
};
|
||||||
|
@ -201,8 +201,10 @@ impl<D: Dispatcher + 'static> Signer for SignerClient<D> {
|
|||||||
Err(err) => Err(errors::invalid_params("Invalid signature received.", err)),
|
Err(err) => Err(errors::invalid_params("Invalid signature received.", err)),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO [ToDr]: Decrypt - pass through?
|
ConfirmationPayload::Decrypt(_address, _data) => {
|
||||||
_ => Err(errors::unimplemented(Some("Non-transaction requests does not support RAW signing yet.".into()))),
|
// TODO [ToDr]: Decrypt can we verify if the answer is correct?
|
||||||
|
Ok(ConfirmationResponse::Decrypt(bytes))
|
||||||
|
},
|
||||||
};
|
};
|
||||||
if let Ok(ref response) = result {
|
if let Ok(ref response) = result {
|
||||||
signer.request_confirmed(id, Ok(response.clone()));
|
signer.request_confirmed(id, Ok(response.clone()));
|
||||||
|
@ -28,7 +28,7 @@ use jsonrpc_core::IoHandler;
|
|||||||
use v1::{SignerClient, Signer, Origin};
|
use v1::{SignerClient, Signer, Origin};
|
||||||
use v1::metadata::Metadata;
|
use v1::metadata::Metadata;
|
||||||
use v1::tests::helpers::TestMinerService;
|
use v1::tests::helpers::TestMinerService;
|
||||||
use v1::types::H520;
|
use v1::types::{Bytes as RpcBytes, H520};
|
||||||
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
||||||
use v1::helpers::dispatch::{FullDispatcher, eth_data_hash};
|
use v1::helpers::dispatch::{FullDispatcher, eth_data_hash};
|
||||||
|
|
||||||
@ -479,7 +479,6 @@ fn should_confirm_sign_transaction_with_rlp() {
|
|||||||
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
|
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_confirm_data_sign_with_signature() {
|
fn should_confirm_data_sign_with_signature() {
|
||||||
// given
|
// given
|
||||||
@ -510,6 +509,34 @@ fn should_confirm_data_sign_with_signature() {
|
|||||||
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
|
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_confirm_decrypt_with_phrase() {
|
||||||
|
// given
|
||||||
|
let tester = signer_tester();
|
||||||
|
let address = tester.accounts.new_account("test").unwrap();
|
||||||
|
tester.signer.add_request(ConfirmationPayload::Decrypt(
|
||||||
|
address,
|
||||||
|
vec![1, 2, 3, 4].into(),
|
||||||
|
), Origin::Unknown).unwrap();
|
||||||
|
assert_eq!(tester.signer.requests().len(), 1);
|
||||||
|
|
||||||
|
let decrypted = serde_json::to_string(&RpcBytes::new(b"phrase".to_vec())).unwrap();
|
||||||
|
|
||||||
|
// when
|
||||||
|
let request = r#"{
|
||||||
|
"jsonrpc":"2.0",
|
||||||
|
"method":"signer_confirmRequestRaw",
|
||||||
|
"params":["0x1", "#.to_owned() + &decrypted + r#"],
|
||||||
|
"id":1
|
||||||
|
}"#;
|
||||||
|
let response = r#"{"jsonrpc":"2.0","result":"#.to_owned() + &decrypted + r#","id":1}"#;
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(tester.io.handle_request_sync(&request), Some(response.to_owned()));
|
||||||
|
assert_eq!(tester.signer.requests().len(), 0);
|
||||||
|
assert_eq!(tester.miner.imported_transactions.lock().len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn should_generate_new_token() {
|
fn should_generate_new_token() {
|
||||||
// given
|
// given
|
||||||
|
Loading…
Reference in New Issue
Block a user