Ejemplo n.º 1
0
        public async Task <SolutionKey[]> FulfillOffer(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            int cycleId,
            [ModelBinder(BinderType = typeof(UInt160ModelBinder))]
            uint160 channelId,
            [FromBody] SignatureWrapper wrapper)
        {
            var signature = wrapper?.Signature;

            if (tumblerId == null)
            {
                throw new ArgumentNullException(nameof(tumblerId));
            }
            if (signature == null)
            {
                throw new ActionResultException(BadRequest("Missing Signature"));
            }
            var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase);

            AssertNotDuplicateQuery(cycleId, channelId);
            var feeRate = await Services.FeeService.GetFeeRateAsync();

            if (session.Status != SolverServerStates.WaitingFulfillment)
            {
                throw new InvalidStateException("Invalid state, actual " + session.Status + " while expected is " +
                                                SolverServerStates.WaitingFulfillment);
            }
            var cycle   = GetCycle(cycleId);
            var cashout = await Services.WalletService.GenerateAddressAsync();

            var fulfill = session.FulfillOffer(signature, cashout.ScriptPubKey, feeRate);

            fulfill.BroadcastAt = new LockTime(cycle.GetPeriods().Payment.End - 1);
            Repository.Save(cycle.Start, session);

            var signedOffer = session.GetSignedOfferTransaction();

            signedOffer.BroadcastAt = fulfill.BroadcastAt - 1;
            var correlation = GetCorrelation(session);

            var offerScriptPubKey = session.GetInternalState().OfferCoin.ScriptPubKey;


            await Services.BlockExplorerService.TrackAsync(offerScriptPubKey);

            Tracker.AddressCreated(cycle.Start, TransactionType.ClientOffer, offerScriptPubKey, correlation);
            Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientOffer, correlation,
                                                       signedOffer);

            Tracker.AddressCreated(cycle.Start, TransactionType.ClientFulfill, cashout.ScriptPubKey, correlation);

            if (!Runtime.NoFulFill)
            {
                Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientFulfill, correlation,
                                                           fulfill);
            }

            return(Runtime.Cooperative ? session.GetSolutionKeys() : new SolutionKey[0]);
        }
Ejemplo n.º 2
0
        public async Task <NoData> GiveEscapeKey(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            int cycleId,
            [ModelBinder(BinderType = typeof(UInt160ModelBinder))]  uint160 channelId,
            [FromBody] SignatureWrapper wrapper)
        {
            var clientSignature = wrapper?.Signature;

            if (tumblerId == null)
            {
                throw new ArgumentNullException(nameof(tumblerId));
            }
            var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase);

            AssertNotDuplicateQuery(cycleId, channelId);
            if (session.Status != SolverServerStates.WaitingEscape)
            {
                throw new ActionResultException(BadRequest("invalid-state"));
            }

            var fee = await Services.FeeService.GetFeeRateAsync();

            try
            {
                var dummy = new Key().PubKey.Hash.ScriptPubKey;
                var tx    = session.GetSignedEscapeTransaction(clientSignature, fee, dummy);
                var state = session.GetInternalState();

                // The previous tx is broadcastable, but let's give change to the wallet to join everything in a single transaction
                var unused = Runtime.Services.WalletService.ReceiveAsync(state.EscrowedCoin, clientSignature, state.EscrowKey, fee)
                             .ContinueWith(async(Task <Transaction> task) =>
                {
                    try
                    {
                        tx = await task.ConfigureAwait(false);
                        if (Repository.MarkUsedNonce(cycleId, new uint160(tx.GetHash().ToBytes().Take(20).ToArray())))
                        {
                            Logs.Tumbler.LogInformation($"Cashing out from {tx.Inputs.Count} Alices");
                            var correlation = GetCorrelation(session);
                            Tracker.AddressCreated(cycleId, TransactionType.ClientEscape, tx.Outputs[0].ScriptPubKey, correlation);
                            Tracker.TransactionCreated(cycleId, TransactionType.ClientEscape, tx.GetHash(), correlation);
                            await Services.BroadcastService.BroadcastAsync(tx).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex)
                    {
                        Logs.Tumbler.LogCritical(new EventId(), ex, "Error during escape transaction callback");
                    }
                });
            }
            catch (PuzzleException ex)
            {
                throw new ActionResultException(BadRequest(ex.Message));
            }
            return(new NoData());
        }
