예제 #1
0
 private void InitializeConsensus(byte view_number)
 {
     lock (context)
     {
         if (view_number == 0)
         {
             context.Reset(wallet);
         }
         else
         {
             context.ChangeView(view_number);
         }
         if (context.MyIndex < 0)
         {
             return;
         }
         Log($"initialize: height={context.BlockIndex} view={view_number} index={context.MyIndex} role={(context.MyIndex == context.PrimaryIndex ? ConsensusState.Primary : ConsensusState.Backup)}");
         if (context.MyIndex == context.PrimaryIndex)
         {
             context.State |= ConsensusState.Primary;
             if (!context.State.HasFlag(ConsensusState.SignatureSent))
             {
                 FillContext();
             }
             if (context.TransactionHashes.Length > 1)
             {
                 InvPayload invPayload = InvPayload.Create(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray());
                 foreach (RemoteNode node in localNode.GetRemoteNodes())
                 {
                     node.EnqueueMessage("inv", invPayload);
                 }
             }
             timer_height = context.BlockIndex;
             timer_view   = view_number;
             // 议长发起共识时间控制
             TimeSpan span = DateTime.Now - block_received_time;
             if (span >= Blockchain.TimePerBlock)
             {
                 timer.Change(0, Timeout.Infinite);// 间隔时间大于预订时间则立即发起共识
             }
             else
             {
                 timer.Change(Blockchain.TimePerBlock - span, Timeout.InfiniteTimeSpan);// 定时执行
             }
         }
         else
         {
             context.State = ConsensusState.Backup;
             timer_height  = context.BlockIndex;
             timer_view    = view_number;
             // 议员超时控制 t * 2 ^ (view_number + 1)
             timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (view_number + 1)), Timeout.InfiniteTimeSpan);
         }
     }
 }
예제 #2
0
 private void ClearRts(LocalNode localNode)
 {
     foreach (RemoteNode node in localNode.GetRemoteNodes())
     {
         node.ClearCounters();
     }
 }
예제 #3
0
        private JObject GetPeers(JObject param)
        {
            LocalNode localNode = GetTargetNode(param);

            JObject json = new JObject();

            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);
        }
예제 #4
0
        private void OnShowStateCommand()
        {
            var cancel = new CancellationTokenSource();

            Console.CursorVisible = false;
            Console.Clear();

            Task broadcast = Task.Run(async() =>
            {
                while (!cancel.Token.IsCancellationRequested)
                {
                    NeoSystem.LocalNode.Tell(Message.Create(MessageCommand.Ping, PingPayload.Create(NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView))));
                    await Task.Delay(NeoSystem.Settings.TimePerBlock, cancel.Token);
                }
            });
            Task task = Task.Run(async() =>
            {
                int maxLines = 0;
                while (!cancel.Token.IsCancellationRequested)
                {
                    uint height       = NativeContract.Ledger.CurrentIndex(NeoSystem.StoreView);
                    uint headerHeight = NeoSystem.HeaderCache.Last?.Index ?? height;

                    Console.SetCursorPosition(0, 0);
                    WriteLineWithoutFlicker($"block: {height}/{headerHeight}  connected: {LocalNode.ConnectedCount}  unconnected: {LocalNode.UnconnectedCount}", Console.WindowWidth - 1);

                    int linesWritten = 1;
                    foreach (RemoteNode node in LocalNode.GetRemoteNodes().OrderByDescending(u => u.LastBlockIndex).Take(Console.WindowHeight - 2).ToArray())
                    {
                        ConsoleHelper.Info("  ip: ",
                                           $"{ node.Remote.Address,-15}\t",
                                           "port: ",
                                           $"{node.Remote.Port,-5}\t",
                                           "listen: ",
                                           $"{node.ListenerTcpPort,-5}\t",
                                           "height: ",
                                           $"{node.LastBlockIndex,-7}");
                        linesWritten++;
                    }

                    maxLines = Math.Max(maxLines, linesWritten);

                    while (linesWritten < maxLines)
                    {
                        WriteLineWithoutFlicker("", Console.WindowWidth - 1);
                        maxLines--;
                    }

                    await Task.Delay(500, cancel.Token);
                }
            });

            ReadLine();
            cancel.Cancel();
            try { Task.WaitAll(task, broadcast); } catch { }
            Console.WriteLine();
            Console.CursorVisible = true;
        }
