コード例 #1
0
        public static InteropTransaction MakeInteropTx(Logger logger, NeoTx tx, NeoAPI api, string[] origSwapAddresses,
                                                       string coldStorage)
        {
            logger.Debug("checking tx: " + tx.Hash);
            var swapAddresses = new List <Address>();

            foreach (var addr in origSwapAddresses)
            {
                swapAddresses.Add(NeoWallet.EncodeAddress(addr));
            }

            List <InteropTransfer> interopTransfers = new List <InteropTransfer>();

            var emptyTx = new InteropTransaction(Hash.Null, interopTransfers.ToArray());

            PBigInteger amount;
            var         witness = tx.witnesses.ElementAtOrDefault(0);

            if (witness == null)
            {
                // tx has no witness
                return(emptyTx);
            }

            var interopAddress = witness.ExtractAddress();

            if (tx.witnesses.Length != 1 || interopAddress == Address.Null || interopAddress == null)
            {
                //currently only one witness allowed
                // if ExtractAddress returns Address.Null, the tx is not properly signed
                return(emptyTx);
            }

            var sourceScriptHash = witness.verificationScript.Sha256().RIPEMD160();
            var sourceAddress    = NeoWallet.EncodeByteArray(sourceScriptHash);
            var sourceDecoded    = NeoWallet.DecodeAddress(sourceAddress);

            if (sourceAddress == interopAddress || sourceDecoded == coldStorage)
            {
                logger.Warning("self send tx or cold storage transfer found, ignoring: " + tx.Hash);
                // self send, probably consolidation tx, ignore
                return(emptyTx);
            }

            //logger.Debug("interop address: " + interopAddress);
            //logger.Debug("xswapAddress: " + swapAddress);
            //logger.Debug("interop sourceAddress: " + sourceAddress);
            //logger.Debug("neo sourceAddress: " + NeoWallet.DecodeAddress(sourceAddress));

            if (tx.attributes != null && tx.attributes.Length > 0)
            {
                foreach (var attr in tx.attributes)
                {
                    if (attr.Usage == TransactionAttributeUsage.Description)
                    {
                        try
                        {
                            var text = Encoding.UTF8.GetString(attr.Data);
                            if (Address.IsValidAddress(text))
                            {
                                interopAddress = Address.FromText(text);
                                //logger.Debug("new interop address: " + interopAddress);
                            }
                        }
                        catch {}
                    }
                }
            }

            if (tx.outputs.Length > 0)
            {
                foreach (var output in tx.outputs)
                {
                    var targetAddress = NeoWallet.EncodeByteArray(output.scriptHash.ToArray());
                    //logger.Debug("interop targetAddress : " + targetAddress);
                    //logger.Debug("neo targetAddress: " + NeoWallet.DecodeAddress(targetAddress));
                    //logger.Debug("interopSwapAddress: " + interopSwapAddress);
                    //logger.Debug("targetAddress: " + targetAddress);

                    //var swpAddress = NeoWallet.EncodeAddress(swapAddress);
                    //logger.Debug("interop swpAddress: " + swpAddress);
                    //logger.Debug("neo swpAddress: " + NeoWallet.DecodeAddress(swpAddress));
                    //if (targetAddress.ToString() == swapAddress)
                    if (swapAddresses.Contains(targetAddress))
                    {
                        var token = FindSymbolFromAsset(new UInt256(output.assetID).ToString());
                        CryptoCurrencyInfo tokenInfo;
                        if (NeoTokenInfo.TryGetValue(token, out tokenInfo))
                        {
                            amount = Phantasma.Numerics.UnitConversion.ToBigInteger(
                                output.value, tokenInfo.Decimals);
                        }
                        else
                        {
                            // asset not swapable at the moment...
                            //logger.Debug("Asset not swapable");
                            return(emptyTx);
                        }

                        //logger.Debug("UTXO " + amount);
                        interopTransfers.Add
                        (
                            new InteropTransfer
                            (
                                NeoWallet.NeoPlatform,
                                sourceAddress,
                                DomainSettings.PlatformName,
                                targetAddress,
                                interopAddress, // interop address
                                token.ToString(),
                                amount
                            )
                        );
                    }
                }
            }

            if (tx.script != null && tx.script.Length > 0) // NEP5 transfers
            {
                var script = NeoDisassembler.Disassemble(tx.script, true);

                //logger.Debug("SCRIPT ====================");
                //foreach (var entry in script.lines)
                //{
                //    logger.Debug($"{entry.name} : { entry.opcode }");
                //}
                //logger.Debug("SCRIPT ====================");

                if (script.lines.Count() < 7)
                {
                    //logger.Debug("NO SCRIPT!!!!");
                    return(emptyTx);
                }

                var disasmEntry = script.lines.ElementAtOrDefault(6);

                //if ( disasmEntry == null )
                //{
                //    logger.Debug("disasmEntry is null");
                //}
                //if ( disasmEntry != null )
                //{
                //    if ( disasmEntry.data == null)
                //        logger.Debug("disasmEntry.data is 0");
                //}

                if (disasmEntry.name != "APPCALL" || disasmEntry.data == null || disasmEntry.data.Length == 0)
                {
                    //logger.Debug("NO APPCALL");
                    return(emptyTx);
                }
                else
                {
                    var assetString = new UInt160(disasmEntry.data).ToString();
                    if (string.IsNullOrEmpty(assetString) || FindSymbolFromAsset(assetString) == null)
                    {
                        //logger.Debug("Ignore TX due to non swapable token.");
                        return(emptyTx);
                    }
                }

                int pos = 0;
                foreach (var entry in script.lines)
                {
                    pos++;
                    if (pos > 3)
                    {
                        // we are only interested in the first three elements
                        break;
                    }

                    if (entry.data == null || entry.data.Length == 0)
                    {
                        logger.Debug("Ignore tx, invalid data field: " + tx);
                        return(emptyTx);
                    }

                    if (pos == 1)
                    {
                        amount = PBigInteger.FromUnsignedArray(entry.data, true);
                    }
                    if (pos == 2 || pos == 3)
                    {
                        if (pos == 2)
                        {
                            if (entry.data == null || entry.data.Length == 0)
                            {
                                logger.Debug("Invalid op on pos 2, ignoring tx: " + tx);
                                return(emptyTx);
                            }
                            var targetScriptHash = new UInt160(entry.data);
                            //logger.Debug("neo targetAddress: " + targetScriptHash.ToAddress());
                            var targetAddress = NeoWallet.EncodeByteArray(entry.data);
                            //logger.Debug("targetAddress : " + targetAddress);
                            //logger.Debug("interopSwapAddress: " + interopSwapAddress);
                            //logger.Debug("SwapAddress: " + swapAddress);
                            if (swapAddresses.Contains(targetAddress))
                            {
                                // found a swap, call getapplicationlog now to get transaction details and verify the tx was actually processed.
                                ApplicationLog[] appLogs = null;
                                try
                                {
                                    appLogs = api.GetApplicationLog(tx.Hash);
                                }
                                catch (Exception e)
                                {
                                    logger.Error("Getting application logs failed: " + e.Message);
                                    return(new InteropTransaction(Hash.Null, interopTransfers.ToArray()));
                                }

                                if (appLogs != null)
                                {
                                    for (var i = 0; i < appLogs.Length; i++)
                                    {
                                        //logger.Debug("appLogs[i].contract" + appLogs[i].contract);
                                        var token = FindSymbolFromAsset(appLogs[i].contract);
                                        //logger.Debug("TOKEN::::::::::::::::::: " + token);
                                        //logger.Debug("amount: " + appLogs[i].amount + " " + token);
                                        var sadd = NeoWallet.EncodeByteArray(appLogs[i].sourceAddress.ToArray());
                                        var tadd = NeoWallet.EncodeByteArray(appLogs[i].targetAddress.ToArray());


                                        interopTransfers.Add
                                        (
                                            new InteropTransfer
                                            (
                                                "neo", // todo Pay.Chains.NeoWallet.NeoPlatform
                                                       //NeoWallet.EncodeByteArray(appLogs[i].sourceAddress.ToArray()),
                                                sourceAddress,
                                                DomainSettings.PlatformName,
                                                targetAddress,
                                                interopAddress, // interop address
                                                token,
                                                appLogs[i].amount
                                            )
                                        );
                                    }
                                }
                                else
                                {
                                    logger.Warning("Neo swap is found but application log is not available for tx " + tx.Hash);
                                }
                            }
                        }
                        else
                        {
                            //TODO reverse swap
                            sourceScriptHash = new UInt160(entry.data).ToArray();
                            sourceAddress    = NeoWallet.EncodeByteArray(sourceScriptHash.ToArray());
                        }
                    }
                }
            }

            var total = interopTransfers.Count();

            if (total > 0)
            {
                logger.Message($"Found {total} swaps in neo tx {tx.Hash}");
            }
            else
            {
                logger.Debug($"No swaps in neo tx {tx.Hash}");
            }

            return((interopTransfers.Count() > 0)
                ? new InteropTransaction(Hash.Parse(tx.Hash.ToString()), interopTransfers.ToArray())
                : new InteropTransaction(Hash.Null, interopTransfers.ToArray()));
        }