From 67e0949b2534eac47f86c597a94295b531fde581 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Sat, 29 Jun 2024 23:02:55 +0800 Subject: [PATCH 1/3] build the structure. --- SpellingExclusions.dic | 2 + neo.sln | 28 +++- src/Neo.Extensions/AssemblyUtility.cs | 25 ++++ src/Neo.Extensions/LogLevel.cs | 7 +- .../Buffers/MemoryPoolBlock.cs | 44 ++++++ .../Buffers/PinnedBlockMemoryPool.cs | 68 +++++++++ src/Neo.Hosting.App/Buffers/Struffer.cs | 136 ++++++++++++++++++ .../Host/LoggerCategoryDefaults.cs | 19 +++ src/Neo.Hosting.App/Host/NeoDefaults.cs | 18 +++ .../Host/NeoEnvironmentVariableDefaults.cs | 20 +++ .../Host/NeoHostingEnvironments.cs | 25 ++++ .../Host/NeoJsonSectionNameDefaults.cs | 25 ++++ .../Host/NeoProtocolSettingsDefaults.cs | 120 ++++++++++++++++ src/Neo.Hosting.App/Neo.Hosting.App.csproj | 62 ++++++++ src/Neo.Hosting.App/Program.cs | 42 ++++++ src/Neo.Hosting.App/config.localnet.json | 83 +++++++++++ src/Neo.Hosting.App/config.mainnet.json | 54 +++++++ src/Neo.Hosting.App/config.testnet.json | 57 ++++++++ src/Neo/Cryptography/Crc32.cs | 116 +++++++++++++++ src/Neo/Neo.csproj | 2 + .../Neo.Hosting.App.Tests.csproj | 32 +++++ .../DataCases/TestMemberDataCases.cs | 43 ++++++ .../UTHelpers/Default/TestBlockchain.cs | 53 +++++++ .../UTHelpers/Default/TestProtocolSettings.cs | 70 +++++++++ .../UTHelpers/Logging/TestLogger.cs | 43 ++++++ .../UTHelpers/Logging/TestLoggerProvider.cs | 43 ++++++ .../UTHelpers/Logging/TestTextWriter.cs | 103 +++++++++++++ .../SetupClasses/TestSetupLogging.cs | 54 +++++++ tests/Neo.UnitTests/Cryptography/UT_Crc32.cs | 44 ++++++ 29 files changed, 1430 insertions(+), 8 deletions(-) create mode 100644 src/Neo.Extensions/AssemblyUtility.cs create mode 100644 src/Neo.Hosting.App/Buffers/MemoryPoolBlock.cs create mode 100644 src/Neo.Hosting.App/Buffers/PinnedBlockMemoryPool.cs create mode 100644 src/Neo.Hosting.App/Buffers/Struffer.cs create mode 100644 src/Neo.Hosting.App/Host/LoggerCategoryDefaults.cs create mode 100644 src/Neo.Hosting.App/Host/NeoDefaults.cs create mode 100644 src/Neo.Hosting.App/Host/NeoEnvironmentVariableDefaults.cs create mode 100644 src/Neo.Hosting.App/Host/NeoHostingEnvironments.cs create mode 100644 src/Neo.Hosting.App/Host/NeoJsonSectionNameDefaults.cs create mode 100644 src/Neo.Hosting.App/Host/NeoProtocolSettingsDefaults.cs create mode 100644 src/Neo.Hosting.App/Neo.Hosting.App.csproj create mode 100644 src/Neo.Hosting.App/Program.cs create mode 100644 src/Neo.Hosting.App/config.localnet.json create mode 100644 src/Neo.Hosting.App/config.mainnet.json create mode 100644 src/Neo.Hosting.App/config.testnet.json create mode 100644 src/Neo/Cryptography/Crc32.cs create mode 100644 tests/Neo.Hosting.App.Tests/Neo.Hosting.App.Tests.csproj create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/DataCases/TestMemberDataCases.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestBlockchain.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestProtocolSettings.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLogger.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLoggerProvider.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestTextWriter.cs create mode 100644 tests/Neo.Hosting.App.Tests/UTHelpers/SetupClasses/TestSetupLogging.cs create mode 100644 tests/Neo.UnitTests/Cryptography/UT_Crc32.cs diff --git a/SpellingExclusions.dic b/SpellingExclusions.dic index e69de29bb2..f186c01c26 100644 --- a/SpellingExclusions.dic +++ b/SpellingExclusions.dic @@ -0,0 +1,2 @@ +barc +scripthash diff --git a/neo.sln b/neo.sln index b0de1c27b1..4ef3a10680 100644 --- a/neo.sln +++ b/neo.sln @@ -40,6 +40,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.IO", "src\Neo.IO\Neo.IO EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Extensions", "src\Neo.Extensions\Neo.Extensions.csproj", "{9C5213D6-3833-4570-8AE2-47E9F9017A8F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Hosting.App", "src\Neo.Hosting.App\Neo.Hosting.App.csproj", "{DF99D759-46D5-4CDB-89CB-EF56DC9728DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Hosting.App.Tests", "tests\Neo.Hosting.App.Tests\Neo.Hosting.App.Tests.csproj", "{FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "plugins", "plugins", "{C2DC830A-327A-42A7-807D-295216D30DBB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Cryptography.MPTTrie.Tests", "tests\Neo.Cryptography.MPTTrie.Tests\Neo.Cryptography.MPTTrie.Tests.csproj", "{FAF5D8AC-B6B3-4CD4-879D-0E5F6211480F}" @@ -50,8 +54,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.OracleService.T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.RpcServer.Tests", "tests\Neo.Plugins.RpcServer.Tests\Neo.Plugins.RpcServer.Tests.csproj", "{2CBD2311-BA2E-4921-A000-FDDA59B74958}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.Storage.Tests", "tests\Neo.Plugins.Storage.Tests\Neo.Plugins.Storage.Tests.csproj", "{EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{7F257712-D033-47FF-B439-9D4320D06599}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationLogs", "src\Plugins\ApplicationLogs\ApplicationLogs.csproj", "{22E2CE64-080B-4138-885F-7FA74A9159FB}" @@ -78,6 +80,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TokensTracker", "src\Plugin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcClient", "src\Plugins\RpcClient\RpcClient.csproj", "{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neo.Plugins.Storage.Tests", "tests\Neo.Plugins.Storage.Tests\Neo.Plugins.Storage.Tests.csproj", "{9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -148,6 +152,14 @@ Global {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU {9C5213D6-3833-4570-8AE2-47E9F9017A8F}.Release|Any CPU.Build.0 = Release|Any CPU + {DF99D759-46D5-4CDB-89CB-EF56DC9728DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF99D759-46D5-4CDB-89CB-EF56DC9728DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF99D759-46D5-4CDB-89CB-EF56DC9728DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF99D759-46D5-4CDB-89CB-EF56DC9728DA}.Release|Any CPU.Build.0 = Release|Any CPU + {FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228}.Release|Any CPU.Build.0 = Release|Any CPU {FAF5D8AC-B6B3-4CD4-879D-0E5F6211480F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FAF5D8AC-B6B3-4CD4-879D-0E5F6211480F}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAF5D8AC-B6B3-4CD4-879D-0E5F6211480F}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -164,10 +176,6 @@ Global {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Debug|Any CPU.Build.0 = Debug|Any CPU {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|Any CPU.ActiveCfg = Release|Any CPU {2CBD2311-BA2E-4921-A000-FDDA59B74958}.Release|Any CPU.Build.0 = Release|Any CPU - {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C}.Release|Any CPU.Build.0 = Release|Any CPU {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {22E2CE64-080B-4138-885F-7FA74A9159FB}.Debug|Any CPU.Build.0 = Debug|Any CPU {22E2CE64-080B-4138-885F-7FA74A9159FB}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -216,6 +224,10 @@ Global {185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Release|Any CPU.ActiveCfg = Release|Any CPU {185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Release|Any CPU.Build.0 = Release|Any CPU + {9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -237,11 +249,12 @@ Global {387CCF6C-9A26-43F6-A639-0A82E91E10D8} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} {4CDAC1AA-45C6-4157-8D8E-199050433048} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} {9C5213D6-3833-4570-8AE2-47E9F9017A8F} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {DF99D759-46D5-4CDB-89CB-EF56DC9728DA} = {B5339DF7-5D1D-43BA-B332-74B825E1770E} + {FB1FA9F6-B6B4-48B7-A522-1FAF55DFB228} = {EDE05FA8-8E73-4924-BC63-DD117127EEE1} {FAF5D8AC-B6B3-4CD4-879D-0E5F6211480F} = {7F257712-D033-47FF-B439-9D4320D06599} {0E92F219-1225-4DD0-8C4A-98840985D59C} = {7F257712-D033-47FF-B439-9D4320D06599} {5D9764FB-827D-4DDE-84E3-3C05FD8ABC89} = {7F257712-D033-47FF-B439-9D4320D06599} {2CBD2311-BA2E-4921-A000-FDDA59B74958} = {7F257712-D033-47FF-B439-9D4320D06599} - {EF01E062-DBBC-47AF-AF3B-9EDEB00CFF7C} = {7F257712-D033-47FF-B439-9D4320D06599} {7F257712-D033-47FF-B439-9D4320D06599} = {C2DC830A-327A-42A7-807D-295216D30DBB} {22E2CE64-080B-4138-885F-7FA74A9159FB} = {C2DC830A-327A-42A7-807D-295216D30DBB} {4C39E872-FC37-4BFD-AE4C-3E3F0546B726} = {C2DC830A-327A-42A7-807D-295216D30DBB} @@ -255,6 +268,7 @@ Global {FF76D8A4-356B-461A-8471-BC1B83E57BBC} = {C2DC830A-327A-42A7-807D-295216D30DBB} {5E4947F3-05D3-4806-B0F3-30DAC71B5986} = {C2DC830A-327A-42A7-807D-295216D30DBB} {185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0} = {C2DC830A-327A-42A7-807D-295216D30DBB} + {9B6BC5EC-EC11-408C-BFBA-C7ABD732F5B8} = {7F257712-D033-47FF-B439-9D4320D06599} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC} diff --git a/src/Neo.Extensions/AssemblyUtility.cs b/src/Neo.Extensions/AssemblyUtility.cs new file mode 100644 index 0000000000..f7cc10678b --- /dev/null +++ b/src/Neo.Extensions/AssemblyUtility.cs @@ -0,0 +1,25 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// AssemblyUtility.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Reflection; + +namespace Neo.Extensions +{ + public static class AssemblyUtility + { + public static int GetVersionNumber() + { + var version = Assembly.GetCallingAssembly().GetName().Version; + if (version is null) return 0; + return version.Major * 1000 + version.Minor * 100 + version.Build * 10 + version.Revision; + } + } +} diff --git a/src/Neo.Extensions/LogLevel.cs b/src/Neo.Extensions/LogLevel.cs index 5e3acca37c..5dc3bf81f1 100644 --- a/src/Neo.Extensions/LogLevel.cs +++ b/src/Neo.Extensions/LogLevel.cs @@ -41,6 +41,11 @@ public enum LogLevel : byte /// /// The fatal log level. /// - Fatal = Error + 1 + Fatal = Error + 1, + + /// + /// The trace log level. + /// + Trace = Fatal + 1, } } diff --git a/src/Neo.Hosting.App/Buffers/MemoryPoolBlock.cs b/src/Neo.Hosting.App/Buffers/MemoryPoolBlock.cs new file mode 100644 index 0000000000..98f1d3dc08 --- /dev/null +++ b/src/Neo.Hosting.App/Buffers/MemoryPoolBlock.cs @@ -0,0 +1,44 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// MemoryPoolBlock.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Buffers; +using System.Runtime.InteropServices; + +namespace Neo.Hosting.App.Buffers +{ + internal sealed class MemoryPoolBlock : IMemoryOwner + { + public PinnedBlockMemoryPool Pool { get; } + + internal MemoryPoolBlock( + PinnedBlockMemoryPool pool, + int length) + { + Pool = pool; + + var pinnedArray = GC.AllocateUninitializedArray(length, pinned: true); + + Memory = MemoryMarshal.CreateFromPinnedArray(pinnedArray, 0, pinnedArray.Length); + } + + #region IMemoryOwner + + public Memory Memory { get; } + + void IDisposable.Dispose() + { + Pool.Return(this); + } + + #endregion + } +} diff --git a/src/Neo.Hosting.App/Buffers/PinnedBlockMemoryPool.cs b/src/Neo.Hosting.App/Buffers/PinnedBlockMemoryPool.cs new file mode 100644 index 0000000000..9881d8b8b9 --- /dev/null +++ b/src/Neo.Hosting.App/Buffers/PinnedBlockMemoryPool.cs @@ -0,0 +1,68 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// PinnedBlockMemoryPool.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Buffers; +using System.Collections.Concurrent; + +namespace Neo.Hosting.App.Buffers +{ + internal sealed class PinnedBlockMemoryPool : MemoryPool + { + private const int AnySize = -1; + + private static readonly int s_blockSize = 4096; + + public static int BlockSize => s_blockSize; + + public override int MaxBufferSize { get; } = s_blockSize; + + private readonly ConcurrentQueue _blocks = new(); + private readonly object _disposedSync = new(); + + private bool _isDisposed; + + public override IMemoryOwner Rent(int size = AnySize) + { + ArgumentOutOfRangeException.ThrowIfGreaterThan(size, s_blockSize); + ObjectDisposedException.ThrowIf(_isDisposed, this); + + if (_blocks.TryDequeue(out var block)) + return block; + + return new MemoryPoolBlock(this, BlockSize); + } + + internal void Return(MemoryPoolBlock block) + { + if (_isDisposed == false) + _blocks.Enqueue(block); + } + + protected override void Dispose(bool disposing) + { + if (_isDisposed) + return; + + lock (_disposedSync) + { + _isDisposed = true; + + if (disposing) + { + while (_blocks.TryDequeue(out _)) + { + } + } + } + } + } +} diff --git a/src/Neo.Hosting.App/Buffers/Struffer.cs b/src/Neo.Hosting.App/Buffers/Struffer.cs new file mode 100644 index 0000000000..d9a56a1cda --- /dev/null +++ b/src/Neo.Hosting.App/Buffers/Struffer.cs @@ -0,0 +1,136 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// Struffer.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Collections; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Neo.Hosting.App.Buffers +{ + /// + /// Structure byte buffer + /// + internal sealed class Struffer : IEnumerable + { + private static readonly UTF8Encoding s_utf8NoBom = new(false, true); + + private byte[] _data; + + public int Position { get; set; } + + public Struffer() + { + _data = []; + Position = 0; + } + + public Struffer(byte[] buffer) + { + _data = buffer; + } + + public Struffer(int capacity) + { + _data = GC.AllocateUninitializedArray(capacity); + Position = 0; + } + + public static int SizeOf(string value) => + s_utf8NoBom.GetByteCount(value) + sizeof(int); + + public Struffer Write(T value) + where T : unmanaged + { + var typeSize = Unsafe.SizeOf(); + + if (Position + typeSize > _data.Length) + Array.Resize(ref _data, _data.Length + typeSize); + + Unsafe.As(ref _data[Position]) = value; + + Position += typeSize; + return this; + } + + public Struffer Write(T[] values) + where T : unmanaged + { + Write(values.Length); + foreach (var value in values) + Write(value); + return this; + } + + public Struffer Write(string value) + { + var strByteCount = s_utf8NoBom.GetByteCount(value); + Write(strByteCount); + + if (Position + strByteCount > _data.Length) + Array.Resize(ref _data, _data.Length + strByteCount); + + Position += s_utf8NoBom.GetBytes(value, _data.AsSpan(Position)); + return this; + } + + public T Read() + where T : unmanaged + { + var typeSize = Unsafe.SizeOf(); + + if (Position + typeSize > _data.Length) + throw new IndexOutOfRangeException(); + + var value = Unsafe.As(ref _data[Position]); + Position += typeSize; + + return value; + } + + public T[] ReadArray() + where T : unmanaged + { + var length = Read(); + var values = new T[length]; + for (var i = 0; i < length; i++) + values[i] = Read(); + return values; + } + + public string ReadString() + { + var strByteCount = Read(); + + if (Position + strByteCount > _data.Length) + throw new IndexOutOfRangeException(); + + var value = s_utf8NoBom.GetString(_data, Position, strByteCount); + Position += strByteCount; + + return value; + } + + #region IEnumerable + + public IEnumerator GetEnumerator() + { + foreach (var b in _data) + yield return b; + } + + IEnumerator IEnumerable.GetEnumerator() => + GetEnumerator(); + + #endregion + } +} diff --git a/src/Neo.Hosting.App/Host/LoggerCategoryDefaults.cs b/src/Neo.Hosting.App/Host/LoggerCategoryDefaults.cs new file mode 100644 index 0000000000..ed7f5e6aa0 --- /dev/null +++ b/src/Neo.Hosting.App/Host/LoggerCategoryDefaults.cs @@ -0,0 +1,19 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// LoggerCategoryDefaults.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Host +{ + internal static class LoggerCategoryDefaults + { + public static readonly string RemoteManagement = "Remote.Management"; + public static readonly string NeoSystemService = $"{typeof(NeoSystem).Name}Service"; + } +} diff --git a/src/Neo.Hosting.App/Host/NeoDefaults.cs b/src/Neo.Hosting.App/Host/NeoDefaults.cs new file mode 100644 index 0000000000..6da3601936 --- /dev/null +++ b/src/Neo.Hosting.App/Host/NeoDefaults.cs @@ -0,0 +1,18 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoDefaults.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Host +{ + internal static class NeoDefaults + { + public static readonly string StoreProviderName = "MemoryStore"; + } +} diff --git a/src/Neo.Hosting.App/Host/NeoEnvironmentVariableDefaults.cs b/src/Neo.Hosting.App/Host/NeoEnvironmentVariableDefaults.cs new file mode 100644 index 0000000000..1cbc16478d --- /dev/null +++ b/src/Neo.Hosting.App/Host/NeoEnvironmentVariableDefaults.cs @@ -0,0 +1,20 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoEnvironmentVariableDefaults.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Host +{ + internal static class NeoEnvironmentVariableDefaults + { + public const string PREFIX = "NEO_"; + public static readonly string PipeName = $"{PREFIX}_NAMEDPIPE__NAME"; + public static readonly string Environment = $"{PREFIX}ENVIRONMENT"; + } +} diff --git a/src/Neo.Hosting.App/Host/NeoHostingEnvironments.cs b/src/Neo.Hosting.App/Host/NeoHostingEnvironments.cs new file mode 100644 index 0000000000..4fc25ea874 --- /dev/null +++ b/src/Neo.Hosting.App/Host/NeoHostingEnvironments.cs @@ -0,0 +1,25 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoHostingEnvironments.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Host +{ + internal static class NeoHostingEnvironments + { + public static readonly string LocalNet = "localnet"; + + public static readonly string TestNet = "testnet"; + + public static readonly string MainNet = "mainnet"; + + public static readonly string PrivateNet = "privatenet"; + + } +} diff --git a/src/Neo.Hosting.App/Host/NeoJsonSectionNameDefaults.cs b/src/Neo.Hosting.App/Host/NeoJsonSectionNameDefaults.cs new file mode 100644 index 0000000000..14e291a9ae --- /dev/null +++ b/src/Neo.Hosting.App/Host/NeoJsonSectionNameDefaults.cs @@ -0,0 +1,25 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoJsonSectionNameDefaults.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Host +{ + internal class NeoJsonSectionNameDefaults + { + public static readonly string Application = "ApplicationConfiguration"; + public static readonly string Archive = "Archive"; + public static readonly string Contract = "Contract"; + public static readonly string NamedPipeTransport = "NamedPipeTransport"; + public static readonly string PeerToPeer = "P2P"; + public static readonly string Plugin = "Plugin"; + public static readonly string Remote = "Remote"; + public static readonly string Storage = "Storage"; + } +} diff --git a/src/Neo.Hosting.App/Host/NeoProtocolSettingsDefaults.cs b/src/Neo.Hosting.App/Host/NeoProtocolSettingsDefaults.cs new file mode 100644 index 0000000000..81246732be --- /dev/null +++ b/src/Neo.Hosting.App/Host/NeoProtocolSettingsDefaults.cs @@ -0,0 +1,120 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoProtocolSettingsDefaults.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.Cryptography.ECC; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Neo.Hosting.App.Host +{ + internal class NeoProtocolSettingsDefaults + { + public static ProtocolSettings MainNet = new() + { + Network = 860833102u, + AddressVersion = 53, + MillisecondsPerBlock = 15_000u, + MaxTransactionsPerBlock = 512u, + MemoryPoolMaxTransactions = 50_000, + MaxTraceableBlocks = 2_102_400u, + InitialGasDistribution = 5_200_000_000_000_000ul, + ValidatorsCount = 7, + StandbyCommittee = [ + // Validators + ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1), + ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", ECCurve.Secp256r1), + ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", ECCurve.Secp256r1), + ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", ECCurve.Secp256r1), + ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", ECCurve.Secp256r1), + ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", ECCurve.Secp256r1), + ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", ECCurve.Secp256r1), + // Other Members + ECPoint.Parse("023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", ECCurve.Secp256r1), + ECPoint.Parse("03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", ECCurve.Secp256r1), + ECPoint.Parse("03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", ECCurve.Secp256r1), + ECPoint.Parse("03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", ECCurve.Secp256r1), + ECPoint.Parse("02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", ECCurve.Secp256r1), + ECPoint.Parse("03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", ECCurve.Secp256r1), + ECPoint.Parse("0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", ECCurve.Secp256r1), + ECPoint.Parse("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", ECCurve.Secp256r1), + ECPoint.Parse("0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", ECCurve.Secp256r1), + ECPoint.Parse("03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", ECCurve.Secp256r1), + ECPoint.Parse("02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", ECCurve.Secp256r1), + ECPoint.Parse("0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", ECCurve.Secp256r1), + ECPoint.Parse("03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", ECCurve.Secp256r1), + ECPoint.Parse("02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a", ECCurve.Secp256r1) + ], + SeedList = [ + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + ], + Hardforks = new Dictionary() + { + [Hardfork.HF_Aspidochelone] = 1_730_000u, + [Hardfork.HF_Basilisk] = 4_120_000u, + [Hardfork.HF_Cockatrice] = 5_450_000u, + }.ToImmutableDictionary(), + }; + + public static ProtocolSettings TestNet = new() + { + Network = 894710606u, + AddressVersion = 53, + MillisecondsPerBlock = 15_000u, + MaxTransactionsPerBlock = 5_000u, + MemoryPoolMaxTransactions = 50_000, + MaxTraceableBlocks = 2_102_400u, + InitialGasDistribution = 5_200_000_000_000_000ul, + ValidatorsCount = 7, + StandbyCommittee = [ + // Validators + ECPoint.Parse("023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", ECCurve.Secp256r1), + ECPoint.Parse("03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", ECCurve.Secp256r1), + ECPoint.Parse("02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", ECCurve.Secp256r1), + ECPoint.Parse("03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", ECCurve.Secp256r1), + ECPoint.Parse("02a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b", ECCurve.Secp256r1), + ECPoint.Parse("0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01", ECCurve.Secp256r1), + ECPoint.Parse("030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba", ECCurve.Secp256r1), + // Other Members + ECPoint.Parse("025831cee3708e87d78211bec0d1bfee9f4c85ae784762f042e7f31c0d40c329b8", ECCurve.Secp256r1), + ECPoint.Parse("02cf9dc6e85d581480d91e88e8cbeaa0c153a046e89ded08b4cefd851e1d7325b5", ECCurve.Secp256r1), + ECPoint.Parse("03840415b0a0fcf066bcc3dc92d8349ebd33a6ab1402ef649bae00e5d9f5840828", ECCurve.Secp256r1), + ECPoint.Parse("026328aae34f149853430f526ecaa9cf9c8d78a4ea82d08bdf63dd03c4d0693be6", ECCurve.Secp256r1), + ECPoint.Parse("02c69a8d084ee7319cfecf5161ff257aa2d1f53e79bf6c6f164cff5d94675c38b3", ECCurve.Secp256r1), + ECPoint.Parse("0207da870cedb777fceff948641021714ec815110ca111ccc7a54c168e065bda70", ECCurve.Secp256r1), + ECPoint.Parse("035056669864feea401d8c31e447fb82dd29f342a9476cfd449584ce2a6165e4d7", ECCurve.Secp256r1), + ECPoint.Parse("0370c75c54445565df62cfe2e76fbec4ba00d1298867972213530cae6d418da636", ECCurve.Secp256r1), + ECPoint.Parse("03957af9e77282ae3263544b7b2458903624adc3f5dee303957cb6570524a5f254", ECCurve.Secp256r1), + ECPoint.Parse("03d84d22b8753cf225d263a3a782a4e16ca72ef323cfde04977c74f14873ab1e4c", ECCurve.Secp256r1), + ECPoint.Parse("02147c1b1d5728e1954958daff2f88ee2fa50a06890a8a9db3fa9e972b66ae559f", ECCurve.Secp256r1), + ECPoint.Parse("03c609bea5a4825908027e4ab217e7efc06e311f19ecad9d417089f14927a173d5", ECCurve.Secp256r1), + ECPoint.Parse("0231edee3978d46c335e851c76059166eb8878516f459e085c0dd092f0f1d51c21", ECCurve.Secp256r1), + ECPoint.Parse("03184b018d6b2bc093e535519732b3fd3f7551c8cffaf4621dd5a0b89482ca66c9", ECCurve.Secp256r1) + ], + SeedList = [ + "seed1t5.neo.org:20333", + "seed2t5.neo.org:20333", + "seed3t5.neo.org:20333", + "seed4t5.neo.org:20333", + "seed5t5.neo.org:20333" + ], + Hardforks = new Dictionary() + { + [Hardfork.HF_Aspidochelone] = 210_000u, + [Hardfork.HF_Basilisk] = 2_680_000u, + [Hardfork.HF_Cockatrice] = 3_967_000u, + }.ToImmutableDictionary(), + }; + } +} diff --git a/src/Neo.Hosting.App/Neo.Hosting.App.csproj b/src/Neo.Hosting.App/Neo.Hosting.App.csproj new file mode 100644 index 0000000000..47cf313b67 --- /dev/null +++ b/src/Neo.Hosting.App/Neo.Hosting.App.csproj @@ -0,0 +1,62 @@ + + + + Exe + net8.0 + Neo.Hosting.App + neo-cmd + enable + true + ../../bin/$(AssemblyTitle) + + + + + + + + + + + Always + + + Always + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Neo.Hosting.App/Program.cs b/src/Neo.Hosting.App/Program.cs new file mode 100644 index 0000000000..2633d51c54 --- /dev/null +++ b/src/Neo.Hosting.App/Program.cs @@ -0,0 +1,42 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// Program.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Microsoft.Extensions.Hosting.Systemd; +using Microsoft.Extensions.Hosting.WindowsServices; +using Neo.Extensions; +using System; +using System.Reflection; +using System.Threading.Tasks; + +namespace Neo.Hosting.App +{ + public sealed partial class Program + { + internal const string DEFAULT_VERSION_STRING = "0.0.0"; + + internal static int ApplicationVersionNumber => + AssemblyUtility.GetVersionNumber(); + + internal static Version ApplicationVersion => + Assembly.GetExecutingAssembly().GetName().Version ?? new Version("0.0.0"); + + internal static bool IsRunningAsService => + (SystemdHelpers.IsSystemdService() || WindowsServiceHelpers.IsWindowsService()) || Environment.UserInteractive == false; + + static Task Main(string[] args) + { + Console.BackgroundColor = ConsoleColor.Black; + Console.Clear(); + + return Task.FromResult(-1); + } + } +} diff --git a/src/Neo.Hosting.App/config.localnet.json b/src/Neo.Hosting.App/config.localnet.json new file mode 100644 index 0000000000..ec91c176bb --- /dev/null +++ b/src/Neo.Hosting.App/config.localnet.json @@ -0,0 +1,83 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information" + }, + "NeoError": { + "LogLevel": { + "Default": "Error" + } + } + }, + "ApplicationConfiguration": { + "Storage": { + "Engine": "MemoryStore", + "Verify": false, + "Archive": { + "FileName": "chain.{0}.acc" + } + }, + "P2P": { + "Listen": "127.0.0.1", + "Port": 226 + }, + "Contract": { + "NeoNameService": "0x50ac1c37690cc2cfc594472833cf57505d5f46de" + }, + "NamedPipe": { + "Name": "HelloPipe" + }, + "Wallets": [ + { + "Name": "MyTestWallet", + "Path": "./wallets/hello.json", + "Password": "hello", + "IsActive": true + } + ] + }, + "ProtocolConfiguration": { + "Network": 860833102, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 1730000, + "HF_Basilisk": 4120000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", + "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", + "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", + "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", + "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", + "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" + ], + "SeedList": [ + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + ] + } +} diff --git a/src/Neo.Hosting.App/config.mainnet.json b/src/Neo.Hosting.App/config.mainnet.json new file mode 100644 index 0000000000..5db07486e7 --- /dev/null +++ b/src/Neo.Hosting.App/config.mainnet.json @@ -0,0 +1,54 @@ +{ + "ApplicationConfiguration": { + "Storage": { + "Engine": "LevelDBStore" + }, + "Contracts": { + "NeoNameService": "0x50ac1c37690cc2cfc594472833cf57505d5f46de" + } + }, + "ProtocolConfiguration": { + "Network": 860833102, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 512, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 1730000, + "HF_Basilisk": 4120000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", + "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", + "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", + "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", + "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", + "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", + "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", + "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", + "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", + "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", + "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", + "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", + "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", + "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", + "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", + "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", + "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", + "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", + "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", + "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", + "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" + ], + "SeedList": [ + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + ] + } +} diff --git a/src/Neo.Hosting.App/config.testnet.json b/src/Neo.Hosting.App/config.testnet.json new file mode 100644 index 0000000000..4bef69b0d4 --- /dev/null +++ b/src/Neo.Hosting.App/config.testnet.json @@ -0,0 +1,57 @@ +{ + "ApplicationConfiguration": { + "Storage": { + "Engine": "LevelDBStore" + }, + "P2P": { + "Port": 20333 + }, + "Contracts": { + "NeoNameService": "0x50ac1c37690cc2cfc594472833cf57505d5f46de" + } + }, + "ProtocolConfiguration": { + "Network": 894710606, + "AddressVersion": 53, + "MillisecondsPerBlock": 15000, + "MaxTransactionsPerBlock": 5000, + "MemoryPoolMaxTransactions": 50000, + "MaxTraceableBlocks": 2102400, + "Hardforks": { + "HF_Aspidochelone": 210000, + "HF_Basilisk": 2680000 + }, + "InitialGasDistribution": 5200000000000000, + "ValidatorsCount": 7, + "StandbyCommittee": [ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + "02a7834be9b32e2981d157cb5bbd3acb42cfd11ea5c3b10224d7a44e98c5910f1b", + "0214baf0ceea3a66f17e7e1e839ea25fd8bed6cd82e6bb6e68250189065f44ff01", + "030205e9cefaea5a1dfc580af20c8d5aa2468bb0148f1a5e4605fc622c80e604ba", + "025831cee3708e87d78211bec0d1bfee9f4c85ae784762f042e7f31c0d40c329b8", + "02cf9dc6e85d581480d91e88e8cbeaa0c153a046e89ded08b4cefd851e1d7325b5", + "03840415b0a0fcf066bcc3dc92d8349ebd33a6ab1402ef649bae00e5d9f5840828", + "026328aae34f149853430f526ecaa9cf9c8d78a4ea82d08bdf63dd03c4d0693be6", + "02c69a8d084ee7319cfecf5161ff257aa2d1f53e79bf6c6f164cff5d94675c38b3", + "0207da870cedb777fceff948641021714ec815110ca111ccc7a54c168e065bda70", + "035056669864feea401d8c31e447fb82dd29f342a9476cfd449584ce2a6165e4d7", + "0370c75c54445565df62cfe2e76fbec4ba00d1298867972213530cae6d418da636", + "03957af9e77282ae3263544b7b2458903624adc3f5dee303957cb6570524a5f254", + "03d84d22b8753cf225d263a3a782a4e16ca72ef323cfde04977c74f14873ab1e4c", + "02147c1b1d5728e1954958daff2f88ee2fa50a06890a8a9db3fa9e972b66ae559f", + "03c609bea5a4825908027e4ab217e7efc06e311f19ecad9d417089f14927a173d5", + "0231edee3978d46c335e851c76059166eb8878516f459e085c0dd092f0f1d51c21", + "03184b018d6b2bc093e535519732b3fd3f7551c8cffaf4621dd5a0b89482ca66c9" + ], + "SeedList": [ + "seed1t5.neo.org:20333", + "seed2t5.neo.org:20333", + "seed3t5.neo.org:20333", + "seed4t5.neo.org:20333", + "seed5t5.neo.org:20333" + ] + } +} diff --git a/src/Neo/Cryptography/Crc32.cs b/src/Neo/Cryptography/Crc32.cs new file mode 100644 index 0000000000..15af3bad88 --- /dev/null +++ b/src/Neo/Cryptography/Crc32.cs @@ -0,0 +1,116 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// Crc32.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Collections.Generic; +using System.Security.Cryptography; + +namespace Neo.Cryptography +{ + public sealed class Crc32 : HashAlgorithm + { + public static readonly uint DefaultPolynomial = 0xedb88320u; + public static readonly uint DefaultSeed = 0xffffffffu; + + private static uint[] s_defaultTable; + + public override int HashSize => 32; + + private readonly uint _seed; + private readonly uint[] _table; + private uint _hash; + + public Crc32() : this(DefaultPolynomial, DefaultSeed) + { + + } + + public Crc32( + uint polynomial, + uint seed) + { + if (BitConverter.IsLittleEndian) + throw new PlatformNotSupportedException("Not supported on Big Endian processors"); + + _table = InitializeTable(polynomial); + _seed = seed; + } + + public override void Initialize() + { + _hash = _seed; + } + + protected override void HashCore(byte[] array, int ibStart, int cbSize) + { + _hash = CalculateHash(_table, _hash, array, ibStart, cbSize); + } + + protected override byte[] HashFinal() + { + var hashBuffer = Crc32.UInt32ToBigEndianBytes(~_hash); + HashValue = hashBuffer; + return hashBuffer; + } + + public static uint Compute(byte[] buffer) => + Compute(DefaultSeed, buffer); + + public static uint Compute(uint seed, byte[] buffer) => + Compute(DefaultPolynomial, seed, buffer); + + public static uint Compute(uint polynomial, uint seed, byte[] buffer) => + ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length); + + private static uint[] InitializeTable(uint polynomial) + { + if (polynomial == DefaultPolynomial && s_defaultTable != null) + return s_defaultTable; + + var createTable = new uint[256]; + for (var i = 0u; i < 256u; i++) + { + var entry = i; + for (var j = 0; j < 8; j++) + { + if ((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + } + createTable[i] = entry; + } + + if (polynomial == DefaultPolynomial) + s_defaultTable = createTable; + + return createTable; + } + + private static uint CalculateHash(uint[] table, uint seed, IList buffer, int start, int size) + { + var hash = seed; + for (var i = start; i < start + size; i++) + hash = (hash >> 8) ^ table[buffer[i] ^ hash & 0xff]; + return hash; + } + + private static byte[] UInt32ToBigEndianBytes(uint value) + { + var result = BitConverter.GetBytes(value); + + if (BitConverter.IsLittleEndian) + Array.Reverse(result); + + return result; + } + } +} diff --git a/src/Neo/Neo.csproj b/src/Neo/Neo.csproj index 835224eddd..d38e02e2ce 100644 --- a/src/Neo/Neo.csproj +++ b/src/Neo/Neo.csproj @@ -29,7 +29,9 @@ + + diff --git a/tests/Neo.Hosting.App.Tests/Neo.Hosting.App.Tests.csproj b/tests/Neo.Hosting.App.Tests/Neo.Hosting.App.Tests.csproj new file mode 100644 index 0000000000..38de1a2849 --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/Neo.Hosting.App.Tests.csproj @@ -0,0 +1,32 @@ + + + + net8.0 + enable + false + true + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/DataCases/TestMemberDataCases.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/DataCases/TestMemberDataCases.cs new file mode 100644 index 0000000000..69d0903a23 --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/DataCases/TestMemberDataCases.cs @@ -0,0 +1,43 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestMemberDataCases.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo; +using Neo.Hosting; +using Neo.Hosting.App; +using Neo.Hosting.App.Tests; +using Neo.Hosting.App.Tests.UTHelpers; +using Neo.Hosting.App.Tests.UTHelpers.DataCases; + +namespace Neo.Hosting.App.Tests.UTHelpers.DataCases +{ + internal static class TestMemberDataCases + { + public static TheoryData Struffer_ReadWrite_Cases => + new() + { + { (byte)0x01, [0x01,] }, + { (sbyte)0x7f, [0x7f,] }, + { (short)0x0102, [0x02, 0x01,] }, + { (ushort)0xf0f1u, [0xf1, 0xf0,] }, + { 0xd0d1d2d3, [0xd3, 0xd2, 0xd1, 0xd0,] }, + { 0x12345678u, [0x78, 0x56, 0x34, 0x12,] }, + { 0x1234567890abcdef, [0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12,] }, + { 0xdeadc0debad0c0deul, [0xde, 0xc0, 0xd0, 0xba, 0xde, 0xc0, 0xad, 0xde,] }, + }; + + public static TheoryData Struffer_ReadWrite_String_Cases => + new() + { + { "Hello", [0x05, 0x00, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f,] }, + { "World", [0x05, 0x00, 0x00, 0x00, 0x57, 0x6f, 0x72, 0x6c, 0x64,] }, + }; + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestBlockchain.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestBlockchain.cs new file mode 100644 index 0000000000..7158bacd47 --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestBlockchain.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestBlockchain.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Akka.Actor; +using Neo.Ledger; +using Neo.Persistence; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Neo.Hosting.App.Tests.UTHelpers.Default +{ + public static class TestBlockchain + { + public static readonly NeoSystem TheNeoSystem; + public static readonly UInt160[] DefaultExtensibleWitnessWhiteList; + private static readonly MemoryStore Store = new(); + + private class StoreProvider : IStoreProvider + { + public string Name => "TestProvider"; + + public IStore GetStore(string path) => Store; + } + + static TestBlockchain() + { + Console.WriteLine("initialize NeoSystem"); + TheNeoSystem = new NeoSystem(TestProtocolSettings.Default, new StoreProvider()); + } + + internal static void ResetStore() + { + Store.Reset(); + TheNeoSystem.Blockchain.Ask(new Blockchain.Initialize()).Wait(); + } + + internal static DataCache GetTestSnapshot() + { + return TheNeoSystem.GetSnapshot().CreateSnapshot(); + } + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestProtocolSettings.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestProtocolSettings.cs new file mode 100644 index 0000000000..a2bac495ff --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/Default/TestProtocolSettings.cs @@ -0,0 +1,70 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestProtocolSettings.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.Cryptography.ECC; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Neo.Hosting.App.Tests.UTHelpers.Default +{ + public static class TestProtocolSettings + { + public static ProtocolSettings Default = new() + { + Network = 0x334F454Eu, + AddressVersion = ProtocolSettings.Default.AddressVersion, + StandbyCommittee = new[] + { + //Validators + ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", ECCurve.Secp256r1), + ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", ECCurve.Secp256r1), + ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", ECCurve.Secp256r1), + ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", ECCurve.Secp256r1), + ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", ECCurve.Secp256r1), + ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", ECCurve.Secp256r1), + ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", ECCurve.Secp256r1), + //Other Members + ECPoint.Parse("023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", ECCurve.Secp256r1), + ECPoint.Parse("03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", ECCurve.Secp256r1), + ECPoint.Parse("03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", ECCurve.Secp256r1), + ECPoint.Parse("03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", ECCurve.Secp256r1), + ECPoint.Parse("02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", ECCurve.Secp256r1), + ECPoint.Parse("03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", ECCurve.Secp256r1), + ECPoint.Parse("0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", ECCurve.Secp256r1), + ECPoint.Parse("020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", ECCurve.Secp256r1), + ECPoint.Parse("0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", ECCurve.Secp256r1), + ECPoint.Parse("03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", ECCurve.Secp256r1), + ECPoint.Parse("02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", ECCurve.Secp256r1), + ECPoint.Parse("0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", ECCurve.Secp256r1), + ECPoint.Parse("03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", ECCurve.Secp256r1), + ECPoint.Parse("02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a", ECCurve.Secp256r1) + }, + ValidatorsCount = 7, + SeedList = new[] + { + "seed1.neo.org:10333", + "seed2.neo.org:10333", + "seed3.neo.org:10333", + "seed4.neo.org:10333", + "seed5.neo.org:10333" + }, + MillisecondsPerBlock = ProtocolSettings.Default.MillisecondsPerBlock, + MaxTransactionsPerBlock = ProtocolSettings.Default.MaxTransactionsPerBlock, + MemoryPoolMaxTransactions = ProtocolSettings.Default.MemoryPoolMaxTransactions, + MaxTraceableBlocks = ProtocolSettings.Default.MaxTraceableBlocks, + InitialGasDistribution = ProtocolSettings.Default.InitialGasDistribution, + Hardforks = ProtocolSettings.Default.Hardforks + }; + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLogger.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLogger.cs new file mode 100644 index 0000000000..de3b632238 --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLogger.cs @@ -0,0 +1,43 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestLogger.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Microsoft.Extensions.Logging; +using Neo; +using Neo.Hosting; +using Neo.Hosting.App; +using Neo.Hosting.App.Tests; +using Neo.Hosting.App.Tests.UTHelpers; +using Neo.Hosting.App.Tests.UTHelpers.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit.Abstractions; + +namespace Neo.Hosting.App.Tests.UTHelpers.Logging +{ + public sealed class TestLogger + (ITestOutputHelper testOutputHelper, string categoryName) : ILogger + { + private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; + private readonly string _categoryName = categoryName; + + public IDisposable? BeginScope(TState state) where TState : notnull => + default!; + + public bool IsEnabled(Microsoft.Extensions.Logging.LogLevel logLevel) => + true; + + public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) => + _testOutputHelper.WriteLine($"[{DateTime.Now}] {logLevel}: {_categoryName}[{eventId.Id}] {formatter(state, exception)}"); + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLoggerProvider.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLoggerProvider.cs new file mode 100644 index 0000000000..850c9d07ae --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestLoggerProvider.cs @@ -0,0 +1,43 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestLoggerProvider.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Microsoft.Extensions.Logging; +using Neo; +using Neo.Hosting; +using Neo.Hosting.App; +using Neo.Hosting.App.Tests; +using Neo.Hosting.App.Tests.UTHelpers; +using Neo.Hosting.App.Tests.UTHelpers.Logging; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit.Abstractions; + +namespace Neo.Hosting.App.Tests.UTHelpers.Logging +{ + public sealed class TestLoggerProvider + (ITestOutputHelper testOutputHelper) : ILoggerProvider + { + private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; + private readonly ConcurrentDictionary _loggers = new(StringComparer.OrdinalIgnoreCase); + + public ILogger CreateLogger(string categoryName) => + _loggers.GetOrAdd(categoryName, name => new TestLogger(_testOutputHelper, name)); + + public void Dispose() + { + _loggers.Clear(); + } + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestTextWriter.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestTextWriter.cs new file mode 100644 index 0000000000..5cdbe7ff7d --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/Logging/TestTextWriter.cs @@ -0,0 +1,103 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestTextWriter.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo; +using Neo.Hosting; +using Neo.Hosting.App; +using Neo.Hosting.App.Tests; +using Neo.Hosting.App.Tests.UTHelpers; +using Neo.Hosting.App.Tests.UTHelpers.Logging; +using Org.BouncyCastle.X509; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit.Abstractions; + +namespace Neo.Hosting.App.Tests.UTHelpers.Logging +{ + internal class TestTextWriter + (ITestOutputHelper testOutputHelper) : TextWriter + { + private readonly ITestOutputHelper _testOutputHelper = testOutputHelper; + + public override Encoding Encoding => Utility.StrictUTF8; + + private void WriteOutput(string? value, params object[] args) + { + if (string.IsNullOrEmpty(value)) + _testOutputHelper.WriteLine(string.Empty); + else + _testOutputHelper.WriteLine(value, args); + } + + public override void Write(string? value) + { + WriteOutput(value); + } + + public override void Write([StringSyntax("CompositeFormat")] string format, object? arg0) + { + WriteOutput(format, arg0); + } + + public override void Write([StringSyntax("CompositeFormat")] string format, object? arg0, object? arg1) + { + WriteOutput(format, arg0, arg1); + } + + public override void Write([StringSyntax("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) + { + WriteOutput(format, arg0, arg1, arg2); + } + + public override void Write([StringSyntax("CompositeFormat")] string format, params object?[] arg) + { + WriteOutput(format, arg); + } + + public override void WriteLine() + { + WriteOutput(null); + } + + public override void WriteLine(string? value) + { + WriteOutput(value); + } + + public override void WriteLine([StringSyntax("CompositeFormat")] string format, object? arg0) + { + WriteOutput(format, arg0); + } + + public override void WriteLine([StringSyntax("CompositeFormat")] string format, object? arg0, object? arg1) + { + WriteOutput(format, arg0, arg1); + } + + public override void WriteLine([StringSyntax("CompositeFormat")] string format, object? arg0, object? arg1, object? arg2) + { + WriteOutput(format, arg0, arg1, arg2); + } + + public override void WriteLine([StringSyntax("CompositeFormat")] string format, params object?[] arg) + { + WriteOutput(format, arg); + } + } +} diff --git a/tests/Neo.Hosting.App.Tests/UTHelpers/SetupClasses/TestSetupLogging.cs b/tests/Neo.Hosting.App.Tests/UTHelpers/SetupClasses/TestSetupLogging.cs new file mode 100644 index 0000000000..c19d49edd9 --- /dev/null +++ b/tests/Neo.Hosting.App.Tests/UTHelpers/SetupClasses/TestSetupLogging.cs @@ -0,0 +1,54 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// TestSetupLogging.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Microsoft.Extensions.Logging; +using Neo; +using Neo.Hosting; +using Neo.Hosting.App; +using Neo.Hosting.App.Tests; +using Neo.Hosting.App.Tests.UTHelpers; +using Neo.Hosting.App.Tests.UTHelpers.Logging; +using Neo.Hosting.App.Tests.UTHelpers.SetupClasses; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit.Abstractions; + +namespace Neo.Hosting.App.Tests.UTHelpers.SetupClasses +{ + public class TestSetupLogging : IDisposable + { + private readonly TestTextWriter _logConsole; + + public ILoggerFactory LoggerFactory { get; } + + public TestSetupLogging( + ITestOutputHelper testOutputHelper) + { + _logConsole = new TestTextWriter(testOutputHelper); + Console.SetOut(_logConsole); + + LoggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(builder => + { + builder.AddDebug(); + builder.AddProvider(new TestLoggerProvider(testOutputHelper)); + builder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); + }); + } + + public void Dispose() + { + _logConsole.Dispose(); + } + } +} diff --git a/tests/Neo.UnitTests/Cryptography/UT_Crc32.cs b/tests/Neo.UnitTests/Cryptography/UT_Crc32.cs new file mode 100644 index 0000000000..c33cbf3e5b --- /dev/null +++ b/tests/Neo.UnitTests/Cryptography/UT_Crc32.cs @@ -0,0 +1,44 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// UT_Crc32.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 FluentAssertions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using System.Text; + +namespace Neo.UnitTests.Cryptography +{ + [TestClass] + public class UT_Crc32 + { + private const string SimpleString = @"The quick brown fox jumps over the lazy dog."; + private readonly byte[] _simpleBytesAscii = Encoding.ASCII.GetBytes(SimpleString); + + private const string SimpleString2 = @"Life moves pretty fast. If you don't stop and look around once in a while, you could miss it."; + private readonly byte[] _simpleBytes2Ascii = Encoding.ASCII.GetBytes(SimpleString2); + + [TestMethod] + public void StaticDefaultSeedAndPolynomialWithShortAsciiString() + { + var actual = Crc32.Compute(_simpleBytesAscii); + + actual.Should().Be(0x519025e9U); + } + + [TestMethod] + public void StaticDefaultSeedAndPolynomialWithShortAsciiString2() + { + var actual = Crc32.Compute(_simpleBytes2Ascii); + + actual.Should().Be(0x6ee3ad88U); + } + } +} From 78902893c670e953b7d644504d9bfa8a0fdee517 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Sat, 29 Jun 2024 23:20:27 +0800 Subject: [PATCH 2/3] add configurations and helpers --- .../NamedPipeClientTransportOptions.cs | 25 ++++ .../NamedPipeServerTransportOptions.cs | 26 ++++ .../Configuration/NeoConfigurationSource.cs | 23 ++++ .../Configuration/NeoOptions.cs | 110 ++++++++++++++++ src/Neo.Hosting.App/Helpers/ConsoleUtility.cs | 53 ++++++++ src/Neo.Hosting.App/Helpers/ParseUtility.cs | 24 ++++ src/Neo.Hosting.App/Helpers/RegexUtility.cs | 21 +++ .../Providers/NeoConfigurationProvider.cs | 120 ++++++++++++++++++ 8 files changed, 402 insertions(+) create mode 100644 src/Neo.Hosting.App/Configuration/NamedPipeClientTransportOptions.cs create mode 100644 src/Neo.Hosting.App/Configuration/NamedPipeServerTransportOptions.cs create mode 100644 src/Neo.Hosting.App/Configuration/NeoConfigurationSource.cs create mode 100644 src/Neo.Hosting.App/Configuration/NeoOptions.cs create mode 100644 src/Neo.Hosting.App/Helpers/ConsoleUtility.cs create mode 100644 src/Neo.Hosting.App/Helpers/ParseUtility.cs create mode 100644 src/Neo.Hosting.App/Helpers/RegexUtility.cs create mode 100644 src/Neo.Hosting.App/Providers/NeoConfigurationProvider.cs diff --git a/src/Neo.Hosting.App/Configuration/NamedPipeClientTransportOptions.cs b/src/Neo.Hosting.App/Configuration/NamedPipeClientTransportOptions.cs new file mode 100644 index 0000000000..b29a28bc3b --- /dev/null +++ b/src/Neo.Hosting.App/Configuration/NamedPipeClientTransportOptions.cs @@ -0,0 +1,25 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NamedPipeClientTransportOptions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.Hosting.App.Buffers; +using System; +using System.Buffers; + +namespace Neo.Hosting.App.Configuration +{ + internal sealed class NamedPipeClientTransportOptions + { + public long MaxReadBufferSize { get; set; } = 1024 * 1024; + public long MaxWriteBufferSize { get; set; } = 64 * 1024; + public bool CurrentUserOnly { get; set; } = true; + internal Func> MemoryPoolFactory { get; set; } = () => new PinnedBlockMemoryPool(); + } +} diff --git a/src/Neo.Hosting.App/Configuration/NamedPipeServerTransportOptions.cs b/src/Neo.Hosting.App/Configuration/NamedPipeServerTransportOptions.cs new file mode 100644 index 0000000000..a3f00efb59 --- /dev/null +++ b/src/Neo.Hosting.App/Configuration/NamedPipeServerTransportOptions.cs @@ -0,0 +1,26 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NamedPipeServerTransportOptions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.Hosting.App.Buffers; +using System; +using System.Buffers; + +namespace Neo.Hosting.App.Configuration +{ + internal sealed class NamedPipeServerTransportOptions + { + public int ListenerQueueCount { get; set; } = Math.Min(Environment.ProcessorCount, 16); + public long MaxReadBufferSize { get; set; } = 1024 * 1024; + public long MaxWriteBufferSize { get; set; } = 64 * 1024; + public bool CurrentUserOnly { get; set; } = true; + internal Func> MemoryPoolFactory { get; set; } = () => new PinnedBlockMemoryPool(); + } +} diff --git a/src/Neo.Hosting.App/Configuration/NeoConfigurationSource.cs b/src/Neo.Hosting.App/Configuration/NeoConfigurationSource.cs new file mode 100644 index 0000000000..d80f17174e --- /dev/null +++ b/src/Neo.Hosting.App/Configuration/NeoConfigurationSource.cs @@ -0,0 +1,23 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoConfigurationSource.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Microsoft.Extensions.Configuration; +using Neo.Hosting.App.Providers; + +namespace Neo.Hosting.App.Configuration +{ + internal class NeoConfigurationSource + (IConfigurationSection? configurationSection = null) : IConfigurationSource + { + public IConfigurationProvider Build(IConfigurationBuilder builder) => + new NeoConfigurationProvider(configurationSection); + } +} diff --git a/src/Neo.Hosting.App/Configuration/NeoOptions.cs b/src/Neo.Hosting.App/Configuration/NeoOptions.cs new file mode 100644 index 0000000000..0cda4dc1bb --- /dev/null +++ b/src/Neo.Hosting.App/Configuration/NeoOptions.cs @@ -0,0 +1,110 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoOptions.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Neo.Hosting.App.Helpers; +using Neo.Hosting.App.Host; +using Neo.Network.P2P; +using System; +using System.Collections.Generic; +using System.IO; +using System.Security; + +namespace Neo.Hosting.App.Configuration +{ + internal sealed class NeoOptions + { + public StorageOptions Storage { get; set; } = new(); + public P2POptions P2P { get; set; } = new(); + public ContractOptions Contract { get; set; } = new("0x50ac1c37690cc2cfc594472833cf57505d5f46de"); + public PluginOptions Plugin { get; set; } = new(); + public NamedPipeOptions NamedPipe { get; set; } = new(); + public List Wallets { get; set; } = []; + } + + internal sealed class StorageOptions + { + public class ArchiveSettings + { + public string Path { get; set; } = AppContext.BaseDirectory; + public string FileName { get; set; } = "chain.0.acc"; + } + + public string Engine { get; set; } = NeoDefaults.StoreProviderName; + public string Path { get; set; } = "Data_LevelDB_{0:X2}"; + public bool Verify { get; set; } = true; + public ArchiveSettings Archive { get; set; } = new(); + } + + internal sealed class P2POptions + { + public string Listen { get; set; } = "0.0.0.0"; + public ushort Port { get; set; } = 10333; + public int MinDesiredConnections { get; set; } = Peer.DefaultMinDesiredConnections; + public int MaxConnections { get; set; } = Peer.DefaultMaxConnections; + public int MaxConnectionsPerAddress { get; set; } = 3; + } + + internal sealed class ContractOptions + (string neoNameService) + { + private static readonly string s_defualtNameServiceString = "0x50ac1c37690cc2cfc594472833cf57505d5f46de"; + private static readonly UInt160 s_defaultNameServiceScriptHash = UInt160.Parse(s_defualtNameServiceString); + + private UInt160 _neoNameService = s_defaultNameServiceScriptHash; + + public UInt160 NeoNameService + { + get => _neoNameService; + set => _neoNameService = ParseUtility.TryParseUInt160(neoNameService) ?? s_defaultNameServiceScriptHash; + } + } + + internal sealed class PluginOptions + { + public string DownloadUrl { get; set; } = "https://api.github.com/repos/neo-project/neo/releases"; + public bool Prerelease { get; set; } = false; + public Version Version { get; set; } = new(0, 0); + } + + internal sealed class NamedPipeOptions + { + public string Name { get; set; } = default!; + } + + internal sealed class WalletOptions + (string name, string path, string password, bool isActive) + { + public string Name { get; set; } = name; + public FileInfo Path { get; set; } = new(path); + public bool IsActive { get; set; } = isActive; + + public required SecureString Password + { + get => _encryptedPassword; + set + { + var passwordOptionValue = password; + + unsafe + { + fixed (char* passwordChars = passwordOptionValue) + { + var securePasswordString = new SecureString(passwordChars, passwordOptionValue.Length); + securePasswordString.MakeReadOnly(); + _encryptedPassword = value = securePasswordString; + } + } + } + } + + private SecureString _encryptedPassword = new(); + } +} diff --git a/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs b/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs new file mode 100644 index 0000000000..28e2164bc5 --- /dev/null +++ b/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs @@ -0,0 +1,53 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// ConsoleUtility.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Runtime.InteropServices; + +namespace Neo.Hosting.App +{ + internal static partial class ConsoleUtility + { + private const int STD_OUTPUT_HANDLE = -11; + private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4; + private const uint DISABLE_NEWLINE_AUTO_RETURN = 8; + + [LibraryImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool GetConsoleMode(nint hConsoleHandle, out uint lpMode); + + [LibraryImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool SetConsoleMode(nint hConsoleHandle, uint dwMode); + + [LibraryImport("kernel32.dll", SetLastError = true)] + private static partial nint GetStdHandle(int nStdHandle); + + public static void EnableAnsi() + { + var handle = GetStdHandle(STD_OUTPUT_HANDLE); + + if (!GetConsoleMode(handle, out var mode)) + { + Console.Error.WriteLine("Failed to get console mode"); + return; + } + + // Enable the virtual terminal processing mode + mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN; + if (!SetConsoleMode(handle, mode)) + { + Console.Error.WriteLine("Failed to set console mode"); + return; + } + } + } +} diff --git a/src/Neo.Hosting.App/Helpers/ParseUtility.cs b/src/Neo.Hosting.App/Helpers/ParseUtility.cs new file mode 100644 index 0000000000..1bbec4f350 --- /dev/null +++ b/src/Neo.Hosting.App/Helpers/ParseUtility.cs @@ -0,0 +1,24 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// ParseUtility.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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. + +namespace Neo.Hosting.App.Helpers +{ + internal static class ParseUtility + { + public static UInt160? TryParseUInt160(string? value) + { + if (string.IsNullOrEmpty(value)) return default; + if (UInt160.TryParse(value, out var result)) + return result; + return UInt160.Zero; + } + } +} diff --git a/src/Neo.Hosting.App/Helpers/RegexUtility.cs b/src/Neo.Hosting.App/Helpers/RegexUtility.cs new file mode 100644 index 0000000000..f176c5b1cc --- /dev/null +++ b/src/Neo.Hosting.App/Helpers/RegexUtility.cs @@ -0,0 +1,21 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// RegexUtility.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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.Text.RegularExpressions; + +namespace Neo.Hosting.App +{ + internal static partial class RegexUtility + { + [GeneratedRegex(@"\d+")] + public static partial Regex AllNumbersWithOneOrMoreDigits(); + } +} diff --git a/src/Neo.Hosting.App/Providers/NeoConfigurationProvider.cs b/src/Neo.Hosting.App/Providers/NeoConfigurationProvider.cs new file mode 100644 index 0000000000..59005a3664 --- /dev/null +++ b/src/Neo.Hosting.App/Providers/NeoConfigurationProvider.cs @@ -0,0 +1,120 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// NeoConfigurationProvider.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository 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 Akka.Util.Internal; +using Microsoft.Extensions.Configuration; +using Neo.Hosting.App.Host; +using Neo.Network.P2P; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Neo.Hosting.App.Providers +{ + internal class NeoConfigurationProvider + (IConfigurationSection? configurationSection = null) : ConfigurationProvider + { + public override void Load() + { + Data = CreateDefaultKeys(); + Load(Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User)); + Load(Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process)); + + if (configurationSection is not null) + Load(configurationSection); + } + + internal void Load(IDictionary envVariables) + { + var e = envVariables.GetEnumerator(); + + try + { + while (e.MoveNext()) + { + var key = (string)e.Entry.Key; + var value = (string?)e.Entry.Value; + + AddIfNormalizedKeyMatchesPrefix(Data, Normalize(key), value); + } + } + finally + { + (e as IDisposable)?.Dispose(); + } + } + + internal void Load(IConfigurationSection section) + { + var e = section.AsEnumerable().GetEnumerator(); + var prefix = $"{section.Key}:"; + + try + { + while (e.MoveNext()) + { + var key = e.Current.Key; + var value = e.Current.Value; + + if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) + Data.AddOrSet(key[prefix.Length..], value); + } + } + finally + { + (e as IDisposable)?.Dispose(); + } + } + + private static Dictionary CreateDefaultKeys() => + new(StringComparer.OrdinalIgnoreCase) + { + // Storage + ["STORAGE:PATH"] = "Data_LevelDB_{0:X2}", + ["STORAGE:ENGINE"] = NeoDefaults.StoreProviderName, + ["STORAGE:VERIFY"] = bool.TrueString, + ["STORAGE:ARCHIVE:PATH"] = AppContext.BaseDirectory, + ["STORAGE:ARCHIVE:FILENAME"] = "chain.{0}.acc", + + // P2P + ["P2P:LISTEN"] = "0.0.0.0", + ["P2P:PORT"] = "10333", + ["P2P:MINDESIREDCONNECTIONS"] = $"{Peer.DefaultMinDesiredConnections}", + ["P2P:MAXCONNECTIONS"] = $"{Peer.DefaultMaxConnections}", + ["P2P:MAXCONNECTIONSPERADDRESS"] = "3", + + // Contracts + ["CONTRACT:NEONAMESERVICE"] = "0x50ac1c37690cc2cfc594472833cf57505d5f46de", + + // Plugin + ["PLUGIN:DOWNLOADURL"] = "https://api.github.com/repos/neo-project/neo/releases", + ["PLUGIN:PRERELEASE"] = bool.FalseString, + ["PLUGIN:VERSION"] = $"{Program.ApplicationVersion.ToString(3)}", + + // Remote + ["NAMEDPIPE:NAME"] = $"NEO_SERVICE", + }; + + private static void AddIfNormalizedKeyMatchesPrefix(IDictionary data, string normalizedKey, string? value) + { + var normalizedPrefix1 = NeoEnvironmentVariableDefaults.PREFIX; + var normalizedPrefix2 = $"NEO:"; + + if (normalizedKey.StartsWith(normalizedPrefix1, StringComparison.OrdinalIgnoreCase)) + data[normalizedKey[normalizedPrefix1.Length..]] = value; + else if (normalizedKey.StartsWith(normalizedPrefix2, StringComparison.OrdinalIgnoreCase)) + data[normalizedKey[normalizedPrefix2.Length..]] = value; + } + + private static string Normalize(string key) => + key.Replace("__", ConfigurationPath.KeyDelimiter); + } +} From 54359ddd884e72a272b5552e96e263f96f4f627b Mon Sep 17 00:00:00 2001 From: Jimmy Date: Sat, 29 Jun 2024 23:31:44 +0800 Subject: [PATCH 3/3] update format --- src/Neo.Hosting.App/Helpers/ConsoleUtility.cs | 2 +- src/Neo.Hosting.App/Helpers/ParseUtility.cs | 2 +- src/Neo.Hosting.App/Helpers/RegexUtility.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs b/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs index 28e2164bc5..bdbe643ef9 100644 --- a/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs +++ b/src/Neo.Hosting.App/Helpers/ConsoleUtility.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2024 The Neo Project. +// Copyright (C) 2015-2024 The Neo Project. // // ConsoleUtility.cs file belongs to the neo project and is free // software distributed under the MIT software license, see the diff --git a/src/Neo.Hosting.App/Helpers/ParseUtility.cs b/src/Neo.Hosting.App/Helpers/ParseUtility.cs index 1bbec4f350..a250a4f370 100644 --- a/src/Neo.Hosting.App/Helpers/ParseUtility.cs +++ b/src/Neo.Hosting.App/Helpers/ParseUtility.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2024 The Neo Project. +// Copyright (C) 2015-2024 The Neo Project. // // ParseUtility.cs file belongs to the neo project and is free // software distributed under the MIT software license, see the diff --git a/src/Neo.Hosting.App/Helpers/RegexUtility.cs b/src/Neo.Hosting.App/Helpers/RegexUtility.cs index f176c5b1cc..b394656502 100644 --- a/src/Neo.Hosting.App/Helpers/RegexUtility.cs +++ b/src/Neo.Hosting.App/Helpers/RegexUtility.cs @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2024 The Neo Project. +// Copyright (C) 2015-2024 The Neo Project. // // RegexUtility.cs file belongs to the neo project and is free // software distributed under the MIT software license, see the