예제 #5
0
 private bool OnShowNodeCommand(string[] args)
 {
     RemoteNode[] nodes = localnode.GetRemoteNodes();
     for (int i = 0; i < nodes.Length; i++)
     {
         Console.WriteLine($"{nodes[i].RemoteEndpoint.Address} port:{nodes[i].RemoteEndpoint.Port} listen:{nodes[i].ListenerEndpoint?.Port ?? 0} [{i + 1}/{nodes.Length}]");
     }
     return(true);
 }
예제 #6
0
        private void ShowState(LocalNode localNode, bool printRemoteNode)
        {
            Blockchain blockchain = localNode.Blockchain;

            Console.WriteLine($"block:{blockchain.Name} {blockchain.ChainHash.ToString()} {blockchain.Height}/{blockchain.HeaderHeight}  connected: {localNode.ConnectedCount}  unconnected: {localNode.UnconnectedCount}  mempool:{blockchain.GetMemoryPoolCount()}");
            if (printRemoteNode)
            {
                foreach (RemoteNode node in localNode.GetRemoteNodes())
                {
                    Console.WriteLine($"  ip: {node.Remote.Address}\tport: {node.Remote.Port}\tlisten: {node.ListenerPort}\theight: {node.Height}\tlatency: {node.Latency}");
                }
            }
        }
예제 #7
0
        private void ShowRts(LocalNode localNode, InventoryType type)
        {
            Blockchain blockchain = localNode.Blockchain;

            Console.WriteLine($"block:{blockchain.Name} {blockchain.ChainHash.ToString()} {blockchain.Height}/{blockchain.HeaderHeight}  connected: {localNode.ConnectedCount}  mempool:{blockchain.GetMemoryPoolCount()}  TX:{GetTXRate(localNode.TxRate)}");

            foreach (RemoteNode node in localNode.GetRemoteNodes())
            {
                Console.WriteLine($"  ip: {node.Remote.Address}\t" +
                                  $"send: {node.GetCounter(RemoteNode.CounterType.Send, type)} " +
                                  $"request: {node.GetCounter(RemoteNode.CounterType.Request, type)} " +
                                  $"recv: {node.GetCounter(RemoteNode.CounterType.Received, type)} " +
                                  $"timeout: {node.GetCounter(RemoteNode.CounterType.Timeout, type)} " +
                                  $"TX:{GetTXRate(node.TXRate)}");
            }
        }
예제 #8
0
 private void OnTimeout(object state)
 {
     lock (context)
     {
         if (timer_height != context.BlockIndex || timer_view != context.ViewNumber)
         {
             return;
         }
         Log($"timeout: height={timer_height} view={timer_view} state={context.State}");
         if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
         {
             Log($"send perpare request: height={timer_height} view={timer_view}");
             context.State |= ConsensusState.RequestSent;
             if (!context.State.HasFlag(ConsensusState.SignatureSent))
             {
                 context.Timestamp = Math.Max(DateTime.Now.ToTimestamp(), Blockchain.Default.GetHeader(context.PrevHash).Timestamp + 1);
                 context.Nonce     = GetNonce();
                 List <Transaction> transactions = LocalNode.GetMemoryPool().Where(p => CheckPolicy(p)).ToList();
                 if (transactions.Count >= Settings.Default.MaxTransactionsPerBlock)
                 {
                     transactions = transactions.OrderByDescending(p => p.NetworkFee / p.Size).Take(Settings.Default.MaxTransactionsPerBlock - 1).ToList();
                 }
                 transactions.Insert(0, CreateMinerTransaction(transactions, context.BlockIndex, context.Nonce));
                 context.TransactionHashes           = transactions.Select(p => p.Hash).ToArray();
                 context.Transactions                = transactions.ToDictionary(p => p.Hash);
                 context.NextConsensus               = Blockchain.GetConsensusAddress(Blockchain.Default.GetValidators(transactions).ToArray());
                 context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair);
             }
             InvPayload invPayload = InvPayload.Create(InventoryType.TX, context.TransactionHashes);
             foreach (RemoteNode node in localNode.GetRemoteNodes())
             {
                 node.EnqueueMessage("inv", invPayload);
             }
             SignAndRelay(context.MakePrepareRequest());
             timer.Change(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer_view + 1)), Timeout.InfiniteTimeSpan);
         }
         else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
         {
             RequestChangeView();
         }
     }
 }
