diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 5dee51124..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,172 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -## [Unreleased] - -## [2.7.6.1] - 2018-07-09 -### Fixed -- Fix a bug that crashes when the non-consensus node runs the "Start consensus" command. -- Fix a bug that do not load plugins when the node is started. - -## [2.7.6] - 2018-06-19 -### Added -- New CLI command: `import multisigaddress`. -- New CLI commands: `sign` and `relay`. -- New RPC command: `getvalidators`. -- New smart contract APIs: `Neo.Enumerator.*`. -- New smart contract API: `System.Blockchain.GetTransactionHeight`. -- New smart contract API: `System.Storage.GetReadOnlyContext` and `Neo.StorageContext.AsReadOnly`. - -### Changed -- Support for NeoContract Standary Namespace. -- Improved Plugins System: filter transactions in plugin. -- Improve the speed of creating addresses. - -## [2.7.5] - 2018-05-18 -### Added -- Importing/exporting blocks with sharding. -- Daemonizing the neo process. -- Support for Neo Plugins System. -- New smart contract API: `Neo.Contract.IsPayable`. - -### Changed -- Optimize RPC command `getbalance` for NEP-5. -- Optimize config.json -- Improve the performance of p2p network. -- Improve the performance of block synchronization. - -### Fixed -- Prevents blocking when the second instance is started. - -## [2.7.4] - 2018-03-29 -### Added -- New smart contract feature: Maps. - -### Changed -- Optimize protocol.json - -### Fixed -- Fix the issue of `Neo.Storage.Find`.(smart contract) -- Record application logs when importing blocks. - -## [2.7.3] - 2018-03-14 -### Added -- New CLI command: `broadcast`. -- GzipCompression over RPC. -- New smart contract APIs: `Neo.Iterator.*`, `Neo.Storage.Find`. -- New smart contract APIs: `Neo.Runtime.Serialize`, `Neo.Runtime.Deserialize`. -- New smart contract API: `Neo.TransactionInvocation.GetScript`. - -### Changed -- Improve the performance of importing blocks. -- Improve the performance of p2p network. -- Optimize CLI commands: `show node`, `show pool`. - -### Fixed -- Fix crash on exiting. - -## [2.7.1] - 2018-01-31 -### Added -- Allow user to create db3 wallet. - -## [2.7.0] - 2018-01-26 -### Added -- New RPC command: `listaddress`. -- New RPC command: `getapplicationlog`. -- New opcode `REMOVE`.(smart contract) - -### Removed -- Remove option `--record-notifications`. - -## [2.6.0] - 2018-01-15 -### Added -- New RPC command: `sendfrom`. - -### Changed -- Improve the performance of rebuilding wallet index. -- Prevent the creation of wallet files with blank password. -- Add `time` to the outputs of `Blockchain_Notify`. - -### Fixed -- Save wallet file when creating address by calling RPC command `getnewaddress`. -- Fix the issue of RPC commands `invoke*`. - -### Removed -- Remove `Neo.Account.SetVotes` and `Neo.Validator.Register`.(smart contract) - -## [2.5.2] - 2017-12-14 -### Added -- New smart contract API: `Neo.Runtime.GetTime`. -- New opcodes `APPEND`, `REVERSE`.(smart contract) - -### Changed -- Add fields `tx` and `script` to RPC commands `invoke*`. -- Improve the performance of p2p network. -- Optimize protocol.json - -### Fixed -- Fix the network issue when restart the client. - -## [2.5.0] - 2017-12-12 -### Added -- Support for NEP-6 wallets. -- Add startup parameter: `--nopeers`. - -## [2.4.1] - 2017-11-24 -### Added -- New smart contract feature: Dynamic Invocation.(NEP-4) -- New smart contract APIs: `Neo.Transaction.GetUnspentCoins`, `Neo.Header.GetIndex`. - -### Changed -- Optimize CLI command: `show state`. -- Optimize config.json -- Improve the performance of p2p network. - -## [2.3.5] - 2017-10-27 -### Changed -- Optimize RPC commands `sendtoaddress` and `sendmany` for NEP-5 transfer. -- Optimize CLI command `send` for NEP-5 transfer. - -## [2.3.4] - 2017-10-12 -### Added -- Add startup parameter: `--record-notifications`. -- New RPC commands: `invoke`, `invokefunction`, `invokescript`. -- New RPC command: `getversion`. -- Console colors. - -### Fixed -- Improve stability. - -## [2.3.2] - 2017-09-06 -### Added -- New CLI command: `send all`. -- New opcodes `THROW`, `THROWIFNOT`.(smart contract) - -### Changed -- Optimize opcode `CHECKMULTISIG`. - -### Fixed -- Fix the issue of `Neo.Runtime.CheckWitness`.(smart contract) - -## [2.1.0] - 2017-08-15 -### Added -- New RPC command: `sendmany`. -- New CLI command: `show utxo`. -- New smart contract feature: Triggers. - -## [2.0.2] - 2017-08-14 -### Changed -- Improve the performance of p2p network. - -## [2.0.1] - 2017-07-20 -### Added -- New RPC commands: `getpeers`, `getblocksysfee`. -- New RPC commands: `getaccountstate`, `getassetstate`, `getcontractstate`, `getstorage`. -- Add default config files for MAINNET and TESTNET. - -### Changed -- Improve the performance of p2p network. - -## [2.0.0] - 2017-07-13 -### Changed -- Rebrand from AntShares to NEO. 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/Consensus/ConsensusWithPolicy.cs b/neo-cli/Consensus/ConsensusWithPolicy.cs new file mode 100644 index 000000000..b5ced7f2f --- /dev/null +++ b/neo-cli/Consensus/ConsensusWithPolicy.cs @@ -0,0 +1,54 @@ +using Neo.Core; +using Neo.Network; +using Neo.Wallets; +using System; +using System.IO; +using System.Linq; + +namespace Neo.Consensus +{ + internal class ConsensusWithPolicy : ConsensusService + { + private string log_dictionary; + + public ConsensusWithPolicy(LocalNode localNode, Wallet wallet, string log_dictionary) + : base(localNode, wallet) + { + this.log_dictionary = log_dictionary; + } + + protected override bool CheckPolicy(Transaction tx) + { + switch (Policy.Default.PolicyLevel) + { + case PolicyLevel.AllowAll: + return true; + case PolicyLevel.AllowList: + return tx.Scripts.All(p => Policy.Default.List.Contains(p.VerificationScript.ToScriptHash())) || tx.Outputs.All(p => Policy.Default.List.Contains(p.ScriptHash)); + case PolicyLevel.DenyList: + return tx.Scripts.All(p => !Policy.Default.List.Contains(p.VerificationScript.ToScriptHash())) && tx.Outputs.All(p => !Policy.Default.List.Contains(p.ScriptHash)); + default: + return base.CheckPolicy(tx); + } + } + + 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 }); + } + } + + public void RefreshPolicy() + { + Policy.Default.Refresh(); + } + } +} diff --git a/neo-cli/Consensus/Policy.cs b/neo-cli/Consensus/Policy.cs new file mode 100644 index 000000000..c7cc384f8 --- /dev/null +++ b/neo-cli/Consensus/Policy.cs @@ -0,0 +1,38 @@ +using Neo.Wallets; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Neo.Consensus +{ + internal class Policy + { + public PolicyLevel PolicyLevel { get; private set; } + public HashSet List { get; private set; } + + public static Policy Default { get; private set; } + + static Policy() + { + Default = new Policy(); + Default.Refresh(); + } + + public void Refresh() + { + if (File.Exists("policy.json")) + { + IConfigurationSection section = new ConfigurationBuilder().AddJsonFile("policy.json").Build().GetSection("PolicyConfiguration"); + PolicyLevel = (PolicyLevel)Enum.Parse(typeof(PolicyLevel), section.GetSection("PolicyLevel").Value, true); + List = new HashSet(section.GetSection("List").GetChildren().Select(p => Wallet.ToScriptHash(p.Value))); + } + else + { + PolicyLevel = PolicyLevel.AllowAll; + List = new HashSet(); + } + } + } +} diff --git a/neo-cli/Consensus/PolicyLevel.cs b/neo-cli/Consensus/PolicyLevel.cs new file mode 100644 index 000000000..55ea03489 --- /dev/null +++ b/neo-cli/Consensus/PolicyLevel.cs @@ -0,0 +1,10 @@ +namespace Neo.Consensus +{ + internal enum PolicyLevel : byte + { + AllowAll, + DenyAll, + AllowList, + DenyList + } +} diff --git a/neo-cli/Network/RPC/RpcServerWithWallet.cs b/neo-cli/Network/RPC/RpcServerWithWallet.cs index bf19b559f..e6a2de9b6 100644 --- a/neo-cli/Network/RPC/RpcServerWithWallet.cs +++ b/neo-cli/Network/RPC/RpcServerWithWallet.cs @@ -34,18 +34,11 @@ protected override JObject Process(string method, JArray _params) throw new RpcException(-400, "Access denied."); else { + UInt256 assetId = UInt256.Parse(_params[0].AsString()); + IEnumerable coins = Program.Wallet.GetCoins().Where(p => !p.State.HasFlag(CoinState.Spent) && p.Output.AssetId.Equals(assetId)); 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; - } + 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(); return json; } case "listaddress": diff --git a/neo-cli/Program.cs b/neo-cli/Program.cs index 2d7d67e46..01c8a38a4 100644 --- a/neo-cli/Program.cs +++ b/neo-cli/Program.cs @@ -7,7 +7,7 @@ namespace Neo { static class Program { - internal static Wallet Wallet; + internal static Wallet Wallet; private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { @@ -21,11 +21,7 @@ private static void CurrentDomain_UnhandledException(object sender, UnhandledExc static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - var bufferSize = 1024 * 67 + 128; - Stream inputStream = Console.OpenStandardInput(bufferSize); - Console.SetIn(new StreamReader(inputStream, Console.InputEncoding, false, bufferSize)); - var mainService = new MainService(); - mainService.Run(args); + new MainService().Run(args); } private static void PrintErrorLogs(StreamWriter writer, Exception ex) diff --git a/neo-cli/Services/ConsoleServiceBase.cs b/neo-cli/Services/ConsoleServiceBase.cs index f229a094a..fb2a9e51f 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 { @@ -14,7 +13,7 @@ public abstract class ConsoleServiceBase protected bool ShowPrompt { get; set; } = true; - protected virtual bool OnCommand(string[] args) + protected virtual bool OnCommand(string[] args) { switch (args[0].ToLower()) { diff --git a/neo-cli/Settings.cs b/neo-cli/Settings.cs index 22cb8e307..d7daf39e3 100644 --- a/neo-cli/Settings.cs +++ b/neo-cli/Settings.cs @@ -1,5 +1,7 @@ using Microsoft.Extensions.Configuration; using Neo.Network; +using System; +using System.IO; namespace Neo { @@ -8,7 +10,6 @@ internal class Settings public PathsSettings Paths { get; } public P2PSettings P2P { get; } public RPCSettings RPC { get; } - public UnlockWalletSettings UnlockWallet { get; set; } public static Settings Default { get; } @@ -23,7 +24,6 @@ public Settings(IConfigurationSection section) this.Paths = new PathsSettings(section.GetSection("Paths")); this.P2P = new P2PSettings(section.GetSection("P2P")); this.RPC = new RPCSettings(section.GetSection("RPC")); - this.UnlockWallet = new UnlockWalletSettings(section.GetSection("UnlockWallet")); } } @@ -34,8 +34,8 @@ internal class PathsSettings 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.Chain = section.GetSection("Chain").Value; + this.ApplicationLogs = Path.Combine(AppContext.BaseDirectory, $"ApplicationLogs_{Message.Magic:X8}"); } } @@ -64,23 +64,4 @@ public RPCSettings(IConfigurationSection section) this.SslCertPassword = section.GetSection("SslCertPassword").Value; } } - - public class UnlockWalletSettings - { - public string Path { get; } - public string Password { get; } - public bool StartConsensus { get; } - public bool IsActive { get; } - - public UnlockWalletSettings(IConfigurationSection section) - { - if (section.Exists()) - { - 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); - } - } - } } diff --git a/neo-cli/Shell/MainService.cs b/neo-cli/Shell/MainService.cs index d944f4d6d..fd96d487c 100644 --- a/neo-cli/Shell/MainService.cs +++ b/neo-cli/Shell/MainService.cs @@ -6,7 +6,6 @@ using Neo.IO; using Neo.IO.Json; using Neo.Network; -using Neo.Network.Payloads; using Neo.Network.RPC; using Neo.Services; using Neo.SmartContract; @@ -17,12 +16,8 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Net; using System.Security.Cryptography; -using System.Text.RegularExpressions; using System.Threading.Tasks; -using ECCurve = Neo.Cryptography.ECC.ECCurve; -using ECPoint = Neo.Cryptography.ECC.ECPoint; namespace Neo.Shell { @@ -31,43 +26,36 @@ internal class MainService : ConsoleServiceBase private const string PeerStatePath = "peers.dat"; private RpcServerWithWallet rpc; - private ConsensusWithLog consensus; + private ConsensusWithPolicy consensus; 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 void ImportBlocks(Stream stream) { LevelDBBlockchain blockchain = (LevelDBBlockchain)Blockchain.Default; + blockchain.VerifyBlocks = false; 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++) + for (int height = 0; height < count; height++) { byte[] array = r.ReadBytes(r.ReadInt32()); - if (height > blockchain.Height) + if (height > Blockchain.Default.Height) { Block block = array.AsSerializable(); - blockchain.AddBlockDirectly(block); + Blockchain.Default.AddBlock(block); } } } + blockchain.VerifyBlocks = true; } protected override bool OnCommand(string[] args) { switch (args[0].ToLower()) { - case "broadcast": - return OnBroadcastCommand(args); - case "relay": - return OnRelayCommand(args); - case "sign": - return OnSignCommand(args); case "create": return OnCreateCommand(args); case "export": @@ -84,6 +72,8 @@ protected override bool OnCommand(string[] args) return OnOpenCommand(args); case "rebuild": return OnRebuildCommand(args); + case "refresh": + return OnRefreshCommand(args); case "send": return OnSendCommand(args); case "show": @@ -97,116 +87,6 @@ protected override bool OnCommand(string[] args) } } - private bool OnBroadcastCommand(string[] args) - { - string command = args[1].ToLower(); - ISerializable payload = null; - switch (command) - { - case "addr": - payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp())); - break; - case "block": - if (args[2].Length == 64 || args[2].Length == 66) - payload = Blockchain.Default.GetBlock(UInt256.Parse(args[2])); - else - payload = Blockchain.Default.GetBlock(uint.Parse(args[2])); - break; - case "getblocks": - case "getheaders": - payload = GetBlocksPayload.Create(UInt256.Parse(args[2])); - break; - case "getdata": - case "inv": - 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])); - break; - case "alert": - case "consensus": - case "filteradd": - case "filterload": - case "headers": - case "merkleblock": - case "ping": - case "pong": - case "reject": - case "verack": - case "version": - Console.WriteLine($"Command \"{command}\" is not supported."); - return true; - } - foreach (RemoteNode node in LocalNode.GetRemoteNodes()) - node.EnqueueMessage(command, payload); - return true; - } - - private bool OnRelayCommand(string [] args) - { - if (args.Length < 2) - { - Console.WriteLine("You must input JSON object to relay."); - return true; - } - var jsonObjectToRelay = string.Join(string.Empty, args.Skip(1)); - if (string.IsNullOrWhiteSpace(jsonObjectToRelay)) - { - Console.WriteLine("You must input JSON object to relay."); - return true; - } - try - { - ContractParametersContext context = ContractParametersContext.Parse(jsonObjectToRelay); - if (!context.Completed) - { - Console.WriteLine("The signature is incomplete."); - return true; - } - context.Verifiable.Scripts = context.GetScripts(); - IInventory inventory = (IInventory)context.Verifiable; - LocalNode.Relay(inventory); - Console.WriteLine($"Data relay success, the hash is shown as follows:\r\n{inventory.Hash}"); - } - catch (Exception e) - { - Console.WriteLine($"One or more errors occurred:\r\n{e.Message}"); - } - return true; - } - - private bool OnSignCommand(string[] args) - { - if (NoWallet()) return true; - - if (args.Length < 2) - { - Console.WriteLine("You must input JSON object pending signature data."); - return true; - } - var jsonObjectToSign = string.Join(string.Empty, args.Skip(1)); - if (string.IsNullOrWhiteSpace(jsonObjectToSign)) - { - Console.WriteLine("You must input JSON object pending signature data."); - return true; - } - try - { - ContractParametersContext context = ContractParametersContext.Parse(jsonObjectToSign); - if (!Program.Wallet.Sign(context)) - { - Console.WriteLine("The private key that can sign the data is not found."); - return true; - } - Console.WriteLine($"Signed Output:\r\n{context}"); - } - catch (Exception e) - { - Console.WriteLine($"One or more errors occurred:\r\n{e.Message}"); - } - return true; - } - private bool OnCreateCommand(string[] args) { switch (args[1].ToLower()) @@ -222,35 +102,27 @@ private bool OnCreateCommand(string[] args) private bool OnCreateAddressCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine("You have to open the wallet first."); + return true; + } if (args.Length > 3) { Console.WriteLine("error"); return true; } - - ushort count; + ushort count = 1; if (args.Length >= 3) count = ushort.Parse(args[2]); - else - count = 1; - - int x = 0; List addresses = new List(); - - Parallel.For(0, count, (i) => + for (int i = 1; i <= count; i++) { WalletAccount account = Program.Wallet.CreateAccount(); - - lock (addresses) - { - x++; - addresses.Add(account.Address); - Console.SetCursorPosition(0, Console.CursorTop); - Console.Write($"[{x}/{count}]"); - } - }); - + addresses.Add(account.Address); + Console.SetCursorPosition(0, Console.CursorTop); + Console.Write($"[{i}/{count}]"); + } if (Program.Wallet is NEP6Wallet wallet) wallet.Save(); Console.WriteLine(); @@ -312,7 +184,6 @@ private bool OnExportCommand(string[] args) { switch (args[1].ToLower()) { - case "block": case "blocks": return OnExportBlocksCommand(args); case "key": @@ -324,74 +195,34 @@ private bool OnExportCommand(string[] args) private bool OnExportBlocksCommand(string[] args) { - if (args.Length > 4) + if (args.Length > 3) { Console.WriteLine("error"); return true; } - if (args.Length >= 3 && uint.TryParse(args[2], out uint start)) + string path = args.Length >= 3 ? args[2] : "chain.acc"; + using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { - 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)) + uint count = Blockchain.Default.Height + 1; + uint start = 0; + if (fs.Length > 0) { - 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}]"); - } + byte[] buffer = new byte[sizeof(uint)]; + fs.Read(buffer, 0, buffer.Length); + start = BitConverter.ToUInt32(buffer, 0); + fs.Seek(0, SeekOrigin.Begin); } - } - 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 (start < count) + fs.Write(BitConverter.GetBytes(count), 0, sizeof(uint)); + fs.Seek(0, SeekOrigin.End); + for (uint i = start; i < count; i++) { - 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}]"); - } + 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 + 1}/{count}]"); } } Console.WriteLine(); @@ -400,7 +231,11 @@ private bool OnExportBlocksCommand(string[] args) private bool OnExportKeyCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine("You have to open the wallet first."); + return true; + } if (args.Length < 2 || args.Length > 4) { Console.WriteLine("error"); @@ -470,18 +305,15 @@ private bool OnHelpCommand(string[] args) "\tcreate address [n=1]\n" + "\timport key \n" + "\texport key [address] [path]\n" + - "\timport multisigaddress m pubkeys...\n" + "\tsend
|all [fee=0]\n" + - "\tsign \n" + "Node Commands:\n" + "\tshow state\n" + "\tshow node\n" + - "\tshow pool [verbose]\n" + - "\texport block[s] [path=chain.acc]\n" + - "\texport block[s] [count]\n" + - "\trelay \n" + + "\tshow pool\n" + + "\texport blocks [path=chain.acc]\n" + "Advanced Commands:\n" + - "\tstart consensus\n"); + "\tstart consensus\n" + + "\trefresh policy\n"); return true; } @@ -491,46 +323,11 @@ private bool OnImportCommand(string[] args) { case "key": return OnImportKeyCommand(args); - case "multisigaddress": - return OnImportMultisigAddress(args); default: return base.OnCommand(args); } } - private bool OnImportMultisigAddress(string[] args) - { - if (NoWallet()) return true; - - if (args.Length < 5) - { - Console.WriteLine("Error. Use at least 2 public keys to create a multisig address."); - return true; - } - - int m = int.Parse(args[2]); - int n = args.Length - 3; - - if (m < 1 || m > n || n > 1024) - { - Console.WriteLine("Error. Invalid parameters."); - return true; - } - - ECPoint[] publicKeys = args.Skip(3).Select(p => ECPoint.Parse(p, ECCurve.Secp256r1)).ToArray(); - - Contract multiSignContract = Contract.CreateMultiSigContract(m, publicKeys); - KeyPair keyPair = Program.Wallet.GetAccounts().FirstOrDefault(p => p.HasKey && publicKeys.Contains(p.GetKey().PublicKey))?.GetKey(); - - WalletAccount account = Program.Wallet.CreateAccount(multiSignContract, keyPair); - if (Program.Wallet is NEP6Wallet wallet) - wallet.Save(); - - Console.WriteLine("Multisig. Addr.: " + multiSignContract.Address); - - return true; - } - private bool OnImportKeyCommand(string[] args) { if (args.Length > 3) @@ -589,7 +386,11 @@ private bool OnListCommand(string[] args) private bool OnClaimCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine($"Please open a wallet"); + return true; + } Coins coins = new Coins(Program.Wallet, LocalNode); @@ -597,9 +398,9 @@ private bool OnClaimCommand(string[] args) { case "gas": ClaimTransaction tx = coins.Claim(); - if (tx != null) + if (tx is ClaimTransaction) { - Console.WriteLine($"Tranaction Suceeded: {tx.Hash}"); + Console.WriteLine($"Tranaction Suceeded: {tx.Hash.ToString()}"); } return true; default: @@ -609,7 +410,11 @@ private bool OnClaimCommand(string[] args) private bool OnShowGasCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine($"Please open a wallet"); + return true; + } Coins coins = new Coins(Program.Wallet, LocalNode); Console.WriteLine($"unavailable: {coins.UnavailableBonus().ToString()}"); @@ -619,7 +424,7 @@ private bool OnShowGasCommand(string[] args) private bool OnListKeyCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) return true; foreach (KeyPair key in Program.Wallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey())) { Console.WriteLine(key.PublicKey); @@ -629,7 +434,7 @@ private bool OnListKeyCommand(string[] args) private bool OnListAddressCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) return true; foreach (Contract contract in Program.Wallet.GetAccounts().Where(p => !p.WatchOnly).Select(p => p.Contract)) { Console.WriteLine($"{contract.Address}\t{(contract.IsStandard ? "Standard" : "Nonstandard")}"); @@ -639,7 +444,7 @@ private bool OnListAddressCommand(string[] args) private bool OnListAssetCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) 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), @@ -689,13 +494,31 @@ private bool OnOpenWalletCommand(string[] args) Console.WriteLine("cancelled"); return true; } - try + if (Path.GetExtension(path) == ".db3") { - Program.Wallet = OpenWallet(path, password); + try + { + Program.Wallet = UserWallet.Open(path, password); + } + catch (CryptographicException) + { + Console.WriteLine($"failed to open file \"{path}\""); + return true; + } } - catch (CryptographicException) + else { - Console.WriteLine($"failed to open file \"{path}\""); + NEP6Wallet nep6wallet = new NEP6Wallet(path); + try + { + nep6wallet.Unlock(password); + } + catch (CryptographicException) + { + Console.WriteLine($"failed to open file \"{path}\""); + return true; + } + Program.Wallet = nep6wallet; } return true; } @@ -717,6 +540,24 @@ private bool OnRebuildIndexCommand(string[] args) return true; } + private bool OnRefreshCommand(string[] args) + { + switch (args[1].ToLower()) + { + case "policy": + return OnRefreshPolicyCommand(args); + default: + return base.OnCommand(args); + } + } + + private bool OnRefreshPolicyCommand(string[] args) + { + if (consensus == null) return true; + consensus.RefreshPolicy(); + return true; + } + private bool OnSendCommand(string[] args) { if (args.Length < 4 || args.Length > 5) @@ -724,7 +565,11 @@ private bool OnSendCommand(string[] args) Console.WriteLine("error"); return true; } - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine("You have to open the wallet first."); + return true; + } string password = ReadPassword("password"); if (password.Length == 0) { @@ -837,19 +682,17 @@ 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}]"); + Console.WriteLine($"{nodes[i].RemoteEndpoint.Address} port:{nodes[i].RemoteEndpoint.Port} listen:{nodes[i].ListenerEndpoint?.Port ?? 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(); - if (verbose) - foreach (Transaction tx in transactions) - Console.WriteLine($"{tx.Hash} {tx.GetType().Name}"); - Console.WriteLine($"total: {transactions.Length}"); + foreach (Transaction tx in LocalNode.GetMemoryPool()) + { + Console.WriteLine($"{tx.Hash} {tx.GetType().Name}"); + } return true; } @@ -866,7 +709,11 @@ private bool OnShowStateCommand(string[] args) private bool OnShowUtxoCommand(string[] args) { - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine("You have to open the wallet first."); + return true; + } IEnumerable coins = Program.Wallet.FindUnspentCoins(); if (args.Length >= 3) { @@ -899,99 +746,58 @@ private bool OnShowUtxoCommand(string[] args) protected internal override void OnStart(string[] args) { - bool useRPC = false, nopeers = false, useLog = false; - for (int i = 0; i < args.Length; i++) - switch (args[i]) - { - case "/rpc": - case "--rpc": - 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)) + Blockchain.RegisterBlockchain(new LevelDBBlockchain(Settings.Default.Paths.Chain)); + if (!args.Contains("--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(() => { - const string path_acc = "chain.acc"; - if (File.Exists(path_acc)) + const string acc_path = "chain.acc"; + const string acc_zip_path = acc_path + ".zip"; + if (File.Exists(acc_path)) { - using (FileStream fs = new FileStream(path_acc, FileMode.Open, FileAccess.Read, FileShare.None)) + using (FileStream fs = new FileStream(acc_path, FileMode.Open, FileAccess.Read, FileShare.None)) { ImportBlocks(fs); } + File.Delete(acc_path); } - const string path_acc_zip = path_acc + ".zip"; - if (File.Exists(path_acc_zip)) + else if (File.Exists(acc_zip_path)) { - using (FileStream fs = new FileStream(path_acc_zip, FileMode.Open, FileAccess.Read, FileShare.None)) + using (FileStream fs = new FileStream(acc_zip_path, FileMode.Open, FileAccess.Read, FileShare.None)) using (ZipArchive zip = new ZipArchive(fs, ZipArchiveMode.Read)) - using (Stream zs = zip.GetEntry(path_acc).Open()) + using (Stream zs = zip.GetEntry(acc_path).Open()) { ImportBlocks(zs); } - } - 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 (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); - } - } + File.Delete(acc_zip_path); } LocalNode.Start(Settings.Default.P2P.Port, Settings.Default.P2P.WsPort); - if (Settings.Default.UnlockWallet.IsActive) + bool log = false; + for (int i = 0; i < args.Length; i++) { - try - { - Program.Wallet = OpenWallet(Settings.Default.UnlockWallet.Path, Settings.Default.UnlockWallet.Password); - } - catch (CryptographicException) + switch (args[i]) { - Console.WriteLine($"failed to open file \"{Settings.Default.UnlockWallet.Path}\""); + case "/rpc": + case "--rpc": + case "-r": + if (rpc == null) + { + rpc = new RpcServerWithWallet(LocalNode); + rpc.Start(Settings.Default.RPC.Port, Settings.Default.RPC.SslCert, Settings.Default.RPC.SslCertPassword); + } + break; + case "-l": + case "--log": + log = true; + break; } - 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 (log) + LevelDBBlockchain.ApplicationExecuted += LevelDBBlockchain_ApplicationExecuted; }); } @@ -1009,9 +815,13 @@ private bool OnStartCommand(string[] args) private bool OnStartConsensusCommand(string[] args) { if (consensus != null) return true; - if (NoWallet()) return true; + if (Program.Wallet == null) + { + Console.WriteLine("You have to open the wallet first."); + return true; + } string log_dictionary = Path.Combine(AppContext.BaseDirectory, "Logs"); - consensus = new ConsensusWithLog(LocalNode, Program.Wallet, log_dictionary); + consensus = new ConsensusWithPolicy(LocalNode, Program.Wallet, log_dictionary); ShowPrompt = false; consensus.Start(); return true; @@ -1070,34 +880,14 @@ private bool OnUpgradeWalletCommand(string[] args) return true; } - private static Wallet OpenWallet(string path, string password) - { - if (Path.GetExtension(path) == ".db3") - { - return UserWallet.Open(path, password); - } - else - { - NEP6Wallet nep6wallet = new NEP6Wallet(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 => + json["vmstate"] = e.VMState; + json["gas_consumed"] = e.GasConsumed.ToString(); + json["stack"] = e.Stack.Select(p => p.ToParameter().ToJson()).ToArray(); + json["notifications"] = e.Notifications.Select(p => { JObject notification = new JObject(); notification["contract"] = p.ScriptHash.ToString(); diff --git a/neo-cli/config.json b/neo-cli/config.json index 6edf3941f..aef142130 100644 --- a/neo-cli/config.json +++ b/neo-cli/config.json @@ -1,8 +1,7 @@ { "ApplicationConfiguration": { "Paths": { - "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Chain": "Chain" }, "P2P": { "Port": 10333, @@ -12,12 +11,6 @@ "Port": 10332, "SslCert": "", "SslCertPassword": "" - }, - "UnlockWallet": { - "Path": "", - "Password": "", - "StartConsensus": false, - "IsActive": false } } } diff --git a/neo-cli/config.mainnet.json b/neo-cli/config.mainnet.json index 6edf3941f..aef142130 100644 --- a/neo-cli/config.mainnet.json +++ b/neo-cli/config.mainnet.json @@ -1,8 +1,7 @@ { "ApplicationConfiguration": { "Paths": { - "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Chain": "Chain" }, "P2P": { "Port": 10333, @@ -12,12 +11,6 @@ "Port": 10332, "SslCert": "", "SslCertPassword": "" - }, - "UnlockWallet": { - "Path": "", - "Password": "", - "StartConsensus": false, - "IsActive": false } } } diff --git a/neo-cli/config.testnet.json b/neo-cli/config.testnet.json index dc835e63b..293945920 100644 --- a/neo-cli/config.testnet.json +++ b/neo-cli/config.testnet.json @@ -1,8 +1,7 @@ { "ApplicationConfiguration": { "Paths": { - "Chain": "Chain_{0}", - "ApplicationLogs": "ApplicationLogs_{0}" + "Chain": "ChainTestNet" }, "P2P": { "Port": 20333, @@ -12,12 +11,6 @@ "Port": 20332, "SslCert": "", "SslCertPassword": "" - }, - "UnlockWallet": { - "Path": "", - "Password": "", - "StartConsensus": false, - "IsActive": false } } } diff --git a/neo-cli/neo-cli.csproj b/neo-cli/neo-cli.csproj index eee86931c..2b8fdf817 100644 --- a/neo-cli/neo-cli.csproj +++ b/neo-cli/neo-cli.csproj @@ -1,9 +1,9 @@  - 2016-2018 The Neo Project + 2016-2017 The Neo Project Neo.CLI - 2.7.6.1 + 2.7.1 The Neo Project netcoreapp2.0 neo-cli @@ -28,7 +28,7 @@ - + diff --git a/neo-cli/protocol.json b/neo-cli/protocol.json index d32abd432..633757a07 100644 --- a/neo-cli/protocol.json +++ b/neo-cli/protocol.json @@ -2,7 +2,6 @@ "ProtocolConfiguration": { "Magic": 7630401, "AddressVersion": 23, - "SecondsPerBlock": 15, "StandbyValidators": [ "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", diff --git a/neo-cli/protocol.mainnet.json b/neo-cli/protocol.mainnet.json index fedbbbe39..633757a07 100644 --- a/neo-cli/protocol.mainnet.json +++ b/neo-cli/protocol.mainnet.json @@ -2,7 +2,6 @@ "ProtocolConfiguration": { "Magic": 7630401, "AddressVersion": 23, - "SecondsPerBlock": 15, "StandbyValidators": [ "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", diff --git a/neo-cli/protocol.testnet.json b/neo-cli/protocol.testnet.json index 998d04c5c..f6b2d2fd4 100644 --- a/neo-cli/protocol.testnet.json +++ b/neo-cli/protocol.testnet.json @@ -2,7 +2,6 @@ "ProtocolConfiguration": { "Magic": 1953787457, "AddressVersion": 23, - "SecondsPerBlock": 15, "StandbyValidators": [ "0327da12b5c40200e9f65569476bbff2218da4f32548ff43b6387ec1416a231ee8", "026ce35b29147ad09e4afe4ec4a7319095f08198fa8babbe3c56e970b143528d22",