示例#1
0
        public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Logger logger, NeoBlock block,
                                                                                  NeoAPI api, string[] swapAddresses, string coldStorage)
        {
            List <Hash> hashes = new List <Hash>();
            //logger.Debug($"Read block {block.Height} with hash {block.Hash}");

            // if the block has no swap tx, it's currently not of interest
            bool blockOfInterest = false;
            List <InteropTransaction> interopTransactions = new List <InteropTransaction>();

            foreach (var tx in block.transactions)
            {
                if (tx.type == TransactionType.InvocationTransaction ||
                    tx.type == TransactionType.ContractTransaction)
                {
                    var interopTx = MakeInteropTx(logger, tx, api, swapAddresses, coldStorage);
                    if (interopTx.Hash != Hash.Null)
                    {
                        interopTransactions.Add(interopTx);
                        hashes.Add(Hash.FromBytes(tx.Hash.ToArray()));
                        blockOfInterest = true;
                    }
                }
            }

            InteropBlock iBlock = (blockOfInterest)
                ? new InteropBlock("neo", "neo", Hash.Parse(block.Hash.ToString()), hashes.ToArray())
                : new InteropBlock("neo", "neo", Hash.Null, hashes.ToArray());

            return(Tuple.Create(iBlock, interopTransactions.ToArray()));
        }
示例#2
0
        public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Nexus nexus, Logger logger, EthAPI api
                                                                                  , BigInteger height, string[] contracts, uint confirmations, string[] swapAddress)
        {
            Hash blockHash           = Hash.Null;
            var  interopTransactions = new List <InteropTransaction>();

            //TODO HACK
            var combinedAddresses = contracts.ToList();

            combinedAddresses.AddRange(swapAddress);

            Dictionary <string, Dictionary <string, List <InteropTransfer> > > transfers = new Dictionary <string, Dictionary <string, List <InteropTransfer> > >();

            try
            {
                // TODO pass from outside to not instantiate for each call to MakeInteropBlock
                Func <string, Address> addressEncoder = (address) => { return(BSCWallet.EncodeAddress(address)); };
                Func <Nethereum.RPC.Eth.DTOs.Transaction, Address> addressExtractor = (tx) => { return(BSCInterop.ExtractInteropAddress(tx)); };

                var crawler = new EvmBlockCrawler(logger, combinedAddresses.ToArray(), confirmations, api,
                                                  addressEncoder, addressExtractor, BSCWallet.BSCPlatform);
                // fetch blocks
                crawler.Fetch(height);
                transfers = crawler.ExtractInteropTransfers(nexus, logger, swapAddress);
            }
            catch (Exception e)
            {
                logger.Error("Failed to fetch eth blocks: " + e);
            }

            if (transfers.Count == 0)
            {
                var emptyBlock = new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, Hash.Null, new Hash[] {});
                return(Tuple.Create(emptyBlock, interopTransactions.ToArray()));
            }

            blockHash = Hash.Parse(transfers.FirstOrDefault().Key);

            foreach (var block in transfers)
            {
                var txTransferDict = block.Value;
                foreach (var tx in txTransferDict)
                {
                    var interopTx = MakeInteropTx(logger, tx.Key, tx.Value);
                    if (interopTx.Hash != Hash.Null)
                    {
                        interopTransactions.Add(interopTx);
                    }
                }
            }

            var hashes = interopTransactions.Select(x => x.Hash).ToArray();

            InteropBlock interopBlock = (interopTransactions.Count() > 0)
                ? new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, blockHash, hashes)
                : new InteropBlock(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, Hash.Null, hashes);

            return(Tuple.Create(interopBlock, interopTransactions.ToArray()));
        }
