From 534c56b85d93392fcd828263b201c00e27841a5b Mon Sep 17 00:00:00 2001 From: Erik Zhang Date: Fri, 14 Sep 2018 23:46:55 +0800 Subject: [PATCH] NEO-CLI v2.9.0 (#188) --- neo-cli/Consensus/ConsensusWithLog.cs | 32 -- neo-cli/Helper.cs | 39 --- neo-cli/Network/RPC/RpcServerWithWallet.cs | 245 -------------- neo-cli/Services/ConsoleServiceBase.cs | 1 - neo-cli/Settings.cs | 8 +- neo-cli/Shell/Coins.cs | 75 +++-- neo-cli/Shell/MainService.cs | 358 +++++---------------- neo-cli/config.json | 2 +- neo-cli/config.mainnet.json | 2 +- neo-cli/config.testnet.json | 2 +- neo-cli/neo-cli.csproj | 4 +- 11 files changed, 139 insertions(+), 629 deletions(-) delete mode 100644 neo-cli/Consensus/ConsensusWithLog.cs delete mode 100644 neo-cli/Helper.cs delete mode 100644 neo-cli/Network/RPC/RpcServerWithWallet.cs diff --git a/neo-cli/Consensus/ConsensusWithLog.cs b/neo-cli/Consensus/ConsensusWithLog.cs deleted file mode 100644 index 1beeff856..000000000 --- a/neo-cli/Consensus/ConsensusWithLog.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Neo.Network; -using Neo.Wallets; -using System; -using System.IO; - -namespace Neo.Consensus -{ - internal class ConsensusWithLog : ConsensusService - { - private string log_dictionary; - - public ConsensusWithLog(LocalNode localNode, Wallet wallet, string log_dictionary) - : base(localNode, wallet) - { - this.log_dictionary = log_dictionary; - } - - protected override void Log(string message) - { - DateTime now = DateTime.Now; - string line = $"[{now.TimeOfDay:hh\\:mm\\:ss}] {message}"; - Console.WriteLine(line); - if (string.IsNullOrEmpty(log_dictionary)) return; - lock (log_dictionary) - { - Directory.CreateDirectory(log_dictionary); - string path = Path.Combine(log_dictionary, $"{now:yyyy-MM-dd}.log"); - File.AppendAllLines(path, new[] { line }); - } - } - } -} diff --git a/neo-cli/Helper.cs b/neo-cli/Helper.cs deleted file mode 100644 index f35ebb3ab..000000000 --- a/neo-cli/Helper.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using System.Security; - -namespace Neo -{ - internal static class Helper - { - public static bool CompareTo(this SecureString s1, SecureString s2) - { - if (s1.Length != s2.Length) - return false; - IntPtr p1 = IntPtr.Zero; - IntPtr p2 = IntPtr.Zero; - try - { - p1 = SecureStringMarshal.SecureStringToGlobalAllocAnsi(s1); - p2 = SecureStringMarshal.SecureStringToGlobalAllocAnsi(s2); - int i = 0; - while (true) - { - byte b1 = Marshal.ReadByte(p1, i); - byte b2 = Marshal.ReadByte(p2, i++); - if (b1 == 0 && b2 == 0) - return true; - if (b1 != b2) - return false; - if (b1 == 0 || b2 == 0) - return false; - } - } - finally - { - Marshal.ZeroFreeGlobalAllocAnsi(p1); - Marshal.ZeroFreeGlobalAllocAnsi(p2); - } - } - } -} diff --git a/neo-cli/Network/RPC/RpcServerWithWallet.cs b/neo-cli/Network/RPC/RpcServerWithWallet.cs deleted file mode 100644 index 8d0b45ba3..000000000 --- a/neo-cli/Network/RPC/RpcServerWithWallet.cs +++ /dev/null @@ -1,245 +0,0 @@ -using Neo.Core; -using Neo.Implementations.Wallets.NEP6; -using Neo.IO; -using Neo.IO.Json; -using Neo.SmartContract; -using Neo.Wallets; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Neo.Network.RPC -{ - internal class RpcServerWithWallet : RpcServer - { - public RpcServerWithWallet(LocalNode localNode) - : base(localNode) - { - } - - protected override JObject Process(string method, JArray _params) - { - switch (method) - { - case "getapplicationlog": - { - UInt256 hash = UInt256.Parse(_params[0].AsString()); - string path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{hash}.json"); - return File.Exists(path) - ? JObject.Parse(File.ReadAllText(path)) - : throw new RpcException(-100, "Unknown transaction"); - } - case "getbalance": - if (Program.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"] = Program.Wallet.GetAvailable(asset_id_160).ToString(); - break; - case UInt256 asset_id_256: //Global Assets balance - IEnumerable coins = Program.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 "getwalletheight": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied."); - else - return (Program.Wallet.WalletHeight > 0) ? Program.Wallet.WalletHeight - 1 : 0; - case "listaddress": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied."); - else - return Program.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 "sendfrom": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied"); - else - { - UIntBase assetId = UIntBase.Parse(_params[0].AsString()); - AssetDescriptor descriptor = new AssetDescriptor(assetId); - UInt160 from = Wallet.ToScriptHash(_params[1].AsString()); - UInt160 to = Wallet.ToScriptHash(_params[2].AsString()); - BigDecimal value = BigDecimal.Parse(_params[3].AsString(), descriptor.Decimals); - if (value.Sign <= 0) - throw new RpcException(-32602, "Invalid params"); - Fixed8 fee = _params.Count >= 5 ? Fixed8.Parse(_params[4].AsString()) : Fixed8.Zero; - if (fee < Fixed8.Zero) - throw new RpcException(-32602, "Invalid params"); - UInt160 change_address = _params.Count >= 6 ? Wallet.ToScriptHash(_params[5].AsString()) : null; - Transaction tx = Program.Wallet.MakeTransaction(null, new[] - { - new TransferOutput - { - AssetId = assetId, - Value = value, - ScriptHash = to - } - }, from: from, change_address: change_address, fee: fee); - if (tx == null) - throw new RpcException(-300, "Insufficient funds"); - ContractParametersContext context = new ContractParametersContext(tx); - Program.Wallet.Sign(context); - if (context.Completed) - { - tx.Scripts = context.GetScripts(); - Program.Wallet.ApplyTransaction(tx); - LocalNode.Relay(tx); - return tx.ToJson(); - } - else - { - return context.ToJson(); - } - } - case "sendtoaddress": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied"); - else - { - UIntBase assetId = UIntBase.Parse(_params[0].AsString()); - AssetDescriptor descriptor = new AssetDescriptor(assetId); - UInt160 scriptHash = Wallet.ToScriptHash(_params[1].AsString()); - BigDecimal value = BigDecimal.Parse(_params[2].AsString(), descriptor.Decimals); - if (value.Sign <= 0) - throw new RpcException(-32602, "Invalid params"); - Fixed8 fee = _params.Count >= 4 ? Fixed8.Parse(_params[3].AsString()) : Fixed8.Zero; - if (fee < Fixed8.Zero) - throw new RpcException(-32602, "Invalid params"); - UInt160 change_address = _params.Count >= 5 ? Wallet.ToScriptHash(_params[4].AsString()) : null; - Transaction tx = Program.Wallet.MakeTransaction(null, new[] - { - new TransferOutput - { - AssetId = assetId, - Value = value, - ScriptHash = scriptHash - } - }, change_address: change_address, fee: fee); - if (tx == null) - throw new RpcException(-300, "Insufficient funds"); - ContractParametersContext context = new ContractParametersContext(tx); - Program.Wallet.Sign(context); - if (context.Completed) - { - tx.Scripts = context.GetScripts(); - Program.Wallet.ApplyTransaction(tx); - LocalNode.Relay(tx); - return tx.ToJson(); - } - else - { - return context.ToJson(); - } - } - case "sendmany": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied"); - else - { - JArray to = (JArray)_params[0]; - if (to.Count == 0) - throw new RpcException(-32602, "Invalid params"); - TransferOutput[] outputs = new TransferOutput[to.Count]; - for (int i = 0; i < to.Count; i++) - { - UIntBase asset_id = UIntBase.Parse(to[i]["asset"].AsString()); - AssetDescriptor descriptor = new AssetDescriptor(asset_id); - outputs[i] = new TransferOutput - { - AssetId = asset_id, - Value = BigDecimal.Parse(to[i]["value"].AsString(), descriptor.Decimals), - ScriptHash = Wallet.ToScriptHash(to[i]["address"].AsString()) - }; - if (outputs[i].Value.Sign <= 0) - throw new RpcException(-32602, "Invalid params"); - } - Fixed8 fee = _params.Count >= 2 ? Fixed8.Parse(_params[1].AsString()) : Fixed8.Zero; - if (fee < Fixed8.Zero) - throw new RpcException(-32602, "Invalid params"); - UInt160 change_address = _params.Count >= 3 ? Wallet.ToScriptHash(_params[2].AsString()) : null; - Transaction tx = Program.Wallet.MakeTransaction(null, outputs, change_address: change_address, fee: fee); - if (tx == null) - throw new RpcException(-300, "Insufficient funds"); - ContractParametersContext context = new ContractParametersContext(tx); - Program.Wallet.Sign(context); - if (context.Completed) - { - tx.Scripts = context.GetScripts(); - Program.Wallet.ApplyTransaction(tx); - LocalNode.Relay(tx); - return tx.ToJson(); - } - else - { - return context.ToJson(); - } - } - case "getnewaddress": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied"); - else - { - WalletAccount account = Program.Wallet.CreateAccount(); - if (Program.Wallet is NEP6Wallet wallet) - wallet.Save(); - return account.Address; - } - case "dumpprivkey": - if (Program.Wallet == null) - throw new RpcException(-400, "Access denied"); - else - { - UInt160 scriptHash = Wallet.ToScriptHash(_params[0].AsString()); - WalletAccount account = Program.Wallet.GetAccount(scriptHash); - return account.GetKey().Export(); - } - case "invoke": - case "invokefunction": - case "invokescript": - JObject result = base.Process(method, _params); - if (Program.Wallet != null) - { - InvocationTransaction tx = new InvocationTransaction - { - Version = 1, - Script = result["script"].AsString().HexToBytes(), - Gas = Fixed8.Parse(result["gas_consumed"].AsString()) - }; - tx.Gas -= Fixed8.FromDecimal(10); - if (tx.Gas < Fixed8.Zero) tx.Gas = Fixed8.Zero; - tx.Gas = tx.Gas.Ceiling(); - tx = Program.Wallet.MakeTransaction(tx); - if (tx != null) - { - ContractParametersContext context = new ContractParametersContext(tx); - Program.Wallet.Sign(context); - if (context.Completed) - tx.Scripts = context.GetScripts(); - else - tx = null; - } - result["tx"] = tx?.ToArray().ToHexString(); - } - return result; - default: - return base.Process(method, _params); - } - } - } -} diff --git a/neo-cli/Services/ConsoleServiceBase.cs b/neo-cli/Services/ConsoleServiceBase.cs index e9d90a20c..1e5675a75 100644 --- a/neo-cli/Services/ConsoleServiceBase.cs +++ b/neo-cli/Services/ConsoleServiceBase.cs @@ -2,7 +2,6 @@ using System.Reflection; using System.Security; using System.Text; -using Neo.Shell; namespace Neo.Services { diff --git a/neo-cli/Settings.cs b/neo-cli/Settings.cs index 22cb8e307..73f1902a6 100644 --- a/neo-cli/Settings.cs +++ b/neo-cli/Settings.cs @@ -1,5 +1,5 @@ using Microsoft.Extensions.Configuration; -using Neo.Network; +using Neo.Network.P2P; namespace Neo { @@ -30,12 +30,12 @@ public Settings(IConfigurationSection section) internal class PathsSettings { public string Chain { get; } - public string ApplicationLogs { get; } + public string Index { get; } public PathsSettings(IConfigurationSection section) { this.Chain = string.Format(section.GetSection("Chain").Value, Message.Magic.ToString("X8")); - this.ApplicationLogs = string.Format(section.GetSection("ApplicationLogs").Value, Message.Magic.ToString("X8")); + this.Index = string.Format(section.GetSection("Index").Value, Message.Magic.ToString("X8")); } } @@ -79,7 +79,7 @@ public UnlockWalletSettings(IConfigurationSection section) this.Path = section.GetSection("Path").Value; this.Password = section.GetSection("Password").Value; this.StartConsensus = bool.Parse(section.GetSection("StartConsensus").Value); - this.IsActive = bool.Parse(section.GetSection("IsActive").Value); + this.IsActive = bool.Parse(section.GetSection("IsActive").Value); } } } diff --git a/neo-cli/Shell/Coins.cs b/neo-cli/Shell/Coins.cs index a777243ec..f76a62e9e 100644 --- a/neo-cli/Shell/Coins.cs +++ b/neo-cli/Shell/Coins.cs @@ -1,5 +1,7 @@ -using Neo.Core; -using Neo.Network; +using Akka.Actor; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.SmartContract; using Neo.Wallets; using System; @@ -11,35 +13,41 @@ namespace Neo.Shell public class Coins { private Wallet current_wallet; - private LocalNode local_node; + private NeoSystem system; - public Coins(Wallet wallet, LocalNode node) + public Coins(Wallet wallet, NeoSystem system) { - current_wallet = wallet; - local_node = node; + this.current_wallet = wallet; + this.system = system; } public Fixed8 UnavailableBonus() { - uint height = Blockchain.Default.Height + 1; - Fixed8 unavailable; - - try - { - unavailable = Blockchain.CalculateBonus(current_wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), height); - } - catch (Exception) + using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { - unavailable = Fixed8.Zero; - } + uint height = snapshot.Height + 1; + Fixed8 unavailable; - return unavailable; + try + { + unavailable = snapshot.CalculateBonus(current_wallet.FindUnspentCoins().Where(p => p.Output.AssetId.Equals(Blockchain.GoverningToken.Hash)).Select(p => p.Reference), height); + } + catch (Exception) + { + unavailable = Fixed8.Zero; + } + + return unavailable; + } } public Fixed8 AvailableBonus() { - return Blockchain.CalculateBonus(current_wallet.GetUnclaimedCoins().Select(p => p.Reference)); + using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) + { + return snapshot.CalculateBonus(current_wallet.GetUnclaimedCoins().Select(p => p.Reference)); + } } @@ -55,24 +63,27 @@ public ClaimTransaction Claim() CoinReference[] claims = current_wallet.GetUnclaimedCoins().Select(p => p.Reference).ToArray(); if (claims.Length == 0) return null; - ClaimTransaction tx = new ClaimTransaction + using (Snapshot snapshot = Blockchain.Singleton.GetSnapshot()) { - Claims = claims, - Attributes = new TransactionAttribute[0], - Inputs = new CoinReference[0], - Outputs = new[] + ClaimTransaction tx = new ClaimTransaction { - new TransactionOutput + Claims = claims, + Attributes = new TransactionAttribute[0], + Inputs = new CoinReference[0], + Outputs = new[] { - AssetId = Blockchain.UtilityToken.Hash, - Value = Blockchain.CalculateBonus(claims), - ScriptHash = current_wallet.GetChangeAddress() + new TransactionOutput + { + AssetId = Blockchain.UtilityToken.Hash, + Value = snapshot.CalculateBonus(claims), + ScriptHash = current_wallet.GetChangeAddress() + } } - } - }; + }; - return (ClaimTransaction)SignTransaction(tx); + return (ClaimTransaction)SignTransaction(tx); + } } @@ -100,10 +111,10 @@ private Transaction SignTransaction(Transaction tx) if (context.Completed) { - context.Verifiable.Scripts = context.GetScripts(); + context.Verifiable.Witnesses = context.GetWitnesses(); current_wallet.ApplyTransaction(tx); - bool relay_result = local_node.Relay(tx); + bool relay_result = system.Blockchain.Ask(tx).Result == RelayResultReason.Succeed; if (relay_result) { diff --git a/neo-cli/Shell/MainService.cs b/neo-cli/Shell/MainService.cs index d944f4d6d..6e9ec653f 100644 --- a/neo-cli/Shell/MainService.cs +++ b/neo-cli/Shell/MainService.cs @@ -1,25 +1,23 @@ -using Neo.Consensus; -using Neo.Core; -using Neo.Implementations.Blockchains.LevelDB; -using Neo.Implementations.Wallets.EntityFramework; -using Neo.Implementations.Wallets.NEP6; +using Akka.Actor; using Neo.IO; -using Neo.IO.Json; -using Neo.Network; -using Neo.Network.Payloads; -using Neo.Network.RPC; +using Neo.Ledger; +using Neo.Network.P2P; +using Neo.Network.P2P.Payloads; +using Neo.Persistence; +using Neo.Persistence.LevelDB; +using Neo.Plugins; using Neo.Services; using Neo.SmartContract; -using Neo.VM; using Neo.Wallets; +using Neo.Wallets.NEP6; +using Neo.Wallets.SQLite; using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using System.Linq; using System.Net; using System.Security.Cryptography; -using System.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using ECCurve = Neo.Cryptography.ECC.ECCurve; using ECPoint = Neo.Cryptography.ECC.ECPoint; @@ -30,36 +28,30 @@ internal class MainService : ConsoleServiceBase { private const string PeerStatePath = "peers.dat"; - private RpcServerWithWallet rpc; - private ConsensusWithLog consensus; + private LevelDBStore store; + private NeoSystem system; + private WalletIndexer indexer; - protected LocalNode LocalNode { get; private set; } protected override string Prompt => "neo"; public override string ServiceName => "NEO-CLI"; - private void ImportBlocks(Stream stream, bool read_start = false) + private WalletIndexer GetIndexer() { - LevelDBBlockchain blockchain = (LevelDBBlockchain)Blockchain.Default; - using (BinaryReader r = new BinaryReader(stream)) - { - uint start = read_start ? r.ReadUInt32() : 0; - uint count = r.ReadUInt32(); - uint end = start + count - 1; - if (end <= blockchain.Height) return; - for (uint height = start; height <= end; height++) - { - byte[] array = r.ReadBytes(r.ReadInt32()); - if (height > blockchain.Height) - { - Block block = array.AsSerializable(); - blockchain.AddBlockDirectly(block); - } - } - } + if (indexer is null) + indexer = new WalletIndexer(Settings.Default.Paths.Index); + return indexer; + } + + private static bool NoWallet() + { + if (Program.Wallet != null) return false; + Console.WriteLine("You have to open the wallet first."); + return true; } protected override bool OnCommand(string[] args) { + if (Plugin.SendMessage(args)) return true; switch (args[0].ToLower()) { case "broadcast": @@ -108,9 +100,9 @@ private bool OnBroadcastCommand(string[] args) break; case "block": if (args[2].Length == 64 || args[2].Length == 66) - payload = Blockchain.Default.GetBlock(UInt256.Parse(args[2])); + payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2])); else - payload = Blockchain.Default.GetBlock(uint.Parse(args[2])); + payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2])); break; case "getblocks": case "getheaders": @@ -121,7 +113,7 @@ private bool OnBroadcastCommand(string[] args) payload = InvPayload.Create(Enum.Parse(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray()); break; case "tx": - payload = LocalNode.GetTransaction(UInt256.Parse(args[2])) ?? Blockchain.Default.GetTransaction(UInt256.Parse(args[2])); + payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2])); break; case "alert": case "consensus": @@ -137,12 +129,11 @@ private bool OnBroadcastCommand(string[] args) Console.WriteLine($"Command \"{command}\" is not supported."); return true; } - foreach (RemoteNode node in LocalNode.GetRemoteNodes()) - node.EnqueueMessage(command, payload); + system.LocalNode.Tell(Message.Create(command, payload)); return true; } - private bool OnRelayCommand(string [] args) + private bool OnRelayCommand(string[] args) { if (args.Length < 2) { @@ -163,9 +154,9 @@ private bool OnRelayCommand(string [] args) Console.WriteLine("The signature is incomplete."); return true; } - context.Verifiable.Scripts = context.GetScripts(); + context.Verifiable.Witnesses = context.GetWitnesses(); IInventory inventory = (IInventory)context.Verifiable; - LocalNode.Relay(inventory); + system.LocalNode.Tell(new LocalNode.Relay { Inventory = inventory }); Console.WriteLine($"Data relay success, the hash is shown as follows:\r\n{inventory.Hash}"); } catch (Exception e) @@ -284,7 +275,7 @@ private bool OnCreateWalletCommand(string[] args) { case ".db3": { - Program.Wallet = UserWallet.Create(path, password); + Program.Wallet = UserWallet.Create(GetIndexer(), path, password); WalletAccount account = Program.Wallet.CreateAccount(); Console.WriteLine($"address: {account.Address}"); Console.WriteLine($" pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); @@ -292,7 +283,7 @@ private bool OnCreateWalletCommand(string[] args) break; case ".json": { - NEP6Wallet wallet = new NEP6Wallet(path); + NEP6Wallet wallet = new NEP6Wallet(GetIndexer(), path); wallet.Unlock(password); WalletAccount account = wallet.CreateAccount(); wallet.Save(); @@ -312,9 +303,6 @@ private bool OnExportCommand(string[] args) { switch (args[1].ToLower()) { - case "block": - case "blocks": - return OnExportBlocksCommand(args); case "key": return OnExportKeyCommand(args); default: @@ -322,82 +310,6 @@ private bool OnExportCommand(string[] args) } } - private bool OnExportBlocksCommand(string[] args) - { - if (args.Length > 4) - { - Console.WriteLine("error"); - return true; - } - if (args.Length >= 3 && uint.TryParse(args[2], out uint start)) - { - if (start > Blockchain.Default.Height) - return true; - uint count = args.Length >= 4 ? uint.Parse(args[3]) : uint.MaxValue; - count = Math.Min(count, Blockchain.Default.Height - start + 1); - uint end = start + count - 1; - string path = $"chain.{start}.acc"; - using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) - { - if (fs.Length > 0) - { - fs.Seek(sizeof(uint), SeekOrigin.Begin); - byte[] buffer = new byte[sizeof(uint)]; - fs.Read(buffer, 0, buffer.Length); - start += BitConverter.ToUInt32(buffer, 0); - fs.Seek(sizeof(uint), SeekOrigin.Begin); - } - else - { - fs.Write(BitConverter.GetBytes(start), 0, sizeof(uint)); - } - if (start <= end) - fs.Write(BitConverter.GetBytes(count), 0, sizeof(uint)); - fs.Seek(0, SeekOrigin.End); - for (uint i = start; i <= end; i++) - { - Block block = Blockchain.Default.GetBlock(i); - byte[] array = block.ToArray(); - fs.Write(BitConverter.GetBytes(array.Length), 0, sizeof(int)); - fs.Write(array, 0, array.Length); - Console.SetCursorPosition(0, Console.CursorTop); - Console.Write($"[{i}/{end}]"); - } - } - } - else - { - start = 0; - uint end = Blockchain.Default.Height; - uint count = end - start + 1; - string path = args.Length >= 3 ? args[2] : "chain.acc"; - using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) - { - if (fs.Length > 0) - { - byte[] buffer = new byte[sizeof(uint)]; - fs.Read(buffer, 0, buffer.Length); - start = BitConverter.ToUInt32(buffer, 0); - fs.Seek(0, SeekOrigin.Begin); - } - if (start <= end) - fs.Write(BitConverter.GetBytes(count), 0, sizeof(uint)); - fs.Seek(0, SeekOrigin.End); - for (uint i = start; i <= end; i++) - { - Block block = Blockchain.Default.GetBlock(i); - byte[] array = block.ToArray(); - fs.Write(BitConverter.GetBytes(array.Length), 0, sizeof(int)); - fs.Write(array, 0, array.Length); - Console.SetCursorPosition(0, Console.CursorTop); - Console.Write($"[{i}/{end}]"); - } - } - } - Console.WriteLine(); - return true; - } - private bool OnExportKeyCommand(string[] args) { if (NoWallet()) return true; @@ -412,7 +324,7 @@ private bool OnExportKeyCommand(string[] args) { try { - scriptHash = Wallet.ToScriptHash(args[2]); + scriptHash = args[2].ToScriptHash(); } catch (FormatException) { @@ -421,7 +333,7 @@ private bool OnExportKeyCommand(string[] args) } else if (args.Length == 4) { - scriptHash = Wallet.ToScriptHash(args[2]); + scriptHash = args[2].ToScriptHash(); path = args[3]; } string password = ReadPassword("password"); @@ -477,8 +389,6 @@ private bool OnHelpCommand(string[] args) "\tshow state\n" + "\tshow node\n" + "\tshow pool [verbose]\n" + - "\texport block[s] [path=chain.acc]\n" + - "\texport block[s] [count]\n" + "\trelay \n" + "Advanced Commands:\n" + "\tstart consensus\n"); @@ -591,7 +501,7 @@ private bool OnClaimCommand(string[] args) { if (NoWallet()) return true; - Coins coins = new Coins(Program.Wallet, LocalNode); + Coins coins = new Coins(Program.Wallet, system); switch (args[1].ToLower()) { @@ -611,7 +521,7 @@ private bool OnShowGasCommand(string[] args) { if (NoWallet()) return true; - Coins coins = new Coins(Program.Wallet, LocalNode); + Coins coins = new Coins(Program.Wallet, system); Console.WriteLine($"unavailable: {coins.UnavailableBonus().ToString()}"); Console.WriteLine($" available: {coins.AvailableBonus().ToString()}"); return true; @@ -642,7 +552,7 @@ private bool OnListAssetCommand(string[] args) if (NoWallet()) return true; foreach (var item in Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent)).GroupBy(p => p.Output.AssetId, (k, g) => new { - Asset = Blockchain.Default.GetAssetState(k), + Asset = Blockchain.Singleton.Store.GetAssets().TryGet(k), Balance = g.Sum(p => p.Output.Value), Confirmed = g.Where(p => p.State.HasFlag(CoinState.Confirmed)).Sum(p => p.Output.Value) })) @@ -691,7 +601,7 @@ private bool OnOpenWalletCommand(string[] args) } try { - Program.Wallet = OpenWallet(path, password); + Program.Wallet = OpenWallet(GetIndexer(), path, password); } catch (CryptographicException) { @@ -713,7 +623,7 @@ private bool OnRebuildCommand(string[] args) private bool OnRebuildIndexCommand(string[] args) { - WalletIndexer.RebuildIndex(); + GetIndexer().RebuildIndex(); return true; } @@ -751,7 +661,7 @@ private bool OnSendCommand(string[] args) assetId = UIntBase.Parse(args[1]); break; } - UInt160 scriptHash = Wallet.ToScriptHash(args[2]); + UInt160 scriptHash = args[2].ToScriptHash(); bool isSendAll = string.Equals(args[3], "all", StringComparison.OrdinalIgnoreCase); Transaction tx; if (isSendAll) @@ -800,9 +710,9 @@ private bool OnSendCommand(string[] args) Program.Wallet.Sign(context); if (context.Completed) { - tx.Scripts = context.GetScripts(); + tx.Witnesses = context.GetWitnesses(); Program.Wallet.ApplyTransaction(tx); - LocalNode.Relay(tx); + system.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); Console.WriteLine($"TXID: {tx.Hash}"); } else @@ -819,8 +729,6 @@ private bool OnShowCommand(string[] args) { case "gas": return OnShowGasCommand(args); - case "node": - return OnShowNodeCommand(args); case "pool": return OnShowPoolCommand(args); case "state": @@ -832,20 +740,10 @@ private bool OnShowCommand(string[] args) } } - 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} height:{nodes[i].Version?.StartHeight ?? 0} [{i + 1}/{nodes.Length}]"); - } - return true; - } - private bool OnShowPoolCommand(string[] args) { bool verbose = args.Length >= 3 && args[2] == "verbose"; - Transaction[] transactions = LocalNode.GetMemoryPool().ToArray(); + Transaction[] transactions = Blockchain.Singleton.GetMemoryPool().ToArray(); if (verbose) foreach (Transaction tx in transactions) Console.WriteLine($"{tx.Hash} {tx.GetType().Name}"); @@ -855,12 +753,23 @@ private bool OnShowPoolCommand(string[] args) private bool OnShowStateCommand(string[] args) { - uint wh = 0; - if (Program.Wallet != null) + bool stop = false; + Task.Run(() => { - wh = (Program.Wallet.WalletHeight > 0) ? Program.Wallet.WalletHeight - 1 : 0; - } - Console.WriteLine($"Height: {wh}/{Blockchain.Default.Height}/{Blockchain.Default.HeaderHeight}, Nodes: {LocalNode.RemoteNodeCount}"); + while (!stop) + { + uint wh = 0; + if (Program.Wallet != null) + wh = (Program.Wallet.WalletHeight > 0) ? Program.Wallet.WalletHeight - 1 : 0; + Console.Clear(); + Console.WriteLine($"block: {wh}/{Blockchain.Singleton.Height}/{Blockchain.Singleton.HeaderHeight} connected: {LocalNode.Singleton.ConnectedCount} unconnected: {LocalNode.Singleton.UnconnectedCount}"); + foreach (RemoteNode node in LocalNode.Singleton.GetRemoteNodes().Take(Console.WindowHeight - 2)) + Console.WriteLine($" ip: {node.Remote.Address}\tport: {node.Remote.Port}\tlisten: {node.ListenerPort}\theight: {node.Version?.StartHeight}"); + Thread.Sleep(500); + } + }); + Console.ReadLine(); + stop = true; return true; } @@ -899,7 +808,7 @@ private bool OnShowUtxoCommand(string[] args) protected internal override void OnStart(string[] args) { - bool useRPC = false, nopeers = false, useLog = false; + bool useRPC = false; for (int i = 0; i < args.Length; i++) switch (args[i]) { @@ -908,91 +817,32 @@ protected internal override void OnStart(string[] args) case "-r": useRPC = true; break; - case "--nopeers": - nopeers = true; - break; - case "-l": - case "--log": - useLog = true; - break; } - Blockchain.RegisterBlockchain(new LevelDBBlockchain(Path.GetFullPath(Settings.Default.Paths.Chain))); - if (!nopeers && File.Exists(PeerStatePath)) - using (FileStream fs = new FileStream(PeerStatePath, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - LocalNode.LoadState(fs); - } - LocalNode = new LocalNode(); - if (useLog) - LevelDBBlockchain.ApplicationExecuted += LevelDBBlockchain_ApplicationExecuted; - Task.Run(() => + store = new LevelDBStore(Path.GetFullPath(Settings.Default.Paths.Chain)); + system = new NeoSystem(store); + system.StartNode(Settings.Default.P2P.Port, Settings.Default.P2P.WsPort); + if (Settings.Default.UnlockWallet.IsActive) { - const string path_acc = "chain.acc"; - if (File.Exists(path_acc)) + try { - using (FileStream fs = new FileStream(path_acc, FileMode.Open, FileAccess.Read, FileShare.None)) - { - ImportBlocks(fs); - } + Program.Wallet = OpenWallet(GetIndexer(), Settings.Default.UnlockWallet.Path, Settings.Default.UnlockWallet.Password); } - const string path_acc_zip = path_acc + ".zip"; - if (File.Exists(path_acc_zip)) + catch (CryptographicException) { - using (FileStream fs = new FileStream(path_acc_zip, FileMode.Open, FileAccess.Read, FileShare.None)) - using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Read)) - using (Stream zs = zip.GetEntry(path_acc).Open()) - { - ImportBlocks(zs); - } + Console.WriteLine($"failed to open file \"{Settings.Default.UnlockWallet.Path}\""); } - var paths = Directory.EnumerateFiles(".", "chain.*.acc", SearchOption.TopDirectoryOnly).Concat(Directory.EnumerateFiles(".", "chain.*.acc.zip", SearchOption.TopDirectoryOnly)).Select(p => new - { - FileName = Path.GetFileName(p), - Start = uint.Parse(Regex.Match(p, @"\d+").Value), - IsCompressed = p.EndsWith(".zip") - }).OrderBy(p => p.Start); - foreach (var path in paths) + if (Settings.Default.UnlockWallet.StartConsensus && Program.Wallet != null) { - if (path.Start > Blockchain.Default.Height + 1) break; - if (path.IsCompressed) - { - using (FileStream fs = new FileStream(path.FileName, FileMode.Open, FileAccess.Read, FileShare.None)) - using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Read)) - using (Stream zs = zip.GetEntry(Path.GetFileNameWithoutExtension(path.FileName)).Open()) - { - ImportBlocks(zs, true); - } - } - else - { - using (FileStream fs = new FileStream(path.FileName, FileMode.Open, FileAccess.Read, FileShare.None)) - { - ImportBlocks(fs, true); - } - } + OnStartConsensusCommand(null); } - LocalNode.Start(Settings.Default.P2P.Port, Settings.Default.P2P.WsPort); - if (Settings.Default.UnlockWallet.IsActive) - { - try - { - Program.Wallet = OpenWallet(Settings.Default.UnlockWallet.Path, Settings.Default.UnlockWallet.Password); - } - catch (CryptographicException) - { - Console.WriteLine($"failed to open file \"{Settings.Default.UnlockWallet.Path}\""); - } - if (Settings.Default.UnlockWallet.StartConsensus && Program.Wallet != null) - { - OnStartConsensusCommand(null); - } - } - if (useRPC) - { - rpc = new RpcServerWithWallet(LocalNode); - rpc.Start(Settings.Default.RPC.Port, Settings.Default.RPC.SslCert, Settings.Default.RPC.SslCertPassword); - } - }); + } + if (useRPC) + { + system.StartRpc(Settings.Default.RPC.Port, + wallet: Program.Wallet, + sslCert: Settings.Default.RPC.SslCert, + password: Settings.Default.RPC.SslCertPassword); + } } private bool OnStartCommand(string[] args) @@ -1008,25 +858,16 @@ private bool OnStartCommand(string[] args) private bool OnStartConsensusCommand(string[] args) { - if (consensus != null) return true; if (NoWallet()) return true; - string log_dictionary = Path.Combine(AppContext.BaseDirectory, "Logs"); - consensus = new ConsensusWithLog(LocalNode, Program.Wallet, log_dictionary); ShowPrompt = false; - consensus.Start(); + system.StartConsensus(Program.Wallet); return true; } protected internal override void OnStop() { - if (consensus != null) consensus.Dispose(); - if (rpc != null) rpc.Dispose(); - LocalNode.Dispose(); - using (FileStream fs = new FileStream(PeerStatePath, FileMode.Create, FileAccess.Write, FileShare.None)) - { - LocalNode.SaveState(fs); - } - Blockchain.Default.Dispose(); + system.Dispose(); + store.Dispose(); } private bool OnUpgradeCommand(string[] args) @@ -1065,48 +906,23 @@ private bool OnUpgradeWalletCommand(string[] args) return true; } string path_new = Path.ChangeExtension(path, ".json"); - NEP6Wallet.Migrate(path_new, path, password).Save(); + NEP6Wallet.Migrate(GetIndexer(), path_new, path, password).Save(); Console.WriteLine($"Wallet file upgrade complete. New wallet file has been auto-saved at: {path_new}"); return true; } - private static Wallet OpenWallet(string path, string password) + private static Wallet OpenWallet(WalletIndexer indexer, string path, string password) { if (Path.GetExtension(path) == ".db3") { - return UserWallet.Open(path, password); + return UserWallet.Open(indexer, path, password); } else { - NEP6Wallet nep6wallet = new NEP6Wallet(path); + NEP6Wallet nep6wallet = new NEP6Wallet(indexer, path); nep6wallet.Unlock(password); return nep6wallet; } } - private static bool NoWallet() - { - if (Program.Wallet != null) return false; - Console.WriteLine("You have to open the wallet first."); - return true; - } - - private void LevelDBBlockchain_ApplicationExecuted(object sender, ApplicationExecutedEventArgs e) - { - JObject json = new JObject(); - json["txid"] = e.Transaction.Hash.ToString(); - json["vmstate"] = e.ExecutionResults[0].VMState; - json["gas_consumed"] = e.ExecutionResults[0].GasConsumed.ToString(); - json["stack"] = e.ExecutionResults[0].Stack.Select(p => p.ToParameter().ToJson()).ToArray(); - json["notifications"] = e.ExecutionResults[0].Notifications.Select(p => - { - JObject notification = new JObject(); - notification["contract"] = p.ScriptHash.ToString(); - notification["state"] = p.State.ToParameter().ToJson(); - return notification; - }).ToArray(); - Directory.CreateDirectory(Settings.Default.Paths.ApplicationLogs); - string path = Path.Combine(Settings.Default.Paths.ApplicationLogs, $"{e.Transaction.Hash}.json"); - File.WriteAllText(path, json.ToString()); - } } } diff --git a/neo-cli/config.json b/neo-cli/config.json index 6edf3941f..7bb9a0b98 100644 --- a/neo-cli/config.json +++ b/neo-cli/config.json @@ -2,7 +2,7 @@ "ApplicationConfiguration": { "Paths": { "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Index": "Index_{0}" }, "P2P": { "Port": 10333, diff --git a/neo-cli/config.mainnet.json b/neo-cli/config.mainnet.json index 6edf3941f..7bb9a0b98 100644 --- a/neo-cli/config.mainnet.json +++ b/neo-cli/config.mainnet.json @@ -2,7 +2,7 @@ "ApplicationConfiguration": { "Paths": { "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Index": "Index_{0}" }, "P2P": { "Port": 10333, diff --git a/neo-cli/config.testnet.json b/neo-cli/config.testnet.json index dc835e63b..a889ff2d6 100644 --- a/neo-cli/config.testnet.json +++ b/neo-cli/config.testnet.json @@ -2,7 +2,7 @@ "ApplicationConfiguration": { "Paths": { "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Index": "Index_{0}" }, "P2P": { "Port": 20333, diff --git a/neo-cli/neo-cli.csproj b/neo-cli/neo-cli.csproj index fbcc16ebf..7a8c5838e 100644 --- a/neo-cli/neo-cli.csproj +++ b/neo-cli/neo-cli.csproj @@ -3,7 +3,7 @@ 2016-2018 The Neo Project Neo.CLI - 2.8.0 + 2.9.0 The Neo Project netcoreapp2.0 neo-cli @@ -28,7 +28,7 @@ - +