示例#1
0
        public static bool IsSwapTransaction(RVN_RPC RPC, dynamic DecodedTransaction, int Block, out RC_Swap Swap)
        {
            /*
             *
             *  A lot of this code is simmilar/duplicated from ListingEntry.cs
             *  Primarily to differentiate between listing submissions and detected on-chain transactions
             *
             */

            Swap = null;

            //if (!(DecodedTransaction.vin.Count >= 1)) return false;
            var vin_asm = DecodedTransaction.vin?[0]?.scriptSig?.asm?.ToString();

            if (vin_asm == null)
            {
                return(false);
            }
            if (!vin_asm.Contains(Constants.SINGLE_ANYONECANPAY))
            {
                return(false);
            }

            //Ins/Outs of the person who setup the swap
            var swap_setup_vin  = DecodedTransaction.vin[0];
            var swap_setup_vout = DecodedTransaction.vout[0];

            //Ins/Outs of the person who executed the swap
            var swap_result_vin  = new List <dynamic>(); // DecodedTransaction.vin.Skip(1).ToList();
            var swap_result_vout = new List <dynamic>(); // DecodedTransaction.vout.Skip(1).ToList();

            for (int vin_idx = 1; vin_idx < DecodedTransaction.vin.Count; vin_idx++)
            {
                var tx_vin = DecodedTransaction.vin[vin_idx];

                if (tx_vin.scriptSig?.asm?.ToString()?.Contains(Constants.SINGLE_ANYONECANPAY))
                {
                    //If we see [SINGLE|ANYONECANPAY] in anything other than the first vin, this is a complex swap. skip for now.
                    //return false; //This happens sometimes :shrug:
                }

                swap_result_vin.Add(tx_vin);
            }
            for (int vout_idx = 1; vout_idx < DecodedTransaction.vout.Count; vout_idx++)
            {
                swap_result_vout.Add(DecodedTransaction.vout[vout_idx]);
            }

            dynamic swap_setup_src      = RPC.GetRawTransaction(swap_setup_vin.txid.ToString());
            dynamic swap_setup_src_vout = swap_setup_src.vout[(int)swap_setup_vin.vout];
            string  txid = DecodedTransaction.txid.ToString();

            var in_type  = (swap_setup_src_vout?.scriptPubKey?.asset != null) ? "asset" : "rvn";
            var out_Type = (swap_setup_vout?.scriptPubKey?.asset != null) ? "asset" : "rvn";

            if (in_type == "asset" && out_Type == "asset")
            {
                Swap = new RC_Swap()
                {
                    TXID        = txid,
                    Block       = Block,
                    OrderType   = SwapType.Trade,
                    InType      = swap_setup_src_vout.scriptPubKey.asset.name,
                    InQuantity  = swap_setup_src_vout.scriptPubKey.asset.amount,
                    OutType     = swap_setup_vout.scriptPubKey.asset.name,
                    OutQuantity = swap_setup_vout.scriptPubKey.asset.amount
                };
                return(true);
            }
            else if (out_Type == "asset")
            {
                Swap = new RC_Swap()
                {
                    TXID        = txid,
                    Block       = Block,
                    OrderType   = SwapType.Buy,
                    InType      = "rvn",
                    InQuantity  = swap_setup_src_vout.value,
                    OutType     = swap_setup_vout.scriptPubKey.asset.name,
                    OutQuantity = swap_setup_vout.scriptPubKey.asset.amount
                };
                return(true);
            }
            else if (in_type == "asset")
            {
                Swap = new RC_Swap()
                {
                    TXID        = txid,
                    Block       = Block,
                    OrderType   = SwapType.Sell,
                    InType      = swap_setup_src_vout.scriptPubKey.asset.name,
                    InQuantity  = swap_setup_src_vout.scriptPubKey.asset.amount,
                    OutType     = "rvn",
                    OutQuantity = swap_setup_vout.value
                };
                return(true);
            }

            return(false);
        }