示例#3
0
        public static Tuple <InteropBlock, InteropTransaction[]> MakeInteropBlock(Nexus nexus, Logger logger, EthAPI api
                                                                                  , BigInteger height, string[] contracts, uint confirmations, string swapAddress)
        {
            Hash blockHash           = Hash.Null;
            var  interopTransactions = new List <InteropTransaction>();

            //TODO HACK
            var combinedAddresses = contracts.ToList();

            combinedAddresses.Add(swapAddress);

            Dictionary <string, Dictionary <string, List <InteropTransfer> > > transfers = new Dictionary <string, Dictionary <string, List <InteropTransfer> > >();

            try
            {
                var crawler = new EthBlockCrawler(logger, combinedAddresses.ToArray(), confirmations, api);
                // fetch blocks
                crawler.Fetch(height);
                transfers = crawler.ExtractInteropTransfers(nexus, logger, swapAddress);
            }
            catch (Exception e)
            {
                logger.Error("Failed to fetch eth blocks: " + e);
            }

            if (transfers.Count == 0)
            {
                var emptyBlock = new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, Hash.Null, new Hash[] {});
                return(Tuple.Create(emptyBlock, interopTransactions.ToArray()));
            }

            blockHash = Hash.Parse(transfers.FirstOrDefault().Key);

            foreach (var block in transfers)
            {
                var txTransferDict = block.Value;
                foreach (var tx in txTransferDict)
                {
                    var interopTx = MakeInteropTx(logger, tx.Key, tx.Value);
                    if (interopTx.Hash != Hash.Null)
                    {
                        interopTransactions.Add(interopTx);
                    }
                }
            }

            var hashes = interopTransactions.Select(x => x.Hash).ToArray();

            InteropBlock interopBlock = (interopTransactions.Count() > 0)
                ? new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, blockHash, hashes)
                : new InteropBlock(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, Hash.Null, hashes);

            return(Tuple.Create(interopBlock, interopTransactions.ToArray()));
        }
示例#4
0
        private void ProcessBlock(InteropBlock block, ref List <PendingSwap> result)
        {
            foreach (var txHash in block.Transactions)
            {
                var interopTx = OracleReader.ReadTransaction(BSCWallet.BSCPlatform, "bsc", txHash);

                foreach (var interopTransfer in interopTx.Transfers)
                {
                    result.Add(
                        new PendingSwap(
                            this.PlatformName
                            , txHash
                            , interopTransfer.sourceAddress
                            , interopTransfer.interopAddress)
                        );
                }
            }
        }
示例#5
0
        protected override InteropBlock PullPlatformBlock(string platformName, string chainName, Hash hash, NativeBigInt height)
        {
            InteropBlock interopBlock = null;

            switch (platformName)
            {
            case "neo":
            {
                switch (chainName)
                {
                // we abuse chainName here to simulate different results
                case "neoEmpty":
                    interopBlock = new InteropBlock(platformName, chainName, Hash.Null, new Hash[0]);
                    break;

                case "neo":
                    interopBlock = new InteropBlock(platformName, chainName, Hash.FromString("neohash"), new Hash[0]);
                    break;
                }
            }
            break;

            case "ethereum":
            {
                switch (chainName)
                {
                // we abuse chainName here to simulate different results
                case "ethereumEmpty":
                    interopBlock = new InteropBlock(platformName, chainName, Hash.Null, new Hash[0]);
                    break;

                case "ethereum":
                    interopBlock = new InteropBlock(platformName, chainName, Hash.FromString("neohash"), new Hash[0]);
                    break;
                }
            }
            break;
            }

            return(interopBlock);
        }
示例#6
0
        public InteropBlock ReadBlock(Hash hash)
        {
            var blockText = hash.ToString();

            if (blockText.StartsWith("0x"))
            {
                blockText = blockText.Substring(2);
            }

            var apiCall = $"get_block/{blockText}";
            var json    = ExecuteRequest(apiCall);

            if (json == null)
            {
                throw new OracleException("Network read failure: " + apiCall);
            }

            try
            {
                var root = JSONReader.ReadFromString(json);

                var transactions = root.GetNode("transactions");
                var hashes       = new List <Hash>();

                foreach (var entry in transactions.Children)
                {
                    var txHash = Hash.Parse(entry.Value);
                    hashes.Add(txHash);
                }

                var block = new InteropBlock(platformName, "main", Hash.Parse(blockText), hashes.ToArray());
                return(block);
            }
            catch (Exception e)
            {
                throw new OracleException(e.Message);
            }
        }
