diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.changelog b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.changelog new file mode 100644 index 000000000..8b076190a --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.changelog @@ -0,0 +1,6 @@ +eth-node-nethermind (1.33.1-1) bookworm; urgency=medium + + * Support for 1.33.1-1 + + -- Eniko Nagy Sat, 06 Sep 2025 09:10:20 +0000 + diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sps b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sps new file mode 100644 index 000000000..1c8aa3450 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sps @@ -0,0 +1,19 @@ +name = "eth-node-nethermind" +architecture = "any" +summary = "Nethermind Ethereum client" +conflicts = [] +recommends = [] +provides = ["eth-node-execution-client (= 1)"] +suggests = ["eth-node (= 1)"] +# TODO can't add depends, piuparts are failing +#depends = ["aspnetcore-runtime-7.0", "ca-certificates"] +depends = [] +add_files = [ + "src/Nethermind/artifacts/bin /usr/lib/eth-node-nethermind", + "src/Nethermind/artifacts/obj /usr/lib/eth-node-nethermind" + ] +add_links = ["/usr/lib/eth-node-nethermind/bin/Nethermind.Runner/release/nethermind /usr/bin/nethermind"] +add_manpages = [] +long_doc = """ +Nethermind is a high-performance, highly configurable full Ethereum protocol execution client built on .NET that runs on Linux, Windows, and macOS, and supports Clique, Aura, and Ethash. Nethermind offers very fast sync speeds and support for external plugins. Enjoy reliable access to rich on-chain data thanks to high-performance JSON-RPC based on the Kestrel web server. Healthy node monitoring is secured with Grafana analytics and Seq logging. +""" diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sss b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sss new file mode 100644 index 000000000..512ebecf5 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/eth-node-nethermind.sss @@ -0,0 +1,11 @@ +name = "eth-node-nethermind" +maintainer = "Eniko Nagy " +section = "net" +variants = [] +build_depends = [ + "libsnappy-dev", + "dotnet-sdk-8.0", +] +packages = ["eth-node-nethermind"] +skip_debug_symbols = true + diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder-verify.toml b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder-verify.toml new file mode 100644 index 000000000..9fc24d26d --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder-verify.toml @@ -0,0 +1,7 @@ +[verify] +package_hash=[ + { hash="4f966bb21b44e1461e3e7da2f1b2353faedc592d", name= "eth-node-nethermind_1.33.1-1.dsc"}, + { hash="fe0a78885b8650f379a25ed19e2fad8048d031c1", name= "eth-node-nethermind_1.33.1.orig.tar.gz"}, + { hash="32f3fe07dd2a6d37f072f58b9bd89b34bd6f7ce0", name= "eth-node-nethermind_1.33.1-1.debian.tar.xz"}, + { hash="1e4e8d246aacc0d71cf674a869ffc1aa312b8174", name= "eth-node-nethermind_1.33.1-1_amd64.deb"}, +] diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder.toml b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder.toml new file mode 100644 index 000000000..78eb069ef --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/pkg-builder.toml @@ -0,0 +1,45 @@ +[package_fields] +spec_file = "eth-node-nethermind.sss" +package_name = "eth-node-nethermind" +version_number = "1.33.1" +revision_number = "1" +homepage = "https://github.com/NethermindEth/nethermind" + +[package_type] +# virtual | git | default +package_type = "default" +tarball_url = "https://github.com/NethermindEth/nethermind/archive/refs/tags/1.33.1.tar.gz" +## Provided by debian package maintainer not by team developing the software +tarball_hash = "2511a73733caef8cd8095a5c13db18c59b5d4823b7d5624dbb459393e9d4dfde" + +[package_type.language_env] +language_env = "dotnet" +## because MS force pushes package version +dotnet_packages = [ + { name = "aspnetcore-runtime-9.0_9.0.0-1_amd64", hash = "2031dd260660a7e7f77f32b7e4c993fd9c23d3c1", url = "http://backup.eth-nodes.com/bookworm/20250107/aspnetcore-runtime-9.0_9.0.0-1_amd64.deb" }, + { name = "aspnetcore-targeting-pack-9.0_9.0.0-1_amd64", hash = "4038bdc5a54178fe2bfc329680906a14d43b282e", url = "http://backup.eth-nodes.com/bookworm/20250107/aspnetcore-targeting-pack-9.0_9.0.0-1_amd64.deb" }, + { name = "dotnet-apphost-pack-9.0_9.0.0-1_amd64", hash = "03e19d0580ab4114c64ef12d0c02a4f13f0da717", url = "http://backup.eth-nodes.com/bookworm/20250107/dotnet-apphost-pack-9.0_9.0.0-1_amd64.deb" }, + { name = "dotnet-hostfxr-9.0_9.0.0-1_amd64", hash = "4b677d008ac0135168bb49074135e213c7d335ac", url = "http://backup.eth-nodes.com/bookworm/20250107/dotnet-hostfxr-9.0_9.0.0-1_amd64.deb" }, + { name = "dotnet-runtime-9.0_9.0.0-1_amd64", hash = "5ed8ce77eecf489180ab7e366d868e443f2900b4", url = "http://backup.eth-nodes.com/bookworm/20250107/dotnet-runtime-9.0_9.0.0-1_amd64.deb" }, + { name = "dotnet-sdk-9.0_9.0.101-1_amd64", hash = "e97ce6be21ad8d7401ca45829c708b5c9e2532f0", url = "http://backup.eth-nodes.com/bookworm/20250107/dotnet-sdk-9.0_9.0.101-1_amd64.deb" }, + { name = "dotnet-targeting-pack-9.0_9.0.0-1_amd64", hash = "cb3967451b497e72ea773a2db1be15b862dd0b0b", url = "http://backup.eth-nodes.com/bookworm/20250107/dotnet-targeting-pack-9.0_9.0.0-1_amd64.deb" }, + { name = "netstandard-targeting-pack-2.1_2.1.0-1_amd64", hash = "c849f17d5e8cdce4b068e2897939be7de4b839d3", url = "http://backup.eth-nodes.com/bookworm/20250107/netstandard-targeting-pack-2.1_2.1.0-1_amd64.deb" }, +] + +use_backup_version = false + +[build_env] +codename = "bookworm" +arch = "amd64" +pkg_builder_version = "0.3.1" +debcrafter_version = "2711b53" +run_lintian = true +run_piuparts = true +run_autopkgtest = true +lintian_version = "2.116.3" +piuparts_version = "1.1.7" +autopkgtest_version = "5.28" +sbuild_version = "0.85.6" +# package directory +workdir = "~/.pkg-builder/packages/bookworm" +language_env = "dotnet" diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/.timestamp b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/.timestamp new file mode 100644 index 000000000..e69de29bb diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Directory.Build.props b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Directory.Build.props new file mode 100644 index 000000000..4be9e2550 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Directory.Build.props @@ -0,0 +1,31 @@ + + + + Debug + true + true + 13.0 + direct + en + net9.0 + true + true + + + + $([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()) + Demerzel Solutions Limited + Nethermind + $(Commit) + 1.32.1 + + + + + + <_Parameter1>BuildTimestamp + <_Parameter2>$(BuildTimestamp) + + + + diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Nethermind.Runner/Program.cs b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Nethermind.Runner/Program.cs new file mode 100644 index 000000000..a23239ddd --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/.pc/001-build-date.patch/src/Nethermind/Nethermind.Runner/Program.cs @@ -0,0 +1,566 @@ +// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited +// SPDX-License-Identifier: LGPL-3.0-only + +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Help; +using System.CommandLine.Invocation; +using System.CommandLine.Parsing; +using System.IO; +using System.IO.Abstractions; +using System.Linq; +using System.Reflection; +using System.Runtime; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +#if !DEBUG +using DotNetty.Common; +#endif +using Nethermind.Api; +using Nethermind.Api.Extensions; +using Nethermind.Config; +using Nethermind.Consensus.AuRa; +using Nethermind.Consensus.Clique; +using Nethermind.Consensus.Ethash; +using Nethermind.Core; +using Nethermind.Core.Exceptions; +using Nethermind.Db.Rocks; +using Nethermind.Hive; +using Nethermind.Init.Snapshot; +using Nethermind.KeyStore.Config; +using Nethermind.Logging; +using Nethermind.Logging.NLog; +using Nethermind.Runner; +using Nethermind.Runner.Ethereum; +using Nethermind.Runner.Ethereum.Api; +using Nethermind.Runner.Logging; +using Nethermind.Seq.Config; +using Nethermind.Serialization.Json; +using Nethermind.Specs.ChainSpecStyle; +using Nethermind.UPnP.Plugin; +using NLog; +using NLog.Config; +using ILogger = Nethermind.Logging.ILogger; +using NullLogger = Nethermind.Logging.NullLogger; + +Console.Title = ProductInfo.Name; +// Increase regex cache size as more added in log coloring matches +Regex.CacheSize = 128; +#if !DEBUG +ResourceLeakDetector.Level = ResourceLeakDetector.DetectionLevel.Disabled; +#endif +BlocksConfig.SetDefaultExtraDataWithVersion(); + +ManualResetEventSlim exit = new(true); +ILogger logger = new(SimpleConsoleLogger.Instance); +ProcessExitSource? processExitSource = default; +var unhandledError = "A critical error has occurred"; + +AppDomain.CurrentDomain.UnhandledException += (sender, e) => +{ + ILogger criticalLogger = GetCriticalLogger(); + + if (e.ExceptionObject is Exception ex) + criticalLogger.Error($"{unhandledError}.", ex); + else + criticalLogger.Error($"{unhandledError}: {e.ExceptionObject}"); +}; + +try +{ + return await ConfigureAsync(args); +} +catch (Exception ex) +{ + ILogger criticalLogger = GetCriticalLogger(); + + ex = ex is AggregateException aex ? aex.InnerException : ex; + + criticalLogger.Error($"{unhandledError}.", ex); + + return ex is IExceptionWithExitCode exc ? exc.ExitCode : ExitCodes.GeneralError; +} +finally +{ + NLogManager.Shutdown(); +} + +async Task ConfigureAsync(string[] args) +{ + CliConfiguration cli = ConfigureCli(); + ParseResult parseResult = cli.Parse(args); + // Suppress logs if run with `--help` or `--version` + bool silent = parseResult.CommandResult.Children + .Any(c => c is OptionResult { Option: HelpOption or VersionOption }); + + ConsoleHelpers.EnableConsoleColorOutput(); + + ConfigureLogger(parseResult); + + if (!silent) + { + logger.Info("Nethermind is starting up"); + logger.Info($"Version: {ProductInfo.Version}"); + } + + AppDomain.CurrentDomain.ProcessExit += (_, _) => + { + processExitSource?.Exit(ExitCodes.SigTerm); + exit.Wait(); + }; + GlobalDiagnosticsContext.Set("version", ProductInfo.Version); + + PluginLoader pluginLoader = new( + parseResult.GetValue(BasicOptions.PluginsDirectory) ?? "plugins", + new FileSystem(), + silent ? NullLogger.Instance : logger, + typeof(AuRaPlugin), + typeof(CliquePlugin), + typeof(EthashPlugin), + typeof(NethDevPlugin), + typeof(HivePlugin), + typeof(UPnPPlugin) + ); + pluginLoader.Load(); + + CheckForDeprecatedOptions(parseResult); + + // leaving here as an example of adding Debug plugin + // IPluginLoader mevLoader = SinglePluginLoader.Instance; + // CompositePluginLoader pluginLoader = new (pluginLoader, mevLoader); + + TypeDiscovery.Initialize(typeof(INethermindPlugin)); + + AddConfigurationOptions(cli.RootCommand); + + cli.RootCommand.SetAction((result, token) => RunAsync(result, pluginLoader, token)); + + try + { + return await cli.InvokeAsync(args); + } + finally + { + exit.Wait(); + } +} + +async Task RunAsync(ParseResult parseResult, PluginLoader pluginLoader, CancellationToken cancellationToken) +{ + + IConfigProvider configProvider = CreateConfigProvider(parseResult); + IInitConfig initConfig = configProvider.GetConfig(); + IKeyStoreConfig keyStoreConfig = configProvider.GetConfig(); + ISnapshotConfig snapshotConfig = configProvider.GetConfig(); + IPluginConfig pluginConfig = configProvider.GetConfig(); + + pluginLoader.OrderPlugins(pluginConfig); + + ResolveDataDirectory(parseResult.GetValue(BasicOptions.DataDirectory), + initConfig, keyStoreConfig, snapshotConfig); + + NLogManager logManager = new(initConfig.LogFileName, initConfig.LogDirectory, initConfig.LogRules); + + logger = logManager.GetClassLogger(); + + ConfigureSeqLogger(configProvider); + ResolveDatabaseDirectory(parseResult.GetValue(BasicOptions.DatabasePath), initConfig); + + logger.Info("Configuration complete"); + + EthereumJsonSerializer serializer = new(); + + if (logger.IsDebug) + { + logger.Debug($"Nethermind configuration:\n{serializer.Serialize(initConfig, true)}"); + + logger.Debug($"Server GC: {GCSettings.IsServerGC}"); + logger.Debug($"GC latency mode: {GCSettings.LatencyMode}"); + logger.Debug($"LOH compaction mode: {GCSettings.LargeObjectHeapCompactionMode}"); + } + + if (logger.IsInfo) logger.Info($"RocksDB: v{DbOnTheRocks.GetRocksDbVersion()}"); + + processExitSource = new(cancellationToken); + ApiBuilder apiBuilder = new(processExitSource!, configProvider, logManager); + IList plugins = await pluginLoader.LoadPlugins(configProvider, apiBuilder.ChainSpec); + EthereumRunner ethereumRunner = apiBuilder.CreateEthereumRunner(plugins); + + try + { + await ethereumRunner.Start(processExitSource.Token); + await processExitSource.ExitTask; + } + catch (OperationCanceledException) + { + if (logger.IsTrace) logger.Trace("Nethermind operation was canceled."); + } + catch (Exception ex) + { + if (logger.IsError) logger.Error(unhandledError, ex); + + processExitSource.Exit(ex is IExceptionWithExitCode withExit ? withExit.ExitCode : ExitCodes.GeneralError); + } + + logger.Info("Nethermind is shutting down... Please wait until all activities are stopped."); + + await ethereumRunner.StopAsync(); + + logger.Info("Nethermind is shut down"); + + exit.Set(); + + return processExitSource.ExitCode; +} + +void AddConfigurationOptions(CliCommand command) +{ + static CliOption CreateOption(string name, Type configType) => + new CliOption( + $"--{ConfigExtensions.GetCategoryName(configType)}.{name}", + $"--{ConfigExtensions.GetCategoryName(configType)}-{name}".ToLowerInvariant()); + + IEnumerable configTypes = TypeDiscovery + .FindNethermindBasedTypes(typeof(IConfig)) + .Where(ct => ct.IsInterface); + + foreach (Type configType in + configTypes.Where(ct => !ct.IsAssignableTo(typeof(INoCategoryConfig))).OrderBy(c => c.Name)) + { + if (configType is null) + continue; + + ConfigCategoryAttribute? typeLevel = configType.GetCustomAttribute(); + + if (typeLevel is not null && typeLevel.DisabledForCli) + continue; + + bool categoryHidden = typeLevel?.HiddenFromDocs == true; + + foreach (PropertyInfo prop in + configType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) + { + ConfigItemAttribute? configItemAttribute = prop.GetCustomAttribute(); + + if (configItemAttribute?.DisabledForCli != true) + { + CliOption option = prop.PropertyType == typeof(bool) + ? CreateOption(prop.Name, configType) + : CreateOption(prop.Name, configType); + option.Description = configItemAttribute?.Description; + option.HelpName = "value"; + option.Hidden = categoryHidden || configItemAttribute?.HiddenFromDocs == true; + + command.Add(option); + } + + if (configItemAttribute?.IsPortOption == true) + ConfigExtensions.AddPortOptionName(configType, prop.Name); + } + } +} + +void CheckForDeprecatedOptions(ParseResult parseResult) +{ + CliOption[] deprecatedOptions = + [ + BasicOptions.ConfigurationDirectory, + BasicOptions.DatabasePath, + BasicOptions.LoggerConfigurationSource, + BasicOptions.PluginsDirectory + ]; + + foreach (CliToken token in parseResult.Tokens) + { + foreach (CliOption option in deprecatedOptions) + { + if (option.Aliases.Contains(token.Value, StringComparison.Ordinal)) + logger.Warn($"{token} option is deprecated. Use {option.Name} instead."); + } + } +} + +CliConfiguration ConfigureCli() +{ + CliRootCommand rootCommand = + [ + BasicOptions.Configuration, + BasicOptions.ConfigurationDirectory, + BasicOptions.DatabasePath, + BasicOptions.DataDirectory, + BasicOptions.LoggerConfigurationSource, + BasicOptions.LogLevel, + BasicOptions.PluginsDirectory + ]; + + var versionOption = (VersionOption)rootCommand.Children.SingleOrDefault(c => c is VersionOption); + + if (versionOption is not null) + { + versionOption.Action = new AnonymousCliAction(parseResult => + { + parseResult.Configuration.Output.WriteLine($""" + Version: {ProductInfo.Version} + Commit: {ProductInfo.Commit} + Build date: {ProductInfo.BuildTimestamp:u} + Runtime: {ProductInfo.Runtime} + Platform: {ProductInfo.OS} {ProductInfo.OSArchitecture} + """); + + return ExitCodes.Ok; + }); + } + + return new(rootCommand) + { + EnableDefaultExceptionHandler = false, + ProcessTerminationTimeout = Timeout.InfiniteTimeSpan + }; +} + +void ConfigureLogger(ParseResult parseResult) +{ + string nLogConfig = Path.GetFullPath( + parseResult.GetValue(BasicOptions.LoggerConfigurationSource) + ?? "NLog.config".GetApplicationResourcePath()); + + try + { + LogManager.Configuration = new XmlLoggingConfiguration(nLogConfig); + } + catch (Exception ex) + { + logger.Error($"Failed to load logging configuration file.", ex); + return; + } + + using NLogManager logManager = new(); + + logger = logManager.GetClassLogger(); + + string? logLevel = parseResult.GetValue(BasicOptions.LogLevel); + + // TODO: dynamically switch log levels from CLI + if (logLevel is not null) + NLogConfigurator.ConfigureLogLevels(logLevel); +} + +void ConfigureSeqLogger(IConfigProvider configProvider) +{ + ISeqConfig seqConfig = configProvider.GetConfig(); + + if (!seqConfig.MinLevel.Equals("Off", StringComparison.Ordinal)) + { + if (logger.IsInfo) + logger.Info($"Seq logging is enabled on {seqConfig.ServerUrl} with level of {seqConfig.MinLevel}"); + + NLogConfigurator.ConfigureSeqBufferTarget(seqConfig.ServerUrl, seqConfig.ApiKey, seqConfig.MinLevel); + } + else + { + // Clear it up; otherwise, internally it will keep requesting localhost as `all` target includes this. + NLogConfigurator.ClearSeqTarget(); + } +} + +IConfigProvider CreateConfigProvider(ParseResult parseResult) +{ + ConfigProvider configProvider = new(); + Dictionary configArgs = []; + + foreach (SymbolResult child in parseResult.RootCommandResult.Children) + { + if (child is OptionResult result) + { + var isBoolean = result.Option.GetType().GenericTypeArguments.SingleOrDefault() == typeof(bool); + var value = isBoolean + ? result.GetValueOrDefault().ToString().ToLowerInvariant() + : result.GetValueOrDefault(); + + if (value is not null) + configArgs.Add(result.Option.Name.TrimStart('-'), value); + } + } + + IConfigSource argsSource = new ArgsConfigSource(configArgs); + configProvider.AddSource(argsSource); + configProvider.AddSource(new EnvConfigSource()); + + string configFile = parseResult.GetValue(BasicOptions.Configuration) + ?? Environment.GetEnvironmentVariable("NETHERMIND_CONFIG") + ?? "mainnet"; + + // If configFile is not a path, handle it + if (string.IsNullOrEmpty(Path.GetDirectoryName(configFile))) + { + string configsDir = parseResult.GetValue(BasicOptions.ConfigurationDirectory) + ?? "configs".GetApplicationResourcePath(); + + configFile = Path.Join(configsDir, configFile); + + // If the configFile doesn't have an extension, try with supported file extensions + if (!Path.HasExtension(configFile)) + { + string? fallback; + + foreach (var ext in new[] { ".json", ".cfg" }) + { + fallback = $"{configFile}{ext}"; + + if (File.Exists(fallback)) + { + configFile = fallback; + break; + } + } + } + // For backward compatibility. To be removed in the future. + else if (Path.GetExtension(configFile).Equals(".cfg", StringComparison.Ordinal)) + { + var name = Path.GetFileNameWithoutExtension(configFile)!; + + configFile = $"{configFile[..^4]}.json"; + + logger.Warn($"'{name}.cfg' is deprecated. Use '{name}' instead."); + } + } + + // Resolve the full path for logging purposes + configFile = Path.GetFullPath(configFile); + + if (!File.Exists(configFile)) + throw new FileNotFoundException("Configuration file not found.", configFile); + + logger.Info($"Loading configuration from {configFile}"); + + configProvider.AddSource(new JsonConfigSource(configFile)); + configProvider.Initialize(); + + var (ErrorMsg, Errors) = configProvider.FindIncorrectSettings(); + + if (Errors.Any()) + logger.Warn($"Invalid configuration settings:\n{ErrorMsg}"); + + return configProvider; +} + +ILogger GetCriticalLogger() +{ + try + { + return new NLogManager("nethermind.log").GetClassLogger(); + } + catch + { + if (logger.IsWarn) logger.Warn("File logging failed. Using console logging."); + + return logger; + } +} + +void ResolveDatabaseDirectory(string? path, IInitConfig initConfig) +{ + if (string.IsNullOrWhiteSpace(path)) + { + initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); + } + else + { + string dbPath = initConfig.BaseDbPath.GetApplicationResourcePath(path); + + if (logger.IsDebug) logger.Debug($"{nameof(initConfig.BaseDbPath)}: {Path.GetFullPath(dbPath)}"); + + initConfig.BaseDbPath = dbPath; + } +} + +void ResolveDataDirectory(string? path, IInitConfig initConfig, IKeyStoreConfig keyStoreConfig, ISnapshotConfig snapshotConfig) +{ + if (string.IsNullOrWhiteSpace(path)) + { + initConfig.BaseDbPath ??= string.Empty.GetApplicationResourcePath("db"); + keyStoreConfig.KeyStoreDirectory ??= string.Empty.GetApplicationResourcePath("keystore"); + initConfig.LogDirectory ??= string.Empty.GetApplicationResourcePath("logs"); + } + else + { + string newDbPath = initConfig.BaseDbPath.GetApplicationResourcePath(path); + string newKeyStorePath = keyStoreConfig.KeyStoreDirectory.GetApplicationResourcePath(path); + string newLogDirectory = initConfig.LogDirectory.GetApplicationResourcePath(path); + string newSnapshotPath = snapshotConfig.SnapshotDirectory.GetApplicationResourcePath(path); + + if (logger.IsInfo) + { + logger.Info($"{nameof(initConfig.BaseDbPath)}: {Path.GetFullPath(newDbPath)}"); + logger.Info($"{nameof(keyStoreConfig.KeyStoreDirectory)}: {Path.GetFullPath(newKeyStorePath)}"); + logger.Info($"{nameof(initConfig.LogDirectory)}: {Path.GetFullPath(newLogDirectory)}"); + + if (snapshotConfig.Enabled) + logger.Info($"{nameof(snapshotConfig.SnapshotDirectory)}: {Path.GetFullPath(newSnapshotPath)}"); + } + + initConfig.BaseDbPath = newDbPath; + keyStoreConfig.KeyStoreDirectory = newKeyStorePath; + initConfig.LogDirectory = newLogDirectory; + snapshotConfig.SnapshotDirectory = newSnapshotPath; + } +} + +static class BasicOptions +{ + public static CliOption Configuration { get; } = + new("--config", "-c") + { + Description = "The path to the configuration file or the file name (also without extension) of any of the configuration files in the configuration files directory.", + HelpName = "network or file name" + }; + + public static CliOption ConfigurationDirectory { get; } = + new("--configs-dir", "--configsDirectory", "-cd") + { + Description = "The path to the configuration files directory.", + HelpName = "path" + }; + + public static CliOption DatabasePath { get; } = new("--db-dir", "--baseDbPath", "-d") + { + Description = "The path to the Nethermind database directory.", + HelpName = "path" + }; + + public static CliOption DataDirectory { get; } = new("--data-dir", "--datadir", "-dd") + { + Description = "The path to the Nethermind data directory.", + HelpName = "path" + }; + + public static CliOption LoggerConfigurationSource { get; } = + new("--logger-config", "--loggerConfigSource", "-lcs") + { + Description = "The path to the logging configuration file.", + HelpName = "path" + }; + + public static CliOption LogLevel { get; } = new("--log", "-l") + { + Description = "Log level (severity). Allowed values: off, trace, debug, info, warn, error.", + HelpName = "level" + }; + + public static CliOption PluginsDirectory { get; } = + new("--plugins-dir", "--pluginsDirectory", "-pd") + { + Description = "The path to the Nethermind plugins directory.", + HelpName = "path" + }; +} + +class AnonymousCliAction(Func action) : SynchronousCliAction +{ + private readonly Func _action = action ?? throw new ArgumentNullException(nameof(action)); + + /// + public override int Invoke(ParseResult parseResult) => _action(parseResult); +} diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/copyright b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/copyright new file mode 100644 index 000000000..604c596ce --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/copyright @@ -0,0 +1,19 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: nethermind +Upstream-Contact: https://github.com/NethermindEth/nethermind/ +Source: + +Files: * +License: LGPL-3.0 + + +Files: debian/* +License: GPL-3+ + +License: LGPL-3.0 + The full text of the LGPL version 3.0 is distributed in + /usr/share/common-licenses/LGPL-3.0 on Debian systems. + +License: GPL-3+ + The full text of the GPL version 3 is distributed in + /usr/share/common-licenses/GPL-3 on Debian systems. \ No newline at end of file diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/eth-node-nethermind.lintian-overrides b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/eth-node-nethermind.lintian-overrides new file mode 100644 index 000000000..1137d695c --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/eth-node-nethermind.lintian-overrides @@ -0,0 +1,23 @@ +# Not a bug +eth-node-nethermind: embedded-library bzip2 * +eth-node-nethermind: embedded-library gmp * +eth-node-nethermind: embedded-library zlib * + +# Most likely a bug +eth-node-nethermind: library-not-linked-against-libc * + +eth-node-nethermind: executable-not-elf-or-script * + +eth-node-nethermind: initial-upload-closes-no-bugs [usr/share/doc/eth-node-nethermind/changelog.Debian.gz:1] +eth-node-nethermind: maintainer-script-ignores-errors [postrm] +eth-node-nethermind: no-manual-page [usr/bin/nethermind] + + +eth-node-nethermind: unstripped-binary-or-object * + +# TODO +eth-node-nethermind: extended-description-line-too-long line 1 +# TODO +eth-node-nethermind: copyright-without-copyright-notice +eth-node-nethermind: package-has-unnecessary-activation-of-ldconfig-trigger + diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/001-build-date.patch b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/001-build-date.patch new file mode 100644 index 000000000..dbf4fe785 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/001-build-date.patch @@ -0,0 +1,36 @@ +Index: eth-node-nethermind-1.32.1/src/Nethermind/Directory.Build.props +=================================================================== +--- eth-node-nethermind-1.32.1.orig/src/Nethermind/Directory.Build.props ++++ eth-node-nethermind-1.32.1/src/Nethermind/Directory.Build.props +@@ -13,7 +13,6 @@ + + + +- $([System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds()) + Demerzel Solutions Limited + Nethermind + $(Commit) +@@ -21,11 +20,4 @@ + + + +- +- +- <_Parameter1>BuildTimestamp +- <_Parameter2>$(BuildTimestamp) +- +- +- + +Index: eth-node-nethermind-1.32.1/src/Nethermind/Nethermind.Runner/Program.cs +=================================================================== +--- eth-node-nethermind-1.32.1.orig/src/Nethermind/Nethermind.Runner/Program.cs ++++ eth-node-nethermind-1.32.1/src/Nethermind/Nethermind.Runner/Program.cs +@@ -304,7 +304,6 @@ CliConfiguration ConfigureCli() + parseResult.Configuration.Output.WriteLine($""" + Version: {ProductInfo.Version} + Commit: {ProductInfo.Commit} +- Build date: {ProductInfo.BuildTimestamp:u} + Runtime: {ProductInfo.Runtime} + Platform: {ProductInfo.OS} {ProductInfo.OSArchitecture} + """); diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/series b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/series new file mode 100644 index 000000000..50eed271a --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/patches/series @@ -0,0 +1 @@ +001-build-date.patch diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/rules b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/rules new file mode 100644 index 000000000..af4181529 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/rules @@ -0,0 +1,47 @@ +#!/usr/bin/make -f +export CI=true +export DOTNET_CLI_TELEMETRY_OPTOUT=1 + +%: + dh $@ + +override_dh_auto_build: + cd src/Nethermind/Nethermind.Runner && dotnet build -c release + # Delete all other archs then x64 + find src/Nethermind/artifacts/obj -type f -name '*.AssemblyReference.cache' -delete + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/linux-arm64 + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/linux-arm + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/linux-musl-arm64 + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/linux-musl-arm + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/ios-arm64 + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/maccatalyst-arm64 + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/maccatalyst-x64 + rm -rf src/Nethermind/artifacts/bin/Nethermind.Runner/release/runtimes/tvos-arm64 + +# TODO fix tests +override_dh_auto_test: + # # Skip tests as they are failing + # # Run Nethermind tests: + # cd src/Nethermind && dotnet test Nethermind.sln -c release + # # Run Ethereum Foundation tests: + # # cd src/Nethermind && dotnet test EthereumTests.sln -c release + + +override_dh_auto_clean: + # on ubuntu clean fails, before dependency installation + # on bookworm clean succeeds, even if dependency is not installed + -make -j1 clean + + +override_dh_dwz: + # skip of optimization of DWARF debug information in ELF binaries via dwz + +override_dh_strip: + # error: strip --remove-section=.comment --remove-section=.note --strip-unneeded debian/eth-node-nethermind/usr/lib/eth-node-nethermind/bin/Nethermind.Runner/release/runtimes/linux-arm64/native/libgmp.so returned exit code 1 + +override_dh_shlibdeps: + # cannot find library libjemalloc.so.1 needed + dh_shlibdeps \ + --exclude=librocksdb-musl.so \ + --exclude=librocksdb-jemalloc.so \ + --dpkg-shlibdeps-params=--ignore-missing-info diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/source/lintian-overrides b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/source/lintian-overrides new file mode 100644 index 000000000..9b3278f7d --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/source/lintian-overrides @@ -0,0 +1,10 @@ +eth-node-nethermind source: source-is-missing * +eth-node-nethermind source: debian-rules-ignores-make-clean-error * + +# TODO +eth-node-nethermind source: missing-field-in-dep5-copyright Copyright [debian/copyright:10] + +#TODO +eth-node-nethermind source: missing-field-in-dep5-copyright Copyright [debian/copyright:6] + +eth-node-nethermind source: no-newline-at-end [debian/changelog] diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/control b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/control new file mode 100644 index 000000000..6cd635a1a --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/control @@ -0,0 +1,7 @@ +# These tests are run by autopkgtests + +Tests: tests +Depends: @, shunit2, which + +Tests: tests-with-dotnet +Depends: @, shunit2, which, aspnetcore-runtime-8.0 \ No newline at end of file diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests new file mode 100644 index 000000000..ec3bcd929 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +exec 2>&1 + +set -e + +test_binary_in_path(){ + output="$(which nethermind)" + assertEquals "/usr/bin/nethermind" "$output" +} + + +test_invocation_without_dotnet(){ + output="$(nethermind 2>&1 || true)" + assertContains "You must install .NET to run this application." "$output" +} + +. shunit2 \ No newline at end of file diff --git a/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests-with-dotnet b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests-with-dotnet new file mode 100644 index 000000000..9c668d9f3 --- /dev/null +++ b/upcoming/bookworm/amd64/eth-node-nethermind/1.33.1-1/src/debian/tests/tests-with-dotnet @@ -0,0 +1,23 @@ +#!/usr/bin/env sh + +exec 2>&1 + +set -e + +test_binary_in_path(){ + ls -la /usr/lib/eth-node-nethermind/bin || true + ls -la /usr/lib/eth-node-nethermind/bin/Nethermind.Runner || true + output="$(which nethermind)" + assertEquals "/usr/bin/nethermind" "$output" +} + +# test_invocation_with_dotnet(){ +# output="$(nethermind --version)" +# echo "$output" +# # checked against https://github.com/NethermindEth/nethermind/releases/download/1.21.1/nethermind-1.21.1-9b435ba0-linux-x64.zip +# assertContains "$output" "Version: 1.27.0 +# OS: Linux x64 +# Runtime: .NET 7.0.18" +# } + +. shunit2 \ No newline at end of file