示例#2
0
        public static bool TryParse(RVN_RPC rpc, RTDbContext db, ListingHex listing, out ListingEntry Value, out string Error, bool ValidateSignature = true)
        {
            Value = null;
            Error = null;

            if (!Regex.IsMatch(listing.Hex, @"^[0-9a-fA-F]*$"))
            {
                Error = "Invalid input format.";
                return(false);
            }

            JObject decodedTX = null;

            try
            {
                decodedTX = rpc.DecodeRawTransaction(listing.Hex);
            }
            catch { }

            if (decodedTX == null)
            {
                Error = "Unable to decode transaction.";
                return(false);
            }

            if (ValidateSignature)
            {
                //Don't do anything special, if we sign and it says completed, that its properly validated to the owner of the UTXO
                var sign_test = rpc.SignRawTransaction(listing.Hex);

                if ((sign_test?.Value <bool>("complete") ?? false) == false)
                {
                    Error = "Signature is invalid";
                    return(false);
                }
            }

            dynamic parsed_tx = decodedTX;

            if (!parsed_tx.vin[0]?.scriptSig?.asm?.ToString()?.Contains(Constants.SINGLE_ANYONECANPAY))
            {
                Error = "Transaction is not signed with SINGLE|ANYONECANPAY. Not a valid swap.";
                return(false);
            }

            var utxo = $"{parsed_tx.vin[0].txid}-{parsed_tx.vin[0].vout}";

            //Must be fully txindexed to be able to use GetRawTransaction arbitrarily
            //var src_transaction = (dynamic)Utils.FullExternalTXDecode((string)parsed_tx.vin[0].txid);
            var src_transaction = (dynamic)rpc.GetRawTransaction((string)parsed_tx.vin[0].txid);
            var src_vout        = src_transaction.vout[(int)parsed_tx.vin[0].vout];

            var in_type  = (src_vout?.scriptPubKey?.asset != null) ? "asset" : "rvn";
            var out_Type = (parsed_tx.vout[0]?.scriptPubKey?.asset != null) ? "asset" : "rvn";

            SwapType?type = null;

            if (in_type == "asset" && out_Type == "asset")
            {
                type = SwapType.Trade;
            }
            else if (out_Type == "asset")
            {
                type = SwapType.Buy;
            }
            else if (in_type == "asset")
            {
                type = SwapType.Sell;
            }

            if (type == null)
            {
                Error = "Swap does not contain a recognized Input/Output transaction type combination";
                return(false);
            }

            var existing = db.Listings.SingleOrDefault(l => l.UTXO == utxo);

            if (existing == null)
            {
                Value = new ListingEntry()
                {
                    UTXO = utxo
                };
            }
            else
            {
                Value = existing;
            }

            Value.SubmitTime       = DateTime.UtcNow;
            Value.B64SignedPartial = Convert.ToBase64String(Utils.StringToByteArray(listing.Hex));
            Value.OrderType        = type.Value;

            switch (Value.OrderType)
            {
            case SwapType.Buy:
                //For a buy order, the quantity is the amount being requested
                Value.InType      = "rvn";
                Value.InQuantity  = src_vout.value;
                Value.OutType     = parsed_tx.vout[0].scriptPubKey.asset.name;
                Value.OutQuantity = parsed_tx.vout[0].scriptPubKey.asset.amount;

                Value.UnitPrice = Value.InQuantity / Value.OutQuantity;
                break;

            case SwapType.Sell:
                Value.InType      = src_vout.scriptPubKey.asset.name;
                Value.InQuantity  = src_vout.scriptPubKey.asset.amount;
                Value.OutType     = "rvn";
                Value.OutQuantity = parsed_tx.vout[0].value;

                Value.UnitPrice = Value.OutQuantity / Value.InQuantity;
                break;

            case SwapType.Trade:
                Value.InType      = src_vout.scriptPubKey.asset.name;
                Value.InQuantity  = src_vout.scriptPubKey.asset.amount;
                Value.OutType     = parsed_tx.vout[0].scriptPubKey.asset.name;
                Value.OutQuantity = parsed_tx.vout[0].scriptPubKey.asset.amount;

                Value.UnitPrice = Value.InQuantity / Value.OutQuantity;
                break;
            }
            return(true);
        }