public async Task StartOutputRegistrationsAsync(IEnumerable <TxOut> txOuts, BobClient bobClient, CancellationToken cancellationToken) { List <Task> outputTasks = new(); using CancellationTokenSource ctsOnError = new(); using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token); foreach (var(node, txOut) in Enumerable.Zip(Graph.Outputs, txOuts)) { var amountCredsToPresentTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task); var vsizeCredsToPresentTasks = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task); SmartRequestNode smartRequestNode = new( amountCredsToPresentTasks, vsizeCredsToPresentTasks, Array.Empty <TaskCompletionSource <Credential> >(), Array.Empty <TaskCompletionSource <Credential> >()); var task = smartRequestNode .StartOutputRegistrationAsync(bobClient, txOut.ScriptPubKey, cancellationToken) .ContinueWith((t) => { if (t.IsFaulted && t.Exception is { } exception) { // If one task is failing, cancel all the tasks and throw. ctsOnError.Cancel(); throw exception; } }, linkedCts.Token); outputTasks.Add(task); } await Task.WhenAll(outputTasks).ConfigureAwait(false); }
public async Task StartReissuanceAsync(BobClient bobClient, IEnumerable <long> amounts, IEnumerable <long> vsizes, CancellationToken cancellationToken) { await Task.WhenAll(AmountCredentialToPresentTasks.Concat(VsizeCredentialToPresentTasks)).ConfigureAwait(false); IEnumerable <Credential> inputAmountCredentials = AmountCredentialToPresentTasks.Select(x => x.Result); IEnumerable <Credential> inputVsizeCredentials = VsizeCredentialToPresentTasks.Select(x => x.Result); var amountsToRequest = AddExtraCredentialRequests(amounts, inputAmountCredentials.Sum(x => x.Value)); var vsizesToRequest = AddExtraCredentialRequests(vsizes, inputVsizeCredentials.Sum(x => x.Value)); (IEnumerable <Credential> RealAmountCredentials, IEnumerable <Credential> RealVsizeCredentials)result = await bobClient.ReissueCredentialsAsync( amountsToRequest, vsizesToRequest, inputAmountCredentials, inputVsizeCredentials, cancellationToken).ConfigureAwait(false); // TODO keep the credentials that were not needed by the graph var(amountCredentials, _) = SeparateExtraCredentials(result.RealAmountCredentials, amounts); var(vsizeCredentials, _) = SeparateExtraCredentials(result.RealVsizeCredentials, vsizes); foreach (var(tcs, credential) in AmountCredentialTasks.Zip(amountCredentials)) { tcs.SetResult(credential); } foreach (var(tcs, credential) in VsizeCredentialTasks.Zip(vsizeCredentials)) { tcs.SetResult(credential); } }
public async Task StartOutputRegistrationAsync( BobClient bobClient, Script scriptPubKey, CancellationToken cancellationToken) { await Task.WhenAll(AmountCredentialToPresentTasks.Concat(VsizeCredentialToPresentTasks)).ConfigureAwait(false); IEnumerable <Credential> inputAmountCredentials = AmountCredentialToPresentTasks.Select(x => x.Result); IEnumerable <Credential> inputVsizeCredentials = VsizeCredentialToPresentTasks.Select(x => x.Result); await bobClient.RegisterOutputAsync( scriptPubKey, inputAmountCredentials, inputVsizeCredentials, cancellationToken).ConfigureAwait(false); }
public async Task StartReissuancesAsync(IEnumerable <AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken) { var aliceNodePairs = PairAliceClientAndRequestNodes(aliceClients, Graph); // Build tasks and link them together. List <SmartRequestNode> smartRequestNodes = new(); List <Task> allTasks = new(); // Temporary workaround because we don't yet have a mechanism to // propagate the final amounts to request amounts to AliceClient's // connection confirmation loop even though they are already known // after the final successful input registration, which may be well // before the connection confirmation phase actually starts. allTasks.Add(CompleteConnectionConfirmationAsync(aliceClients, bobClient, cancellationToken)); using CancellationTokenSource ctsOnError = new(); using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token); foreach (var node in Graph.Reissuances) { var inputAmountEdgeTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task); var inputVsizeEdgeTasks = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task); var outputAmountEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge]); var outputVsizeEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge]); var requestedAmounts = Graph.OutEdges(node, CredentialType.Amount).Select(edge => edge.Value); var requestedVSizes = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => edge.Value); SmartRequestNode smartRequestNode = new( inputAmountEdgeTasks, inputVsizeEdgeTasks, outputAmountEdgeTaskCompSources, outputVsizeEdgeTaskCompSources); var task = smartRequestNode .StartReissuanceAsync(bobClient, requestedAmounts, requestedVSizes, linkedCts.Token) .ContinueWith((t) => { if (t.IsFaulted && t.Exception is { } exception) { // If one task is failing, cancel all the tasks and throw. ctsOnError.Cancel(); throw exception; } }, linkedCts.Token); allTasks.Add(task); } await Task.WhenAll(allTasks).ConfigureAwait(false); var amountEdges = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Amount)); var vsizeEdges = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Vsize)); // Check if all tasks were finished, otherwise Task.Result will block. if (!amountEdges.Concat(vsizeEdges).All(edge => DependencyTasks[edge].Task.IsCompletedSuccessfully)) { throw new InvalidOperationException("Some Output nodes in-edges failed to complete"); } }
private async Task CompleteConnectionConfirmationAsync(IEnumerable <AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken) { var aliceNodePairs = PairAliceClientAndRequestNodes(aliceClients, Graph); List <Task> connectionConfirmationTasks = new(); using CancellationTokenSource ctsOnError = new(); using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token); foreach ((var aliceClient, var node) in aliceNodePairs) { var amountEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge]); var vsizeEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge]); SmartRequestNode smartRequestNode = new( aliceClient.IssuedAmountCredentials.Take(ProtocolConstants.CredentialNumber).Select(Task.FromResult), aliceClient.IssuedVsizeCredentials.Take(ProtocolConstants.CredentialNumber).Select(Task.FromResult), amountEdgeTaskCompSources, vsizeEdgeTaskCompSources); var amountsToRequest = Graph.OutEdges(node, CredentialType.Amount).Select(e => e.Value); var vsizesToRequest = Graph.OutEdges(node, CredentialType.Vsize).Select(e => e.Value); // Although connection confirmation requests support k // credential requests, for now we only know which amounts to // request after connection confirmation has finished and the // final decomposition can be computed, so as a workaround we // unconditionally request the full amount in one credential and // then do an equivalent reissuance request for every connection // confirmation. var task = smartRequestNode .StartReissuanceAsync(bobClient, amountsToRequest, vsizesToRequest, linkedCts.Token) .ContinueWith((t) => { if (t.IsFaulted && t.Exception is { } exception) { // If one task is failing, cancel all the tasks and throw. ctsOnError.Cancel(); throw exception; } }, linkedCts.Token); connectionConfirmationTasks.Add(task); } await Task.WhenAll(connectionConfirmationTasks).ConfigureAwait(false); var amountEdges = Graph.Inputs.SelectMany(node => Graph.OutEdges(node, CredentialType.Amount)); var vsizeEdges = Graph.Inputs.SelectMany(node => Graph.OutEdges(node, CredentialType.Vsize)); // Check if all tasks were finished, otherwise Task.Result will block. if (!amountEdges.Concat(vsizeEdges).All(edge => DependencyTasks[edge].Task.IsCompletedSuccessfully)) { throw new InvalidOperationException("Some Input nodes out-edges failed to complete."); } }
public async Task StartReissuancesAsync(IEnumerable <AliceClient> aliceClients, BobClient bobClient, CancellationToken cancellationToken) { var aliceNodePairs = PairAliceClientAndRequestNodes(aliceClients, Graph); // Build tasks and link them together. List <SmartRequestNode> smartRequestNodes = new(); List <Task> allTasks = new(); using CancellationTokenSource ctsOnError = new(); using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ctsOnError.Token); foreach (var node in Graph.Reissuances) { var inputAmountEdgeTasks = Graph.InEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge].Task); var inputVsizeEdgeTasks = Graph.InEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge].Task); var outputAmountEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Amount).Select(edge => DependencyTasks[edge]); var outputVsizeEdgeTaskCompSources = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => DependencyTasks[edge]); var requestedAmounts = Graph.OutEdges(node, CredentialType.Amount).Select(edge => (long)edge.Value); var requestedVSizes = Graph.OutEdges(node, CredentialType.Vsize).Select(edge => (long)edge.Value); SmartRequestNode smartRequestNode = new( inputAmountEdgeTasks, inputVsizeEdgeTasks, outputAmountEdgeTaskCompSources, outputVsizeEdgeTaskCompSources); var task = smartRequestNode .StartReissuanceAsync(bobClient, requestedAmounts, requestedVSizes, linkedCts.Token) .ContinueWith((t) => { if (t.IsFaulted && t.Exception is { } exception) { // If one task is failing, cancel all the tasks and throw. ctsOnError.Cancel(); throw exception; } }, linkedCts.Token); allTasks.Add(task); } await Task.WhenAll(allTasks).ConfigureAwait(false); var amountEdges = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Amount)); var vsizeEdges = Graph.Outputs.SelectMany(node => Graph.InEdges(node, CredentialType.Vsize)); // Check if all tasks were finished, otherwise Task.Result will block. if (!amountEdges.Concat(vsizeEdges).All(edge => DependencyTasks[edge].Task.IsCompletedSuccessfully)) { throw new InvalidOperationException("Some Output nodes in-edges failed to complete"); } }