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

WIP accounts/keystore: don't scan all files, only file affected by event #15580

Closed
wants to merge 5 commits into from

Conversation

holiman
Copy link
Contributor

@holiman holiman commented Nov 29, 2017

In the current codebase, whenever the watcher receives notifications about changes in the keystore directory, it triggers a rescan of files in the directory. This scan uses mtime to see what files are changed, which does not seem to be all to stable (see #15410 and #15498).

This PR instead

  • Acts on every event
  • Uses the path from the event, but ignores the other particulars.
  • Checks the path against already known files/accounts, to determine if the file was modified, changed, or deleted (or nothing)
  • Updates the cache accordingly.
  • Uses a 'canonicalized' path for temporary keystores: earlier, the path returned from osx when creating tempfiles contained a soft link. That link is now resolved, to ensure that the path returned from the fs notification is identical to the one used by the keystore.

See https://godoc.org/github.com/rjeczalik/notify for info about the notify library.
The PR fixes #15410 (comment) , and reverts #15498, since those changes are seemingly no longer needed.

@holiman
Copy link
Contributor Author

holiman commented Nov 29, 2017

Failures:

?   	github.com/ethereum/go-ethereum/accounts/abi/bind/backends	[no test files]

--- FAIL: TestWalletNotifications (1.80s)

	keystore_test.go:344: wallet list doesn't match required accounts: have 707, want 540

	keystore_test.go:372: can't find event with Kind=2 for 1f6bdcbda3e60e9e2b4ff95fe4f4b0058fd3604f

--- FAIL: TestWatchNewFile (7.40s)

	account_cache_test.go:91: got ([]accounts.Account) (len=3 cap=3) {

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8,

		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8

		 },

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0xf466859eAD1932D743d622CB74FC058882E8648A,

		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/aaa

		 },

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0x289d485D9771714CCe91D3393D764E1311907ACc,

		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz

		 }

		}

		, want ([]accounts.Account) (len=3 cap=3) {

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8,

		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8

		 },

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0xf466859eAD1932D743d622CB74FC058882E8648A,

		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/aaa

		 },

		 (accounts.Account) {

		  Address: (common.Address) (len=20 cap=20) 0x289d485D9771714CCe91D3393D764E1311907ACc,

		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz

		 }

		}

--- FAIL: TestUpdatedKeyfileContents (17.29s)

	account_cache_test.go:363: First replacement failed

	account_cache_test.go:364: 

		got  [{[244 102 133 158 173 25 50 215 67 214 34 203 116 252 5 136 130 232 100 138] keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-watch-test-5729-4925858546685333139/aaa} {[126 245 166 19 95 31 214 160 37 147 238 220 134 156 109 65 217 52 174 248] keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-watch-test-5729-4925858546685333139/aaa}]

		want [{[244 102 133 158 173 25 50 215 67 214 34 203 116 252 5 136 130 232 100 138] keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-watch-test-5729-4925858546685333139/aaa}]

FAIL

I wonder if the 1.9.1 travis-builder, which ran for 26 min 55 sec, is just damn slow, and the changes are handled to slowly for the watcher to update the cache in the allotted time.

@holiman
Copy link
Contributor Author

holiman commented Nov 29, 2017

Hm, I don't see what's wrong with this, looks correct to me:

	account_cache_test.go:91: got ([]accounts.Account) (len=3 cap=3) {
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8,
		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
		 },
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0xf466859eAD1932D743d622CB74FC058882E8648A,
		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/aaa
		 },
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0x289d485D9771714CCe91D3393D764E1311907ACc,
		  URL: (accounts.URL) keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz
		 }
		}
		, want ([]accounts.Account) (len=3 cap=3) {
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0x7EF5A6135f1FD6a02593eEdC869c6D41D934aef8,
		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
		 },
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0xf466859eAD1932D743d622CB74FC058882E8648A,
		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/aaa
		 },
		 (accounts.Account) {
		  Address: (common.Address) (len=20 cap=20) 0x289d485D9771714CCe91D3393D764E1311907ACc,
		  URL: (accounts.URL) keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz
		 }
		}

@holiman
Copy link
Contributor Author

holiman commented Nov 29, 2017

Oh:
keystore:///private/var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz versus keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-test737915495/zzz

The path returned from the notify-library is absolute on the host, whereas the want - path is absolute on the container. Or something like that. Weird.

@holiman
Copy link
Contributor Author

holiman commented Nov 29, 2017

Same error on TestUpdatedKeyfileContents! The actual data is correct:

	got  [{[244 102 133 158 173 25 50 215 67 214 34 203 116 252 5 136 130 232 100 138] 
	want [{[244 102 133 158 173 25 50 215 67 214 34 203 116 252 5 136 130 232 100 138] 

However, the got part also did not remove the old one: keystore:///var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/eth-keystore-watch-test-5729-4925858546685333139/aaa. This totally makes sense, since the new logic detected a change in /private/var.., and didn't bother flagging the one at /var/... as deleted.

So, afaict, this actually does work, but there's some issue with resolving the paths properly.

@holiman
Copy link
Contributor Author

holiman commented Nov 30, 2017

This is the problem:https://stackoverflow.com/questions/45122459/docker-mounts-denied-the-paths-are-not-shared-from-os-x-and-are-not-known/45123074#45123074

/var in macOS is a symbolic link into /private.

The go-test is using

	dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watch-test-%d-%d", os.Getpid(), rand.Int()))

so os.TempDir on osx appears to return /var/folders/bb/n7t3rs157850byt_jfdcq9k80000gn/T/. I've now added a fix which canonicalises the path returned from os.Tempdir(), using EvalSymlinks. Let's see if it works.

@holiman
Copy link
Contributor Author

holiman commented Nov 30, 2017

The PR seems to work, the remaining travis-failure does not seem to be related (https://travis-ci.org/ethereum/go-ethereum/jobs/309404326)

@holiman holiman changed the title WIP:accounts/keystore: don't scan all files, only file affected by event accounts/keystore: don't scan all files, only file affected by event Dec 1, 2017
@holiman holiman requested review from fjl and karalabe December 1, 2017 10:22
if err != nil {
return "", err
}
return filepath.Join(tmpdir, fmt.Sprintf("eth-keystore-watch-test-%d-%d", os.Getpid(), rand.Int())), nil
Copy link
Contributor

Choose a reason for hiding this comment

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

Please move the call to rand.Seed into func init() { ... }. You can also remove other seed calls further down in the file.

creates, deletes, updates, err := ac.fileC.scan(ac.keydir)
// readAccount is a helper-function to read an encrypted keyfile
func readAccount(path string, buf *bufio.Reader) *accounts.Account {

Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove blank lines at the beginning and end of functions.

@fjl
Copy link
Contributor

fjl commented Dec 21, 2017

I'm fine with how the code looks now, but tests are still flaking.

@holiman holiman changed the title accounts/keystore: don't scan all files, only file affected by event WIP accounts/keystore: don't scan all files, only file affected by event Dec 21, 2017
@holiman
Copy link
Contributor Author

holiman commented Dec 21, 2017

Sigh, you're right. The appveyor one is a swarm-test going OOM, but the travis test is exactly the type of error that this PR aims to solve. Let's not merge this at the moment, I'll see if I have some time to fix it up perhaps after christmas.

@fjl
Copy link
Contributor

fjl commented May 29, 2018

The only question is: which Christmas?

@fjl fjl closed this May 29, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants