Handle Zero credentials, make the test pass.
MODIFY
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
WalletWasabi/WabiSabi/Client/CoinJoinClient.cs
@@ -76,9 +76,8 @@ namespace WalletWasabi.WabiSabi.Client
// Output registration.
roundState = await RoundStatusUpdater.CreateRoundAwaiter(roundState.Id, rs => rs.Phase == Phase.OutputRegistration, cancellationToken).ConfigureAwait(false);
- var outputsWithCredentials = outputTxOuts.Zip(aliceClients, (output, alice) => (output, alice.RealAmountCredentials, alice.RealVsizeCredentials));
- var bobClients = Enumerable.Range(0, int.MaxValue).Select(_ => CreateBobClient(roundState));
- await RegisterOutputsAsync(bobClients, outputsWithCredentials, cancellationToken).ConfigureAwait(false);
+
+ await RegisterOutputsAsync(bobClient, outputTxOuts, outputs, cancellationToken).ConfigureAwait(false);
roundState = await RoundStatusUpdater.CreateRoundAwaiter(roundState.Id, rs => rs.Phase == Phase.TransactionSigning, cancellationToken).ConfigureAwait(false);
var signingState = roundState.Assert<SigningState>();
@@ -95,6 +94,8 @@ namespace WalletWasabi.WabiSabi.Client
await SignTransactionAsync(aliceClients, unsignedCoinJoin, cancellationToken).ConfigureAwait(false);
}
+
+
private List<AliceClient> CreateAliceClients(RoundState roundState)
{
List<AliceClient> aliceClients = new();
@@ -173,11 +174,12 @@ namespace WalletWasabi.WabiSabi.Client
yield return realAmountCredentialValues.Zip(realVsizeCredentialValues, outputValues, (a, v, o) => (a, v, o));
}
- private async Task RegisterOutputsAsync(
- IEnumerable<BobClient> bobClients,
- IEnumerable<(TxOut Output, Credential[] RealAmountCredentials, Credential[] RealVsizeCredentials)> outputsWithCredentials,
+ private async Task RegisterOutputsAsync(BobClient bobClient,
+ IEnumerable<TxOut> outputTxOuts,
+ List<(Money Amount, Credential[] AmounCreds, Credential[] VsizeCreds)> outputCredentials,
CancellationToken cancellationToken)
{
+
async Task<TxOut?> RegisterOutputTask(BobClient bobClient, TxOut output, Credential[] realAmountCredentials, Credential[] realVsizeCredentials)
{
try
@@ -192,9 +194,20 @@ namespace WalletWasabi.WabiSabi.Client
}
}
- var outputRegisterRequests = bobClients.Zip(
- outputsWithCredentials,
- (bobClient, data) => RegisterOutputTask(bobClient, data.Output, data.RealAmountCredentials, data.RealVsizeCredentials));
+ List<(TxOut Output, Credential[] RealAmountCredentials, Credential[] RealVsizeCredentials)> outputWithCredentials = new();
+ var remainingCredentials = outputCredentials.ToList();
+
+ foreach (var txOut in outputTxOuts)
+ {
+ var creds = remainingCredentials.First(op => op.Amount == txOut.Value);
+ outputWithCredentials.Add((txOut, creds.AmounCreds, creds.VsizeCreds));
+
+ // Make sure to not use the same credentials twice.
+ remainingCredentials.Remove(creds);
+ }
+
+
+ var outputRegisterRequests = outputWithCredentials.Select(output => RegisterOutputTask(bobClient, output.Output, output.RealAmountCredentials, output.RealVsizeCredentials));
await Task.WhenAll(outputRegisterRequests).ConfigureAwait(false);
}

MODIFY
WalletWasabi/WabiSabi/Client/DependencyGraphResolver.cs
WalletWasabi/WabiSabi/Client/DependencyGraphResolver.cs
@@ -23,22 +23,33 @@ namespace WalletWasabi.WabiSabi.Client
}
private DependencyGraph Graph { get; }
- private Dictionary<CredentialDependency, TaskCompletionSource<Credential>> DependencyTasks { get; }
+ private Dictionary<CredentialDependency, TaskCompletionSource<Credential?>> DependencyTasks { get; }
public async Task<List<(Money Amount, Credential[] AmounCreds, Credential[] VsizeCreds)>> ResolveAsync(IEnumerable<AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken)
{
// Set the result for the inputs.
foreach ((var aliceClient, var node) in Enumerable.Zip(aliceClients, Graph.Inputs))
{
- foreach ((var edge, var credential) in Enumerable.Zip(Graph.OutEdges(node, CredentialType.Amount), aliceClient.RealAmountCredentials))
+
+ foreach ((var edge, var credential) in Enumerable.Zip(Graph.OutEdges(node, CredentialType.Amount).Where(edge => edge.Value > 0), aliceClient.RealAmountCredentials))
{
DependencyTasks[edge].SetResult(credential);
}
- foreach ((var edge, var credential) in Enumerable.Zip(Graph.OutEdges(node, CredentialType.Vsize), aliceClient.RealVsizeCredentials))
+ foreach (var edge in Graph.OutEdges(node, CredentialType.Amount).Where(edge => edge.Value == 0))
+ {
+ DependencyTasks[edge].SetResult(null);
+ }
+
+ foreach ((var edge, var credential) in Enumerable.Zip(Graph.OutEdges(node, CredentialType.Vsize).Where(edge => edge.Value > 0), aliceClient.RealVsizeCredentials))
{
DependencyTasks[edge].SetResult(credential);
}
+
+ foreach (var edge in Graph.OutEdges(node, CredentialType.Vsize).Where(edge => edge.Value == 0))
+ {
+ DependencyTasks[edge].SetResult(null);
+ }
}
// Build tasks and link them together.
@@ -76,8 +87,8 @@ namespace WalletWasabi.WabiSabi.Client
throw new InvalidOperationException("");
}
- var amountCreds = amountEdges.Select(edge => DependencyTasks[edge].Task.Result);
- var vsizeCreds = vsizeEdges.Select(edge => DependencyTasks[edge].Task.Result);
+ var amountCreds = amountEdges.Select(edge => DependencyTasks[edge].Task.Result).Where(cred => cred != null);
+ var vsizeCreds = vsizeEdges.Select(edge => DependencyTasks[edge].Task.Result).Where(cred => cred != null);
List<(Money, Credential[], Credential[])> outputs = new();

Handle Zero credentials, make the test pass.