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

accounts: cache key addresses #2284

Merged
merged 17 commits into from Apr 12, 2016
Merged

Conversation

fjl
Copy link
Contributor

@fjl fjl commented Mar 3, 2016

In this PR:

  • keystore and all related code moves to package accounts
  • key addresses are cached, Accounts and HasAccount do not hit disk
  • keys can have any file name

A few minor issues remain before this can be considered ready:

  • On kqueue platforms (OS X, FreeBSD...), the fsnotify package polls every 100ms. I submitted a fix upstream (kqueue: wait without timeout fsnotify/fsnotify#124).
  • On kqueue platforms, fsnotify uses lots of file descriptors (3 + one for each key) to provide per-file events. We don't need this granularity, but there is no way to prevent it.
  • Use https://github.com/rjeczalik/notify instead because it has less problems.
  • The filesystem watcher is not shut down properly.
  • We need a fallback for platforms where fsnotify doesn't work.
  • Improve handling of duplicate addresses

Fixes #2100
Fixes #1785

@fjl fjl added the in progress label Mar 3, 2016
@robotally
Copy link

Vote Count Reviewers
👍 2 @bas-vk @karalabe
👎 0
Reaction Users
:21: @fjl

Updated: Tue Apr 12 14:04:45 UTC 2016

@fjl fjl force-pushed the accounts-addr-cache branch 2 times, most recently from 53a269e to c06922e Compare March 3, 2016 00:19
@codecov-io
Copy link

Current coverage is 51.18%

Merging #2284 into develop will increase coverage by +0.29% as of 6ccf4d6

Powered by Codecov. Updated on successful CI builds.

@Gustav-Simonsson
Copy link

This solution seems unnecessary complex. How about simply tracking a map of addresses to key files in a metadata file? Then getting all addresses is a single file read, which will be cached automatically by the OS if called often.

This would also resolve the privacy issue of having addresses in (exported) key file (names), though it would require a user to import a key using a geth command, which would need to decrypt the file in order to get the address to update the map. IMO that would be a good thing though, as it prevents import of files the user has forgotten the password to, and also avoids users from having to manually place files into a internal directory.

@fjl fjl added this to the 1.4.0 milestone Mar 14, 2016
@fjl fjl force-pushed the accounts-addr-cache branch 3 times, most recently from be07070 to 6d1ef71 Compare March 18, 2016 20:46
}
if err != nil {
return err
}
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't it be better to check the error first and then zero the key? If not, could you add a comment as to why not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The call to GetKey verifies that the password is correct. We don't actually need the key, so it should be zeroed always even if loading it produces an unrelated error.

Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't GetKey ensure that if a password is wrong, it does not give you back the key?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but I think it is good style not to assume anything about the relationship between key and err if the intention is to zero it in all possible cases.

Copy link
Member

Choose a reason for hiding this comment

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

Fair point!

@fjl
Copy link
Contributor Author

fjl commented Mar 22, 2016

I have thought about, and don't understand, the privacy concern about keeping the address recorded in the key file. As of this PR, keys can have any file name but the address must be present in the JSON.
Before this PR, the address had to be in the file name.

In order for {sign,unlock}-by-address to work, the addresses need to be tracked somehow.

@fjl fjl force-pushed the accounts-addr-cache branch 6 times, most recently from f47f876 to 7388a48 Compare March 31, 2016 00:24
fjl added a commit to fjl/mist that referenced this pull request Apr 1, 2016
fjl added a commit to fjl/mist that referenced this pull request Apr 1, 2016
@fjl fjl added review and removed in progress labels Apr 1, 2016
@karalabe
Copy link
Member

@fjl Merge conflict

@fjl
Copy link
Contributor Author

fjl commented Apr 12, 2016

fixed

@karalabe
Copy link
Member

@fjl Test compile error :P

Unlocking the accounts in the test doesn't help with anything.
@fjl fjl force-pushed the accounts-addr-cache branch 2 times, most recently from f686a2f to 3ad8d6e Compare April 12, 2016 13:44
fjl added 16 commits April 12, 2016 15:56
These changes make prompting behave consistently on all platforms:

* The input buffer is now global.
  Buffering was previously set up for each prompt, which can cause weird
  behaviour, e.g. when running "geth account update <input.txt" where
  input.txt contains three lines. In this case, the first password
  prompt would fill up the buffer with all lines and then use only the
  first one.

* Print the "unsupported terminal" warning only once.
  Now that stdin prompting has global state, we can use it to track
  the warning there.

* Work around small liner issues, particularly on Windows.
  Prompting didn't work under most of the third-party terminal emulators
  on Windows because liner assumes line editing is always available.
The account management API was originally implemented as a thin layer
around crypto.KeyStore, on the grounds that several kinds of key stores
would be implemented later on. It turns out that this won't happen so
KeyStore is a superflous abstraction.

In this commit crypto.KeyStore and everything related to it moves to
package accounts and is unexported.
- Manager.Accounts no longer returns an error.
- Manager methods take Account instead of common.Address.
- All uses of Account with unkeyed fields are converted.
In order to avoid disk thrashing for Accounts and HasAccount,
address->key file mappings are now cached in memory. This makes it no
longer necessary to keep the key address in the file name. The address
of each key is derived from file content instead.

There are minor user-visible changes:

- "geth account list" now reports key file paths alongside the address.
- If multiple keys are present for an address, unlocking by address is
  not possible. Users are directed to remove the duplicate files
  instead. Unlocking by index is still possible.
- Key files are overwritten written in place when updating the password.
Text files created on Windows typically have \r\n line endings.
Trim them when reading password files.
- Sign takes common.Address, not Account
- Import/Export methods work with encrypted JSON keys
@fjl
Copy link
Contributor Author

fjl commented Apr 12, 2016

fixed again

@karalabe karalabe merged commit 1e9b504 into ethereum:develop Apr 12, 2016
@obscuren obscuren removed the review label Apr 12, 2016
return os.Rename(f.Name(), file)
}

// keyFileName implements the naming convention for keyfiles:

Choose a reason for hiding this comment

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

@fjl hello! Where can I'm read this convention?

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.

None yet

8 participants