예제 #1
0
        private T ReadChainOracle <T>(string platformName, string chainName, string[] input) where T : class
        {
            if (input == null || input.Length != 2)
            {
                throw new OracleException("missing oracle input");
            }

            var cmd = input[0].ToLower();

            switch (cmd)
            {
            case "tx":
            case "transaction":
            {
                Hash hash;
                if (Hash.TryParse(input[1], out hash))
                {
                    InteropTransaction tx;

                    if (platformName == DomainSettings.PlatformName)
                    {
                        var chain = Nexus.GetChainByName(chainName);

                        var blockHash = chain.GetBlockHashOfTransaction(hash);
                        var block     = chain.GetBlockByHash(blockHash);

                        var temp = chain.GetTransactionByHash(hash);
                        if (block == null || temp == null)
                        {
                            throw new OracleException($"invalid transaction hash for chain {chainName} @ {platformName}");
                        }

                        var events    = block.GetEventsForTransaction(hash);
                        var transfers = new List <InteropTransfer>();
                        foreach (var evt in events)
                        {
                            switch (evt.Kind)
                            {
                            case EventKind.TokenSend:
                            {
                                var   data = evt.GetContent <TokenEventData>();
                                Event other;
                                if (FindMatchingEvent(events, out other,
                                                      (x) =>
                                        {
                                            if (x.Kind != EventKind.TokenReceive && x.Kind != EventKind.TokenStake)
                                            {
                                                return(false);
                                            }

                                            var y = x.GetContent <TokenEventData>();
                                            return(y.Symbol == data.Symbol && y.Value == data.Value);
                                        }))
                                {
                                    var otherData = other.GetContent <TokenEventData>();

                                    byte[] rawData = null;

                                    var token = Nexus.GetTokenInfo(Nexus.RootStorage, data.Symbol);
                                    if (!token.IsFungible())
                                    {
                                        Event nftEvent;
                                        if (!FindMatchingEvent(events, out nftEvent,
                                                               (x) =>
                                                {
                                                    if (x.Kind != EventKind.PackedNFT)
                                                    {
                                                        return(false);
                                                    }

                                                    var y = x.GetContent <PackedNFTData>();
                                                    return(y.Symbol == data.Symbol);
                                                }))
                                        {
                                            throw new OracleException($"invalid nft transfer with hash in chain {chainName} @ {platformName}");
                                        }

                                        rawData = nftEvent.Data;
                                    }

                                    transfers.Add(new InteropTransfer(data.ChainName, evt.Address, otherData.ChainName, other.Address, Address.Null, data.Symbol, data.Value, rawData));
                                }
                                break;
                            }
                            }
                        }

                        tx = new InteropTransaction(hash, transfers);
                        if (typeof(T) == typeof(byte[]))
                        {
                            return(Serialization.Serialize(tx) as T);
                        }
                    }
                    else
                    {
                        tx = PullPlatformTransaction(platformName, chainName, hash);

                        if (tx == null)
                        {
                            return(null);
                        }
                    }

                    if (typeof(T) == typeof(byte[]))
                    {
                        return(Serialization.Serialize(tx) as T);
                    }

                    return(tx as T);
                }
                else
                {
                    throw new OracleException($"invalid transaction hash for chain {chainName} @ {platformName}");
                }
            }

            case "block":
            {
                Hash         hash;
                InteropBlock block;
                NativeBigInt height;
                // if it fails it might be block height
                if (Hash.TryParse(input[1], out hash))
                {
                    if (platformName == DomainSettings.PlatformName)
                    {
                        var chain = Nexus.GetChainByName(chainName);
                        var temp  = chain.GetBlockByHash(hash);
                        if (temp == null)
                        {
                            throw new OracleException($"invalid block hash for chain {chainName} @ {platformName}");
                        }

                        block = new InteropBlock(platformName, chainName, hash, temp.TransactionHashes);
                    }
                    else
                    {
                        block = PullPlatformBlock(platformName, chainName, hash);
                    }

                    if (typeof(T) == typeof(byte[]))
                    {
                        return(Serialization.Serialize(block) as T);
                    }

                    return((block) as T);
                }
                //TODO
                else if (NativeBigInt.TryParse(input[1], out height))
                {
                    if (platformName == DomainSettings.PlatformName)
                    {
                        var chain = Nexus.GetChainByName(chainName);
                        var temp  = chain.GetBlockByHash(hash);
                        if (temp == null)
                        {
                            throw new OracleException($"invalid block hash for chain {chainName} @ {platformName}");
                        }

                        block = new InteropBlock(platformName, chainName, hash, temp.TransactionHashes);
                    }
                    else
                    {
                        block = PullPlatformBlock(platformName, chainName, Hash.Null, height);
                    }

                    if (typeof(T) == typeof(byte[]))
                    {
                        return(Serialization.Serialize(block) as T);
                    }

                    return((block) as T);
                }
                else
                {
                    throw new OracleException($"invalid block hash for chain {chainName} @ {platformName}");
                }
            }

            default:
                throw new OracleException("unknown platform oracle");
            }
        }