예제 #9
0
파일: RpcServer.cs 프로젝트: FDship/SBC
        protected virtual JObject Process(string method, JArray _params)
        {
            switch (method)
            {
            case "getaccountstate":
            {
                UInt160      script_hash = Wallet.ToScriptHash(_params[0].AsString());
                AccountState account     = Blockchain.Default.GetAccountState(script_hash) ?? new AccountState(script_hash);
                return(account.ToJson());
            }

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

            case "getbestblockhash":
                return(Blockchain.Default.CurrentBlockHash.ToString());

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

            case "getblockcount":
                return(Blockchain.Default.Height + 1);

            case "getblockhash":
            {
                uint height = (uint)_params[0].AsNumber();
                if (height >= 0 && height <= Blockchain.Default.Height)
                {
                    return(Blockchain.Default.GetBlockHash(height).ToString());
                }
                else
                {
                    throw new RpcException(-100, "Invalid Height");
                }
            }

            case "getblocksysfee":
            {
                uint height = (uint)_params[0].AsNumber();
                if (height >= 0 && height <= Blockchain.Default.Height)
                {
                    return(Blockchain.Default.GetSysFeeAmount(height).ToString());
                }
                else
                {
                    throw new RpcException(-100, "Invalid Height");
                }
            }

            case "getconnectioncount":
                return(LocalNode.RemoteNodeCount);

            case "getcontractstate":
            {
                UInt160       script_hash = UInt160.Parse(_params[0].AsString());
                ContractState contract    = Blockchain.Default.GetContract(script_hash);
                return(contract?.ToJson() ?? throw new RpcException(-100, "Unknown contract"));
            }

            case "getrawmempool":
                return(new JArray(LocalNode.GetMemoryPool().Select(p => (JObject)p.Hash.ToString())));

            case "getrawtransaction":
            {
                UInt256     hash    = UInt256.Parse(_params[0].AsString());
                bool        verbose = _params.Count >= 2 && _params[1].AsBooleanOrDefault(false);
                int         height  = -1;
                Transaction tx      = LocalNode.GetTransaction(hash);
                if (tx == null)
                {
                    tx = Blockchain.Default.GetTransaction(hash, out height);
                }
                if (tx == null)
                {
                    throw new RpcException(-100, "Unknown transaction");
                }
                if (verbose)
                {
                    JObject json = tx.ToJson();
                    if (height >= 0)
                    {
                        Header header = Blockchain.Default.GetHeader((uint)height);
                        json["blockhash"]     = header.Hash.ToString();
                        json["confirmations"] = Blockchain.Default.Height - header.Index + 1;
                        json["blocktime"]     = header.Timestamp;
                    }
                    return(json);
                }
                else
                {
                    return(tx.ToArray().ToHexString());
                }
            }

            case "getstorage":
            {
                UInt160     script_hash = UInt160.Parse(_params[0].AsString());
                byte[]      key         = _params[1].AsString().HexToBytes();
                StorageItem item        = Blockchain.Default.GetStorageItem(new StorageKey
                    {
                        ScriptHash = script_hash,
                        Key        = key
                    }) ?? new StorageItem();
                return(item.Value?.ToHexString());
            }

            case "gettxout":
            {
                UInt256 hash  = UInt256.Parse(_params[0].AsString());
                ushort  index = (ushort)_params[1].AsNumber();
                return(Blockchain.Default.GetUnspent(hash, index)?.ToJson(index));
            }

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

            case "invokefunction":
            {
                UInt160             script_hash = UInt160.Parse(_params[0].AsString());
                string              operation   = _params[1].AsString();
                ContractParameter[] args        = _params.Count >= 3 ? ((JArray)_params[2]).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(script));
            }

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

            case "sendrawtransaction":
            {
                Transaction tx = Transaction.DeserializeFrom(_params[0].AsString().HexToBytes());
                return(LocalNode.Relay(tx));
            }

            case "submitblock":
            {
                Block block = _params[0].AsString().HexToBytes().AsSerializable <Block>();
                return(LocalNode.Relay(block));
            }

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

            case "getpeers":
            {
                JObject json = new JObject();

                {
                    JArray unconnectedPeers = new JArray();
                    foreach (IPEndPoint peer in LocalNode.GetUnconnectedPeers())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = peer.Address.ToString();
                        peerJson["port"]    = peer.Port;
                        unconnectedPeers.Add(peerJson);
                    }
                    json["unconnected"] = unconnectedPeers;
                }

                {
                    JArray badPeers = new JArray();
                    foreach (IPEndPoint peer in LocalNode.GetBadPeers())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = peer.Address.ToString();
                        peerJson["port"]    = peer.Port;
                        badPeers.Add(peerJson);
                    }
                    json["bad"] = badPeers;
                }

                {
                    JArray connectedPeers = new JArray();
                    foreach (RemoteNode node in LocalNode.GetRemoteNodes())
                    {
                        JObject peerJson = new JObject();
                        peerJson["address"] = node.RemoteEndpoint.Address.ToString();
                        peerJson["port"]    = node.ListenerEndpoint?.Port ?? 0;
                        connectedPeers.Add(peerJson);
                    }
                    json["connected"] = connectedPeers;
                }

                return(json);
            }

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

            default:
                throw new RpcException(-32601, "Method not found");
            }
        }
