Ejemplo n.º 1
0
        private bool AppChain_ChangeValidators(ExecutionEngine engine)
        {
            if (Trigger != TriggerType.Application)
            {
                return(false);
            }

            UInt160 hash = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            AppChainState state = Snapshot.AppChains.TryGet(hash);

            if (state == null)
            {
                return(false);
            }

            int seedCount = (int)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger();

            string[] seedList = new string[seedCount];
            for (int i = 0; i < seedCount; i++)
            {
                seedList[i] = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            }

            state.SeedList = seedList;

            LocalNode appnode = LocalNode.GetLocalNode(hash);

            if (appnode != null)
            {
                appnode.SeedList = seedList;
            }

            return(true);
        }
Ejemplo n.º 2
0
 public ConsensusService(ZoroSystem system, Wallet wallet, UInt160 chainHash)
 {
     this.system     = system;
     this.wallet     = wallet;
     this.chainHash  = chainHash;
     this.localNode  = LocalNode.GetLocalNode(chainHash);
     this.blockchain = Blockchain.GetBlockchain(chainHash);
 }
Ejemplo n.º 3
0
        private JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getaccountstate":
            {
                UInt160      script_hash = _params[0].AsString().ToScriptHash();
                AccountState account     = Blockchain.Root.Store.GetAccounts().TryGet(script_hash) ?? new AccountState(script_hash);
                return(account.ToJson());
            }

            case "getassetstate":
            {
                UInt256    asset_id = UInt256.Parse(_params[0].AsString());
                AssetState asset    = Blockchain.Root.Store.GetAssets().TryGet(asset_id);
                return(asset?.ToJson() ?? throw new RpcException(-100, "Unknown asset"));
            }

            case "getbalance":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    JObject json = new JObject();
                    switch (UIntBase.Parse(_params[0].AsString()))
                    {
                    case UInt160 asset_id_160:         //NEP-5 balance
                        json["balance"] = wallet.GetAvailable(asset_id_160).ToString();
                        break;

                    case UInt256 asset_id_256:         //Global Assets balance
                        IEnumerable <Coin> coins = wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(asset_id_256));
                        json["balance"]   = coins.Sum(p => p.Output.Value).ToString();
                        json["confirmed"] = coins.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value).ToString();
                        break;
                    }
                    return(json);
                }

            case "getbestblockhash":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }
                return(blockchain.CurrentBlockHash.ToString());
            }

            case "getblock":
            {
                Block      block;
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }
                if (_params[1] is JNumber)
                {
                    uint index = (uint)_params[1].AsNumber();
                    block = blockchain.Store.GetBlock(index);
                }
                else
                {
                    UInt256 hash = UInt256.Parse(_params[1].AsString());
                    block = blockchain.Store.GetBlock(hash);
                }
                if (block == null)
                {
                    throw new RpcException(-100, "Unknown block");
                }
                bool verbose = _params.Count >= 3 && _params[2].AsBooleanOrDefault(false);
                if (verbose)
                {
                    JObject json = block.ToJson();
                    json["confirmations"] = blockchain.Height - block.Index + 1;
                    UInt256 hash = blockchain.Store.GetNextBlockHash(block.Hash);
                    if (hash != null)
                    {
                        json["nextblockhash"] = hash.ToString();
                    }
                    return(json);
                }
                return(block.ToArray().ToHexString());
            }

            case "getblockcount":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }
                return(blockchain.Height + 1);
            }

            case "getblockhash":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }
                uint height = (uint)_params[1].AsNumber();
                if (height <= blockchain.Height)
                {
                    return(blockchain.GetBlockHash(height).ToString());
                }
                throw new RpcException(-100, "Invalid Height");
            }

            case "getblockheader":
            {
                Header     header;
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }
                if (_params[1] is JNumber)
                {
                    uint height = (uint)_params[1].AsNumber();
                    header = blockchain.Store.GetHeader(height);
                }
                else
                {
                    UInt256 hash = UInt256.Parse(_params[1].AsString());
                    header = blockchain.Store.GetHeader(hash);
                }
                if (header == null)
                {
                    throw new RpcException(-100, "Unknown block");
                }

                bool verbose = _params.Count >= 3 && _params[2].AsBooleanOrDefault(false);
                if (verbose)
                {
                    JObject json = header.ToJson();
                    json["confirmations"] = blockchain.Height - header.Index + 1;
                    UInt256 hash = blockchain.Store.GetNextBlockHash(header.Hash);
                    if (hash != null)
                    {
                        json["nextblockhash"] = hash.ToString();
                    }
                    return(json);
                }

                return(header.ToArray().ToHexString());
            }

            case "getblocksysfee":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                uint height = (uint)_params[1].AsNumber();
                if (height <= blockchain.Height)
                {
                    return(blockchain.Store.GetSysFeeAmount(height).ToString());
                }
                throw new RpcException(-100, "Invalid Height");
            }

            case "getconnectioncount":
            {
                UInt160   chain_hash = _params[0].AsString().ToScriptHash();
                LocalNode localNode  = LocalNode.GetLocalNode(chain_hash);
                return(localNode != null ? localNode.ConnectedCount : 0);
            }

            case "getcontractstate":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                UInt160       script_hash = UInt160.Parse(_params[1].AsString());
                ContractState contract    = blockchain.Store.GetContracts().TryGet(script_hash);
                return(contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"));
            }

            case "getnewaddress":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied");
                }
                else
                {
                    WalletAccount account = wallet.CreateAccount();
                    if (wallet is NEP6Wallet nep6)
                    {
                        nep6.Save();
                    }
                    return(account.Address);
                }

            case "getpeers":
            {
                JObject   json       = new JObject();
                UInt160   chain_hash = UInt160.Parse(_params[0].AsString());
                LocalNode localNode  = LocalNode.GetLocalNode(chain_hash);
                if (localNode != null)
                {
                    json["unconnected"] = new JArray(localNode.GetUnconnectedPeers().Select(p =>
                        {
                            JObject peerJson    = new JObject();
                            peerJson["address"] = p.Address.ToString();
                            peerJson["port"]    = p.Port;
                            return(peerJson);
                        }));
                    json["bad"]       = new JArray();   //badpeers has been removed
                    json["connected"] = new JArray(localNode.GetRemoteNodes().Select(p =>
                        {
                            JObject peerJson    = new JObject();
                            peerJson["address"] = p.Remote.Address.ToString();
                            peerJson["port"]    = p.ListenerPort;
                            return(peerJson);
                        }));
                }

                return(json);
            }

            case "getrawmempool":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                return(new JArray(blockchain.GetMemoryPool().Select(p => (JObject)p.Hash.ToString())));
            }

            case "getrawtransaction":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                UInt256     hash    = UInt256.Parse(_params[1].AsString());
                bool        verbose = _params.Count >= 3 && _params[2].AsBooleanOrDefault(false);
                Transaction tx      = blockchain.GetTransaction(hash);
                if (tx == null)
                {
                    throw new RpcException(-100, "Unknown transaction");
                }
                if (verbose)
                {
                    JObject json   = tx.ToJson();
                    uint?   height = blockchain.Store.GetTransactions().TryGet(hash)?.BlockIndex;
                    if (height != null)
                    {
                        Header header = blockchain.Store.GetHeader((uint)height);
                        json["blockhash"]     = header.Hash.ToString();
                        json["confirmations"] = blockchain.Height - header.Index + 1;
                        json["blocktime"]     = header.Timestamp;
                    }
                    return(json);
                }
                return(tx.ToArray().ToHexString());
            }

            case "getstorage":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                UInt160     script_hash = UInt160.Parse(_params[1].AsString());
                byte[]      key         = _params[1].AsString().HexToBytes();
                StorageItem item        = blockchain.Store.GetStorages().TryGet(new StorageKey
                    {
                        ScriptHash = script_hash,
                        Key        = key
                    }) ?? new StorageItem();
                return(item.Value?.ToHexString());
            }

            case "gettxout":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                UInt256 hash  = UInt256.Parse(_params[1].AsString());
                ushort  index = (ushort)_params[2].AsNumber();
                return(blockchain.Store.GetUnspent(hash, index)?.ToJson(index));
            }

            case "getvalidators":
            {
                UInt160    chain_hash = _params[0].AsString().ToScriptHash();
                Blockchain blockchain = Blockchain.GetBlockchain(chain_hash);
                if (blockchain == null)
                {
                    throw new RpcException(-100, "Unknown blockchain");
                }

                using (Snapshot snapshot = blockchain.GetSnapshot())
                {
                    var validators = snapshot.GetValidators();
                    return(snapshot.GetEnrollments().Select(p =>
                        {
                            JObject validator = new JObject();
                            validator["publickey"] = p.PublicKey.ToString();
                            validator["votes"] = p.Votes.ToString();
                            validator["active"] = validators.Contains(p.PublicKey);
                            return validator;
                        }).ToArray());
                }
            }

            case "getversion":
            {
                JObject json = new JObject();
                json["port"]      = LocalNode.Root.ListenerPort;
                json["nonce"]     = LocalNode.Nonce;
                json["useragent"] = LocalNode.UserAgent;
                return(json);
            }

            case "getwalletheight":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    return((wallet.WalletHeight > 0) ? wallet.WalletHeight - 1 : 0);
                }

            case "invoke":
            {
                UInt160             chain_hash  = UInt160.Parse(_params[0].AsString());
                UInt160             script_hash = UInt160.Parse(_params[1].AsString());
                ContractParameter[] parameters  = ((JArray)_params[2]).Select(p => ContractParameter.FromJson(p)).ToArray();
                byte[] script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, parameters).ToArray();
                }
                return(GetInvokeResult(chain_hash, script));
            }

            case "invokefunction":
            {
                UInt160             chain_hash  = UInt160.Parse(_params[0].AsString());
                UInt160             script_hash = UInt160.Parse(_params[1].AsString());
                string              operation   = _params[2].AsString();
                ContractParameter[] args        = _params.Count >= 4 ? ((JArray)_params[3]).Select(p => ContractParameter.FromJson(p)).ToArray() : new ContractParameter[0];
                byte[]              script;
                using (ScriptBuilder sb = new ScriptBuilder())
                {
                    script = sb.EmitAppCall(script_hash, operation, args).ToArray();
                }
                return(GetInvokeResult(chain_hash, script));
            }

            case "invokescript":
            {
                UInt160 chain_hash = UInt160.Parse(_params[0].AsString());
                byte[]  script     = _params[1].AsString().HexToBytes();
                return(GetInvokeResult(chain_hash, script));
            }

            case "listaddress":
                if (wallet == null)
                {
                    throw new RpcException(-400, "Access denied.");
                }
                else
                {
                    return(wallet.GetAccounts().Select(p =>
                    {
                        JObject account = new JObject();
                        account["address"] = p.Address;
                        account["haskey"] = p.HasKey;
                        account["label"] = p.Label;
                        account["watchonly"] = p.WatchOnly;
                        return account;
                    }).ToArray());
                }

            case "sendrawtransaction":
            {
                UInt160 chain_hash = UInt160.Parse(_params[0].AsString());
                if (system.GetAppChainSystem(chain_hash, out ZoroSystem targetSystem))
                {
                    Transaction       tx     = Transaction.DeserializeFrom(_params[1].AsString().HexToBytes());
                    RelayResultReason reason = targetSystem.Blockchain.Ask <RelayResultReason>(tx).Result;
                    return(GetRelayResult(reason));
                }
                return(RelayResultReason.Invalid);
            }

            case "submitblock":
            {
                UInt160 chain_hash = UInt160.Parse(_params[0].AsString());
                if (system.GetAppChainSystem(chain_hash, out ZoroSystem targetSystem))
                {
                    Block             block  = _params[0].AsString().HexToBytes().AsSerializable <Block>();
                    RelayResultReason reason = targetSystem.Blockchain.Ask <RelayResultReason>(block).Result;
                    return(GetRelayResult(reason));
                }
                return(RelayResultReason.Invalid);
            }

            case "validateaddress":
            {
                JObject json = new JObject();
                UInt160 scriptHash;
                try
                {
                    scriptHash = _params[0].AsString().ToScriptHash();
                }
                catch
                {
                    scriptHash = null;
                }
                json["address"] = _params[0];
                json["isvalid"] = scriptHash != null;
                return(json);
            }

            default:
                throw new RpcException(-32601, "Method not found");
            }
        }