public UnsignedVoucherInformation AskUnsignedVoucher()
        {
            var height          = Services.BlockExplorerService.GetCurrentHeight();
            var cycleParameters = Parameters.CycleGenerator.GetRegistratingCycle(height);
            BobServerChannelNegotiation session = CreateBobServerChannelNegotiation(cycleParameters.Start);

            return(session.GenerateUnsignedVoucher());
        }
        public IActionResult OpenChannel([FromBody] OpenChannelRequest request)
        {
            var height = Services.BlockExplorerService.GetCurrentHeight();
            BobServerChannelNegotiation session = CreateBobServerChannelNegotiation(request.CycleStart);
            var cycle = session.GetCycle();

            if (!cycle.IsInPhase(CyclePhase.TumblerChannelEstablishment, height))
            {
                return(BadRequest("incorrect-phase"));
            }
            var fee = Services.FeeService.GetFeeRate();

            try
            {
                session.ReceiveBobEscrowInformation(request);
                if (!Repository.MarkUsedNonce(request.CycleStart, request.Nonce))
                {
                    return(BadRequest("nonce-already-used"));
                }
                Logs.Server.LogInformation($"Cycle {cycle.Start} Asked to open channel");
                var txOut = session.BuildEscrowTxOut();
                var tx    = Services.WalletService.FundTransaction(txOut, fee);
                if (tx == null)
                {
                    Logs.Server.LogInformation("Not funds left for creating a channel");
                    return(BadRequest("tumbler-insufficient-funds"));
                }

                var escrowTumblerLabel = $"Cycle {cycle.Start} Tumbler Escrow";
                Services.BlockExplorerService.Track(escrowTumblerLabel, txOut.ScriptPubKey);
                Services.BroadcastService.Broadcast(escrowTumblerLabel, tx);
                Logs.Server.LogInformation($"Cycle {cycle.Start} Channel created " + tx.GetHash());
                var promiseServerSession = session.SetSignedTransaction(tx);
                Repository.Save(cycle.Start, promiseServerSession);

                var redeem   = Services.WalletService.GenerateAddress($"Cycle {cycle.Start} Tumbler Redeem");
                var redeemTx = promiseServerSession.CreateRedeemTransaction(fee, redeem.ScriptPubKey);
                Services.TrustedBroadcastService.Broadcast($"Cycle {session.GetCycle().Start} Tumbler Redeem (locked until: {redeemTx.Transaction.LockTime})", redeemTx);
                return(Json(promiseServerSession.EscrowedCoin));
            }
            catch (PuzzleException)
            {
                return(BadRequest("incorrect-voucher"));
            }
        }