From 48c4df6f47d8396df55371903e487c84bdfb323d Mon Sep 17 00:00:00 2001 From: Jessica <413074538@qq.com> Date: Fri, 10 Apr 2020 12:03:14 +0800 Subject: [PATCH 1/9] Fix Parse manifestFilePath --- neo-cli/CLI/MainService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs index 5beef1924..272107919 100644 --- a/neo-cli/CLI/MainService.cs +++ b/neo-cli/CLI/MainService.cs @@ -245,7 +245,7 @@ private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, throw new ArgumentException(nameof(manifestFilePath)); } - var manifest = ContractManifest.Parse(File.ReadAllText(manifestFilePath)); + var manifest = ContractManifest.Parse(new ReadOnlySpan(File.ReadAllBytes(manifestFilePath))); // Read nef From 8ec2af126140c4b4a2f33f43d295a57b81a4b14b Mon Sep 17 00:00:00 2001 From: cloud8little <413074538@qq.com> Date: Mon, 20 Jul 2020 15:55:36 +0800 Subject: [PATCH 2/9] merge master --- .github/workflows/dotnetcore.yml | 2 +- .github/workflows/test-neo-cli.expect | 2 +- Dockerfile | 1 + Neo.ConsoleService/ConsoleColorSet.cs | 41 ++ neo-cli/CLI/Logger.cs | 97 ++++ neo-cli/CLI/MainService.Blockchain.cs | 2 +- neo-cli/CLI/MainService.Contracts.cs | 66 +-- neo-cli/CLI/MainService.NEP5.cs | 97 ++++ neo-cli/CLI/MainService.Native.cs | 19 + neo-cli/CLI/MainService.Network.cs | 2 +- neo-cli/CLI/MainService.Plugins.cs | 11 +- neo-cli/CLI/MainService.Tools.cs | 465 ++++++++++++++++++ neo-cli/CLI/MainService.Vote.cs | 175 +++++++ neo-cli/CLI/MainService.Wallet.cs | 90 +++- neo-cli/CLI/MainService.cs | 201 ++++++-- neo-cli/Program.cs | 38 -- neo-cli/Settings.cs | 32 +- neo-cli/config.json | 5 + neo-cli/config.mainnet.json | 5 + neo-cli/config.testnet.json | 5 + neo-cli/neo-cli.csproj | 4 +- neo-cli/protocol.json | 19 +- neo-cli/protocol.mainnet.json | 19 +- neo-cli/protocol.testnet.json | 3 +- neo-gui/GUI/DeployContractDialog.cs | 2 +- .../DeveloperToolsForm.ContractParameters.cs | 4 +- neo-gui/GUI/Helper.cs | 2 +- neo-gui/GUI/InvokeContractDialog.cs | 1 - neo-gui/GUI/MainForm.cs | 15 +- neo-gui/GUI/SigningTxDialog.cs | 2 +- .../Wrappers/TransactionAttributeWrapper.cs | 12 +- neo-gui/GUI/Wrappers/TransactionWrapper.cs | 3 - neo-gui/neo-gui.csproj | 4 +- 33 files changed, 1246 insertions(+), 200 deletions(-) create mode 100644 Neo.ConsoleService/ConsoleColorSet.cs create mode 100644 neo-cli/CLI/Logger.cs create mode 100644 neo-cli/CLI/MainService.NEP5.cs create mode 100644 neo-cli/CLI/MainService.Native.cs create mode 100644 neo-cli/CLI/MainService.Tools.cs create mode 100644 neo-cli/CLI/MainService.Vote.cs diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 678281ca5..57913bafa 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: diff --git a/.github/workflows/test-neo-cli.expect b/.github/workflows/test-neo-cli.expect index ff1f1ba88..d726413b3 100755 --- a/.github/workflows/test-neo-cli.expect +++ b/.github/workflows/test-neo-cli.expect @@ -36,7 +36,7 @@ expect { } expect { - "address:" { } + " Address:" { } "error" { exit 2 } timeout { exit 1 } } diff --git a/Dockerfile b/Dockerfile index 5b5d28097..670cffebd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS Build COPY neo-cli /neo-cli +COPY Neo.ConsoleService /Neo.ConsoleService COPY NuGet.Config /neo-cli WORKDIR /neo-cli diff --git a/Neo.ConsoleService/ConsoleColorSet.cs b/Neo.ConsoleService/ConsoleColorSet.cs new file mode 100644 index 000000000..c5cc9e4fb --- /dev/null +++ b/Neo.ConsoleService/ConsoleColorSet.cs @@ -0,0 +1,41 @@ +using System; + +namespace Neo.ConsoleService +{ + public class ConsoleColorSet + { + public ConsoleColor Foreground; + public ConsoleColor Background; + + /// + /// Create a new color set with the current console colors + /// + public ConsoleColorSet() : this(Console.ForegroundColor, Console.BackgroundColor) { } + + /// + /// Create a new color set + /// + /// Foreground color + public ConsoleColorSet(ConsoleColor foreground) : this(foreground, Console.BackgroundColor) { } + + /// + /// Create a new color set + /// + /// Foreground color + /// Background color + public ConsoleColorSet(ConsoleColor foreground, ConsoleColor background) + { + Foreground = foreground; + Background = background; + } + + /// + /// Apply the current set + /// + public void Apply() + { + Console.ForegroundColor = Foreground; + Console.BackgroundColor = Background; + } + } +} diff --git a/neo-cli/CLI/Logger.cs b/neo-cli/CLI/Logger.cs new file mode 100644 index 000000000..795916a41 --- /dev/null +++ b/neo-cli/CLI/Logger.cs @@ -0,0 +1,97 @@ +using Neo.ConsoleService; +using Neo.Plugins; +using System; +using System.IO; +using System.Text; +using static System.IO.Path; + +namespace Neo.CLI +{ + internal class Logger : Plugin, ILogPlugin + { + private static readonly ConsoleColorSet DebugColor = new ConsoleColorSet(ConsoleColor.Cyan); + private static readonly ConsoleColorSet InfoColor = new ConsoleColorSet(ConsoleColor.White); + private static readonly ConsoleColorSet WarningColor = new ConsoleColorSet(ConsoleColor.Yellow); + private static readonly ConsoleColorSet ErrorColor = new ConsoleColorSet(ConsoleColor.Red); + private static readonly ConsoleColorSet FatalColor = new ConsoleColorSet(ConsoleColor.Red); + + public override string Name => "SystemLog"; + public override string Description => "Prints consensus log and is a built-in plugin which cannot be uninstalled"; + public override string ConfigFile => Combine(GetDirectoryName(Path), "config.json"); + public override string Path => GetType().Assembly.Location; + + private static void GetErrorLogs(StringBuilder sb, Exception ex) + { + sb.AppendLine(ex.GetType().ToString()); + sb.AppendLine(ex.Message); + sb.AppendLine(ex.StackTrace); + if (ex is AggregateException ex2) + { + foreach (Exception inner in ex2.InnerExceptions) + { + sb.AppendLine(); + GetErrorLogs(sb, inner); + } + } + else if (ex.InnerException != null) + { + sb.AppendLine(); + GetErrorLogs(sb, ex.InnerException); + } + } + + void ILogPlugin.Log(string source, LogLevel level, object message) + { + if (!Settings.Default.Logger.Active) + return; + + if (message is Exception ex) + { + var sb = new StringBuilder(); + GetErrorLogs(sb, ex); + message = sb.ToString(); + } + + lock (typeof(Logger)) + { + DateTime now = DateTime.Now; + var log = $"[{now.TimeOfDay:hh\\:mm\\:ss\\.fff}] {message}"; + + if (Settings.Default.Logger.ConsoleOutput) + { + var currentColor = new ConsoleColorSet(); + + switch (level) + { + case LogLevel.Debug: DebugColor.Apply(); break; + case LogLevel.Error: ErrorColor.Apply(); break; + case LogLevel.Fatal: FatalColor.Apply(); break; + case LogLevel.Info: InfoColor.Apply(); break; + case LogLevel.Warning: WarningColor.Apply(); break; + } + + Console.WriteLine(log); + currentColor.Apply(); + } + + if (!string.IsNullOrEmpty(Settings.Default.Logger.Path)) + { + StringBuilder sb = new StringBuilder(source); + foreach (char c in GetInvalidFileNameChars()) + sb.Replace(c, '-'); + var path = Combine(Settings.Default.Logger.Path, sb.ToString()); + Directory.CreateDirectory(path); + path = Combine(path, $"{now:yyyy-MM-dd}.log"); + try + { + File.AppendAllLines(path, new[] { $"[{level}]{log}" }); + } + catch (IOException) + { + Console.WriteLine("Error writing the log file: " + path); + } + } + } + } + } +} diff --git a/neo-cli/CLI/MainService.Blockchain.cs b/neo-cli/CLI/MainService.Blockchain.cs index 10b323a4a..dcd24785f 100644 --- a/neo-cli/CLI/MainService.Blockchain.cs +++ b/neo-cli/CLI/MainService.Blockchain.cs @@ -17,7 +17,7 @@ private void OnExportBlocksStartCountCommand(uint start, uint count = uint.MaxVa { if (Blockchain.Singleton.Height < start) { - Console.WriteLine("error: invalid start height."); + Console.WriteLine("Error: invalid start height."); return; } diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs index f3f4f3d56..57454422c 100644 --- a/neo-cli/CLI/MainService.Contracts.cs +++ b/neo-cli/CLI/MainService.Contracts.cs @@ -49,81 +49,31 @@ private void OnDeployCommand(string filePath, string manifestPath = null) /// Contract parameters /// Witness address [ConsoleCommand("invoke", Category = "Contract Commands")] - private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] witnessAddress = null) + private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contractParameters = null, UInt160[] signerAccounts = null) { - List parameters = new List(); - List signCollection = new List(); - - if (!NoWallet() && witnessAddress != null) - { - using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) - { - UInt160[] accounts = CurrentWallet.GetAccounts().Where(p => !p.Lock && !p.WatchOnly).Select(p => p.ScriptHash).Where(p => NativeContract.GAS.BalanceOf(snapshot, p).Sign > 0).ToArray(); - foreach (var signAccount in accounts) - { - if (witnessAddress is null) - { - break; - } - foreach (var witness in witnessAddress) - { - if (witness.Equals(signAccount)) - { - signCollection.Add(new Cosigner() { Account = signAccount }); - break; - } - } - } - } - } - - if (contractParameters != null) - { - foreach (var contractParameter in contractParameters) - { - parameters.Add(ContractParameter.FromJson(contractParameter)); - } - } + Signer[] signers = Array.Empty(); + if (signerAccounts != null && !NoWallet()) + signers = CurrentWallet.GetAccounts().Where(p => !p.Lock && !p.WatchOnly && signerAccounts.Contains(p.ScriptHash)).Select(p => new Signer() { Account = p.ScriptHash, Scopes = WitnessScope.CalledByEntry }).ToArray(); Transaction tx = new Transaction { - Sender = UInt160.Zero, - Attributes = Array.Empty(), + Signers = signers, Witnesses = Array.Empty(), - Cosigners = signCollection.ToArray() }; - using (ScriptBuilder scriptBuilder = new ScriptBuilder()) - { - scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray()); - tx.Script = scriptBuilder.ToArray(); - Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'"); - } - - using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, testMode: true)) - { - Console.WriteLine($"VM State: {engine.State}"); - Console.WriteLine($"Gas Consumed: {new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals)}"); - Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToParameter().ToJson()))}"); - Console.WriteLine(); - if (engine.State.HasFlag(VMState.FAULT)) - { - Console.WriteLine("Engine faulted."); - return; - } - } + _ = OnInvokeWithResult(scriptHash, operation, tx, contractParameters); if (NoWallet()) return; try { - tx = CurrentWallet.MakeTransaction(tx.Script, null, tx.Attributes, tx.Cosigners); + tx = CurrentWallet.MakeTransaction(tx.Script, signers.Length > 0 ? signers[0].Account : null, signers); } catch (InvalidOperationException) { Console.WriteLine("Error: insufficient balance."); return; } - if (!ReadUserInput("relay tx(no|yes)").IsYes()) + if (!ReadUserInput("Relay tx(no|yes)").IsYes()) { return; } diff --git a/neo-cli/CLI/MainService.NEP5.cs b/neo-cli/CLI/MainService.NEP5.cs new file mode 100644 index 000000000..aa788f803 --- /dev/null +++ b/neo-cli/CLI/MainService.NEP5.cs @@ -0,0 +1,97 @@ +using Neo.ConsoleService; +using Neo.IO.Json; +using Neo.Network.P2P.Payloads; +using Neo.VM.Types; +using Neo.Wallets; +using System; +using System.Globalization; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "transfer" command + /// + /// Script hash + /// To + /// Ammount + [ConsoleCommand("transfer", Category = "NEP5 Commands")] + private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount) + { + var asset = new AssetDescriptor(tokenHash); + var value = BigDecimal.Parse(amount.ToString(CultureInfo.InvariantCulture), asset.Decimals); + + if (NoWallet()) return; + + Transaction tx; + try + { + tx = CurrentWallet.MakeTransaction(new[] + { + new TransferOutput + { + AssetId = tokenHash, + Value = value, + ScriptHash = to + } + }, from: null); + } + catch (InvalidOperationException) + { + Console.WriteLine("Error: insufficient balance."); + return; + } + if (!ReadUserInput("Relay tx(no|yes)").IsYes()) + { + return; + } + SignAndSendTx(tx); + } + + /// + /// Process "balanceOf" command + /// + /// Script hash + /// Address + [ConsoleCommand("balanceOf", Category = "NEP5 Commands")] + private void OnBalanceOfCommand(UInt160 tokenHash, UInt160 address) + { + var arg = new JObject(); + arg["type"] = "Hash160"; + arg["value"] = address.ToString(); + + var asset = new AssetDescriptor(tokenHash); + + var balanceResult = OnInvokeWithResult(tokenHash, "balanceOf", null, new JArray(arg)); + var balance = new BigDecimal(((PrimitiveType)balanceResult).GetInteger(), asset.Decimals); + + Console.WriteLine(); + Console.WriteLine($"{asset.AssetName} balance: {balance}"); + } + + /// + /// Process "name" command + /// + /// Script hash + [ConsoleCommand("name", Category = "NEP5 Commands")] + private void OnNameCommand(UInt160 tokenHash) + { + var result = OnInvokeWithResult(tokenHash, "name", null); + + Console.WriteLine($"Result : {((PrimitiveType)result).GetString()}"); + } + + /// + /// Process "decimals" command + /// + /// Script hash + [ConsoleCommand("decimals", Category = "NEP5 Commands")] + private void OnDecimalsCommand(UInt160 tokenHash) + { + var result = OnInvokeWithResult(tokenHash, "decimals", null); + + Console.WriteLine($"Result : {((PrimitiveType)result).GetInteger()}"); + } + } +} diff --git a/neo-cli/CLI/MainService.Native.cs b/neo-cli/CLI/MainService.Native.cs new file mode 100644 index 000000000..21de56436 --- /dev/null +++ b/neo-cli/CLI/MainService.Native.cs @@ -0,0 +1,19 @@ +using Neo.ConsoleService; +using Neo.SmartContract.Native; +using System; +using System.Linq; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "list nativecontract" command + /// + [ConsoleCommand("list nativecontract", Category = "Native Contract")] + private void OnListNativeContract() + { + NativeContract.Contracts.ToList().ForEach(p => Console.WriteLine("\t" + p.Name + "\t" + p.Hash)); + } + } +} diff --git a/neo-cli/CLI/MainService.Network.cs b/neo-cli/CLI/MainService.Network.cs index b26f41ecf..a167f1424 100644 --- a/neo-cli/CLI/MainService.Network.cs +++ b/neo-cli/CLI/MainService.Network.cs @@ -141,7 +141,7 @@ private void OnRelayCommand(JObject jsonObjectToRelay) return; } tx.Witnesses = context.GetWitnesses(); - NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); + NeoSystem.Blockchain.Tell(tx); Console.WriteLine($"Data relay success, the hash is shown as follows:{Environment.NewLine}{tx.Hash}"); } catch (Exception e) diff --git a/neo-cli/CLI/MainService.Plugins.cs b/neo-cli/CLI/MainService.Plugins.cs index aee450600..c1f32d931 100644 --- a/neo-cli/CLI/MainService.Plugins.cs +++ b/neo-cli/CLI/MainService.Plugins.cs @@ -77,6 +77,11 @@ private void OnUnInstallCommand(string pluginName) Console.WriteLine("Plugin not found"); return; } + if (plugin is Logger) + { + Console.WriteLine("You cannot uninstall a built-in plugin."); + return; + } File.Delete(plugin.Path); File.Delete(plugin.ConfigFile); @@ -99,7 +104,11 @@ private void OnPluginsCommand() if (Plugin.Plugins.Count > 0) { Console.WriteLine("Loaded plugins:"); - Plugin.Plugins.ForEach(p => Console.WriteLine("\t" + p.Name)); + foreach (Plugin plugin in Plugin.Plugins) + { + if (plugin is Logger) continue; + Console.WriteLine("\t" + plugin.Name + "\t" + plugin.Description); + } } else { diff --git a/neo-cli/CLI/MainService.Tools.cs b/neo-cli/CLI/MainService.Tools.cs new file mode 100644 index 000000000..0686ddb8d --- /dev/null +++ b/neo-cli/CLI/MainService.Tools.cs @@ -0,0 +1,465 @@ +using Neo.ConsoleService; +using Neo.IO; +using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "parse" command + /// + [ConsoleCommand("parse", Category = "Base Commands", Description = "Parse a value to its possible conversions.")] + private void OnParseCommand(string value) + { + var parseFunctions = new Dictionary>() + { + { "Address to ScriptHash", AddressToScripthash }, + { "Address to Base64", AddressToBase64 }, + { "ScriptHash to Address", ScripthashToAddress }, + { "Base64 to Address", Base64ToAddress }, + { "Base64 to String", Base64ToString }, + { "Base64 to Big Integer", Base64ToNumber }, + { "Big Integer to Hex String", NumberToHex }, + { "Big Integer to Base64", NumberToBase64 }, + { "Hex String to String", HexToString }, + { "Hex String to Big Integer", HexToNumber }, + { "String to Hex String", StringToHex }, + { "String to Base64", StringToBase64 } + }; + + bool any = false; + + foreach (var pair in parseFunctions) + { + var parseMethod = pair.Value; + var result = parseMethod(value); + + if (result != null) + { + Console.WriteLine($"{pair.Key,-30}\t{result}"); + any = true; + } + } + + if (!any) + { + Console.WriteLine($"Was not possible to convert: '{value}'"); + } + } + + /// + /// Converts an hexadecimal value to an UTF-8 string + /// + /// + /// Hexadecimal value to be converted + /// + /// + /// Returns null when is not possible to parse the hexadecimal value to a UTF-8 + /// string or when the converted string is not printable; otherwise, returns + /// the string represented by the hexadecimal value + /// + private string HexToString(string hexString) + { + try + { + var clearHexString = ClearHexString(hexString); + var bytes = clearHexString.HexToBytes(); + var utf8String = Encoding.UTF8.GetString(bytes); + + if (!IsPrintable(utf8String)) + { + return null; + } + + return utf8String; + } + catch + { + return null; + } + } + + /// + /// Converts an hex value to a big integer + /// + /// + /// Hexadecimal value to be converted + /// + /// + /// Returns null when is not possible to parse the hex value to big integer value; + /// otherwise, returns the string that represents the converted big integer. + /// + private string HexToNumber(string hexString) + { + try + { + var clearHexString = ClearHexString(hexString); + var bytes = clearHexString.HexToBytes(); + var number = new BigInteger(bytes); + + return number.ToString(); + } + catch + { + return null; + } + } + + /// + /// Formats a string value to a default hexadecimal representation of a byte array + /// + /// + /// The string value to be formatted + /// + /// + /// Returns the formatted string. + /// + /// + /// Throw when is the string is not a valid hex representation of a byte array. + /// + private string ClearHexString(string hexString) + { + bool hasHexPrefix = hexString.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase); + + try + { + if (hasHexPrefix) + { + hexString = hexString.Substring(2); + } + + if (hexString.Length % 2 == 1) + { + // if the length is an odd number, it cannot be parsed to a byte array + // it may be a valid hex string, so include a leading zero to parse correctly + hexString = "0" + hexString; + } + + if (hasHexPrefix) + { + // if the input value starts with '0x', the first byte is the less significant + // to parse correctly, reverse the byte array + return hexString.HexToBytes().Reverse().ToArray().ToHexString(); + } + } + catch (FormatException) + { + throw new ArgumentException(); + } + + return hexString; + } + + /// + /// Converts a string in a hexadecimal value + /// + /// + /// String value to be converted + /// + /// + /// Returns null when it is not possible to parse the string value to a hexadecimal + /// value; otherwise returns the hexadecimal value that represents the converted string + /// + private string StringToHex(string strParam) + { + try + { + var bytesParam = Encoding.UTF8.GetBytes(strParam); + return bytesParam.ToHexString(); + } + catch + { + return null; + } + } + + /// + /// Converts a string in Base64 string + /// + /// + /// String value to be converted + /// + /// + /// Returns null when is not possible to parse the string value to a Base64 value; + /// otherwise returns the Base64 value that represents the converted string + /// + /// + /// Throw . + /// + private string StringToBase64(string strParam) + { + try + { + byte[] bytearray = Encoding.UTF8.GetBytes(strParam); + string base64 = Convert.ToBase64String(bytearray.AsSpan()); + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts a string number in hexadecimal format + /// + /// + /// String that represents the number to be converted + /// + /// + /// Returns null when the string does not represent a big integer value or when + /// it is not possible to parse the big integer value to hexadecimal; otherwise, + /// returns the string that represents the converted hexadecimal value + /// + private string NumberToHex(string strParam) + { + try + { + if (!BigInteger.TryParse(strParam, out var numberParam)) + { + return null; + } + return numberParam.ToByteArray().ToHexString(); + } + catch + { + return null; + } + } + + /// + /// Converts a string number in Base64 byte array + /// + /// + /// String that represents the number to be converted + /// + /// + /// Returns null when the string does not represent a big integer value or when + /// it is not possible to parse the big integer value to Base64 value; otherwise, + /// returns the string that represents the converted Base64 value + /// + private string NumberToBase64(string strParam) + { + try + { + if (!BigInteger.TryParse(strParam, out var number)) + { + return null; + } + byte[] bytearray = number.ToByteArray(); + string base64 = Convert.ToBase64String(bytearray.AsSpan()); + + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts an address to its corresponding scripthash + /// + /// + /// String that represents the address to be converted + /// + /// + /// Returns null when the string does not represent an address or when + /// it is not possible to parse the address to scripthash; otherwise returns + /// the string that represents the converted scripthash + /// + private string AddressToScripthash(string address) + { + try + { + var bigEndScript = address.ToScriptHash(); + + return bigEndScript.ToString(); + } + catch + { + return null; + } + } + + /// + /// Converts an address to Base64 byte array + /// + /// + /// String that represents the address to be converted + /// + /// + /// Returns null when the string does not represent an address or when it is + /// not possible to parse the address to Base64 value; otherwise returns + /// the string that represents the converted Base64 value. + /// + private string AddressToBase64(string address) + { + try + { + var script = address.ToScriptHash(); + string base64 = Convert.ToBase64String(script.ToArray().AsSpan()); + + return base64; + } + catch + { + return null; + } + } + + /// + /// Converts a big end script hash to its equivalent address + /// + /// + /// String that represents the scripthash to be converted + /// + /// + /// Returns null when the string does not represent an scripthash; + /// otherwise, returns the string that represents the converted address + /// + private string ScripthashToAddress(string script) + { + try + { + UInt160 scriptHash; + if (script.StartsWith("0x")) + { + if (!UInt160.TryParse(script, out scriptHash)) + { + return null; + } + } + else + { + if (!UInt160.TryParse(script, out UInt160 littleEndScript)) + { + return null; + } + string bigEndScript = littleEndScript.ToArray().ToHexString(); + if (!UInt160.TryParse(bigEndScript, out scriptHash)) + { + return null; + } + } + + var hexScript = scriptHash.ToAddress(); + return hexScript; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 byte array to address + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to address; otherwise, + /// returns the string that represents the converted address + /// + private string Base64ToAddress(string bytearray) + { + try + { + byte[] result = Convert.FromBase64String(bytearray).Reverse().ToArray(); + string hex = result.ToHexString(); + + if (!UInt160.TryParse(hex, out var scripthash)) + { + return null; + } + + string address = scripthash.ToAddress(); + return address; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 hex string to string + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to string value or the converted + /// string is not printable; otherwise, returns the string that represents + /// the Base64 value. + /// + private string Base64ToString(string bytearray) + { + try + { + byte[] result = Convert.FromBase64String(bytearray); + string utf8string = Encoding.UTF8.GetString(result); + + if (!IsPrintable(utf8string)) + { + return null; + } + + return utf8string; + } + catch + { + return null; + } + } + + /// + /// Converts an Base64 hex string to big integer value + /// + /// + /// String that represents the Base64 value + /// + /// + /// Returns null when the string does not represent an Base64 value or when + /// it is not possible to parse the Base64 value to big integer value; otherwise + /// returns the string that represents the converted big integer + /// + private string Base64ToNumber(string bytearray) + { + try + { + var bytes = Convert.FromBase64String(bytearray); + var number = new BigInteger(bytes); + return number.ToString(); + } + catch + { + return null; + } + } + + /// + /// Checks if the string is null or cannot be printed. + /// + /// + /// The string to test + /// + /// + /// Returns false if the string is null, or if it is empty, or if each character cannot be printed; + /// otherwise, returns true. + /// + private bool IsPrintable(string value) + { + return !string.IsNullOrWhiteSpace(value) && value.Any(c => !char.IsControl(c)); + } + } +} diff --git a/neo-cli/CLI/MainService.Vote.cs b/neo-cli/CLI/MainService.Vote.cs new file mode 100644 index 000000000..d3aec7537 --- /dev/null +++ b/neo-cli/CLI/MainService.Vote.cs @@ -0,0 +1,175 @@ +using Neo.ConsoleService; +using Neo.Cryptography.ECC; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using System; + +namespace Neo.CLI +{ + partial class MainService + { + /// + /// Process "register candidate" command + /// + /// register account scriptHash + [ConsoleCommand("register candidate", Category = "Vote Commands")] + private void OnRegisterCandidateCommand(UInt160 account) + { + if (NoWallet()) + { + Console.WriteLine("Need open wallet!"); + return; + } + + ECPoint publicKey = CurrentWallet.GetAccount(account)?.GetKey()?.PublicKey; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitAppCall(NativeContract.NEO.Hash, "registerCandidate", publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, account); + } + + /// + /// Process "unregister candidate" command + /// + /// unregister account scriptHash + [ConsoleCommand("unregister candidate", Category = "Vote Commands")] + private void OnUnregisterCandidateCommand(UInt160 account) + { + if (NoWallet()) + { + Console.WriteLine("Need open wallet!"); + return; + } + + ECPoint publicKey = CurrentWallet.GetAccount(account)?.GetKey()?.PublicKey; + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitAppCall(NativeContract.NEO.Hash, "unregisterCandidate", publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, account); + } + + /// + /// Process "vote" command + /// + /// Sender account + /// Voting publicKey + [ConsoleCommand("vote", Category = "Vote Commands")] + private void OnVoteCommand(UInt160 senderAccount, ECPoint publicKey) + { + if (NoWallet()) + { + Console.WriteLine("Need open wallet!"); + return; + } + + byte[] script; + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitAppCall(NativeContract.NEO.Hash, "vote", senderAccount, publicKey); + script = scriptBuilder.ToArray(); + } + + SendTransaction(script, senderAccount); + } + + /// + /// Process "get candidates" + /// + [ConsoleCommand("get candidates", Category = "Vote Commands")] + private void OnGetCandidatesCommand() + { + var result = OnInvokeWithResult(NativeContract.NEO.Hash, "getCandidates", null, null, false); + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + Console.WriteLine("Candidates:"); + + foreach (var item in resJArray) + { + var value = (VM.Types.Array)item; + + Console.Write(((ByteString)value?[0])?.GetSpan().ToHexString() + "\t"); + Console.WriteLine(((Integer)value?[1]).GetInteger()); + } + } + } + + /// + /// Process "get validators" + /// + [ConsoleCommand("get validators", Category = "Vote Commands")] + private void OnGetValidatorsCommand() + { + var result = OnInvokeWithResult(NativeContract.NEO.Hash, "getValidators", null, null, false); + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + Console.WriteLine("Validators:"); + + foreach (var item in resJArray) + { + Console.WriteLine(((ByteString)item)?.GetSpan().ToHexString()); + } + } + } + + /// + /// Process "get committee" + /// + [ConsoleCommand("get committee", Category = "Vote Commands")] + private void OnGetCommitteeCommand() + { + var result = OnInvokeWithResult(NativeContract.NEO.Hash, "getCommittee", null, null, false); + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + Console.WriteLine("Committee:"); + + foreach (var item in resJArray) + { + Console.WriteLine(((ByteString)item)?.GetSpan().ToHexString()); + } + } + } + + /// + /// Process "get next validators" + /// + [ConsoleCommand("get next validators", Category = "Vote Commands")] + private void OnGetNextBlockValidatorsCommand() + { + var result = OnInvokeWithResult(NativeContract.NEO.Hash, "getNextBlockValidators", null, null, false); + + var resJArray = (VM.Types.Array)result; + + if (resJArray.Count > 0) + { + Console.WriteLine(); + Console.WriteLine("Next validators:"); + + foreach (var item in resJArray) + { + Console.WriteLine(((ByteString)item)?.GetSpan().ToHexString()); + } + } + } + } +} diff --git a/neo-cli/CLI/MainService.Wallet.cs b/neo-cli/CLI/MainService.Wallet.cs index a2d114118..5ebc7a728 100644 --- a/neo-cli/CLI/MainService.Wallet.cs +++ b/neo-cli/CLI/MainService.Wallet.cs @@ -36,7 +36,7 @@ private void OnOpenWallet(string path) string password = ReadUserInput("password", true); if (password.Length == 0) { - Console.WriteLine("cancelled"); + Console.WriteLine("Cancelled"); return; } try @@ -45,7 +45,7 @@ private void OnOpenWallet(string path) } catch (System.Security.Cryptography.CryptographicException) { - Console.WriteLine($"failed to open file \"{path}\""); + Console.WriteLine($"Failed to open file \"{path}\""); } } @@ -83,7 +83,7 @@ private void OnUpgradeWalletCommand(string path) string password = ReadUserInput("password", true); if (password.Length == 0) { - Console.WriteLine("cancelled"); + Console.WriteLine("Cancelled"); return; } string path_new = Path.ChangeExtension(path, ".json"); @@ -131,7 +131,7 @@ private void OnCreateAddressCommand(ushort count = 1) if (CurrentWallet is NEP6Wallet wallet) wallet.Save(); - Console.WriteLine($"export addresses to {path}"); + Console.WriteLine($"Export addresses to {path}"); File.WriteAllLines(path, addresses); } @@ -152,7 +152,7 @@ private void OnExportKeyCommand(string path = null, UInt160 scriptHash = null) string password = ReadUserInput("password", true); if (password.Length == 0) { - Console.WriteLine("cancelled"); + Console.WriteLine("Cancelled"); return; } if (!CurrentWallet.VerifyPassword(password)) @@ -181,13 +181,13 @@ private void OnCreateWalletCommand(string path) string password = ReadUserInput("password", true); if (password.Length == 0) { - Console.WriteLine("cancelled"); + Console.WriteLine("Cancelled"); return; } string password2 = ReadUserInput("password", true); if (password != password2) { - Console.WriteLine("error"); + Console.WriteLine("Error"); return; } if (!File.Exists(path)) @@ -277,8 +277,8 @@ private void OnImportKeyCommand(string wifOrFile) { WalletAccount account = CurrentWallet.CreateAccount(prikey); Array.Clear(prikey, 0, prikey.Length); - Console.WriteLine($"address: {account.Address}"); - Console.WriteLine($" pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); + Console.WriteLine($"Address: {account.Address}"); + Console.WriteLine($" Pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); } if (CurrentWallet is NEP6Wallet wallet) wallet.Save(); @@ -311,7 +311,8 @@ private void OnListAddressCommand() type = "Deployed-Nonstandard"; } - Console.WriteLine($"{contract.Address}\t{type}"); + Console.WriteLine($"{" Address: "}{contract.Address}\t{type}"); + Console.WriteLine($"{"ScriptHash: "}{contract.ScriptHash}\n"); } } } @@ -346,7 +347,8 @@ private void OnListKeyCommand() if (NoWallet()) return; foreach (KeyPair key in CurrentWallet.GetAccounts().Where(p => p.HasKey).Select(p => p.GetKey())) { - Console.WriteLine(key.PublicKey); + Console.WriteLine($" Address: {Contract.CreateSignatureContract(key.PublicKey).Address}"); + Console.WriteLine($"PublicKey: {key.PublicKey}\n"); } } @@ -393,7 +395,7 @@ private void OnSendCommand(UInt160 asset, UInt160 to, string amount) string password = ReadUserInput("password", true); if (password.Length == 0) { - Console.WriteLine("cancelled"); + Console.WriteLine("Cancelled"); return; } if (!CurrentWallet.VerifyPassword(password)) @@ -430,7 +432,7 @@ private void OnSendCommand(UInt160 asset, UInt160 to, string amount) if (context.Completed) { tx.Witnesses = context.GetWitnesses(); - NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); + NeoSystem.Blockchain.Tell(tx); Console.WriteLine($"TXID: {tx.Hash}"); } else @@ -453,7 +455,65 @@ private void OnShowGasCommand() { gas += NativeContract.NEO.UnclaimedGas(snapshot, account, snapshot.Height + 1); } - Console.WriteLine($"unclaimed gas: {new BigDecimal(gas, NativeContract.GAS.Decimals)}"); + Console.WriteLine($"Unclaimed gas: {new BigDecimal(gas, NativeContract.GAS.Decimals)}"); + } + + /// + /// Process "change password" command + /// + [ConsoleCommand("change password", Category = "Wallet Commands")] + private void OnChangePasswordCommand() + { + if (NoWallet()) return; + string oldPassword = ReadUserInput("password", true); + if (oldPassword.Length == 0) + { + Console.WriteLine("Cancelled"); + return; + } + if (!CurrentWallet.VerifyPassword(oldPassword)) + { + Console.WriteLine("Incorrect password"); + return; + } + string newPassword = ReadUserInput("New password", true); + string newPasswordReEntered = ReadUserInput("Re-Enter Password", true); + if (!newPassword.Equals(newPasswordReEntered)) + { + Console.WriteLine("Two passwords entered are inconsistent!"); + return; + } + + if (CurrentWallet is NEP6Wallet wallet) + { + string backupFile = wallet.Path + ".bak"; + if (!File.Exists(wallet.Path) || File.Exists(backupFile)) + { + Console.WriteLine("Wallet backup fail"); + return; + } + try + { + File.Copy(wallet.Path, backupFile); + } + catch (IOException) + { + Console.WriteLine("Wallet backup fail"); + return; + } + } + + bool succeed = CurrentWallet.ChangePassword(oldPassword, newPassword); + if (succeed) + { + if (CurrentWallet is NEP6Wallet nep6Wallet) + nep6Wallet.Save(); + Console.WriteLine("Password changed successfully"); + } + else + { + Console.WriteLine("Failed to change password"); + } } private void SignAndSendTx(Transaction tx) @@ -474,7 +534,7 @@ private void SignAndSendTx(Transaction tx) { tx.Witnesses = context.GetWitnesses(); - NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); + NeoSystem.Blockchain.Tell(tx); msg = $"Signed and relayed transaction with hash={tx.Hash}"; Console.WriteLine(msg); diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs index 272107919..d528b4d3d 100644 --- a/neo-cli/CLI/MainService.cs +++ b/neo-cli/CLI/MainService.cs @@ -1,5 +1,4 @@ using Akka.Actor; -using Microsoft.Extensions.Configuration; using Neo.ConsoleService; using Neo.Cryptography.ECC; using Neo.IO; @@ -7,15 +6,19 @@ using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.Plugins; using Neo.SmartContract; using Neo.SmartContract.Manifest; +using Neo.SmartContract.Native; using Neo.VM; +using Neo.VM.Types; using Neo.Wallets; using Neo.Wallets.NEP6; using Neo.Wallets.SQLite; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; @@ -70,8 +73,8 @@ public MainService() : base() { switch (str.ToLowerInvariant()) { - case "neo": return SmartContract.Native.NativeContract.NEO.Hash; - case "gas": return SmartContract.Native.NativeContract.GAS.Hash; + case "neo": return NativeContract.NEO.Hash; + case "gas": return NativeContract.GAS.Hash; } // Try to parse as UInt160 @@ -94,8 +97,8 @@ public MainService() : base() { switch (str.ToLowerInvariant()) { - case "neo": return SmartContract.Native.NativeContract.NEO.Hash; - case "gas": return SmartContract.Native.NativeContract.GAS.Hash; + case "neo": return NativeContract.NEO.Hash; + case "gas": return NativeContract.GAS.Hash; } // Try to parse as UInt160 @@ -112,8 +115,10 @@ public MainService() : base() .ToArray(); }); + RegisterCommandHander((str) => ECPoint.Parse(str.Trim(), ECCurve.Secp256r1)); RegisterCommandHander((str) => str.Select(u => ECPoint.Parse(u.Trim(), ECCurve.Secp256r1)).ToArray()); RegisterCommandHander((str) => JObject.Parse(str)); + RegisterCommandHander((str) => decimal.Parse(str, CultureInfo.InvariantCulture)); RegisterCommandHander((obj) => (JArray)obj); RegisterCommand(this); @@ -140,8 +145,9 @@ public void CreateWallet(string path, string password) { UserWallet wallet = UserWallet.Create(path, password); WalletAccount account = wallet.CreateAccount(); - Console.WriteLine($"address: {account.Address}"); - Console.WriteLine($" pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); + Console.WriteLine($" Address: {account.Address}"); + Console.WriteLine($" Pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); + Console.WriteLine($"ScriptHash: {account.ScriptHash}"); CurrentWallet = wallet; } break; @@ -151,8 +157,9 @@ public void CreateWallet(string path, string password) wallet.Unlock(password); WalletAccount account = wallet.CreateAccount(); wallet.Save(); - Console.WriteLine($"address: {account.Address}"); - Console.WriteLine($" pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); + Console.WriteLine($" Address: {account.Address}"); + Console.WriteLine($" Pubkey: {account.GetKey().PublicKey.EncodePoint(true).ToHexString()}"); + Console.WriteLine($"ScriptHash: {account.ScriptHash}"); CurrentWallet = wallet; } break; @@ -245,7 +252,7 @@ private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, throw new ArgumentException(nameof(manifestFilePath)); } - var manifest = ContractManifest.Parse(new ReadOnlySpan(File.ReadAllBytes(manifestFilePath))); + var manifest = ContractManifest.Parse(File.ReadAllBytes(manifestFilePath)); // Read nef @@ -263,7 +270,7 @@ private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, // Basic script checks - using (var engine = new ApplicationEngine(TriggerType.Application, null, null, 0, true)) + using (var engine = ApplicationEngine.Create(TriggerType.Application, null, null, 0, true)) { var context = engine.LoadScript(file.Script); @@ -278,20 +285,6 @@ private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, throw new FormatException($"OpCode not found at {context.InstructionPointer}-{((byte)ci.OpCode).ToString("x2")}"); } - switch (ci.OpCode) - { - case OpCode.SYSCALL: - { - // Check bad syscalls (NEO2) - - if (!InteropService.SupportedMethods().Any(u => u.Hash == ci.TokenU32)) - { - throw new FormatException($"Syscall not found {ci.TokenU32.ToString("x2")}. Are you using a NEO2 smartContract?"); - } - break; - } - } - context.InstructionPointer += ci.Size; } } @@ -301,7 +294,7 @@ private byte[] LoadDeploymentScript(string nefFilePath, string manifestFilePath, scriptHash = file.ScriptHash; using (ScriptBuilder sb = new ScriptBuilder()) { - sb.EmitSysCall(InteropService.Contract.Create, file.Script, manifest.ToJson().ToString()); + sb.EmitSysCall(ApplicationEngine.System_Contract_Create, file.Script, manifest.ToJson().ToString()); return sb.ToArray(); } } @@ -325,15 +318,21 @@ public void OpenWallet(string path, string password) throw new FileNotFoundException(); } - if (Path.GetExtension(path) == ".db3") - { - CurrentWallet = UserWallet.Open(path, password); - } - else + switch (Path.GetExtension(path).ToLowerInvariant()) { - NEP6Wallet nep6wallet = new NEP6Wallet(path); - nep6wallet.Unlock(password); - CurrentWallet = nep6wallet; + case ".db3": + { + CurrentWallet = UserWallet.Open(path, password); + break; + } + case ".json": + { + NEP6Wallet nep6wallet = new NEP6Wallet(path); + nep6wallet.Unlock(password); + CurrentWallet = nep6wallet; + break; + } + default: throw new NotSupportedException(); } } @@ -348,19 +347,10 @@ public async void Start(string[] args) case "--noverify": verifyImport = false; break; - case "/testnet": - case "--testnet": - case "-t": - ProtocolSettings.Initialize(new ConfigurationBuilder().AddJsonFile("protocol.testnet.json").Build()); - Settings.Initialize(new ConfigurationBuilder().AddJsonFile("config.testnet.json").Build()); - break; - case "/mainnet": - case "--mainnet": - case "-m": - ProtocolSettings.Initialize(new ConfigurationBuilder().AddJsonFile("protocol.mainnet.json").Build()); - Settings.Initialize(new ConfigurationBuilder().AddJsonFile("config.mainnet.json").Build()); - break; } + + _ = new Logger(); + NeoSystem = new NeoSystem(Settings.Default.Storage.Engine); foreach (var plugin in Plugin.Plugins) @@ -409,7 +399,7 @@ public async void Start(string[] args) } catch (System.Security.Cryptography.CryptographicException) { - Console.WriteLine($"failed to open file \"{Settings.Default.UnlockWallet.Path}\""); + Console.WriteLine($"Failed to open file \"{Settings.Default.UnlockWallet.Path}\""); } if (Settings.Default.UnlockWallet.StartConsensus && CurrentWallet != null) { @@ -476,5 +466,122 @@ private static void WriteLineWithoutFlicker(string message = "", int maxWidth = if (spacesToErase < 0) spacesToErase = 0; Console.WriteLine(new string(' ', spacesToErase)); } + + /// + /// Make and send transaction with script, sender + /// + /// script + /// sender + private void SendTransaction(byte[] script, UInt160 account = null) + { + Signer[] signers = System.Array.Empty(); + + if (account != null) + { + using (SnapshotView snapshot = Blockchain.Singleton.GetSnapshot()) + { + signers = CurrentWallet.GetAccounts() + .Where(p => !p.Lock && !p.WatchOnly && p.ScriptHash == account && NativeContract.GAS.BalanceOf(snapshot, p.ScriptHash).Sign > 0) + .Select(p => new Signer() { Account = p.ScriptHash, Scopes = WitnessScope.CalledByEntry }) + .ToArray(); + } + } + + try + { + Transaction tx = CurrentWallet.MakeTransaction(script, account, signers); + Console.WriteLine($"Invoking script with: '{tx.Script.ToHexString()}'"); + + using (ApplicationEngine engine = ApplicationEngine.Run(tx.Script, tx, null, testMode: true)) + { + Console.WriteLine($"VM State: {engine.State}"); + Console.WriteLine($"Gas Consumed: {new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals)}"); + Console.WriteLine($"Evaluation Stack: {new JArray(engine.ResultStack.Select(p => p.ToJson()))}"); + Console.WriteLine(); + if (engine.State.HasFlag(VMState.FAULT)) + { + Console.WriteLine("Error: " + GetExceptionMessage(engine.FaultException)); + return; + } + } + + if (!ReadUserInput("relay tx(no|yes)").IsYes()) + { + return; + } + + SignAndSendTx(tx); + } + catch (InvalidOperationException e) + { + Console.WriteLine("Error: " + GetExceptionMessage(e)); + return; + } + + return; + } + + /// + /// Process "invoke" command + /// + /// Script hash + /// Operation + /// Transaction + /// Contract parameters + private StackItem OnInvokeWithResult(UInt160 scriptHash, string operation, IVerifiable verificable = null, JArray contractParameters = null, bool showStack = true) + { + List parameters = new List(); + + if (contractParameters != null) + { + foreach (var contractParameter in contractParameters) + { + parameters.Add(ContractParameter.FromJson(contractParameter)); + } + } + + byte[] script; + + using (ScriptBuilder scriptBuilder = new ScriptBuilder()) + { + scriptBuilder.EmitAppCall(scriptHash, operation, parameters.ToArray()); + script = scriptBuilder.ToArray(); + Console.WriteLine($"Invoking script with: '{script.ToHexString()}'"); + } + + if (verificable is Transaction tx) + { + tx.Script = script; + } + + using (ApplicationEngine engine = ApplicationEngine.Run(script, verificable, testMode: true)) + { + Console.WriteLine($"VM State: {engine.State}"); + Console.WriteLine($"Gas Consumed: {new BigDecimal(engine.GasConsumed, NativeContract.GAS.Decimals)}"); + + if (showStack) + Console.WriteLine($"Result Stack: {new JArray(engine.ResultStack.Select(p => p.ToJson()))}"); + + if (engine.State.HasFlag(VMState.FAULT)) + { + Console.WriteLine("Error: " + GetExceptionMessage(engine.FaultException)); + return null; + } + + return engine.ResultStack.Pop(); + } + } + + static string GetExceptionMessage(Exception exception) + { + if (exception == null) return "Engine faulted."; + + if (exception.InnerException != null) + { + return exception.InnerException.Message; + } + + return exception.Message; + } } } diff --git a/neo-cli/Program.cs b/neo-cli/Program.cs index a3253aeac..4165a3788 100644 --- a/neo-cli/Program.cs +++ b/neo-cli/Program.cs @@ -1,51 +1,13 @@ using Neo.CLI; -using System; -using System.IO; namespace Neo { static class Program { - private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) - { - using (FileStream fs = new FileStream("error.log", FileMode.Create, FileAccess.Write, FileShare.None)) - using (StreamWriter w = new StreamWriter(fs)) - if (e.ExceptionObject is Exception ex) - { - PrintErrorLogs(w, ex); - } - else - { - w.WriteLine(e.ExceptionObject.GetType()); - w.WriteLine(e.ExceptionObject); - } - } - static void Main(string[] args) { - AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; var mainService = new MainService(); mainService.Run(args); } - - private static void PrintErrorLogs(StreamWriter writer, Exception ex) - { - writer.WriteLine(ex.GetType()); - writer.WriteLine(ex.Message); - writer.WriteLine(ex.StackTrace); - if (ex is AggregateException ex2) - { - foreach (Exception inner in ex2.InnerExceptions) - { - writer.WriteLine(); - PrintErrorLogs(writer, inner); - } - } - else if (ex.InnerException != null) - { - writer.WriteLine(); - PrintErrorLogs(writer, ex.InnerException); - } - } } } diff --git a/neo-cli/Settings.cs b/neo-cli/Settings.cs index 74108726c..bbcb726b0 100644 --- a/neo-cli/Settings.cs +++ b/neo-cli/Settings.cs @@ -6,6 +6,7 @@ namespace Neo { public class Settings { + public LoggerSettings Logger { get; } public StorageSettings Storage { get; } public P2PSettings P2P { get; } public UnlockWalletSettings UnlockWallet { get; } @@ -39,10 +40,25 @@ public static Settings Default public Settings(IConfigurationSection section) { + this.Logger = new LoggerSettings(section.GetSection("Logger")); this.Storage = new StorageSettings(section.GetSection("Storage")); this.P2P = new P2PSettings(section.GetSection("P2P")); this.UnlockWallet = new UnlockWalletSettings(section.GetSection("UnlockWallet")); - this.PluginURL = section.GetSection("PluginURL").Value; + this.PluginURL = section.GetValue("PluginURL", "https://github.com/neo-project/neo-modules/releases/download/v{1}/{0}.zip"); + } + } + + public class LoggerSettings + { + public string Path { get; } + public bool ConsoleOutput { get; } + public bool Active { get; } + + public LoggerSettings(IConfigurationSection section) + { + this.Path = string.Format(section.GetValue("Path", "Logs_{0}"), ProtocolSettings.Default.Magic.ToString("X8")); + this.ConsoleOutput = section.GetValue("ConsoleOutput", false); + this.Active = section.GetValue("Active", false); } } @@ -52,7 +68,7 @@ public class StorageSettings public StorageSettings(IConfigurationSection section) { - this.Engine = section.GetSection("Engine").Value; + this.Engine = section.GetValue("Engine", "LevelDBStore"); } } @@ -66,8 +82,8 @@ public class P2PSettings public P2PSettings(IConfigurationSection section) { - this.Port = ushort.Parse(section.GetSection("Port").Value); - this.WsPort = ushort.Parse(section.GetSection("WsPort").Value); + this.Port = ushort.Parse(section.GetValue("Port", "10333")); + this.WsPort = ushort.Parse(section.GetValue("WsPort", "10334")); this.MinDesiredConnections = section.GetValue("MinDesiredConnections", Peer.DefaultMinDesiredConnections); this.MaxConnections = section.GetValue("MaxConnections", Peer.DefaultMaxConnections); this.MaxConnectionsPerAddress = section.GetValue("MaxConnectionsPerAddress", 3); @@ -85,10 +101,10 @@ 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); + this.Path = section.GetValue("Path", ""); + this.Password = section.GetValue("Password", ""); + this.StartConsensus = bool.Parse(section.GetValue("StartConsensus", "false")); + this.IsActive = bool.Parse(section.GetValue("IsActive", "false")); } } } diff --git a/neo-cli/config.json b/neo-cli/config.json index 239c1c70e..62df1df84 100644 --- a/neo-cli/config.json +++ b/neo-cli/config.json @@ -1,5 +1,10 @@ { "ApplicationConfiguration": { + "Logger": { + "Path": "Logs_{0}", + "ConsoleOutput": false, + "Active": false + }, "Storage": { "Engine": "LevelDBStore" }, diff --git a/neo-cli/config.mainnet.json b/neo-cli/config.mainnet.json index 239c1c70e..62df1df84 100644 --- a/neo-cli/config.mainnet.json +++ b/neo-cli/config.mainnet.json @@ -1,5 +1,10 @@ { "ApplicationConfiguration": { + "Logger": { + "Path": "Logs_{0}", + "ConsoleOutput": false, + "Active": false + }, "Storage": { "Engine": "LevelDBStore" }, diff --git a/neo-cli/config.testnet.json b/neo-cli/config.testnet.json index d310712ee..688dddac3 100644 --- a/neo-cli/config.testnet.json +++ b/neo-cli/config.testnet.json @@ -1,5 +1,10 @@ { "ApplicationConfiguration": { + "Logger": { + "Path": "Logs_{0}", + "ConsoleOutput": false, + "Active": false + }, "Storage": { "Engine": "LevelDBStore" }, diff --git a/neo-cli/neo-cli.csproj b/neo-cli/neo-cli.csproj index 3f67359d2..03eae04a5 100644 --- a/neo-cli/neo-cli.csproj +++ b/neo-cli/neo-cli.csproj @@ -3,7 +3,7 @@ 2016-2019 The Neo Project Neo.CLI - 3.0.0-preview1 + 3.0.0-preview2 The Neo Project netcoreapp3.0 neo-cli @@ -28,7 +28,7 @@ - + diff --git a/neo-cli/protocol.json b/neo-cli/protocol.json index 7437fc379..88e0e135d 100644 --- a/neo-cli/protocol.json +++ b/neo-cli/protocol.json @@ -2,14 +2,29 @@ "ProtocolConfiguration": { "Magic": 5195086, "MillisecondsPerBlock": 15000, - "StandbyValidators": [ + "ValidatorsCount": 7, + "StandbyCommittee": [ "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", - "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70" + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" ], "SeedList": [ "seed1.neo.org:10333", diff --git a/neo-cli/protocol.mainnet.json b/neo-cli/protocol.mainnet.json index 7437fc379..88e0e135d 100644 --- a/neo-cli/protocol.mainnet.json +++ b/neo-cli/protocol.mainnet.json @@ -2,14 +2,29 @@ "ProtocolConfiguration": { "Magic": 5195086, "MillisecondsPerBlock": 15000, - "StandbyValidators": [ + "ValidatorsCount": 7, + "StandbyCommittee": [ "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", - "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70" + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" ], "SeedList": [ "seed1.neo.org:10333", diff --git a/neo-cli/protocol.testnet.json b/neo-cli/protocol.testnet.json index efb9e1395..ed3afe6d7 100644 --- a/neo-cli/protocol.testnet.json +++ b/neo-cli/protocol.testnet.json @@ -2,7 +2,8 @@ "ProtocolConfiguration": { "Magic": 1951352142, "MillisecondsPerBlock": 15000, - "StandbyValidators": [ + "ValidatorsCount": 7, + "StandbyCommittee": [ "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", diff --git a/neo-gui/GUI/DeployContractDialog.cs b/neo-gui/GUI/DeployContractDialog.cs index f3f715172..2d2ea774b 100644 --- a/neo-gui/GUI/DeployContractDialog.cs +++ b/neo-gui/GUI/DeployContractDialog.cs @@ -18,7 +18,7 @@ public byte[] GetScript() byte[] script = textBox8.Text.HexToBytes(); string manifest = ""; using ScriptBuilder sb = new ScriptBuilder(); - sb.EmitSysCall(InteropService.Contract.Create, script, manifest); + sb.EmitSysCall(ApplicationEngine.System_Contract_Create, script, manifest); return sb.ToArray(); } diff --git a/neo-gui/GUI/DeveloperToolsForm.ContractParameters.cs b/neo-gui/GUI/DeveloperToolsForm.ContractParameters.cs index 6c867ecf5..a4bb5d1b6 100644 --- a/neo-gui/GUI/DeveloperToolsForm.ContractParameters.cs +++ b/neo-gui/GUI/DeveloperToolsForm.ContractParameters.cs @@ -93,8 +93,8 @@ private void button4_Click(object sender, EventArgs e) return; } tx.Witnesses = context.GetWitnesses(); - RelayResultReason reason = Service.NeoSystem.Blockchain.Ask(tx).Result; - if (reason == RelayResultReason.Succeed) + Blockchain.RelayResult reason = Service.NeoSystem.Blockchain.Ask(tx).Result; + if (reason.Result == VerifyResult.Succeed) { InformationBox.Show(tx.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle); } diff --git a/neo-gui/GUI/Helper.cs b/neo-gui/GUI/Helper.cs index 85ec266a0..2b5e4fd72 100644 --- a/neo-gui/GUI/Helper.cs +++ b/neo-gui/GUI/Helper.cs @@ -52,7 +52,7 @@ public static void SignAndShowInformation(Transaction tx) if (context.Completed) { tx.Witnesses = context.GetWitnesses(); - Service.NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); + Service.NeoSystem.Blockchain.Tell(tx); InformationBox.Show(tx.Hash.ToString(), Strings.SendTxSucceedMessage, Strings.SendTxSucceedTitle); } else diff --git a/neo-gui/GUI/InvokeContractDialog.cs b/neo-gui/GUI/InvokeContractDialog.cs index 2830ab280..1efe81b65 100644 --- a/neo-gui/GUI/InvokeContractDialog.cs +++ b/neo-gui/GUI/InvokeContractDialog.cs @@ -73,7 +73,6 @@ private void button5_Click(object sender, EventArgs e) { Sender = UInt160.Zero, Attributes = new TransactionAttribute[0], - Cosigners = new Cosigner[0], Script = script, Witnesses = new Witness[0] }; diff --git a/neo-gui/GUI/MainForm.cs b/neo-gui/GUI/MainForm.cs index 86faab6c7..faafafb03 100644 --- a/neo-gui/GUI/MainForm.cs +++ b/neo-gui/GUI/MainForm.cs @@ -204,11 +204,11 @@ private void timer1_Tick(object sender, EventArgs e) sb.EmitAppCall(assetId, "name"); script = sb.ToArray(); } - using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, extraGAS: 0_20000000L * addresses.Length); + using ApplicationEngine engine = ApplicationEngine.Run(script, snapshot, gas: 0_20000000L * addresses.Length); if (engine.State.HasFlag(VMState.FAULT)) continue; string name = engine.ResultStack.Pop().GetString(); - byte decimals = (byte)engine.ResultStack.Pop().GetBigInteger(); - BigInteger[] balances = ((VMArray)engine.ResultStack.Pop()).Select(p => p.GetBigInteger()).ToArray(); + byte decimals = (byte)engine.ResultStack.Pop().GetInteger(); + BigInteger[] balances = ((VMArray)engine.ResultStack.Pop()).Select(p => p.GetInteger()).ToArray(); string symbol = null; if (assetId.Equals(NativeContract.NEO.Hash)) symbol = NativeContract.NEO.Symbol; @@ -287,11 +287,16 @@ private void 修改密码CToolStripMenuItem_Click(object sender, EventArgs e) { using ChangePasswordDialog dialog = new ChangePasswordDialog(); if (dialog.ShowDialog() != DialogResult.OK) return; - if (!(Service.CurrentWallet is UserWallet wallet)) return; - if (wallet.ChangePassword(dialog.OldPassword, dialog.NewPassword)) + if (Service.CurrentWallet.ChangePassword(dialog.OldPassword, dialog.NewPassword)) + { + if (Service.CurrentWallet is NEP6Wallet wallet) + wallet.Save(); MessageBox.Show(Strings.ChangePasswordSuccessful); + } else + { MessageBox.Show(Strings.PasswordIncorrect); + } } private void 退出XToolStripMenuItem_Click(object sender, EventArgs e) diff --git a/neo-gui/GUI/SigningTxDialog.cs b/neo-gui/GUI/SigningTxDialog.cs index e3eef1d7f..d306bfece 100644 --- a/neo-gui/GUI/SigningTxDialog.cs +++ b/neo-gui/GUI/SigningTxDialog.cs @@ -48,7 +48,7 @@ private void button4_Click(object sender, EventArgs e) return; } tx.Witnesses = context.GetWitnesses(); - Service.NeoSystem.LocalNode.Tell(new LocalNode.Relay { Inventory = tx }); + Service.NeoSystem.Blockchain.Tell(tx); InformationBox.Show(tx.Hash.ToString(), Strings.RelaySuccessText, Strings.RelaySuccessTitle); button4.Visible = false; } diff --git a/neo-gui/GUI/Wrappers/TransactionAttributeWrapper.cs b/neo-gui/GUI/Wrappers/TransactionAttributeWrapper.cs index 748023463..9f0bc3989 100644 --- a/neo-gui/GUI/Wrappers/TransactionAttributeWrapper.cs +++ b/neo-gui/GUI/Wrappers/TransactionAttributeWrapper.cs @@ -1,21 +1,21 @@ using Neo.Network.P2P.Payloads; using System.ComponentModel; +using System.IO; +using System.Text; namespace Neo.GUI.Wrappers { internal class TransactionAttributeWrapper { - public TransactionAttributeUsage Usage { get; set; } + public TransactionAttributeType Usage { get; set; } [TypeConverter(typeof(HexConverter))] public byte[] Data { get; set; } public TransactionAttribute Unwrap() { - return new TransactionAttribute - { - Usage = Usage, - Data = Data - }; + using var reader = new BinaryReader(new MemoryStream(Data), Encoding.UTF8, false); + + return TransactionAttribute.DeserializeFrom(reader); } } } diff --git a/neo-gui/GUI/Wrappers/TransactionWrapper.cs b/neo-gui/GUI/Wrappers/TransactionWrapper.cs index b58329861..d2ef0ce94 100644 --- a/neo-gui/GUI/Wrappers/TransactionWrapper.cs +++ b/neo-gui/GUI/Wrappers/TransactionWrapper.cs @@ -24,8 +24,6 @@ internal class TransactionWrapper [Category("Basic")] public List Attributes { get; set; } = new List(); [Category("Basic")] - public List Cosigners { get; set; } = new List(); - [Category("Basic")] [Editor(typeof(ScriptEditor), typeof(UITypeEditor))] [TypeConverter(typeof(HexConverter))] public byte[] Script { get; set; } @@ -43,7 +41,6 @@ public Transaction Unwrap() NetworkFee = NetworkFee, ValidUntilBlock = ValidUntilBlock, Attributes = Attributes.Select(p => p.Unwrap()).ToArray(), - Cosigners = Cosigners.Select(p => p.Unwrap()).ToArray(), Script = Script, Witnesses = Witnesses.Select(p => p.Unwrap()).ToArray() }; diff --git a/neo-gui/neo-gui.csproj b/neo-gui/neo-gui.csproj index 5f61c6ebf..bcaedd442 100644 --- a/neo-gui/neo-gui.csproj +++ b/neo-gui/neo-gui.csproj @@ -1,9 +1,9 @@ - + 2016-2019 The Neo Project Neo.GUI - 3.0.0-preview1 + 3.0.0-preview2 The Neo Project WinExe netcoreapp3.0 From c7bd2148f9e9cc3bd6db2a125868b18ab729ab6c Mon Sep 17 00:00:00 2001 From: cloud8little <413074538@qq.com> Date: Mon, 20 Jul 2020 23:11:44 +0800 Subject: [PATCH 3/9] enable print exception message when deploy contract --- neo-cli/CLI/MainService.Contracts.cs | 4 ++-- neo-cli/CLI/MainService.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs index 57454422c..28745be06 100644 --- a/neo-cli/CLI/MainService.Contracts.cs +++ b/neo-cli/CLI/MainService.Contracts.cs @@ -30,9 +30,9 @@ private void OnDeployCommand(string filePath, string manifestPath = null) { tx = CurrentWallet.MakeTransaction(script); } - catch (InvalidOperationException) + catch (InvalidOperationException e) { - Console.WriteLine("Engine faulted."); + Console.WriteLine("Error: " + GetExceptionMessage(e)); return; } Console.WriteLine($"Script hash: {scriptHash.ToString()}"); diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs index d528b4d3d..2dc8de110 100644 --- a/neo-cli/CLI/MainService.cs +++ b/neo-cli/CLI/MainService.cs @@ -578,7 +578,7 @@ static string GetExceptionMessage(Exception exception) if (exception.InnerException != null) { - return exception.InnerException.Message; + return GetExceptionMessage(exception.InnerException); } return exception.Message; From 6d06d405a8d8800322602dfa2acdd425bc3c58fd Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 21 Jul 2020 09:49:12 +0200 Subject: [PATCH 4/9] Add other error --- neo-cli/CLI/MainService.Contracts.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo-cli/CLI/MainService.Contracts.cs b/neo-cli/CLI/MainService.Contracts.cs index 28745be06..aaa3546b3 100644 --- a/neo-cli/CLI/MainService.Contracts.cs +++ b/neo-cli/CLI/MainService.Contracts.cs @@ -68,9 +68,9 @@ private void OnInvokeCommand(UInt160 scriptHash, string operation, JArray contra { tx = CurrentWallet.MakeTransaction(tx.Script, signers.Length > 0 ? signers[0].Account : null, signers); } - catch (InvalidOperationException) + catch (InvalidOperationException e) { - Console.WriteLine("Error: insufficient balance."); + Console.WriteLine("Error: " + GetExceptionMessage(e)); return; } if (!ReadUserInput("Relay tx(no|yes)").IsYes()) From 5aac1c263f996de1ca1a8725493c2becaefa4220 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 21 Jul 2020 10:12:50 +0200 Subject: [PATCH 5/9] Add other --- neo-cli/CLI/MainService.NEP5.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo-cli/CLI/MainService.NEP5.cs b/neo-cli/CLI/MainService.NEP5.cs index aa788f803..7230cac72 100644 --- a/neo-cli/CLI/MainService.NEP5.cs +++ b/neo-cli/CLI/MainService.NEP5.cs @@ -37,9 +37,9 @@ private void OnTransferCommand(UInt160 tokenHash, UInt160 to, decimal amount) } }, from: null); } - catch (InvalidOperationException) + catch (InvalidOperationException e) { - Console.WriteLine("Error: insufficient balance."); + Console.WriteLine("Error: " + GetExceptionMessage(e)); return; } if (!ReadUserInput("Relay tx(no|yes)").IsYes()) From 230cc4cf9d995cfd11edaa9c299b6eedf1b57ff8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 22 Jul 2020 15:48:11 +0200 Subject: [PATCH 6/9] Other error --- neo-cli/CLI/MainService.Network.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo-cli/CLI/MainService.Network.cs b/neo-cli/CLI/MainService.Network.cs index a167f1424..4760f290e 100644 --- a/neo-cli/CLI/MainService.Network.cs +++ b/neo-cli/CLI/MainService.Network.cs @@ -146,7 +146,7 @@ private void OnRelayCommand(JObject jsonObjectToRelay) } catch (Exception e) { - Console.WriteLine($"One or more errors occurred:{Environment.NewLine}{e.Message}"); + Console.WriteLine("Error: " + GetExceptionMessage(e)); } } } From c282e1b1c1fee5134119b4082b47c0d545460eab Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 22 Jul 2020 15:54:46 +0200 Subject: [PATCH 7/9] More errors --- neo-cli/CLI/MainService.Wallet.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo-cli/CLI/MainService.Wallet.cs b/neo-cli/CLI/MainService.Wallet.cs index 5ebc7a728..21da5b546 100644 --- a/neo-cli/CLI/MainService.Wallet.cs +++ b/neo-cli/CLI/MainService.Wallet.cs @@ -378,7 +378,7 @@ private void OnSignCommand(JObject jsonObjectToSign) } catch (Exception e) { - Console.WriteLine($"One or more errors occurred:{Environment.NewLine}{e.Message}"); + Console.WriteLine("Error: " + GetExceptionMessage(e)); } } @@ -525,7 +525,7 @@ private void SignAndSendTx(Transaction tx) } catch (InvalidOperationException ex) { - Console.WriteLine($"Error creating contract params: {ex}"); + Console.WriteLine($"Error creating contract params: " + GetExceptionMessage(e)); throw; } CurrentWallet.Sign(context); From 5feea2cbe99cfd4d48a4b1431015d2936202e8aa Mon Sep 17 00:00:00 2001 From: Shargon Date: Wed, 22 Jul 2020 15:58:51 +0200 Subject: [PATCH 8/9] Remove msg var --- neo-cli/CLI/MainService.Wallet.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/neo-cli/CLI/MainService.Wallet.cs b/neo-cli/CLI/MainService.Wallet.cs index 21da5b546..052363bb7 100644 --- a/neo-cli/CLI/MainService.Wallet.cs +++ b/neo-cli/CLI/MainService.Wallet.cs @@ -529,20 +529,14 @@ private void SignAndSendTx(Transaction tx) throw; } CurrentWallet.Sign(context); - string msg; if (context.Completed) { tx.Witnesses = context.GetWitnesses(); - NeoSystem.Blockchain.Tell(tx); - - msg = $"Signed and relayed transaction with hash={tx.Hash}"; - Console.WriteLine(msg); + Console.WriteLine($"Signed and relayed transaction with hash={tx.Hash}"); return; } - - msg = $"Failed sending transaction with hash={tx.Hash}"; - Console.WriteLine(msg); + Console.WriteLine($"Failed sending transaction with hash={tx.Hash}"); } } } From 544b3302c5c054335657f96f0383578ed55ab8b8 Mon Sep 17 00:00:00 2001 From: Luchuan Date: Fri, 24 Jul 2020 13:37:21 +0800 Subject: [PATCH 9/9] fix --- neo-cli/CLI/MainService.Wallet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo-cli/CLI/MainService.Wallet.cs b/neo-cli/CLI/MainService.Wallet.cs index 052363bb7..c524b3338 100644 --- a/neo-cli/CLI/MainService.Wallet.cs +++ b/neo-cli/CLI/MainService.Wallet.cs @@ -523,7 +523,7 @@ private void SignAndSendTx(Transaction tx) { context = new ContractParametersContext(tx); } - catch (InvalidOperationException ex) + catch (InvalidOperationException e) { Console.WriteLine($"Error creating contract params: " + GetExceptionMessage(e)); throw;