-
Notifications
You must be signed in to change notification settings - Fork 492
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
Batching Payments in Coinjoin #10580
Batching Payments in Coinjoin #10580
Conversation
badd0dc
to
a97b254
Compare
Notes for testers:
After your wallet is started (fully synchronized) you can create a new pending payment:
In case your wallet was not configured to start coinjoining automatically you can force it by doing:
Happy paycoinjoining! |
dce2bbd
to
99a5289
Compare
EDIT: unrelated bug here #10621 |
99a5289
to
7329436
Compare
The GUI doesn't react to changes in the underlying model, that's an UI problem. This PR is for payments in coinjoins only. All bugs you find that are not related (can be reproduced in master) please open a bug report in a new issue. |
7329436
to
6a82a31
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.
tACK 6a82a31
It works like a charm!
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.
Partial review
: Payment(Destination, Amount) | ||
{ | ||
public TxOut ToTxOut() => | ||
new (Amount, Destination); |
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.
new (Amount, Destination); | |
new(Amount, Destination); |
f74c29a
to
7ab43dc
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.
Another partial review.
WalletWasabi.Tests/UnitTests/WabiSabi/Client/PaymentAwareOutputProviderTests.cs
Outdated
Show resolved
Hide resolved
WalletWasabi.Tests/UnitTests/WabiSabi/Client/PaymentAwareOutputProviderTests.cs
Outdated
Show resolved
Hide resolved
7ab43dc
to
9d20c6e
Compare
This has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
9d20c6e
to
7961d60
Compare
Introduce a new specialized `OutputProvider` which is aware of the existence of payments and can provide the best set of transaction outputs to be registered in a coinjoin. It also makes sure to decompose the remaining amount (the one still available after payments) in standard denominations taking care of having the less possible effect on the AmountDecomposer's denominations selection algorithm.
Extends the OutputProvider concept to one that is aware of the payments so it can provide those outputs to the CoinJoinClients. Make the Wallet to keep a record of the waiting payments and allow making payments using the RPC interface.
fd61ce2
to
4e066b5
Compare
Can we merge this feature? |
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.
tACK aa57dd9
Interestingly, this already happens from time to time on master #9171 |
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.
Succesfully did a few paymentincoinjoin 's, both test and mainnet🎉 aa57dd9
- What am I/the user supposed to do when all coins are private and want to do a
paymentincoinjoin
? If I dostartcoinjoin
with stopwhenallmixed:false parameter, it doesn't start coinjoin, neither when I schedule a payment. Coinjoin status stays stuck at In Schedule
(Maybe out of scope of this PR and more related to startcoinjoin method) - Maybe add a log when paymentincoinjoin was succesful?
- useful follow-up would be
listpendingpayments
rpc method - I got this ERROR in the log:
log ERROR, exception: overall balance must not be negative
[28] INFO PaymentBatch.LogPaymentSetDetails (103)Best payment set contains 0 payments.
2023-10-17 20:26:23.690 [28] ERROR CoinJoinManager.HandleCoinJoinFinalizationAsync (549) Wallet (Testint): CoinJoinClient failed with exception: 'System.ArgumentException: Overall balance must not be negative.
at WalletWasabi.WabiSabi.Client.CredentialDependencies.DependencyGraph.FromValues(IEnumerable`1 inputValues, IEnumerable`1 outputValues) in WalletWasabi/WabiSabi/Client/CredentialDependencies/DependencyGraph.cs:line 96
at WalletWasabi.WabiSabi.Client.CredentialDependencies.DependencyGraph.ResolveCredentialDependencies(IEnumerable`1 inputValues, IEnumerable`1 outputValues) in WalletWasabi/WabiSabi/Client/CredentialDependencies/DependencyGraph.cs:line 74
at WalletWasabi.WabiSabi.Client.CredentialDependencies.DependencyGraph.ResolveCredentialDependencies(IEnumerable`1 effectiveValuesAndSizes, IEnumerable`1 outputs, FeeRate feeRate, Int64 vsizeAllocationPerInput) in WalletWasabi/WabiSabi/Client/CredentialDependencies/DependencyGraph.cs:line 67
at WalletWasabi.WabiSabi.Client.CoinJoinClient.ProceedWithOutputRegistrationPhaseAsync(uint256 roundId, ImmutableArray`1 registeredAliceClients, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 770
at WalletWasabi.WabiSabi.Client.CoinJoinClient.ProceedWithRoundAsync(RoundState roundState, IEnumerable`1 smartCoins, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 351
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartRoundAsync(IEnumerable`1 smartCoins, RoundState roundState, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 249
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartRoundAsync(IEnumerable`1 smartCoins, RoundState roundState, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 329
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartCoinJoinAsync(Func`1 coinCandidatesFunc, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 198
at WalletWasabi.WabiSabi.Client.CoinJoinManager.HandleCoinJoinFinalizationAsync(CoinJoinTracker finishedCoinJoin, ConcurrentDictionary`2 trackedCoinJoins, ConcurrentDictionary`2 trackedAutoStarts, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinManager.cs:line 499'
while my balance is more than 100k sats
another ERROR in the logs, value cannot be null exception
[22] ERROR CoinJoinManager.HandleCoinJoinFinalizationAsync (549) Wallet (Testint): CoinJoinClient failed with exception: 'System.ArgumentNullException: Value cannot be null. (Parameter 'left')
at NBitcoin.Money.op_GreaterThan(Money left, Money right)
at WalletWasabi.WabiSabi.Client.AmountDecomposer.Decompose(IEnumerable`1 myInputCoinEffectiveValues, IEnumerable`1 othersInputCoinEffectiveValues) in WalletWasabi/WabiSabi/Client/AmountDecomposer.cs:line 87
at WalletWasabi.WabiSabi.Client.OutputProvider.GetOutputs(uint256 roundId, RoundParameters roundParameters, IEnumerable`1 registeredCoinEffectiveValues, IEnumerable`1 theirCoinEffectiveValues, Int32 availableVsize) in WalletWasabi/WabiSabi/Client/OutputProvider.cs:line 30
at WalletWasabi.WabiSabi.Client.Batching.PaymentAwareOutputProvider.<>n__0(uint256 roundId, RoundParameters roundParameters, IEnumerable`1 registeredCoinEffectiveValues, IEnumerable`1 theirCoinEffectiveValues, Int32 availableVsize)
at WalletWasabi.WabiSabi.Client.Batching.PaymentAwareOutputProvider.GetOutputs(uint256 roundId, RoundParameters roundParameters, IEnumerable`1 registeredCoinEffectiveValues, IEnumerable`1 theirCoinEffectiveValues, Int32 availableVsize)+MoveNext() in WalletWasabi/WabiSabi/Client/Batching/PaymentAwareOutputProvider.cs:line 63
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at WalletWasabi.WabiSabi.Client.CoinJoinClient.ProceedWithOutputRegistrationPhaseAsync(uint256 roundId, ImmutableArray`1 registeredAliceClients, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 768
at WalletWasabi.WabiSabi.Client.CoinJoinClient.ProceedWithRoundAsync(RoundState roundState, IEnumerable`1 smartCoins, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 351
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartRoundAsync(IEnumerable`1 smartCoins, RoundState roundState, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 249
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartRoundAsync(IEnumerable`1 smartCoins, RoundState roundState, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 329
at WalletWasabi.WabiSabi.Client.CoinJoinClient.StartCoinJoinAsync(Func`1 coinCandidatesFunc, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinClient.cs:line 198
at WalletWasabi.WabiSabi.Client.CoinJoinManager.HandleCoinJoinFinalizationAsync(CoinJoinTracker finishedCoinJoin, ConcurrentDictionary`2 trackedCoinJoins, ConcurrentDictionary`2 trackedAutoStarts, CancellationToken cancellationToken) in WalletWasabi/WabiSabi/Client/CoinJoinManager.cs:line 499'
and left a few nits
WalletWasabi.Tests/UnitTests/WabiSabi/Client/PaymentAwareOutputProviderTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Marnix <93143998+MarnixCroes@users.noreply.github.com>
@MarnixCroes the second error that you see in the log is solved by nopara73/Sake#44 after we merge it in Sake we can merge it here. |
@MarnixCroes do you know how the first error happened? It is in testnet or main? Do you remember what you did? Is it something related to small payments? |
It was on testnet. I was testing what happens when registering 3 payments, of which 2 are to the same address. All 3 of them were 10k sats each. I'm not 100% sure if that's what caused it, as the error came later in time, after it successfully did my "test case". |
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 overall, maybe some weird edge cases but nothing significant, I think.
I have a conceptual "doubt" about this feature, is it better to choose outputs depending on payments as you are doing or would it be better to select inputs depending on pending payments?
.MaxBy(x => x.PaymentCount)!; | ||
|
||
LogPaymentSetDetails(bestPaymentSet); | ||
return bestPaymentSet; |
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.
Could the fact that this is deterministic pose any privacy concerns? I've given it some thought and couldn't identify any problems
This point was addressed, but not at a thoroughly enough detail, in the design document section "Implementation approaches". This PR implements what in the document we called the The more powerful approach, that includes what you mentioned here, is the called |
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 believe that this should be merged.
PR goal
To allow batching payments in coinjoins
Term definitions
For more detailed explanation about the design considerations see: #10570