Exemplo n.º 1
0
        /// <inheritdoc />
        public async Task <PuzzleSolution> SignVoucherAsync(SignVoucherRequest request)
        {
            PuzzleSolution result = await this.serverAddress.AppendPathSegment("api/v1/tumblers/0/clientchannels/confirm").PostJsonAsync(request).ReceiveJson <PuzzleSolution>();

            return(result);
        }
Exemplo n.º 2
0
 public PuzzleSolution SignVoucher(SignVoucherRequest signVoucherRequest)
 {
     return(SignVoucherAsync(signVoucherRequest).GetAwaiter().GetResult());
 }
Exemplo n.º 3
0
        public async Task <PuzzleSolution> SignVoucher(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            [FromBody] SignVoucherRequest request)
        {
            if (tumblerId == null)
            {
                throw new ArgumentNullException("tumblerId");
            }
            if (request.UnsignedVoucher == null)
            {
                throw new ActionResultException(BadRequest("Missing UnsignedVoucher"));
            }
            if (request.MerkleProof == null)
            {
                throw new ActionResultException(BadRequest("Missing MerkleProof"));
            }
            if (request.Transaction == null)
            {
                throw new ActionResultException(BadRequest("Missing Transaction"));
            }
            if (request.ClientEscrowKey == null)
            {
                throw new ActionResultException(BadRequest("Missing ClientEscrowKey"));
            }
            if (request.ChannelId == null)
            {
                throw new ActionResultException(BadRequest("Missing ChannelId"));
            }

            var cycle  = GetCycle(request.Cycle);
            var height = Services.BlockExplorerService.GetCurrentHeight();

            if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height))
            {
                throw new ActionResultException(BadRequest("invalid-phase"));
            }

            if (request.MerkleProof.PartialMerkleTree
                .GetMatchedTransactions()
                .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork())
            {
                Logs.Tumbler.LogDebug("Invalid transaction merkle proof");
                throw new ActionResultException(BadRequest("invalid-merkleproof"));
            }

            var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash());

            if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration))
            {
                Logs.Tumbler.LogDebug("Not enough confirmations");
                throw new ActionResultException(BadRequest("not-enough-confirmation"));
            }

            var transaction = request.Transaction;

            if (transaction.Outputs.Count > 2)
            {
                Logs.Tumbler.LogDebug("Incorrect number of outputs");
                throw new ActionResultException(BadRequest("invalid-transaction"));
            }

            var key = Repository.GetKey(cycle.Start, request.KeyReference);

            if (Repository.IsUsed(cycle.Start, request.ChannelId))
            {
                throw new ActionResultException(BadRequest("duplicate-query"));
            }

            var expectedEscrow = new EscrowScriptPubKeyParameters(request.ClientEscrowKey, key.PubKey, cycle.GetClientLockTime());

            var expectedTxOut = new TxOut(Parameters.Denomination + Parameters.Fee, expectedEscrow.ToScript().WitHash.ScriptPubKey.Hash);
            var escrowedCoin  =
                transaction
                .Outputs
                .AsCoins()
                .Where(c => c.TxOut.Value == expectedTxOut.Value &&
                       c.TxOut.ScriptPubKey == expectedTxOut.ScriptPubKey)
                .Select(c => c.ToScriptCoin(expectedEscrow.ToScript()))
                .FirstOrDefault();

            if (escrowedCoin == null)
            {
                Logs.Tumbler.LogDebug("Could not find escrowed coin");
                throw new ActionResultException(BadRequest("invalid-transaction"));
            }

            var solverServerSession = new SolverServerSession(Runtime.TumblerKey, Parameters.CreateSolverParamaters());

            solverServerSession.SetChannelId(request.ChannelId);
            solverServerSession.ConfigureEscrowedCoin(escrowedCoin, key);
            await Services.BlockExplorerService.TrackAsync(escrowedCoin.ScriptPubKey);

            if (!await Services.BlockExplorerService.TrackPrunedTransactionAsync(request.Transaction, request.MerkleProof))
            {
                throw new ActionResultException(BadRequest("invalid-merkleproof"));
            }

            //Without this one, someone could spam the nonce db by replaying this request with different channelId
            if (!Repository.MarkUsedNonce(cycle.Start, Hashes.Hash160(escrowedCoin.Outpoint.ToBytes())))
            {
                throw new ActionResultException(BadRequest("duplicate-query"));
            }

            AssertNotDuplicateQuery(cycle.Start, request.ChannelId);

            Repository.Save(cycle.Start, solverServerSession);
            Logs.Tumbler.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash());

            var correlation = GetCorrelation(solverServerSession);

            Tracker.AddressCreated(cycle.Start, TransactionType.ClientEscrow, escrowedCoin.ScriptPubKey, correlation);
            Tracker.TransactionCreated(cycle.Start, TransactionType.ClientEscrow, request.Transaction.GetHash(), correlation);
            var solution = request.UnsignedVoucher.WithRsaKey(Runtime.VoucherKey.PubKey).Solve(Runtime.VoucherKey);

            return(solution);
        }
