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
refactor: Clean up new wallet spend, receive files added #21207 #22100
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
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.
utACK a3f6230
Review hint:
git show --color-moved=dimmed-zebra --color-moved-ws=allow-indentation-change
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); | ||
/** should probably be renamed to IsRelevantToMe */ | ||
bool IsFromMe(const CTransaction& tx) const; | ||
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; | ||
/** Returns whether all of the inputs match the filter */ | ||
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const; | ||
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; |
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.
How come you're able to move GetCredit
but not GetDebit
?
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.
re: #22100 (comment)
How come you're able to move
GetCredit
but notGetDebit
?
I would like to move it, but it's kept in place for now to avoid circular dependencies. The problem is that the CWallet::SyncTransaction
method needs to call CWallet::AddToWalletIfInvolvingMe
which needs to call CWallet::IsFromMe
which needs to call CWallet::GetDebit
. These functions can't be moved out of wallet.cpp
to receive.cpp
, because wallet.cpp
can't depend on receive.cpp
(by design, higher level receive.cpp
spend.cpp
and a future sync.cpp
are all meant to depend on the lower level wallet.cpp
CWallet
object).
I think a future fix for this will move CWallet::SyncTransaction
along with chain attach and rescan code from wallet.cpp
to sync.cpp
. It should then be no problem for sync.cpp
to depend on receive.cpp
and for CWallet::AddToWalletIfInvolvingMe
and related code to move to receive.cpp
. The reason I didn't create sync.cpp
and move these things already is that I was waiting for #20773 to split up the monolithic CWallet::Create
function to make this easier.
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.
Given that #20773 is merged, could the change to GetDebit
be done now?
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.
Or maybe in a (more compact) followup.
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.
re: #22100 (comment)
How come you're able to move
GetCredit
but notGetDebit
?
I would like to move it, but it's kept in place for now to avoid circular dependencies.
Given that #20773 is merged, could the change to
GetDebit
be done now?
Or maybe in a (more compact) followup.
Yes #20733 does make this easier, and yes this would make sense to do as a followup. Doing it in this PR wouldn't make great sense because this PR is not moving code just doing naming/declaration cleanups after a previous move. (Also this is not a tiny change, just in terms of number of lines). Will see what this looks like and post a followup.
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.
Thanks for the review and good color-moved-ws
tip!
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); | ||
/** should probably be renamed to IsRelevantToMe */ | ||
bool IsFromMe(const CTransaction& tx) const; | ||
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; | ||
/** Returns whether all of the inputs match the filter */ | ||
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const; | ||
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; |
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.
re: #22100 (comment)
How come you're able to move
GetCredit
but notGetDebit
?
I would like to move it, but it's kept in place for now to avoid circular dependencies. The problem is that the CWallet::SyncTransaction
method needs to call CWallet::AddToWalletIfInvolvingMe
which needs to call CWallet::IsFromMe
which needs to call CWallet::GetDebit
. These functions can't be moved out of wallet.cpp
to receive.cpp
, because wallet.cpp
can't depend on receive.cpp
(by design, higher level receive.cpp
spend.cpp
and a future sync.cpp
are all meant to depend on the lower level wallet.cpp
CWallet
object).
I think a future fix for this will move CWallet::SyncTransaction
along with chain attach and rescan code from wallet.cpp
to sync.cpp
. It should then be no problem for sync.cpp
to depend on receive.cpp
and for CWallet::AddToWalletIfInvolvingMe
and related code to move to receive.cpp
. The reason I didn't create sync.cpp
and move these things already is that I was waiting for #20773 to split up the monolithic CWallet::Create
function to make this easier.
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.
CAmount OutputGetChange(const CWallet& wallet, const CTxOut& txout) EXCLUSIVE_LOCKS_REQUIRED(wallet.cs_wallet); | ||
CAmount TxGetChange(const CWallet& wallet, const CTransaction& tx); | ||
|
||
CAmount CachedTxGetCredit(const CWallet& wallet, const CWalletTx& wtx, const isminefilter& filter); |
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.
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.
re: #22100 (comment)
Comparing to 4e11f88 (which I reviewed in #21206) what is the motivation to prefix with
Cached
? Is it relevant for the caller that some caching is involved? Is it a way to remember that concurrent syncs can happen and so the return value can be out of date?
There should be no changes since #21206, but CachedTx
is in debit/credit/change function names when the functions take CWalletTx
arguments, since the point of CWalletTx
class is to encapsulate CTransaction
plus cached balance information. Functions named Tx
instead of CachedTx
just take plain CTransaction
arguments by comparison. And functions named Input
, Output
, or Script
take those things as arguments.
I think it makes calling code more readable if function names explicitly say what they compute values from and whether values may be stale due to caching. But this is just a naming convention I settled on because I didnt like the previous convention where there are so many slightly different functions all having the same name. There could be better approaches I didn't think of though.
Re: concurrency, I think cs_wallet doesn't really allow too much and there shouldn't be caching problems related to that. Caching more affects state transitions when blocks are connected disconnected and transactions are abandoned or replaced or added or removed from the mempool.
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.
Functions named Tx instead of CachedTx just take plain CTransaction arguments by comparison
Thanks for the clarification. An alternative prefix could be Wallet
, so in this case, could be WalletTxGetCredit
. But it's fine as is and agree with the convention.
Re: concurrency, I think cs_wallet doesn't really allow too much and there shouldn't be caching problems related to that. Caching more affects state transitions when blocks are connected disconnected and transactions are abandoned or replaced or added or removed from the mempool.
Right, didn't mean to imply otherwise.
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.
re: #22100 (comment)
Functions named Tx instead of CachedTx just take plain CTransaction arguments by comparison
Thanks for the clarification. An alternative prefix could be
Wallet
, so in this case, could beWalletTxGetCredit
. But it's fine as is and agree with the convention.
That suggestion is pretty good too. Maybe I should s/CachedTx/WalletTx/g
in this PR. Will do if reviewers want that. I was anticipating renaming CWalletTx
to CachedTransaction
later (and namespacing so its full name would be wallet::CachedTransaction
) but maybe I am jumping the gun a little bit and should stick with WalletTx
here.
Right, didn't mean to imply otherwise.
Sorry about that, I just misinterpreted "concurrent syncs" it sounds like.
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.
Both are just fine to me, as long as the motivation and convention are clear.
Rebased a3f6230 -> 642843a ( |
Code review ACK 642843a |
Code review re-ACK 54faec8 Confirmed changes since my last review did not change behavior and only addressed mentioned merge conflicts. |
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.
re-crACK 54faec8
LGTM, only resolved merge conflicts since last review.
Sorry about another rebase Russ, I'll review this next 😄 |
Followup to commit "MOVEONLY: CWallet transaction code out of wallet.cpp/.h" that detaches and renames some CWalletTx methods, making into them into standalone functions or CWallet methods instead. There are no changes in behavior and no code changes that aren't purely mechanical. It just gives spend and receive functions more consistent names and removes the circular dependencies added by the earlier MOVEONLY commit. There are also no comment or documentation changes. Removed comments from transaction.h are just migrated to spend.h, receive.h, and wallet.h.
Thanks! And no problem, conflicts were trivial Rebased 54faec8 -> b11a195 ( |
I get that the point is to remove circular dependencies, but I am not sure about the new code layout which removes a lot of the object-oriented-ness of the wallet. It doesn't quite make sense to me why so many functions need or should be changed to take |
This was discussed more here #22100 (comment), but the general idea is that saying |
Is there a description of where this is going and what the end state is going to look like? To me, it feels like many of the changes made here are not well motivated (other than removing the circular dependency). I've read through #21206, #21207, and https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking, but it's not clear to me how these particular changes are related to the end goals stated in those places. |
This PR is my end state for detaching methods and breaking the monolithic wallet.h/cpp into wallet.h/cpp, transaction.h/cpp, receive.h/cpp, and spend.h/spend.cpp modules. Obviously if more work is done on balance tracking and spending code more improvements can be made in these places. This PR is only fixing inconsistencies in naming and moving function declarations out of wallet.h to the new transaction/spend/receive modules where the functions are implemented, Separately, I would like add a sync.h/cpp module and move chain notification and rescan handling code from wallet.cpp there. This should only affect a handful of CWallet methods, and my presumption is that it would be easier implement after #15719 which move some sync code out of the wallet entirely, to the node where it could be shared with other chain clients like indexes. sync.h/cpp module creation would be basically tangential to everything in this except it might detach a few more CWallet methods and follow a similar pattern. #21206 mostly concerns transaction.h/cpp and is basically the end state of transaction representation for all the potential changes described https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking. There would just be pretty small tweaks to the representation after #21206 required to implement the specific changes outlined on the wiki page. #21206 makes these changes safer to implement by taking away the ability to represent invalid transaction states. Definitely you should ask if any of motivations I'm giving in PR descriptions are unclear. Or if any changes in any PR do not seem motivated. This particular PR is just tweaking function names to reflect the places those functions are currently located. So I think there is not very much to get excited about here. |
Ok, I think I get it now. #21207 moved several things, including members of I was confused by the mention of #21206 in the OP and thought this was related to that, but I think it just makes the implementation a bit easier and isn't strictly necessary. |
Like you mentioned, this PR post-moveonly cleanup after #21207, and the overall motivation is described there. The goal of that PR and this one were to increase legibility and improve organization of wallet code. Before #21207 balance computing code was mixed with syncing code and coin selection code and all of this was in random order. After #21207 the code is grouped and organized into different files, separating spending and balance tracking code in different files, with the lower level functions in each file organized first and higher level functions following the lower level functions they call. In this renaming PR after the MOVEONLY PR, circular dependencies are dropped, functions with overloaded names are given distinct names, pointless CWalletTx wallet backpointers are dropped, and functions are named and arranged based on what inputs they are operate on, what they are used for, whether they cache state, how they related to other functions, and things like that, instead of arbitrary things like what convention somebody felt like using in some isolated PR 6 years ago or whether someone flipped a coin and felt like attaching a method to the CWallet class or the CWalletTx class. All of the changes made in these two PRs are very conservative and all are very minor. In almost every case a function name is changing it is just getting longer and more descriptive, and in cases where words are actually different just they are becoming more consistent with other functions. Also, |
ACK b11a195 |
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.
utACK b11a195
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); | ||
/** should probably be renamed to IsRelevantToMe */ | ||
bool IsFromMe(const CTransaction& tx) const; | ||
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; | ||
/** Returns whether all of the inputs match the filter */ | ||
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const; | ||
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; |
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.
Or maybe in a (more compact) followup.
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.
Thanks for reviews!
re: #22100 (comment)
I'm not convinced this change was particularly beneficial especially since it forces a rebase of ~every wallet PR.
I'm struggling with this comment (which I guess was added in editing) because I don't have a great perspective on this problem. The list of conflicts here does not seem very long #22100 (comment), and this seems like the easiest type of rebase conflict to resolve since there are no code logic changes or even moves, just renames.
But maybe the list of conflicts is not a great metric because with function renames there could be silent conflicts in case PRs are adding new calls to a renamed function. Also my perspective on rebases is totally warped because I do them so regularly and follow a procedure to resolve them (manually apply the change from one side of a three way conflict section to the other two sides, and then run a script to collapse identical sides of conflict sections) to ensure changes weren't missed. Also I rely very heavily on rerere. Rebases for me seem mindless and not very important, but I know that makes me a weirdo because rebases are everybody else's favorite thing to complain about.
In defense of rebases for this particular change, I've been hearing for years wallet code is a giant hairball, everything is crammed into a single giant class in one wallet.cpp file. #17261 made a major dent in this, pulling key management out into a separate file. And #21207 untangles the rest of the hairball pulling balance tracking and spending code out, just leaving syncing behind. If feels like if changes like these are done thoughtfully and infrequently then benefits will outweigh the costs, but if I am mispricing costs of rebases, who know what other costs I'm mispricing too. I don't know. That is my thinking about this.
bool IsMine(const CTransaction& tx) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); | ||
/** should probably be renamed to IsRelevantToMe */ | ||
bool IsFromMe(const CTransaction& tx) const; | ||
CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const; | ||
/** Returns whether all of the inputs match the filter */ | ||
bool IsAllFromMe(const CTransaction& tx, const isminefilter& filter) const; | ||
CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const; |
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.
re: #22100 (comment)
How come you're able to move
GetCredit
but notGetDebit
?
I would like to move it, but it's kept in place for now to avoid circular dependencies.
Given that #20773 is merged, could the change to
GetDebit
be done now?
Or maybe in a (more compact) followup.
Yes #20733 does make this easier, and yes this would make sense to do as a followup. Doing it in this PR wouldn't make great sense because this PR is not moving code just doing naming/declaration cleanups after a previous move. (Also this is not a tiny change, just in terms of number of lines). Will see what this looks like and post a followup.
It would be useful to see which PR's are impacted by silent merge conflicts. Afaik most of the big upcoming work, like taproot, doesn't touch this. I also think this reorganization makes future wallet improvements less scary. |
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 haven't given the code a really in-depth review, but have read through it and everything looks good and sane to me. I've also built and run the unit + functional tests.
light ACK b11a195
Adjustments to the wallet code with name changes (like GetNameCredit/Debit, or CreateTransaction with input) made necessary with the upstream change bitcoin/bitcoin#22100. Fixed some of the regtests that were broken by namecoin#453.
This makes
CWallet
andCWalletTx
methods inspend.cpp
andreceive.cpp
files into standalone functions.It's a followup to #21207 MOVEONLY: CWallet transaction code out of wallet.cpp/.h, which moved code from
wallet.cpp
to newspend.cpp
andreceive.cpp
files.There are no changes in behavior. This is just making methods into functions and removing circular dependencies created by #21207. There are no comment or documentation changes, either. Removed comments from
transaction.h
are just migrated tospend.h
,receive.h
, andwallet.h
.This commit was split off from #21206 so there are a few earlier review comments there