示例#7
0
        private void ProcessBlock(InteropBlock block, List <PendingSwap> result)
        {
            foreach (var txHash in block.Transactions)
            {
                var interopTx = OracleReader.ReadTransaction("neo", "neo", txHash);

                if (interopTx.Transfers.Length == 0)
                {
                    continue;
                }

                if (interopTx.Transfers.Length == 0)
                {
                    continue;
                }

                InteropTransfer transfer;

                if (interopTx.Transfers.Length != 1)
                {
                    var sources = interopTx.Transfers.Select(x => x.sourceAddress).Distinct();
                    if (sources.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple source addresses not supported yet");
                    }

                    var dests = interopTx.Transfers.Select(x => x.destinationAddress).Distinct();
                    if (dests.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple destination addresses not supported yet");
                    }

                    var interops = interopTx.Transfers.Select(x => x.interopAddress).Distinct();
                    if (interops.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple interop addresses not supported yet");
                    }

                    var symbols = interopTx.Transfers.Select(x => x.Symbol).Distinct();

                    if (symbols.Count() > 1)
                    {
                        throw new OracleException("neo transfers with multiple tokens not supported yet");
                    }

                    PBigInteger sum = 0;

                    foreach (var temp in interopTx.Transfers)
                    {
                        sum += temp.Value;
                    }

                    var first = interopTx.Transfers.First();

                    if (first.Data != null && first.Data.Length > 0)
                    {
                        throw new OracleException("neo transfers with custom data are not supported yet");
                    }

                    transfer = new InteropTransfer(first.sourceChain, first.sourceAddress, first.destinationChain, first.destinationAddress, first.interopAddress, first.Symbol, sum);
                }
                else
                {
                    transfer = interopTx.Transfers.First();
                }

                if (transfer.sourceAddress == transfer.destinationAddress) // ignore this tx, this is a utxo consolidation
                {
                    continue;
                }

                result.Add(
                    new PendingSwap(
                        this.PlatformName
                        , txHash
                        , transfer.sourceAddress
                        , transfer.interopAddress)
                    );
            }
        }
示例#8
0
        protected override InteropBlock PullPlatformBlock(string platformName, string chainName, Hash hash, NativeBigInt height = new NativeBigInt())
        {
            if (hash == null && height == null)
            {
                throw new OracleException($"Fetching block not possible without hash or height");
            }

            InteropBlock block = Read <InteropBlock>(platformName, chainName, hash, StorageConst.Block);

            if (height == null && block.Hash != null && block.Hash != Hash.Null)
            {
                return(block);
            }

            Tuple <InteropBlock, InteropTransaction[]> interopTuple;

            switch (platformName)
            {
            case NeoWallet.NeoPlatform:

                NeoBlock neoBlock;

                if (height == 0)
                {
                    neoBlock = _cli.NeoAPI.GetBlock(new UInt256(LuxUtils.ReverseHex(hash.ToString()).HexToBytes()));
                }
                else
                {
                    neoBlock = _cli.NeoAPI.GetBlock(height);
                }

                if (neoBlock == null)
                {
                    throw new OracleException($"Neo block is null");
                }

                var coldStorage = _cli.Settings.Oracle.SwapColdStorageNeo;
                interopTuple = NeoInterop.MakeInteropBlock(logger, neoBlock, _cli.NeoAPI,
                                                           _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.Neo], coldStorage);
                break;

            case EthereumWallet.EthereumPlatform:

            {
                var hashes = _cli.Nexus.GetPlatformTokenHashes(EthereumWallet.EthereumPlatform, _cli.Nexus.RootStorage)
                             .Select(x => x.ToString().Substring(0, 40)).ToArray();

                interopTuple = EthereumInterop.MakeInteropBlock(_cli.Nexus, logger, _cli.EthAPI, height,
                                                                hashes, _cli.Settings.Oracle.EthConfirmations, _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.Ethereum]);
                break;
            }

            case BSCWallet.BSCPlatform:
            {
                var hashes = _cli.Nexus.GetPlatformTokenHashes(BSCWallet.BSCPlatform, _cli.Nexus.RootStorage)
                             .Select(x => x.ToString().Substring(0, 40)).ToArray();

                interopTuple = BSCInterop.MakeInteropBlock(_cli.Nexus, logger, _cli.BscAPI, height,
                                                           hashes, _cli.Settings.Oracle.EthConfirmations, _cli.TokenSwapper.SwapAddresses[SwapPlatformChain.BSC]);
                break;
            }


            default:
                throw new OracleException("Uknown oracle platform: " + platformName);
            }

            if (interopTuple.Item1.Hash != Hash.Null)
            {
                var initialStore = Persist <InteropBlock>(platformName, chainName, interopTuple.Item1.Hash, StorageConst.Block,
                                                          interopTuple.Item1);
                var transactions = interopTuple.Item2;

                if (!initialStore)
                {
                    logger.Debug($"Oracle block { interopTuple.Item1.Hash } on platform { platformName } updated!");
                }

                foreach (var tx in transactions)
                {
                    var txInitialStore = Persist <InteropTransaction>(platformName, chainName, tx.Hash, StorageConst.Transaction, tx);
                    if (!txInitialStore)
                    {
                        logger.Debug($"Oracle block { interopTuple.Item1.Hash } on platform { platformName } updated!");
                    }
                }
            }

            return(interopTuple.Item1);
        }