Exemplo n.º 4
0
 public Task <PuzzleSolution> SignVoucherAsync(SignVoucherRequest signVoucherRequest)
 {
     return(SendAsync <PuzzleSolution>(HttpMethod.Post, signVoucherRequest, $"clientchannels/confirm"));
 }
Exemplo n.º 5
0
        public PuzzleSolution SignVoucher(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            [FromBody] SignVoucherRequest request)
        {
            if (tumblerId == null)
            {
                throw new ArgumentNullException("tumblerId");
            }
            if (request.UnsignedVoucher == null)
            {
                throw new ActionResultException(BadRequest("Missing UnsignedVoucher"));
            }
            if (request.MerkleProof == null)
            {
                throw new ActionResultException(BadRequest("Missing MerkleProof"));
            }
            if (request.Transaction == null)
            {
                throw new ActionResultException(BadRequest("Missing Transaction"));
            }
            if (request.ClientEscrowKey == null)
            {
                throw new ActionResultException(BadRequest("Missing ClientEscrowKey"));
            }

            if (request.MerkleProof.PartialMerkleTree
                .GetMatchedTransactions()
                .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork())
            {
                throw new ActionResultException(BadRequest("invalid-merkleproof"));
            }

            var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash());

            if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration))
            {
                throw new ActionResultException(BadRequest("not-enough-confirmation"));
            }

            var transaction = request.Transaction;

            if (transaction.Outputs.Count > 2)
            {
                throw new ActionResultException(BadRequest("invalid-transaction"));
            }

            var cycle  = GetCycle(request.Cycle);
            var height = Services.BlockExplorerService.GetCurrentHeight();

            if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height))
            {
                throw new ActionResultException(BadRequest("invalid-phase"));
            }


            var key = Repository.GetKey(cycle.Start, request.KeyReference);

            var expectedEscrow = new EscrowScriptPubKeyParameters(request.ClientEscrowKey, key.PubKey, cycle.GetClientLockTime());

            var expectedTxOut = new TxOut(Parameters.Denomination + Parameters.Fee, expectedEscrow.ToScript().Hash);
            var escrowedCoin  =
                transaction
                .Outputs
                .AsCoins()
                .Where(c => c.TxOut.Value == expectedTxOut.Value &&
                       c.TxOut.ScriptPubKey == expectedTxOut.ScriptPubKey)
                .Select(c => c.ToScriptCoin(expectedEscrow.ToScript()))
                .FirstOrDefault();

            if (escrowedCoin == null)
            {
                throw new ActionResultException(BadRequest("invalid-transaction"));
            }

            try
            {
                var solverServerSession = new SolverServerSession(Runtime.TumblerKey, Parameters.CreateSolverParamaters());
                solverServerSession.ConfigureEscrowedCoin(escrowedCoin, key);

                Services.BlockExplorerService.Track(escrowedCoin.ScriptPubKey);
                if (!Services.BlockExplorerService.TrackPrunedTransaction(request.Transaction, request.MerkleProof))
                {
                    throw new ActionResultException(BadRequest("invalid-merkleproof"));
                }

                if (!Repository.MarkUsedNonce(cycle.Start, new uint160(key.PubKey.Hash.ToBytes())))
                {
                    throw new ActionResultException(BadRequest("invalid-transaction"));
                }
                Repository.Save(cycle.Start, solverServerSession);
                Logs.Tumbler.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash());

                var correlation = GetCorrelation(solverServerSession);
                Tracker.AddressCreated(cycle.Start, TransactionType.ClientEscrow, escrowedCoin.ScriptPubKey, correlation);
                Tracker.TransactionCreated(cycle.Start, TransactionType.ClientEscrow, request.Transaction.GetHash(), correlation);
                var solution = request.UnsignedVoucher.WithRsaKey(Runtime.VoucherKey.PubKey).Solve(Runtime.VoucherKey);
                return(solution);
            }
            catch (PuzzleException)
            {
                throw new ActionResultException(BadRequest("invalid-transaction"));
            }
        }