예제 #10
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");
            }
        }
예제 #11
0
        private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message)
        {
            Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}");
            if (!context.State.HasFlag(ConsensusState.Backup) || context.State.HasFlag(ConsensusState.RequestReceived))
            {
                return;
            }
            if (payload.ValidatorIndex != context.PrimaryIndex)
            {
                return;
            }
            if (payload.Timestamp <= Blockchain.Default.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.Now.AddMinutes(10).ToTimestamp())
            {
                Log($"Timestamp incorrect: {payload.Timestamp}");
                return;
            }
            context.State            |= ConsensusState.RequestReceived;
            context.Timestamp         = payload.Timestamp;
            context.Nonce             = message.Nonce;
            context.CurrentConsensus  = message.CurrentConsensus;
            context.NextConsensus     = message.NextConsensus;
            context.TransactionHashes = message.TransactionHashes;
            if (context.TransactionHashes.Length > MaxTransactionsPerBlock)
            {
                return;
            }
            context.Transactions = new Dictionary <UInt256, Transaction>();
            if (!Crypto.Default.VerifySignature(context.MakeHeader().GetHashData(), message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false)))
            {
                return;
            }
            context.Signatures = new byte[context.Validators.Length][];
            context.Signatures[payload.ValidatorIndex] = message.Signature;
            Dictionary <UInt256, Transaction> mempool = LocalNode.GetMemoryPool().ToDictionary(p => p.Hash);

            foreach (UInt256 hash in context.TransactionHashes.Skip(1))
            {
                if (mempool.TryGetValue(hash, out Transaction tx))
                {
                    Console.WriteLine("No Verify Add Transaction" + tx.is_consensus_mempool);
                    if (!AddTransaction(tx, true))
                    {
                        return;
                    }
                }
            }
            if (!AddTransaction(message.MinerTransaction, true))
            {
                return;
            }
            if (context.Transactions.Count < context.TransactionHashes.Length)
            {
                LocalNode.AllowHashes(context.TransactionHashes.Except(context.Transactions.Keys));
                UInt256[]  hashes = context.TransactionHashes.ToArray();         // get hashes
                InvPayload msg    = InvPayload.Create(InventoryType.TX, hashes); // create message
                foreach (RemoteNode node in localNode.GetRemoteNodes())          // enqueue message
                {
                    node.EnqueueMessage("getdata", msg);
                }
            }
        }