diff --git a/.github/workflows/test-neo-cli.expect b/.github/workflows/test-neo-cli.expect
index dbf41526b..21ee4ceda 100755
--- a/.github/workflows/test-neo-cli.expect
+++ b/.github/workflows/test-neo-cli.expect
@@ -14,6 +14,10 @@ expect {
timeout { exit 1 }
}
+sleep 5
+
+spawn dotnet out/neo-cli.dll
+
#
# Test 'create wallet'
#
diff --git a/Neo.ConsoleService/ConsoleServiceBase.cs b/Neo.ConsoleService/ConsoleServiceBase.cs
index ae55b5fd7..91b02cfd8 100644
--- a/Neo.ConsoleService/ConsoleServiceBase.cs
+++ b/Neo.ConsoleService/ConsoleServiceBase.cs
@@ -291,7 +291,14 @@ public virtual void OnStart(string[] args)
public virtual void OnStop()
{
- _shutdownAcknowledged.Signal();
+ try
+ {
+ _shutdownAcknowledged.Signal();
+ }
+ catch
+ {
+ // ignore
+ }
}
public string ReadUserInput(string prompt, bool password = false)
diff --git a/neo-cli/CLI/MainService.Mode.cs b/neo-cli/CLI/MainService.Mode.cs
new file mode 100644
index 000000000..291450e92
--- /dev/null
+++ b/neo-cli/CLI/MainService.Mode.cs
@@ -0,0 +1,209 @@
+// Copyright (C) 2016-2022 The Neo Project.
+//
+// The neo-cli is free software distributed under the MIT software
+// license, see the accompanying file LICENSE in the main directory of
+// the project or http://www.opensource.org/licenses/mit-license.php
+// for more details.
+//
+// Redistribution and use in source and binary forms with or without
+// modifications are permitted.
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Akka.Util.Internal;
+using Neo.ConsoleService;
+namespace Neo.CLI;
+
+partial class MainService
+{
+ ///
+ /// Process "mode list" command.
+ ///
+ [ConsoleCommand("mode list", Category = "Mode Commands")]
+ private void OnListModes()
+ {
+ try
+ {
+ Directory.GetDirectories(ModePath).ForEach(p => ConsoleHelper.Info(p));
+ }
+ catch (IOException)
+ {
+ }
+ }
+
+ ///
+ /// Process "mode save" command
+ /// Mode name
+ ///
+ [ConsoleCommand("mode save", Category = "Mode Commands")]
+ private void OnSaveMode(string modeName)
+ {
+ // if no mode name assigned
+ if (modeName is null)
+ {
+ ConsoleHelper.Error("No mode name assigned.");
+ return;
+ }
+ modeName = modeName.ToLower();
+ try
+ {
+ var targetMode = new DirectoryInfo($"{ModePath}/{modeName}");
+ // Create the mode if it does not exist
+ if (!targetMode.Exists) Directory.CreateDirectory(targetMode.FullName);
+ // Get the config files of the node
+ MoveModeConfig(modeName.ToLower());
+ var plugins = new DirectoryInfo(PluginPath);
+ // Cache directories before we start copying
+ var dirs = plugins.GetDirectories();
+ // Create an empty .PLUGINS file
+ File.Create($"{ModePath}/{modeName}/.PLUGINS").Close();
+ // Save the Plugin files
+ foreach (var plugin in dirs)
+ {
+ foreach (var file in plugin.GetFiles().Where(p => p.Extension == ".json"))
+ {
+ file.CopyTo($"{ModePath}/{modeName}/{plugin.Name}.json", true);
+ }
+ AddPluginToMode(plugin.Name, modeName);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ ///
+ /// Process "mode delete" command
+ /// Mode name
+ ///
+ [ConsoleCommand("mode delete", Category = "Mode Commands")]
+ private void OnDeleteMode(string modeName)
+ {
+ try
+ {
+ var dir = new DirectoryInfo($"{ModePath}/{modeName.ToLower()}");
+ if (!dir.Exists)
+ return;
+ Directory.Delete(dir.FullName, true);
+ ConsoleHelper.Info("Mode ", modeName, " was deleted.");
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ ///
+ /// Load the target mode, plugin should be according to the mode,
+ /// if the mode contains the plugin, install the plugin, otherwise delete the plugin
+ ///
+ /// name of the mode
+ /// if the mode is not found
+ private async Task LoadMode(string mode)
+ {
+ try
+ {
+ mode = mode.ToLower();
+ var dir = new DirectoryInfo($"{ModePath}/{mode}");
+ if (!dir.Exists)
+ throw new DirectoryNotFoundException($"Mode not found: {dir.FullName}");
+ // Process the plugin
+ var modePlugins = File.ReadAllLines($"{ModePath}/{_currentMode}/.PLUGINS");
+ // loop modePlugins
+ foreach (var pluginName in modePlugins)
+ {
+ // if the plugin is not installed, install it
+ if (!Directory.Exists($"{PluginPath}/{pluginName}/"))
+ {
+ await InstallPluginAsync(pluginName, overWrite: true, saveConfig: false);
+ _needRestart = true;
+ }
+ // if the mode has the plugin config, load the config from the mode
+ if (File.Exists($"{ModePath}/{mode}/{pluginName}.json"))
+ File.Copy($"{ModePath}/{mode}/{pluginName}.json",
+ $"{PluginPath}/{pluginName}/config.json", true);
+ }
+ // get the system config file from the mode
+ MoveModeConfig(mode, false);
+
+ // Get existing plugins and delete them if they are not in the mode
+ new DirectoryInfo($"{PluginPath}/").GetDirectories().ForEach(p =>
+ {
+ if (modePlugins.Any(k => string.Compare(Path.GetFileNameWithoutExtension(k), p.Name, StringComparison.OrdinalIgnoreCase) == 0)
+ || !File.Exists($"{PluginPath}/{p.Name}/config.json")) return;
+ try
+ {
+ ConsoleHelper.Info("Removing plugin ", p.Name);
+ Directory.Delete($"{PluginPath}/{p.Name}", true);
+ _needRestart = true;
+ }
+ catch
+ {
+ // ignored
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ /// save config.json and config.fs.json to the mode directory
+ /// name of the mode
+ ///
+ /// if the mode is not found
+ private static void MoveModeConfig(string mode, bool toMode = true)
+ {
+ var modeDir = new DirectoryInfo($"{ModePath}/{mode.ToLower()}");
+ var configDir = new DirectoryInfo($"{StrExeFilePath}");
+ if (!modeDir.Exists)
+ throw new DirectoryNotFoundException($"Mode not found: {modeDir.FullName}");
+ try
+ {
+ if (toMode)
+ {
+ File.Copy(configDir.FullName + "/config.json",
+ modeDir.FullName + "/config.json", true);
+ File.Copy(configDir.FullName + "/config.fs.json",
+ modeDir.FullName + "/config.fs.json", true);
+ }
+ else
+ {
+ File.Copy(modeDir.FullName + "/config.json",
+ configDir.FullName + "/config.json", true);
+ File.Copy(modeDir.FullName + "/config.fs.json",
+ configDir.FullName + "/config.fs.json", true);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ throw;
+ }
+ }
+
+ // Add plugin to .PLUGINS file
+ private static void AddPluginToMode(string pluginName, string modeName)
+ {
+ var plugins = File.ReadAllLines($"{ModePath}/{modeName}/.PLUGINS");
+ if (plugins.Contains(pluginName)) return;
+ var newPlugins = plugins.Append(pluginName).ToArray();
+ File.WriteAllLines($"{ModePath}/{modeName}/.PLUGINS", newPlugins);
+ }
+
+ // Remove plugin from .PLUGINS file
+ private static void RemovePluginFromMode(string pluginName, string modeName)
+ {
+ var plugins = File.ReadAllLines($"{ModePath}/{modeName}/.PLUGINS");
+ // if (plugins.All(p => !string.Equals(p, pluginName, StringComparison.CurrentCultureIgnoreCase))) return;
+ var newPlugins = plugins.Where(p => !string.Equals(p, pluginName, StringComparison.CurrentCultureIgnoreCase)).ToArray();
+ File.WriteAllLines($"{ModePath}/{modeName}/.PLUGINS", newPlugins);
+ }
+}
diff --git a/neo-cli/CLI/MainService.Plugins.cs b/neo-cli/CLI/MainService.Plugins.cs
index 6373c9c4a..b06cb0877 100644
--- a/neo-cli/CLI/MainService.Plugins.cs
+++ b/neo-cli/CLI/MainService.Plugins.cs
@@ -1,4 +1,5 @@
// Copyright (C) 2016-2023 The Neo Project.
+
// The neo-cli is free software distributed under the MIT software
// license, see the accompanying file LICENSE in the main directory of
// the project or http://www.opensource.org/licenses/mit-license.php
@@ -34,7 +35,7 @@ private async Task OnInstallCommandAsync(string pluginName)
{
if (PluginExists(pluginName))
{
- ConsoleHelper.Warning($"Plugin already exist.");
+ ConsoleHelper.Warning("Plugin already exist.");
return;
}
@@ -119,9 +120,11 @@ private async Task DownloadPluginAsync(string pluginName)
/// Install plugin from stream
///
/// name of the plugin
+ /// installed dependency
/// Install by force for `update`
+ /// Need to save the config file to the mode
private async Task InstallPluginAsync(string pluginName, HashSet installed = null,
- bool overWrite = false)
+ bool overWrite = false, bool saveConfig = true)
{
installed ??= new HashSet();
if (!installed.Add(pluginName)) return;
@@ -140,7 +143,40 @@ private async Task InstallPluginAsync(string pluginName, HashSet install
await using Stream es = entry.Open();
await InstallDependenciesAsync(es, installed);
}
- zip.ExtractToDirectory("./", true);
+ if (!Directory.Exists($"{StrExeFilePath}/Plugins"))
+ {
+ Directory.CreateDirectory($"{StrExeFilePath}/Plugins");
+ }
+ zip.ExtractToDirectory($"{StrExeFilePath}", true);
+ Console.WriteLine();
+
+ if (!saveConfig) return;
+ // Save the config.json to current mode
+ try
+ {
+ var pluginActualName = GetPluginActualName(pluginName);
+ if (File.Exists($"{ModePath}/{_currentMode}/{pluginActualName}.json"))
+ {
+ if (File.Exists($"{PluginPath}/{pluginActualName}/config.json"))
+ // plugin contains config.json && mode contains plugin.json
+ // replace the config.json with plugin.json from mode
+ File.Copy($"{ModePath}/{_currentMode}/{pluginActualName}.json", $"{PluginPath}/{pluginActualName}/config.json", true);
+ else
+ // plugin doesn't contain config.json && mode contains plugin.json
+ // delete the plugin.json from mode
+ File.Delete($"{ModePath}/{_currentMode}/{pluginActualName}.json");
+ }
+ else if (File.Exists($"{PluginPath}/{pluginActualName}/config.json"))
+ // plugin contains config.json && mode doesn't contain plugin.json
+ // copy the config.json to mode
+ File.Copy($"{PluginPath}/{pluginActualName}/config.json", $"{ModePath}/{_currentMode}/{pluginActualName}.json", false);
+ AddPluginToMode(pluginActualName, _currentMode);
+ }
+ catch (Exception e)
+ {
+ // ignored
+ Console.WriteLine(e.Message);
+ }
}
///
@@ -173,7 +209,8 @@ private async Task InstallDependenciesAsync(Stream config, HashSet insta
///
private static bool PluginExists(string pluginName)
{
- return Plugin.Plugins.Any(p => p.Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase));
+ return Plugin.Plugins.Any(p => p.Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase)) ||
+ new DirectoryInfo($"{StrExeFilePath}/Plugins").GetDirectories().Any(p => p.Name.Equals(pluginName, StringComparison.InvariantCultureIgnoreCase));
}
///
@@ -188,12 +225,12 @@ private void OnUnInstallCommand(string pluginName)
ConsoleHelper.Warning("Plugin not found");
return;
}
-
+ pluginName = GetPluginActualName(pluginName);
foreach (var p in Plugin.Plugins)
{
try
{
- using var reader = File.OpenRead($"./Plugins/{p.Name}/config.json");
+ using var reader = File.OpenRead($"{PluginPath}/{p.Name}/config.json");
if (new ConfigurationBuilder()
.AddJsonStream(reader)
.Build()
@@ -214,7 +251,11 @@ private void OnUnInstallCommand(string pluginName)
}
try
{
- Directory.Delete($"Plugins/{pluginName}", true);
+ Directory.Delete($"{PluginPath}/{pluginName}", true);
+ var config = $"{ModePath}/{_currentMode}/{pluginName}.json";
+ if (File.Exists(config))
+ File.Delete(config);
+ RemovePluginFromMode(pluginName, _currentMode);
}
catch (IOException) { }
ConsoleHelper.Info("Uninstall successful, please restart neo-cli.");
@@ -240,5 +281,17 @@ private void OnPluginsCommand()
ConsoleHelper.Warning("No loaded plugins");
}
}
+
+ private static string GetPluginActualName(string pluginName)
+ {
+ var pluginActualName = "";
+ foreach (var plugin in new DirectoryInfo($"{PluginPath}").GetDirectories())
+ {
+ if (!string.Equals(plugin.Name, pluginName, StringComparison.CurrentCultureIgnoreCase)) continue;
+ pluginActualName = plugin.Name;
+ break;
+ }
+ return pluginActualName;
+ }
}
}
diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs
index 74c288757..a64dab410 100644
--- a/neo-cli/CLI/MainService.cs
+++ b/neo-cli/CLI/MainService.cs
@@ -2,9 +2,9 @@
//
// The neo-cli is free software distributed under the MIT software
// license, see the accompanying file LICENSE in the main directory of
-// the project or http://www.opensource.org/licenses/mit-license.php
+// the project or http://www.opensource.org/licenses/mit-license.php
// for more details.
-//
+//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.
@@ -46,6 +46,13 @@ public partial class MainService : ConsoleServiceBase, IWalletProvider
private Wallet _currentWallet;
public LocalNode LocalNode;
+ private static string _currentMode = "mainnet";
+ private bool _needRestart = false;
+
+ static readonly string StrExeFilePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
+ static readonly string ModePath = Path.Combine(StrExeFilePath, "Modes");
+ static readonly string PluginPath = Path.Combine(StrExeFilePath, "Plugins");
+
public Wallet CurrentWallet
{
@@ -372,6 +379,8 @@ public async void Start(string[] args)
{
if (NeoSystem != null) return;
bool verifyImport = true;
+ // set mainnet as default mode
+ string mode = "mainnet";
for (int i = 0; i < args.Length; i++)
switch (args[i])
{
@@ -379,7 +388,36 @@ public async void Start(string[] args)
case "--noverify":
verifyImport = false;
break;
+ case "--mode":
+ case "/mode":
+ {
+ if (i < args.Length - 1)
+ {
+ i++;
+ // Get all the modes
+ var modes = Directory.GetDirectories($"{ModePath}/");
+ // Find the expected mode
+ if (modes.Any(p => string.Equals(new DirectoryInfo(p).Name, args[i], StringComparison.CurrentCultureIgnoreCase)))
+ {
+ mode = args[i].ToLower();
+ _currentMode = mode;
+ }
+ else
+ {
+ throw new Exception($"Invalid Mode {args[i]}.");
+ }
+ }
+ }
+ break;
}
+ // Load the mode (network)
+ await LoadMode(mode);
+ if (_needRestart)
+ {
+ ConsoleHelper.Warning("Please restart the node to apply the changes.");
+ OnStop();
+ return;
+ }
ProtocolSettings protocol = ProtocolSettings.Load("config.json");
@@ -391,7 +429,6 @@ public async void Start(string[] args)
foreach (var plugin in Plugin.Plugins)
{
// Register plugins commands
-
RegisterCommand(plugin, plugin.Name);
}
diff --git a/neo-cli/Modes/mainnet/.PLUGINS b/neo-cli/Modes/mainnet/.PLUGINS
new file mode 100644
index 000000000..3e16d9f30
--- /dev/null
+++ b/neo-cli/Modes/mainnet/.PLUGINS
@@ -0,0 +1 @@
+LevelDBStore
diff --git a/neo-cli/config.fs.mainnet.json b/neo-cli/Modes/mainnet/config.fs.json
similarity index 100%
rename from neo-cli/config.fs.mainnet.json
rename to neo-cli/Modes/mainnet/config.fs.json
diff --git a/neo-cli/config.mainnet.json b/neo-cli/Modes/mainnet/config.json
similarity index 100%
rename from neo-cli/config.mainnet.json
rename to neo-cli/Modes/mainnet/config.json
diff --git a/neo-cli/Modes/privatenet/.PLUGINS b/neo-cli/Modes/privatenet/.PLUGINS
new file mode 100644
index 000000000..61c2a05da
--- /dev/null
+++ b/neo-cli/Modes/privatenet/.PLUGINS
@@ -0,0 +1,4 @@
+LevelDBStore
+RpcServer
+ApplicationLogs
+DBFTPlugin
diff --git a/neo-cli/Modes/privatenet/NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP.json b/neo-cli/Modes/privatenet/NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP.json
new file mode 100644
index 000000000..823a076be
--- /dev/null
+++ b/neo-cli/Modes/privatenet/NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP.json
@@ -0,0 +1 @@
+{"extra":{},"scrypt":{"r":8,"p":8,"n":16384,"size":64},"name":"NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP","accounts":[{"address":"NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP","extra":{},"lock":false,"contract":{"script":"DCED7s02MiDW5N55Or\/rrgl3l2hGjFmjtuATKp6jsiAQ99hBVuezJw==","deployed":false,"parameters":[{"name":"signature","type":"Signature"}]},"label":"NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP","key":"6PYTrLoLMT1Ms1H2msFTGUDRhHKXsZWA2Lj5rcF2GdPJju1Nuqy4npbef4","isDefault":true}],"version":"1.0"}
diff --git a/neo-cli/Modes/privatenet/config.fs.json b/neo-cli/Modes/privatenet/config.fs.json
new file mode 100644
index 000000000..dadf6f5bf
--- /dev/null
+++ b/neo-cli/Modes/privatenet/config.fs.json
@@ -0,0 +1,53 @@
+{
+ "ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs",
+ "ConsoleOutput": false,
+ "Active": false
+ },
+ "Storage": {
+ "Engine": "LevelDBStore",
+ "Path": "Data_LevelDB_{0}"
+ },
+ "P2P": {
+ "Port": 40333,
+ "WsPort": 40334,
+ "MinDesiredConnections": 10,
+ "MaxConnections": 40,
+ "MaxConnectionsPerAddress": 3
+ },
+ "UnlockWallet": {
+ "Path": "",
+ "Password": "",
+ "IsActive": false
+ }
+ },
+ "ProtocolConfiguration": {
+ "Network": 91414437,
+ "AddressVersion": 53,
+ "MillisecondsPerBlock": 15000,
+ "MaxTransactionsPerBlock": 512,
+ "MemoryPoolMaxTransactions": 50000,
+ "MaxTraceableBlocks": 2102400,
+ "InitialGasDistribution": 5200000000000000,
+ "ValidatorsCount": 7,
+ "StandbyCommittee": [
+ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086",
+ "039a9db2a30942b1843db673aeb0d4fd6433f74cec1d879de6343cb9fcf7628fa4",
+ "0366d255e7ce23ea6f7f1e4bedf5cbafe598705b47e6ec213ef13b2f0819e8ab33",
+ "023f9cb7bbe154d529d5c719fdc39feaa831a43ae03d2a4280575b60f52fa7bc52",
+ "039ba959e0ab6dc616df8b803692f1c30ba9071b76b05535eb994bf5bbc402ad5f",
+ "035a2a18cddafa25ad353dea5e6730a1b9fcb4b918c4a0303c4387bb9c3b816adf",
+ "031f4d9c66f2ec348832c48fd3a16dfaeb59e85f557ae1e07f6696d0375c64f97b"
+ ],
+ "SeedList": [
+ "morph1.fs.neo.org:40333",
+ "morph2.fs.neo.org:40333",
+ "morph3.fs.neo.org:40333",
+ "morph4.fs.neo.org:40333",
+ "morph5.fs.neo.org:40333",
+ "morph6.fs.neo.org:40333",
+ "morph7.fs.neo.org:40333"
+ ]
+ }
+}
diff --git a/neo-cli/Modes/privatenet/config.json b/neo-cli/Modes/privatenet/config.json
new file mode 100644
index 000000000..05656f76e
--- /dev/null
+++ b/neo-cli/Modes/privatenet/config.json
@@ -0,0 +1,39 @@
+{
+ "ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs",
+ "ConsoleOutput": true,
+ "Active": true
+ },
+ "Storage": {
+ "Engine": "LevelDBStore",
+ "Path": "Data_LevelDB_{0}"
+ },
+ "P2P": {
+ "Port": 10333,
+ "WsPort": 10334,
+ "MinDesiredConnections": 10,
+ "MaxConnections": 40,
+ "MaxConnectionsPerAddress": 3
+ },
+ "UnlockWallet": {
+ "Path": "Modes/privatenet/NbVj8GhwToNv4WF2gVaoco6hbkMQ8hrHWP.json",
+ "Password": "12345678",
+ "IsActive": true
+ }
+ },
+ "ProtocolConfiguration": {
+ "Network": 582277343,
+ "AddressVersion": 53,
+ "MillisecondsPerBlock": 15000,
+ "MaxTransactionsPerBlock": 512,
+ "MemoryPoolMaxTransactions": 50000,
+ "MaxTraceableBlocks": 2102400,
+ "InitialGasDistribution": 5200000000000000,
+ "ValidatorsCount": 1,
+ "StandbyCommittee": [
+ "03eecd363220d6e4de793abfebae09779768468c59a3b6e0132a9ea3b22010f7d8"
+ ],
+ "SeedList": []
+ }
+}
diff --git a/neo-cli/Modes/testnet/.PLUGINS b/neo-cli/Modes/testnet/.PLUGINS
new file mode 100644
index 000000000..3e16d9f30
--- /dev/null
+++ b/neo-cli/Modes/testnet/.PLUGINS
@@ -0,0 +1 @@
+LevelDBStore
diff --git a/neo-cli/config.fs.testnet.json b/neo-cli/Modes/testnet/config.fs.json
similarity index 100%
rename from neo-cli/config.fs.testnet.json
rename to neo-cli/Modes/testnet/config.fs.json
diff --git a/neo-cli/config.testnet.json b/neo-cli/Modes/testnet/config.json
similarity index 100%
rename from neo-cli/config.testnet.json
rename to neo-cli/Modes/testnet/config.json
diff --git a/neo-cli/config.fs.json b/neo-cli/config.fs.json
new file mode 100644
index 000000000..94fb94a2a
--- /dev/null
+++ b/neo-cli/config.fs.json
@@ -0,0 +1,53 @@
+{
+ "ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs",
+ "ConsoleOutput": false,
+ "Active": false
+ },
+ "Storage": {
+ "Engine": "LevelDBStore",
+ "Path": "Data_LevelDB_{0}"
+ },
+ "P2P": {
+ "Port": 40333,
+ "WsPort": 40334,
+ "MinDesiredConnections": 10,
+ "MaxConnections": 40,
+ "MaxConnectionsPerAddress": 3
+ },
+ "UnlockWallet": {
+ "Path": "",
+ "Password": "",
+ "IsActive": false
+ }
+ },
+ "ProtocolConfiguration": {
+ "Network": 91414437,
+ "AddressVersion": 53,
+ "MillisecondsPerBlock": 15000,
+ "MaxTransactionsPerBlock": 512,
+ "MemoryPoolMaxTransactions": 50000,
+ "MaxTraceableBlocks": 2102400,
+ "InitialGasDistribution": 5200000000000000,
+ "ValidatorsCount": 7,
+ "StandbyCommittee": [
+ "026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086",
+ "039a9db2a30942b1843db673aeb0d4fd6433f74cec1d879de6343cb9fcf7628fa4",
+ "0366d255e7ce23ea6f7f1e4bedf5cbafe598705b47e6ec213ef13b2f0819e8ab33",
+ "023f9cb7bbe154d529d5c719fdc39feaa831a43ae03d2a4280575b60f52fa7bc52",
+ "039ba959e0ab6dc616df8b803692f1c30ba9071b76b05535eb994bf5bbc402ad5f",
+ "035a2a18cddafa25ad353dea5e6730a1b9fcb4b918c4a0303c4387bb9c3b816adf",
+ "031f4d9c66f2ec348832c48fd3a16dfaeb59e85f557ae1e07f6696d0375c64f97b"
+ ],
+ "SeedList": [
+ "morph1.fs.neo.org:40333",
+ "morph2.fs.neo.org:40333",
+ "morph3.fs.neo.org:40333",
+ "morph4.fs.neo.org:40333",
+ "morph5.fs.neo.org:40333",
+ "morph6.fs.neo.org:40333",
+ "morph7.fs.neo.org:40333"
+ ]
+ }
+}
diff --git a/neo-cli/neo-cli.csproj b/neo-cli/neo-cli.csproj
index 331b60d8b..d6c21172e 100644
--- a/neo-cli/neo-cli.csproj
+++ b/neo-cli/neo-cli.csproj
@@ -17,14 +17,15 @@
-
+
+ PreserveNewest
+ PreserveNewest
+ Modes\%(RecursiveDir)\%(Filename)%(Extension)
+
-
- PreserveNewest
- PreserveNewest
-
+
@@ -34,5 +35,4 @@
-