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
wallet, rpc: FundTransaction
refactor
#28560
wallet, rpc: FundTransaction
refactor
#28560
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
b2efb35
to
ae53820
Compare
84f833e
to
3dfcb81
Compare
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'm still trying to fully grasp the existing code (which is a big mess), so bear with me if I don't make sense. Left some comment/questions based on my current understanding.
3dfcb81
to
0ed0406
Compare
Fixed the |
2361861
to
ebf118f
Compare
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.
A few nits
9ab387e
to
909c6bb
Compare
Addresses review comments from @aureleoules and @achow101 , most notable being now clearing |
26b4336
to
c856a10
Compare
Updated 909c6bb -> c856a10 (compare)
Thanks for the suggestion @achow101 , it looks a lot cleaner now. |
@@ -78,6 +57,27 @@ static void InterpretFeeEstimationInstructions(const UniValue& conf_target, cons | |||
} | |||
} | |||
|
|||
std::set<int> InterpretSubtractFeeFromOutputInstructions(const UniValue& sffo_instructions, const std::vector<std::string>& destinations) |
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.
in 0b0276b
I don't see a reason to extract this function at this point (could be done later in the PR).
There are two disparate cases covered (bool
and vector<string>
). And each case is only used in one and only one place, further commits also don't introduce further usage of this code path as they pass vector<int>
.
Wouldn't it be better if we keep this logic at the call site?
Benefits of my proposal:
- we don't need second parameter for this function
- we don't need to pass dummy value in
fundrawtransaction
RPC code - we can combine
NormalizeOutputs
andParseOutputs
. they are used always together and the only reason forNormalizeOutputs
to exist now is too pass second param toInterpretSubtractFeeFromOutputInstructions
insend
andwalletfundpsbt
RPC. But there second parameter is useless assubtract_fee_from_outputs
option of those RPCs can't be of thevector<string>
type
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 having a single function (as opposed to keeping the logic at the call site) for the following reasons:
- We avoid duplicating code at the RPC call sites:
- The logic for validating SFFO inputs would need to be duplicated at
send
,fundrawtx
andwalletcreatefundedpsbt
. This is the code that checks that the ints passed are not duplicated and in bounds and previously used to be insiderpc/FundTransaction
- The logic for validating SFFO inputs would need to be duplicated at
- We have one place to validate all SFFO inputs:
- Currently,
sendmany
SFFO inputs are not validated (documented in the added functional tests) - Having one function for parsing and validating makes it cleaner to add validation for all inputs in a follow-up PR. The only reason I'm not doing it in this PR is that its a behavior change (it could make calls to
sendmany
invalid that were previously accepted) and I'd like to keep this strictly a refactor
- Currently,
we don't need second parameter for this function
In the case of sendmany
, we do need the array of destinations to lookup their position. In the case of send
, walletcreatefundedpsbt
, and fundrawtransaction
, we need the array of destinations to make sure our ints are in bounds. There are definitely other ways to do it, but it seems fine to use the same vector for lookups and size. More just making the point that the argument is always used.
we can combine NormalizeOutputs and ParseOutputs. they are used always together
Actually, the main goal here was to separate the logic in AddOutputs
to get rid of duplicate validation logic in AddOutputs
and also the original ParseRecipients
function. sendtoaddress
and sendtoaddress
need the validation logic, but don't need NormalizeOutputs
since those RPCs already only allow the user to pass a key-value pair for address and amounts.
The other RPCs (send
, fundrawtransaction
, walletcreatefundedpsbt
) need the logic for parsing how the univalue is passed (NormalizeOutputs
) and validating the addresses (ParseOutputs
).
Code review ACK c856a10 Nice improvements removing duplication between I'd still prefer |
If the serialized transaction passed to `fundrawtransaction` contains duplicates, they will be deserialized and added to the transaction. Add a test to ensure this behavior is not changed during the refactor. A user can pass any number of duplicated and unrelated addresses as an SFFO argument to `sendmany` and the RPC will not throw an error (note, all the rest of the RPCs which take SFFO as an argument will error if the user passes duplicates or specifies outputs not present in the transaction). Add a test to ensure this behavior is not changed during the refactor.
Move the univalue formatting logic out of AddOutputs and into its own function, `NormalizeOutputs`. This allows us to re-use this logic in later commits.
Move the parsing and validation out of `AddOutputs` into its own function, `ParseOutputs`. This allows us to re-use this logic in `ParseRecipients` in a later commit, where the code is currently duplicated. The new `ParseOutputs` function returns a CTxDestination,CAmount tuples. This allows the caller to then translate the validated outputs into either CRecipients or CTxOuts.
Have `ParseRecipients` return a vector of `CRecipients` and rename to `CreateRecipients`.
Move validation logic out of `CreateRecipients` and instead take the already validated outputs from `ParseOutputs` as an input. Move SFFO parsing out of `CreateRecipients` into a new function, `InterpretSubtractFeeFromOutputsInstructions`. This takes the SFFO instructions from `sendmany` and `sendtoaddress` and turns them into a set of integers. In a later commit, we will also move the SFFO parsing logic from `FundTransaction` into this function. Worth noting: a user can pass duplicate addresses and addresses that dont exist in the transaction outputs as SFFO args to `sendmany` and `sendtoaddress` without triggering a warning. This behavior is preserved in to keep this commit strictly a refactor.
Instead turning tx.vout into a vector of `CRecipient`, make `FundTransaction` take a `CRecipient` vector directly. This allows us to remove SFFO logic from the wrapper RPC `FundTransaction` since the `CRecipient` objects have already been created with the correct SFFO values. This also allows us to remove SFFO from both `FundTransaction` function signatures. This sets us up in a future PR to be able to use these RPCs with BIP352 static payment codes.
c856a10
to
18ad1b9
Compare
According to my |
Concept ACK |
for context, this was the reason for the rebase: #29218 (comment) |
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.
ACK 18ad1b9
CTxDestination destination{CNoDestination{CScript() << OP_RETURN << data}}; | ||
CAmount amount{0}; | ||
parsed_outputs.emplace_back(destination, amount); |
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.
In f7384b9 "refactor: move parsing to new function"
nit: Making temp variables is not necessary.
Motivation
The primary motivation for this PR is to enable
FundTransaction
to take a vector ofCRecipient
objects to allow passing BIP352 silent payment addresses to RPCs that useFundTransaction
(e.g.send
,walletcreatefundedpsbt
). To do that, SFFO logic needs to be moved out ofFundTransaction
so theCRecipient
objects with the correct SFFO information can be created and then passed toFundTransaction
.As a secondary motivation, this PR moves the SFFO stuff closer to the caller, making the code cleaner and easier to understand. This is done by having a single function which parses RPC inputs for SFFO and consistently using the
set<int>
method for communicating SFFO.I'm also not convinced we need to pass a full
CMutableTx
object toFundTransaction
, but I'm leaving that for a follow-up PR/discussion, as its not a blocker for silent payments.