Skip to content
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

Trezor Unlock + Deterministic Wallet Groundwork #137

Merged
merged 14 commits into from
Aug 28, 2017
Merged

Trezor Unlock + Deterministic Wallet Groundwork #137

merged 14 commits into from
Aug 28, 2017

Conversation

wbobeirne
Copy link
Contributor

@wbobeirne wbobeirne commented Aug 27, 2017

What This Does

This is the first pass at hardware wallet support, starting with Trezor, since that's the one I own. It allows for the unlocking of, and signing transactions for Trezor wallets. It also lays down a lot of the groundwork for future deterministic path generated wallets (Mnemonic, ledger, etc.)

Don't let the line count fool you, this PR isn't that big. The bulk of it was because of common/vendor/trezor-connect.js. It's not on NPM, so it has to be loaded into the project directly. Currently in talks with them about the future of Trezor Connect.

The wallet modal was modeled after #129, not v3 directly, so there are some noteworthy differences.

What This Doesn't Do

  • Other hardware wallets
  • Nearly enough unit testing, would love to figure out a way to do this better
  • Message signing
    • There's no base method for this on BaseWallet, and I wasn't sure how solid the private key implementation was, so I figured I'd hold off on this until it came up
  • Guaranteed accurate transaction signing
    • I implemented it as best I could from v3, but without broadcasting, it's hard to be sure I'm doing it right. Would love some help in auditing this.

Basic Technical Overview

This is how Trezor does everything, and presumably the other HW wallets will have a similar flow:

  • All interfacing with Trezor happens at the component layer in components/WalletDecrypt/Trezor.jsx via TrezorConnect
  • Callbacks from TrezorConnect update props sent to components/WalletDecrypt/DeterministicWalletsModal.jsx
  • The modal component is connected, and fires off actions to the deterministicWallets reducer / saga
  • Changes that happen in the modal (changing path, selecting address) are bubbled back up to Trezor.jsx
  • Once a wallet is selected, Trezor.jsx calls onUnlock and creates a new TrezorWallet instance
  • TrezorWallet extends the DeterministicWallet, and only differs for signRawTransaction (And presumably signMessage in the future)

Trezor in Action

GIFs were recorded at reduced sizes, and addresses / amounts blurred, so don't worry if things look a little odd

Connecting

trezor-connect


Token Values

trezor-tokens


Paging to More Addresses

trezor-paging


Path Selection

trezor-path


Unlocking

trezor-unlocking

@wbobeirne wbobeirne mentioned this pull request Aug 27, 2017
15 tasks
import TrezorWallet from 'libs/wallet/trezor';

/* eslint-disable quotes */
const TREZOR_PATHS = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider moving out of component (and into config)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -47,8 +48,8 @@ export function getTransactionFields(tx: EthTx) {
const [nonce, gasPrice, gasLimit, to, value, data, v, r, s] = tx.toJSON();

return {
// No value comes back as '0x', but most things expect '0x0'
value: value === '0x' ? '0x0' : value,
// No value comes back as '0x', but most things expect '0x00'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any link to this? seems like we're changing it once already, so would be good to know where this info is coming from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, would definitely be good to figure out the "correct" behavior here. I just used these values based on complaining libraries. 0x0 from 0x came from the node, 0x00 came from Trezor wanting padded values.

@@ -121,13 +122,14 @@ export async function generateTransaction(

// Generate the raw transaction
const txCount = await node.getTransactionCount(tx.from);
const cleanHex = hex => addHexPrefix(padToEven(stripHex(hex)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of padding are we doing here? Maybe some comments to explain?

Copy link
Contributor Author

@wbobeirne wbobeirne Aug 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was taken from v3's sanitizeHex behavior, Trezor wanted %2 length fields. I can definitely add some comments to v3, but I don't truly understand the reasoning.

@@ -139,3 +139,7 @@ export function isValidRawTx(rawTx: RawTransaction): boolean {

return true;
}

export function isValidPath(dPath: string) {
return dPath.split('\'/').length === 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a comment here explaining what's going on. I get that the deterministic path is being split, but its not extremely clear why 4 is important

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki has more information, and test cases, I'll try to add a useful comment and implement some of its test cases.

Copy link
Contributor

@skubakdj skubakdj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome PR @wbobeirne! This looks like a solid foundation from which to add in mneumonic and ledger support. Also huge fan of the simplified HD path modal 👍

@wbobeirne
Copy link
Contributor Author

wbobeirne commented Aug 28, 2017

Added clarifying comments and split dpaths out into a config json, didn't end up implementing the bip32 test cases because they were more about hdk.derive and publicToAddress from hdkey and ethereumjs-util respectively.

Ready to have this merged whenever!

@dternyak dternyak merged commit 1d235cf into develop Aug 28, 2017
@dternyak dternyak deleted the trezor branch August 28, 2017 17:44
@jamesob
Copy link

jamesob commented Aug 29, 2017

🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants