-
-
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
Parity Signer #1349
Parity Signer #1349
Conversation
Exciting to see this in action! 😁 @maciejhirsz Are there any plans to support testnets on the parity mobile signer? Additionally, we'll want to disable Parity when non-ethereum networks are selected (e.g. disable parity option when network is ETC). We'll also want to disable Parity Signer as an option for signing messages, similar to how we disable Trezor (I see there is a red alert once parity is selected to sign a message, but it would be better disable the option altogether) |
Testnets are already supported, or did you run into issues? The UI doesn't separate accounts by network, but the chainId is correctly handled when signing the transaction. Signing messages should be possible with the Parity Signer, I haven't investigated that yet, the UI (on the mobile app) might be a bit dumb about it, so will disable the panel there for now. Also will look at disabling it for non-Ethereum networks. |
Got it. I didn't attempt a testnet tx as I didn't see a way to select testnet on the app, but it's good to see that's supported. 👍 to message signing as a later functionality. |
@dternyak I've been looking into it, and I don't really see any issues why the signer shouldn't be able to handle ETC and other networks as well. Basically anything that can be handled by keystore file / privatekey currently, should work with the app, unless there are some differences in how those networks sign txs/messages that I'm unaware of? |
Updated the PR:
FYI: there will be a nicer logo / icon in near future. |
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.
Definitely let me know if any of this feedback seems off base!
common/components/Footer/index.tsx
Outdated
@@ -219,6 +220,7 @@ export default class Footer extends React.PureComponent<Props, State> { | |||
</div> | |||
</footer> | |||
|
|||
<QrSignerModal /> |
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.
Would prefer this component only be rendered where it contextually makes sense, somewhere in the send form.
reasons: { | ||
[SecureWalletName.TREZOR]: 'This wallet can’t sign messages', | ||
[SecureWalletName.PARITY_SIGNER]: 'This wallet can’t sign messages', |
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.
Not your responsibility, but just a reminder that we should be translating this.
margin: 0 0.4em; | ||
} | ||
|
||
.qr-bounds { |
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.
We use SuitCSS naming convention to avoid class name conflicts. Likewise, the a img
above would be better suited by class names.
</div> | ||
<p>{translate('ADD_PARITY_2')}</p> | ||
<p> | ||
<a href="https://itunes.apple.com/us/app/parity-signer/id1218174838" rel="nofollow"> |
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.
Use the NewTabLink
component here.
styles={{ display: 'inline-block' }} | ||
/> | ||
</div> | ||
<p>{translate('ADD_PARITY_2')}</p> |
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.
At some point we should put together a help article that explains this process, or have some additional descriptive copy here.
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.
We are working on a proper help page that describes how to use the signer, I'll add a link to it here once it's done (ideally before publicity but can be done after the PR is merged).
if (!isValidETHAddress(address)) { | ||
console.error('Invalid address!'); | ||
return; | ||
} |
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.
What's the user experience for when this happens? Does the signer keep watching for a potentially valid address?
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.
Yep, it will keep on scanning until a QR code with a valid address is presented.
@@ -0,0 +1,8 @@ | |||
.QrSignerModal { | |||
.qr-bounds { |
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.
Prefer SuitCSS naming convention.
// values in: wallets/non-deterministic/parity.ts | ||
tx.v = Buffer.from([tx._chainId]); | ||
tx.r = Buffer.from([0]); | ||
tx.s = Buffer.from([0]); |
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.
Looks like you're mutating the tx
props object here. If you want to alter something passed in as props, you'll need to copy it and save it in state. Something like...
public componentDidMount() {
if (this.props.tx) {
this.makeStateTx(this.props);
}
}
public componentWillReceiveProps(nextProps: Props) {
if (nextProps.tx && this.props.tx !== nextProps.tx) {
this.makeStateTx(nextProps);
}
}
private makeStateTx(props: Props) {
const tx = { ...props.tx };
tx.v = Buffer.from([tx._chainId]);
tx.r = Buffer.from([0]);
tx.s = Buffer.from([0]);
this.setState({ tx });
}
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.
The values aren't read anywhere down the line, so it shouldn't really matter. Ideally there would be a way to serialize a transaction to RLP in ethereumjs without including the signature (tx.serialize(false)
to match tx.hash(false)
), but that's not the option. I can make a helper function for it here, and make a PR to ethereumjs.
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.
The problem is it makes for non-deterministic redux state, makes it so there's no way to determine if the tx object has changed (without checking deep equality) and in general is just advised against in React.
If you want to avoid the state boilerplate, it could at least do
const tx = { ...this.props.tx };
in render
.
resolve(tx.serialize()); | ||
}; | ||
|
||
this.setWalletQrTransaction(tx, from, onSignature, onCancel); |
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.
Is there a reason this is a callback argument in constructor, instead of just resolving the promise with these variables? Would be nice if the wallet was more agnostic to where it gets used, so that you could use the same wallet instance to sign transactions with two different implementations.
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.
Yeah, this is the part I'm least happy about, and it goes along with how QrSignerModal
is done. The callbacks go up to the container and are in turn placed in redux state for the modal to use.
The component that instantiates the wallet (ParitySignerDecrypt
container in this case) has no knowledge of the modal, and is unmounted after unlocking so it cannot host the QrSignerModal
itself, hence I'm passing these things over redux, which works but also feels over-engineered for my tastes.
Ideally I'd be able to pass the callbacks from the wallet to the modal as props without going through all these gymnastics, but I haven't been able to figure out how to do it any cleaner so far (my understanding of the existing code base is still pretty shallow).
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.
We came up with a migration strategy to move these things to Redux via slack DMs. Those changes probably won't land for a little while though.
common/reducers/wallet.ts
Outdated
export const INITIAL_STATE: State = { | ||
inst: null, | ||
config: null, | ||
signViaQr: null, |
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.
IMO (Would definitely like additional opinions) this should probably be its own reducer with its own set of actions / sagas. I think this is pretty separate from the other wallet processes, and is specific to only the parity signer.
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.
I definitely see maintainability improvements with such a separation of concerns 👍
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.
Great refactor, tested on https://mycryptobuilds.com/047b7a9ff762bb9b7634a1cd886ce9af53f05cfa and it still works great.
export type TFinalize = typeof finalize; | ||
export function finalize(signature: string | null): types.FinalizeAction { | ||
return { | ||
type: TypeKeys.PARITY_SIGNER_FINALIZE, |
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.
Very minor, but I think it would improve code understanding if the word "signature" was a part of this action as well.
isOpen: true; | ||
rlp: string; | ||
from: string; | ||
finalize: TFinalize; |
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.
We usually split out props into props that get specified by parent component (OwnProps), props that are state from redux (StateProps), and props that are actions (ActionProps), so that we can properly type everything. See something like TXMetaDataPanel
for example.
|
||
export default class ParityWallet implements IFullWallet { | ||
export default class ParitySignerWallet implements IFullWallet { |
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.
Appreciate the consistent nomenclature 👍
@@ -177,7 +177,7 @@ const WalletDecrypt = withRouter<Props>( | |||
component: ParitySignerDecrypt, | |||
initialParams: {}, | |||
unlock: this.props.setWallet, | |||
helpLink: 'https://github.com/paritytech/parity-signer/blob/master/README.md' | |||
helpLink: 'https://wiki.parity.io/Parity-Signer-Mobile-App-MyCrypto-tutorial.md' |
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.
I'm assuming this will go online after launch?
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.
… and ismore robust about adding / removing cameras.
Paritysigner adjustments
Closes #1056
Description
Introduces Parity Signer as another secure wallet option on the main screen. Account is unlocked by scanning a QR code of the address from the mobile app. Signing transactions is done in a modal overlaying the UI that first displays the QR code of the RLP of the transaction and then scans for the signature QR code from the mobile app.
Changes
Promise
is being resolved.Promise
required by theIFullWallet
interface.@parity/qr-signer
as a new dependency.Steps to Test
Due to interactions with the webcam, integration tests might be tricky unless a lot of the stuff gets mocked away.
TODO / Known issues
ParitySigner.tsx
needs to be moved to the containers.Screenshots