Ejemplo n.º 3
0
        public SolutionKey[] FulfillOffer(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            int cycleId, string channelId, [FromBody] SignatureWrapper wrapper)
        {
            var signature = wrapper?.Signature;

            if (tumblerId == null)
            {
                throw new ArgumentNullException("tumblerId");
            }
            if (signature == null)
            {
                throw new ActionResultException(BadRequest("Missing Signature"));
            }
            var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase);
            var feeRate = Services.FeeService.GetFeeRate();

            if (session.Status != SolverServerStates.WaitingFulfillment)
            {
                throw new ActionResultException(BadRequest("invalid-state"));
            }
            try
            {
                var cycle   = GetCycle(cycleId);
                var cashout = Services.WalletService.GenerateAddress();

                var fulfill = session.FulfillOffer(signature, cashout.ScriptPubKey, feeRate);
                fulfill.BroadcastAt = new LockTime(cycle.GetPeriods().Payment.End - 1);
                Repository.Save(cycle.Start, session);

                var signedOffer = session.GetSignedOfferTransaction();
                signedOffer.BroadcastAt = fulfill.BroadcastAt - 1;
                var correlation = GetCorrelation(session);

                var offerScriptPubKey = session.GetInternalState().OfferCoin.ScriptPubKey;
                Services.BlockExplorerService.Track(offerScriptPubKey);

                Tracker.AddressCreated(cycle.Start, TransactionType.ClientOffer, offerScriptPubKey, correlation);
                Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientOffer, correlation, signedOffer);

                Tracker.AddressCreated(cycle.Start, TransactionType.ClientFulfill, cashout.ScriptPubKey, correlation);

                if (!Runtime.NoFulFill)
                {
                    Services.TrustedBroadcastService.Broadcast(cycle.Start, TransactionType.ClientFulfill, correlation, fulfill);
                }
                return(Runtime.Cooperative ? session.GetSolutionKeys() : new SolutionKey[0]);
            }
            catch (PuzzleException ex)
            {
                throw new ActionResultException(BadRequest(ex.Message));
            }
        }
Ejemplo n.º 4
0
        public NoData GiveEscapeKey(
            [ModelBinder(BinderType = typeof(TumblerParametersModelBinder))]
            ClassicTumblerParameters tumblerId,
            int cycleId, string channelId, [FromBody] SignatureWrapper wrapper)
        {
            var clientSignature = wrapper?.Signature;

            if (tumblerId == null)
            {
                throw new ArgumentNullException("tumblerId");
            }
            var session = GetSolverServerSession(cycleId, channelId, CyclePhase.TumblerCashoutPhase);

            if (session.Status != SolverServerStates.WaitingEscape)
            {
                throw new ActionResultException(BadRequest("invalid-state"));
            }

            var fee = Services.FeeService.GetFeeRate();

            try
            {
                var cashout = Services.WalletService.GenerateAddress();
                var tx      = session.GetSignedEscapeTransaction(clientSignature, fee, cashout.ScriptPubKey);

                var correlation = GetCorrelation(session);
                Tracker.AddressCreated(cycleId, TransactionType.ClientEscape, cashout.ScriptPubKey, correlation);
                Tracker.TransactionCreated(cycleId, TransactionType.ClientEscape, tx.GetHash(), correlation);

                Services.BroadcastService.Broadcast(tx);
            }
            catch (PuzzleException ex)
            {
                throw new ActionResultException(BadRequest(ex.Message));
            }
            return(new NoData());
        }