Skip to content

Commit 90bce97

Browse files
Nethereum.DevChain: SQLite storage, hosted service, CLI overhaul, thread-safe impersonation
DevChain library: add SQLite storage implementations (block, tx, receipt, log, state, trie, state-diff), thread-safe NextBlock overrides in DevChainConfig, refactored BlockManager with SemaphoreSlim mine lock and auto-mine batch loop, simplified DevChainNode constructors with factory methods. Tracing moved to CoreChain. DevChain.Server: full CLI with short flags, startup banner, appsettings.json support, DevChainHostedService for graceful lifecycle, persistent/in-memory storage modes, CORS, 10MB body limit, batch JSON-RPC. Server packaged as dotnet tool (nethereum-devchain). Thread-safe account impersonation. Updated to net10.0 and Microsoft.Extensions 10.0.0. Comprehensive READMEs with Aspire integration docs.
1 parent b040698 commit 90bce97

27 files changed

Lines changed: 3058 additions & 1009 deletions

src/Nethereum.DevChain.Server/Accounts/DevAccountManager.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ public class DevAccountManager
88
{
99
private readonly List<DevAccount> _accounts = new();
1010
private readonly HashSet<string> _impersonatedAccounts = new(StringComparer.OrdinalIgnoreCase);
11+
private readonly object _impersonationLock = new();
1112
private readonly MinimalHDWallet _wallet;
1213
private readonly BigInteger _chainId;
1314

1415
public IReadOnlyList<DevAccount> Accounts => _accounts;
15-
public IReadOnlySet<string> ImpersonatedAccounts => _impersonatedAccounts;
1616

1717
public DevAccountManager(DevChainServerConfig config)
1818
{
@@ -49,22 +49,23 @@ public bool IsDevAccount(string address)
4949

5050
public bool CanSign(string address)
5151
{
52-
return IsDevAccount(address) || _impersonatedAccounts.Contains(address);
52+
if (IsDevAccount(address)) return true;
53+
lock (_impersonationLock) { return _impersonatedAccounts.Contains(address); }
5354
}
5455

5556
public void ImpersonateAccount(string address)
5657
{
57-
_impersonatedAccounts.Add(address);
58+
lock (_impersonationLock) { _impersonatedAccounts.Add(address); }
5859
}
5960

6061
public void StopImpersonatingAccount(string address)
6162
{
62-
_impersonatedAccounts.Remove(address);
63+
lock (_impersonationLock) { _impersonatedAccounts.Remove(address); }
6364
}
6465

6566
public bool IsImpersonated(string address)
6667
{
67-
return _impersonatedAccounts.Contains(address);
68+
lock (_impersonationLock) { return _impersonatedAccounts.Contains(address); }
6869
}
6970

7071
public string[] GetAllAddresses()

src/Nethereum.DevChain.Server/Configuration/DevChainServerConfig.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,41 @@ public class DevChainServerConfig
1212
public int ChainId { get; set; } = 31337;
1313
public long BlockGasLimit { get; set; } = 30_000_000;
1414
public bool AutoMine { get; set; } = true;
15+
public long BlockTime { get; set; } = 0;
1516
public int AccountCount { get; set; } = 10;
1617
public string Mnemonic { get; set; } = DefaultMnemonic;
1718
public string AccountBalance { get; set; } = "10000000000000000000000";
1819
public ForkConfig? Fork { get; set; }
1920
public bool Verbose { get; set; } = false;
2021
public int AutoMineBatchSize { get; set; } = 1;
2122
public int AutoMineBatchTimeoutMs { get; set; } = 10;
22-
public string Storage { get; set; } = "memory";
23+
public int MaxTransactionsPerBlock { get; set; } = 10000;
24+
public string Storage { get; set; } = "sqlite";
2325
public string DataDir { get; set; } = "./chaindata";
26+
public bool Persist { get; set; } = false;
2427

2528
public BigInteger GetAccountBalance()
2629
{
2730
return BigInteger.Parse(AccountBalance);
2831
}
2932

33+
public void SetAccountBalanceEth(string ethAmount)
34+
{
35+
var eth = BigInteger.Parse(ethAmount);
36+
AccountBalance = (eth * BigInteger.Parse("1000000000000000000")).ToString();
37+
}
38+
3039
public DevChainConfig ToDevChainConfig()
3140
{
3241
return new DevChainConfig
3342
{
3443
ChainId = ChainId,
3544
BlockGasLimit = BlockGasLimit,
3645
AutoMine = AutoMine,
46+
BlockTime = BlockTime,
3747
AutoMineBatchSize = AutoMineBatchSize,
3848
AutoMineBatchTimeoutMs = AutoMineBatchTimeoutMs,
49+
MaxTransactionsPerBlock = MaxTransactionsPerBlock,
3950
InitialBalance = GetAccountBalance(),
4051
ForkUrl = Fork?.Url,
4152
ForkBlockNumber = Fork?.BlockNumber
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System.Linq;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.Hosting;
4+
using Microsoft.Extensions.Logging;
5+
using Nethereum.DevChain;
6+
using Nethereum.DevChain.Server.Accounts;
7+
8+
namespace Nethereum.DevChain.Server.Hosting
9+
{
10+
public class DevChainHostedService : IHostedService, IDisposable
11+
{
12+
private readonly DevChainNode _node;
13+
private readonly DevAccountManager _accountManager;
14+
private readonly IServiceProvider _serviceProvider;
15+
private readonly ILogger<DevChainHostedService>? _logger;
16+
private bool _stopped;
17+
18+
public bool AlreadyStarted { get; set; }
19+
20+
public DevChainHostedService(
21+
DevChainNode node,
22+
DevAccountManager accountManager,
23+
IServiceProvider serviceProvider,
24+
ILogger<DevChainHostedService>? logger = null)
25+
{
26+
_node = node;
27+
_accountManager = accountManager;
28+
_serviceProvider = serviceProvider;
29+
_logger = logger;
30+
}
31+
32+
public async Task StartAsync(CancellationToken cancellationToken)
33+
{
34+
if (AlreadyStarted)
35+
{
36+
_logger?.LogInformation("DevChain node already started, skipping");
37+
return;
38+
}
39+
40+
_logger?.LogInformation("Starting DevChain node...");
41+
await _node.StartAsync(_accountManager.Accounts.Select(a => a.Address));
42+
_logger?.LogInformation("DevChain node started");
43+
}
44+
45+
public Task StopAsync(CancellationToken cancellationToken)
46+
{
47+
if (_stopped) return Task.CompletedTask;
48+
_stopped = true;
49+
50+
_logger?.LogInformation("Stopping DevChain node...");
51+
52+
if (_node is IDisposable disposable)
53+
disposable.Dispose();
54+
55+
var sqliteManager = _serviceProvider.GetService<Nethereum.DevChain.Storage.Sqlite.SqliteStorageManager>();
56+
sqliteManager?.Dispose();
57+
58+
_logger?.LogInformation("DevChain node stopped");
59+
return Task.CompletedTask;
60+
}
61+
62+
public void Dispose()
63+
{
64+
if (!_stopped && _node is IDisposable disposable)
65+
disposable.Dispose();
66+
}
67+
}
68+
}

src/Nethereum.DevChain.Server/Nethereum.DevChain.Server.csproj

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
<PropertyGroup>
55
<OutputType>Exe</OutputType>
6-
<TargetFramework>net9.0</TargetFramework>
6+
<TargetFramework>$(ServerFrameworks)</TargetFramework>
77
<ImplicitUsings>enable</ImplicitUsings>
88
<Nullable>enable</Nullable>
99
<RootNamespace>Nethereum.DevChain.Server</RootNamespace>
1010

11-
<!-- AOT Configuration (disabled for RocksDB compatibility)
11+
<!-- AOT Configuration
1212
<PublishAot>true</PublishAot>
1313
<IsAotCompatible>true</IsAotCompatible>
1414
-->
@@ -42,18 +42,17 @@
4242
<ItemGroup>
4343
<ProjectReference Include="..\Nethereum.DevChain\Nethereum.DevChain.csproj" />
4444
<ProjectReference Include="..\Nethereum.CoreChain\Nethereum.CoreChain.csproj" />
45-
<ProjectReference Include="..\Nethereum.CoreChain.RocksDB\Nethereum.CoreChain.RocksDB.csproj" />
4645
<ProjectReference Include="..\Nethereum.Web3\Nethereum.Web3.csproj" />
4746
<ProjectReference Include="..\Nethereum.JsonRpc.Client\Nethereum.JsonRpc.Client.csproj" />
4847
<ProjectReference Include="..\Nethereum.JsonRpc.RpcClient\Nethereum.JsonRpc.RpcClient.csproj" />
4948
<ProjectReference Include="..\Nethereum.Signer\Nethereum.Signer.csproj" />
5049
</ItemGroup>
5150

5251
<ItemGroup>
53-
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
54-
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
55-
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="9.0.0" />
56-
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
52+
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
53+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.0" />
54+
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="10.0.0" />
55+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
5756
</ItemGroup>
5857

5958
<ItemGroup>

0 commit comments

Comments
 (0)