Exemplo n.º 6
0
 public void BeginSignVoucher(SignVoucherRequest signVoucherRequest)
 {
     BeginSignVoucherAsync(signVoucherRequest).GetAwaiter().GetResult();
 }
Exemplo n.º 7
0
 public Task BeginSignVoucherAsync(SignVoucherRequest signVoucherRequest)
 {
     //Will always return null
     return(SendAsync <PuzzleSolution>(HttpMethod.Post, signVoucherRequest, $"clientchannels/confirm"));
 }
Exemplo n.º 8
0
        public IActionResult SignVoucher([FromBody] SignVoucherRequest request)
        {
            if (request.MerkleProof.PartialMerkleTree
                .GetMatchedTransactions()
                .FirstOrDefault() != request.Transaction.GetHash() || !request.MerkleProof.Header.CheckProofOfWork())
            {
                return(BadRequest("invalid-merkleproof"));
            }


            var transaction = request.Transaction;

            if (transaction.Outputs.Count > 2)
            {
                return(BadRequest("invalid-transaction"));
            }

            var cycle  = Parameters.CycleGenerator.GetCycle(request.ClientEscrowInformation.Cycle);
            var height = Services.BlockExplorerService.GetCurrentHeight();

            if (!cycle.IsInPhase(CyclePhase.ClientChannelEstablishment, height))
            {
                return(BadRequest("incorrect-phase"));
            }

            AliceServerChannelNegotiation aliceNegotiation = new AliceServerChannelNegotiation(Parameters, Tumbler.TumblerKey, Tumbler.VoucherKey);
            var key = Repository.GetKey(cycle.Start, request.KeyReference);

            if (key.PubKey != request.TumblerEscrowPubKey)
            {
                return(BadRequest("incorrect-escrowpubkey"));
            }

            aliceNegotiation.ReceiveClientEscrowInformation(request.ClientEscrowInformation, key);

            try
            {
                var            expectedTxOut = aliceNegotiation.BuildEscrowTxOut();
                PuzzleSolution voucher;
                var            solverServerSession = aliceNegotiation.ConfirmClientEscrow(transaction, out voucher);

                var confirmations = Services.BlockExplorerService.GetBlockConfirmations(request.MerkleProof.Header.GetHash());
                if ((confirmations < Parameters.CycleGenerator.FirstCycle.SafetyPeriodDuration))
                {
                    return(BadRequest("not-enough-confirmation"));
                }

                Services.BlockExplorerService.Track($"Cycle {cycle.Start} Client Escrow", expectedTxOut.ScriptPubKey);
                if (!Services.BlockExplorerService.TrackPrunedTransaction(request.Transaction, request.MerkleProof))
                {
                    return(BadRequest("invalid-merkleproof"));
                }

                if (!Repository.MarkUsedNonce(cycle.Start, new uint160(key.PubKey.Hash.ToBytes())))
                {
                    return(BadRequest("invalid-transaction"));
                }
                Repository.Save(cycle.Start, solverServerSession);
                Logs.Server.LogInformation($"Cycle {cycle.Start} Proof of Escrow signed for " + transaction.GetHash());
                return(Json(voucher));
            }
            catch (PuzzleException)
            {
                return(BadRequest("invalid-transaction"));
            }
        }