예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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");
            }
        }
예제 #5
0
        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");
            }
        }