-
Notifications
You must be signed in to change notification settings - Fork 1k
fix: concurrency conflict in NEP6Wallet.ToJson #3527
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
Changes from all commits
e3c42ee
65cc69b
a8f5e27
1fc006c
c2e6efa
3b418f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -293,12 +293,18 @@ public override WalletAccount Import(string nep2, string passphrase, int N = 163 | |
| /// </summary> | ||
| public JObject ToJson() | ||
| { | ||
| NEP6Account[] accountValues; | ||
| lock (accounts) | ||
| { | ||
| accountValues = accounts.Values.ToArray(); | ||
| } | ||
|
|
||
| return new() | ||
| { | ||
| ["name"] = name, | ||
| ["version"] = version.ToString(), | ||
| ["scrypt"] = Scrypt.ToJson(), | ||
| ["accounts"] = accounts.Values.Select(p => p.ToJson()).ToArray(), | ||
| ["accounts"] = accountValues.Select(p => p.ToJson()).ToArray(), | ||
| ["extra"] = extra | ||
| }; | ||
| } | ||
|
|
@@ -345,26 +351,28 @@ private bool VerifyPasswordInternal(string password) | |
| public override bool ChangePassword(string oldPassword, string newPassword) | ||
| { | ||
| bool succeed = true; | ||
| NEP6Account[] accountsValues; | ||
| lock (accounts) | ||
| { | ||
| Parallel.ForEach(accounts.Values, (account, state) => | ||
| { | ||
| if (!account.ChangePasswordPrepare(oldPassword, newPassword)) | ||
| { | ||
| state.Stop(); | ||
| succeed = false; | ||
| } | ||
| }); | ||
| accountsValues = accounts.Values.ToArray(); | ||
| } | ||
| Parallel.ForEach(accountsValues, (account, state) => | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not thread safe if multi-
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
In general, it is sufficient to ensure correctness, and there is no need to over-optimize if it is not performance critical path.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should only use |
||
| { | ||
| if (!account.ChangePasswordPrepare(oldPassword, newPassword)) | ||
| { | ||
| state.Stop(); | ||
| succeed = false; | ||
| } | ||
| }); | ||
| if (succeed) | ||
| { | ||
| foreach (NEP6Account account in accounts.Values) | ||
| foreach (NEP6Account account in accountsValues) | ||
| account.ChangePasswordCommit(); | ||
| password = newPassword.ToSecureString(); | ||
| } | ||
| else | ||
| { | ||
| foreach (NEP6Account account in accounts.Values) | ||
| foreach (NEP6Account account in accountsValues) | ||
| account.ChangePasswordRollback(); | ||
| } | ||
| return succeed; | ||
|
|
||
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 prefer locking to be on its own object altogether. The reason for this is so that way it frees it up quicker and it doesn't Lock up when something wants to read it. Only prevents writing when saving the Json
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.
Lock time wasted procesing .ToJson
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.
This is not thread safe if
ToJsonandChangePasswordconcurrently, becauseaccount.ToJsonread fields of theAccountandChangePasswordchanges fields of theAccount.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.
This is not performance critical path, so excessive optimization is not needed.