示例#9
0
        protected override InteropBlock PullPlatformBlock(string platformName, string chainName, Hash hash, NativeBigInt height = new NativeBigInt())
        {
            if (hash == null && height == null)
            {
                throw new OracleException($"Fetching block not possible without hash or height");
            }

            InteropBlock block = Read <InteropBlock>(platformName, chainName, hash, StorageConst.Block);

            if (height == null && block.Hash != null && block.Hash != Hash.Null)
            {
                return(block);
            }

            Tuple <InteropBlock, InteropTransaction[]> interopTuple;

            switch (platformName)
            {
            case NeoWallet.NeoPlatform:

                NeoBlock neoBlock;

                if (height == 0)
                {
                    neoBlock = _cli.NeoAPI.GetBlock(new UInt256(LuxUtils.ReverseHex(hash.ToString()).HexToBytes()));
                }
                else
                {
                    neoBlock = _cli.NeoAPI.GetBlock(height);
                }

                if (neoBlock == null)
                {
                    throw new OracleException($"Neo block is null");
                }

                interopTuple = NeoInterop.MakeInteropBlock(logger, neoBlock, _cli.NeoAPI, _cli.TokenSwapper.SwapAddresses[platformName]);
                break;

            case EthereumWallet.EthereumPlatform:

                //BlockWithTransactions ethBlock;
                //if (height == 0)
                //{
                //    //TODO MakeInteropBlock for a full block not done yet
                //    //ethBlock = _cli.EthAPI.GetBlock(hash.ToString());
                //    //interopTuple = EthereumInterop.MakeInteropBlock(logger, ethBlock, _cli.EthAPI, _cli.TokenSwapper.swapAddress);
                //}
                //else
                //{
                //}

                var hashes = _cli.Nexus.GetPlatformTokenHashes(EthereumWallet.EthereumPlatform, _cli.Nexus.RootStorage)
                             .Select(x => x.ToString().Substring(0, 40)).ToArray();

                interopTuple = EthereumInterop.MakeInteropBlock(_cli.Nexus, logger, _cli.EthAPI, height,
                                                                hashes, _cli.Settings.Oracle.EthConfirmations, _cli.TokenSwapper.SwapAddresses[platformName]);
                break;

            default:
                throw new OracleException("Uknown oracle platform: " + platformName);
            }

            if (interopTuple.Item1.Hash != Hash.Null)
            {
                var persisted = Persist <InteropBlock>(platformName, chainName, interopTuple.Item1.Hash, StorageConst.Block,
                                                       interopTuple.Item1);

                if (persisted)
                {
                    var transactions = interopTuple.Item2;

                    foreach (var tx in transactions)
                    {
                        var txPersisted = Persist <InteropTransaction>(platformName, chainName, tx.Hash, StorageConst.Transaction, tx);
                    }
                }
                else
                {
                    logger.Error($"Persisting oracle block { interopTuple.Item1.Hash } on platform { platformName } failed!");
                }
            }

            return(interopTuple.Item1);
        }