![]() |
VOOZH | about |
dotnet add package Nethereum.Consensus.LightClient --version 6.1.0
NuGet\Install-Package Nethereum.Consensus.LightClient -Version 6.1.0
<PackageReference Include="Nethereum.Consensus.LightClient" Version="6.1.0" />
<PackageVersion Include="Nethereum.Consensus.LightClient" Version="6.1.0" />Directory.Packages.props
<PackageReference Include="Nethereum.Consensus.LightClient" />Project file
paket add Nethereum.Consensus.LightClient --version 6.1.0
#r "nuget: Nethereum.Consensus.LightClient, 6.1.0"
#:package Nethereum.Consensus.LightClient@6.1.0
#addin nuget:?package=Nethereum.Consensus.LightClient&version=6.1.0Install as a Cake Addin
#tool nuget:?package=Nethereum.Consensus.LightClient&version=6.1.0Install as a Cake Tool
Ethereum beacon chain light client implementation for synchronizing with the consensus layer using minimal trust assumptions. Provides BLS signature verification, sync committee validation, and trusted execution header tracking for secure access to Ethereum state without running a full node.
dotnet add package Nethereum.Consensus.LightClient
dotnet add package Nethereum.Signer.Bls.Herumi # For BLS signature verification
Native Library Requirement: BLS signature verification requires the Herumi BLS native library (bls_eth.dll/libbls_eth.so/libbls_eth.dylib). The library is included in the Nethereum.Signer.Bls.Herumi NuGet package for Windows/Linux/macOS x64/arm64.
Nethereum.Consensus.LightClient implements the Ethereum light client sync protocol, enabling applications to verify beacon chain consensus with cryptographic security while maintaining minimal resource requirements. The light client tracks sync committees, verifies BLS aggregate signatures, and maintains finalized and optimistic execution headers.
Key Features:
Security Model:
Main orchestrator for light client synchronization (LightClientService.cs:14-393).
Initialization:
// LightClientService.cs:36-68
public async Task InitializeAsync(CancellationToken cancellationToken = default)
{
_state = await _store.LoadAsync().ConfigureAwait(false);
if (_state != null)
{
return; // Already initialized from persistent storage
}
// Bootstrap from weak subjectivity checkpoint
var blockRootHex = _config.WeakSubjectivityRoot.ToHex(true);
var response = await _apiClient.GetBootstrapAsync(blockRootHex).ConfigureAwait(false);
var bootstrap = LightClientResponseMapper.ToDomain(response);
ValidateBootstrap(bootstrap);
_state = new LightClientState
{
FinalizedHeader = bootstrap.Header.Beacon,
FinalizedExecutionPayload = bootstrap.Header.Execution,
CurrentSyncCommittee = bootstrap.CurrentSyncCommittee,
NextSyncCommittee = bootstrap.CurrentSyncCommittee,
FinalizedSlot = bootstrap.Header.Beacon.Slot,
CurrentPeriod = ComputePeriod(bootstrap.Header.Beacon.Slot),
LastUpdated = DateTimeOffset.UtcNow
};
await _store.SaveAsync(_state).ConfigureAwait(false);
}
Update Methods:
BLS Signature Verification:
// LightClientService.cs:280-306
private bool VerifySyncAggregateCore(byte[] bits, byte[] signature, BeaconBlockHeader attestedHeader)
{
if (bits.Length != SszBasicTypes.SyncCommitteeSize / 8)
{
return false;
}
// Select participating validators from sync committee
var participants = SelectParticipantPubKeys(_state.CurrentSyncCommittee, bits);
if (participants.Count == 0)
{
return false;
}
// Compute domain and signing root
var domain = ComputeSyncCommitteeDomain();
var message = ComputeSigningRoot(attestedHeader.HashTreeRoot(), domain);
if (message == null || message.Length == 0)
{
return false;
}
// Verify BLS aggregate signature
return _bls.VerifyAggregate(signature, participants.ToArray(), new[] { message }, domain);
}
Participant Selection:
// LightClientService.cs:319-343
private List<byte[]> SelectParticipantPubKeys(SyncCommittee committee, byte[] bits)
{
var pubKeys = committee?.PubKeys;
var participants = new List<byte[]>();
if (pubKeys == null || pubKeys.Count == 0 || bits == null)
{
return participants;
}
// Extract participating validators from bitfield
var memberIndex = 0;
for (var byteIndex = 0; byteIndex < bits.Length && memberIndex < pubKeys.Count; byteIndex++)
{
var value = bits[byteIndex];
for (var bitIndex = 0; bitIndex < 8 && memberIndex < pubKeys.Count; bitIndex++, memberIndex++)
{
if ((value & (1 << bitIndex)) != 0)
{
participants.Add(pubKeys[memberIndex]);
}
}
}
return participants;
}
Tracks finalized and optimistic consensus state (LightClientState.cs:7-73).
// LightClientState.cs:7-26
public class LightClientState
{
public const int MaxBlockHashHistorySize = 256;
public BeaconBlockHeader? FinalizedHeader { get; set; }
public ExecutionPayloadHeader? FinalizedExecutionPayload { get; set; }
public SyncCommittee? CurrentSyncCommittee { get; set; }
public SyncCommittee? NextSyncCommittee { get; set; }
public ulong FinalizedSlot { get; set; }
public ulong CurrentPeriod { get; set; }
public DateTimeOffset LastUpdated { get; set; }
public BeaconBlockHeader? OptimisticHeader { get; set; }
public ExecutionPayloadHeader? OptimisticExecutionPayload { get; set; }
public ulong OptimisticSlot { get; set; }
public DateTimeOffset OptimisticLastUpdated { get; set; }
public Dictionary<ulong, byte[]> BlockHashHistory { get; set; } = new Dictionary<ulong, byte[]>();
}
Block Hash Management:
// LightClientState.cs:27-43
public void AddBlockHash(ulong blockNumber, byte[] blockHash)
{
if (blockHash == null || blockHash.Length != 32) return;
BlockHashHistory[blockNumber] = blockHash;
// Automatic pruning when exceeding max size
if (BlockHashHistory.Count > MaxBlockHashHistorySize)
{
PruneOldestEntries();
}
}
public byte[] GetBlockHash(ulong blockNumber)
{
return BlockHashHistory.TryGetValue(blockNumber, out var hash) ? hash : null;
}
Configuration for light client initialization (LightClientConfig.cs:8-16).
// LightClientConfig.cs:8-16
public class LightClientConfig
{
public byte[] GenesisValidatorsRoot { get; set; } = Array.Empty<byte>();
public byte[] CurrentForkVersion { get; set; } = new byte[4];
public ulong SlotsPerEpoch { get; set; } = 32;
public ulong SecondsPerSlot { get; set; } = 12;
public byte[] WeakSubjectivityRoot { get; set; } = Array.Empty<byte>();
public ulong WeakSubjectivityPeriod { get; set; } = 256 * 32; // ~27 hours
}
Provides trusted execution headers with staleness detection (TrustedHeaderProvider.cs:6-103).
// TrustedHeaderProvider.cs:6-31
public class TrustedHeaderProvider : ITrustedHeaderProvider
{
private readonly LightClientService _lightClient;
public TimeSpan FinalizedStalenessThreshold { get; set; } = TimeSpan.FromMinutes(30);
public TimeSpan OptimisticStalenessThreshold { get; set; } = TimeSpan.FromMinutes(5);
public bool ThrowOnStaleHeader { get; set; } = false;
public event EventHandler<StaleHeaderEventArgs> StaleHeaderDetected;
public TrustedExecutionHeader GetLatestFinalized()
{
var state = _lightClient.GetState();
if (state.FinalizedExecutionPayload == null || state.FinalizedHeader == null)
{
throw new InvalidOperationException("Light client state does not include a finalized execution payload yet.");
}
var header = MapToHeader(state.FinalizedExecutionPayload);
ValidateStaleness(header, state.LastUpdated, FinalizedStalenessThreshold, "Finalized");
return header;
}
}
Staleness Validation:
// TrustedHeaderProvider.cs:57-73
private void ValidateStaleness(TrustedExecutionHeader header, DateTimeOffset lastUpdated,
TimeSpan threshold, string headerType)
{
var age = DateTimeOffset.UtcNow - lastUpdated;
if (age > threshold)
{
var args = new StaleHeaderEventArgs(headerType, age, threshold, header);
StaleHeaderDetected?.Invoke(this, args);
if (ThrowOnStaleHeader)
{
throw new StaleHeaderException(
$"{headerType} header is stale. Age: {age.TotalMinutes:F1} minutes, Threshold: {threshold.TotalMinutes:F1} minutes.",
age, threshold);
}
}
}
Persistent storage abstraction for light client state (ILightClientStore.cs:5-10).
// ILightClientStore.cs:5-10
public interface ILightClientStore
{
Task<LightClientState?> LoadAsync();
Task SaveAsync(LightClientState state);
}
InMemoryLightClientStore:
// InMemoryLightClientStore.cs:8-19
public class InMemoryLightClientStore : ILightClientStore
{
private LightClientState? _state;
public Task<LightClientState?> LoadAsync() => Task.FromResult(_state);
public Task SaveAsync(LightClientState state)
{
_state = state;
return Task.CompletedTask;
}
}
Execution layer header extracted from consensus layer (TrustedExecutionHeader.cs:8-16).
// TrustedExecutionHeader.cs:8-16
public class TrustedExecutionHeader
{
public byte[] BlockHash { get; set; } = Array.Empty<byte>();
public ulong BlockNumber { get; set; }
public byte[] StateRoot { get; set; } = Array.Empty<byte>();
public byte[] ReceiptsRoot { get; set; } = Array.Empty<byte>();
public DateTimeOffset Timestamp { get; set; }
}
using Nethereum.Consensus.LightClient;
using Nethereum.Beaconchain;
using Nethereum.Beaconchain.LightClient;
using Nethereum.Signer.Bls;
using Nethereum.Signer.Bls.Herumi;
using Nethereum.Hex.HexConvertors.Extensions;
// Source: LightClientLiveIntegrationTests.cs:76-112
// Get recent finalized checkpoint from beacon node
var beaconClient = new BeaconApiClient("https://ethereum-beacon-api.publicnode.com");
var response = await beaconClient.LightClient.GetFinalityUpdateAsync();
var finalityUpdate = LightClientResponseMapper.ToDomain(response);
var weakSubjectivityRoot = finalityUpdate.FinalizedHeader.Beacon.HashTreeRoot();
Console.WriteLine($"Using weak subjectivity root: {weakSubjectivityRoot.ToHex(true)}");
// Mainnet configuration (LightClientLiveIntegrationTests.cs:289-299)
var config = new LightClientConfig
{
GenesisValidatorsRoot = "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95".HexToByteArray(),
CurrentForkVersion = "0x06000000".HexToByteArray(), // Electra fork
SlotsPerEpoch = 32,
SecondsPerSlot = 12,
WeakSubjectivityRoot = weakSubjectivityRoot
};
// Initialize BLS verification with Herumi native library
var nativeBls = new NativeBls(new HerumiNativeBindings());
await nativeBls.InitializeAsync();
var store = new InMemoryLightClientStore();
var lightClient = new LightClientService(beaconClient.LightClient, nativeBls, config, store);
// Bootstrap from checkpoint
await lightClient.InitializeAsync();
var state = lightClient.GetState();
Console.WriteLine($"Light client initialized at slot: {state.FinalizedSlot}");
Console.WriteLine($"Block number: {state.FinalizedExecutionPayload.BlockNumber}");
Console.WriteLine($"Block hash: {state.FinalizedExecutionPayload.BlockHash.ToHex(true)}");
// Apply updates
var updated = await lightClient.UpdateAsync();
Console.WriteLine($"Update applied: {updated}");
using Nethereum.Consensus.LightClient;
// Periodic update loop
while (true)
{
try
{
// Update finalized state (processes up to 4 periods)
bool updated = await lightClient.UpdateAsync();
if (updated)
{
var state = lightClient.GetState();
Console.WriteLine($"Updated to slot {state.FinalizedSlot}");
Console.WriteLine($"Current period: {state.CurrentPeriod}");
Console.WriteLine($"Block number: {state.FinalizedExecutionPayload?.BlockNumber}");
}
else
{
Console.WriteLine("No updates available");
}
// Wait before next update (typical: every epoch or period)
await Task.Delay(TimeSpan.FromMinutes(5));
}
catch (Exception ex)
{
Console.WriteLine($"Update failed: {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(30));
}
}
using Nethereum.Consensus.LightClient;
// Update optimistic (latest) header more frequently
while (true)
{
// Optimistic updates happen every slot (~12 seconds)
bool updated = await lightClient.UpdateOptimisticAsync();
if (updated)
{
var state = lightClient.GetState();
Console.WriteLine($"Optimistic slot: {state.OptimisticSlot}");
Console.WriteLine($"Optimistic block: {state.OptimisticExecutionPayload?.BlockNumber}");
Console.WriteLine($"Age: {(DateTimeOffset.UtcNow - state.OptimisticLastUpdated).TotalSeconds:F1}s");
}
await Task.Delay(TimeSpan.FromSeconds(12)); // One slot
}
using Nethereum.Consensus.LightClient;
// Create trusted header provider
var headerProvider = new TrustedHeaderProvider(lightClient)
{
FinalizedStalenessThreshold = TimeSpan.FromMinutes(30),
OptimisticStalenessThreshold = TimeSpan.FromMinutes(5),
ThrowOnStaleHeader = false
};
// Subscribe to staleness events
headerProvider.StaleHeaderDetected += (sender, args) =>
{
Console.WriteLine($"{args.HeaderType} header is stale!");
Console.WriteLine($"Age: {args.Age.TotalMinutes:F1} minutes");
Console.WriteLine($"Threshold: {args.Threshold.TotalMinutes:F1} minutes");
};
// Get finalized header (2/3 finality guarantee)
var finalized = headerProvider.GetLatestFinalized();
Console.WriteLine($"Finalized block: {finalized.BlockNumber}");
Console.WriteLine($"Block hash: {finalized.BlockHash.ToHex(true)}");
Console.WriteLine($"State root: {finalized.StateRoot.ToHex(true)}");
// Get optimistic header (latest, may reorg)
var optimistic = headerProvider.GetLatestOptimistic();
Console.WriteLine($"Optimistic block: {optimistic.BlockNumber}");
Console.WriteLine($"Timestamp: {optimistic.Timestamp}");
using Nethereum.Consensus.LightClient;
using Nethereum.ChainStateVerification;
using Nethereum.JsonRpc.Client;
using Nethereum.RPC.Eth;
using Nethereum.Beaconchain;
using Nethereum.Signer.Bls.Herumi;
// Source: LightClientLiveIntegrationTests.cs:115-162
// Initialize light client (see Example 1)
var beaconClient = new BeaconApiClient("https://ethereum-beacon-api.publicnode.com");
var response = await beaconClient.LightClient.GetFinalityUpdateAsync();
var finalityUpdate = LightClientResponseMapper.ToDomain(response);
var weakSubjectivityRoot = finalityUpdate.FinalizedHeader.Beacon.HashTreeRoot();
var config = new LightClientConfig
{
GenesisValidatorsRoot = "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95".HexToByteArray(),
CurrentForkVersion = "0x06000000".HexToByteArray(),
SlotsPerEpoch = 32,
SecondsPerSlot = 12,
WeakSubjectivityRoot = weakSubjectivityRoot
};
var nativeBls = new NativeBls(new HerumiNativeBindings());
await nativeBls.InitializeAsync();
var store = new InMemoryLightClientStore();
var lightClient = new LightClientService(beaconClient.LightClient, nativeBls, config, store);
await lightClient.InitializeAsync();
// Create verified state service
var trustedProvider = new TrustedHeaderProvider(lightClient);
var rpcClient = new RpcClient(new Uri("https://mainnet.infura.io/v3/YOUR_KEY"));
var ethGetProof = new EthGetProof(rpcClient);
var ethGetCode = new EthGetCode(rpcClient);
var trieVerifier = new TrieProofVerifier();
var verifiedState = new VerifiedStateService(trustedProvider, ethGetProof, ethGetCode, trieVerifier);
verifiedState.Mode = VerificationMode.Finalized;
// Query account balance with cryptographic proof verification
var accountAddress = "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B";
var balance = await verifiedState.GetBalanceAsync(accountAddress);
var balanceInEth = (decimal)balance / 1_000_000_000_000_000_000m;
Console.WriteLine($"Account: {accountAddress}");
Console.WriteLine($"Balance: {balance} wei ({balanceInEth:F4} ETH)");
// Query nonce
var nonce = await verifiedState.GetNonceAsync(accountAddress);
Console.WriteLine($"Nonce: {nonce}");
// Get current header being verified against
var header = verifiedState.GetCurrentHeader();
Console.WriteLine($"Verified at block: {header.BlockNumber}");
Console.WriteLine($"State root: {header.StateRoot.ToHex(true)}");
// Optimistic mode for lower latency (may reorg)
await lightClient.UpdateOptimisticAsync();
verifiedState.Mode = VerificationMode.Optimistic;
var optimisticBalance = await verifiedState.GetBalanceAsync(accountAddress);
Console.WriteLine($"Optimistic balance: {optimisticBalance} wei");
Note: VerifiedStateService validates all data against merkle proofs from the light client's trusted state root. This provides trustless verification without requiring a full node.
Archive Node Requirement: State proof verification requires an archive node or a node with sufficient historical state. Standard pruned nodes may return errors like "missing trie node" or "old data not available due to pruning" for older blocks (LightClientLiveIntegrationTests.cs:369-372). Use recent finalized blocks or an archive node endpoint for historical queries.
using Nethereum.Consensus.LightClient;
var headerProvider = new TrustedHeaderProvider(lightClient);
// Light client maintains last 256 block hashes
ulong blockNumber = 15537394;
byte[] blockHash = headerProvider.GetBlockHash(blockNumber);
if (blockHash != null)
{
Console.WriteLine($"Block {blockNumber}: {blockHash.ToHex(true)}");
}
else
{
Console.WriteLine($"Block {blockNumber} not in history");
}
// Access current state
var state = lightClient.GetState();
Console.WriteLine($"History size: {state.BlockHashHistory.Count}");
Console.WriteLine($"Finalized block: {state.FinalizedExecutionPayload?.BlockNumber}");
using Nethereum.Consensus.LightClient;
using System.IO;
using System.Text.Json;
// Custom persistent store
public class FileLightClientStore : ILightClientStore
{
private readonly string _filePath;
public FileLightClientStore(string filePath)
{
_filePath = filePath;
}
public async Task<LightClientState?> LoadAsync()
{
if (!File.Exists(_filePath))
{
return null;
}
var json = await File.ReadAllTextAsync(_filePath);
return JsonSerializer.Deserialize<LightClientState>(json);
}
public async Task SaveAsync(LightClientState state)
{
var json = JsonSerializer.Serialize(state, new JsonSerializerOptions
{
WriteIndented = true
});
await File.WriteAllTextAsync(_filePath, json);
}
}
// Usage
var store = new FileLightClientStore("lightclient-state.json");
var lightClient = new LightClientService(apiClient, bls, config, store);
// State persists across restarts
await lightClient.InitializeAsync();
using Nethereum.Consensus.LightClient;
// Combined update strategy
async Task UpdateLightClientAsync()
{
// Update finalized state (slower, ~6-13 minutes)
bool finalityUpdated = await lightClient.UpdateFinalityAsync();
if (finalityUpdated)
{
var state = lightClient.GetState();
Console.WriteLine($"Finality updated to slot {state.FinalizedSlot}");
Console.WriteLine($"Block {state.FinalizedExecutionPayload?.BlockNumber} is finalized");
}
// Update optimistic state (faster, ~12 seconds)
bool optimisticUpdated = await lightClient.UpdateOptimisticAsync();
if (optimisticUpdated)
{
var state = lightClient.GetState();
Console.WriteLine($"Optimistic updated to slot {state.OptimisticSlot}");
Console.WriteLine($"Latest block: {state.OptimisticExecutionPayload?.BlockNumber}");
Console.WriteLine($"Note: May reorg before finality");
}
}
// Finalized: Guaranteed by 2/3 validators (cannot reorg)
// Optimistic: Latest attestation (small reorg risk)
using Nethereum.Consensus.LightClient;
// Monitor sync committee rotation
var previousPeriod = lightClient.GetState().CurrentPeriod;
await lightClient.UpdateAsync();
var state = lightClient.GetState();
if (state.CurrentPeriod > previousPeriod)
{
Console.WriteLine($"Sync committee rotated!");
Console.WriteLine($"Old period: {previousPeriod}");
Console.WriteLine($"New period: {state.CurrentPeriod}");
Console.WriteLine($"Current committee updated");
// Sync committees rotate every 256 epochs (~27 hours)
// LightClientService automatically handles rotation
}
using Nethereum.Consensus.LightClient;
using Nethereum.Beaconchain;
using Nethereum.Signer.Bls.Herumi;
using Nethereum.Hex.HexConvertors.Extensions;
public class EthereumLightClient
{
private readonly LightClientService _lightClient;
private readonly TrustedHeaderProvider _headerProvider;
private readonly NativeBls _nativeBls;
private readonly CancellationTokenSource _cts = new();
public EthereumLightClient(string beaconNodeUrl, byte[] checkpointRoot)
{
var config = new LightClientConfig
{
GenesisValidatorsRoot = "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95".HexToByteArray(),
CurrentForkVersion = "0x06000000".HexToByteArray(), // Electra
SlotsPerEpoch = 32,
SecondsPerSlot = 12,
WeakSubjectivityRoot = checkpointRoot
};
var beaconClient = new BeaconApiClient(beaconNodeUrl);
_nativeBls = new NativeBls(new HerumiNativeBindings());
var store = new FileLightClientStore("lightclient.json");
_lightClient = new LightClientService(beaconClient.LightClient, _nativeBls, config, store);
_headerProvider = new TrustedHeaderProvider(_lightClient)
{
ThrowOnStaleHeader = false
};
_headerProvider.StaleHeaderDetected += OnStaleHeader;
}
public async Task InitializeAsync()
{
await _nativeBls.InitializeAsync();
}
public async Task StartAsync()
{
await InitializeAsync();
await _lightClient.InitializeAsync(_cts.Token);
Console.WriteLine("Light client started");
// Background update loop
_ = Task.Run(async () =>
{
while (!_cts.Token.IsCancellationRequested)
{
try
{
await _lightClient.UpdateAsync(_cts.Token);
await _lightClient.UpdateOptimisticAsync(_cts.Token);
}
catch (Exception ex)
{
Console.WriteLine($"Update error: {ex.Message}");
}
await Task.Delay(TimeSpan.FromSeconds(12), _cts.Token);
}
}, _cts.Token);
}
public TrustedExecutionHeader GetLatestBlock()
{
return _headerProvider.GetLatestOptimistic();
}
public TrustedExecutionHeader GetFinalizedBlock()
{
return _headerProvider.GetLatestFinalized();
}
public byte[] GetBlockHash(ulong blockNumber)
{
return _headerProvider.GetBlockHash(blockNumber);
}
private void OnStaleHeader(object sender, StaleHeaderEventArgs e)
{
Console.WriteLine($"Warning: {e.HeaderType} header is stale");
Console.WriteLine($"Age: {e.Age.TotalMinutes:F1} min, Threshold: {e.Threshold.TotalMinutes:F1} min");
}
public async Task StopAsync()
{
_cts.Cancel();
await Task.Delay(100);
_cts.Dispose();
}
}
// Usage - get checkpoint from beacon node first
var beaconApi = new BeaconApiClient("https://ethereum-beacon-api.publicnode.com");
var finalityUpdate = await beaconApi.LightClient.GetFinalityUpdateAsync();
var checkpoint = LightClientResponseMapper.ToDomain(finalityUpdate).FinalizedHeader.Beacon.HashTreeRoot();
var client = new EthereumLightClient("https://ethereum-beacon-api.publicnode.com", checkpoint);
await client.StartAsync(); // Calls InitializeAsync() then begins background updates
// Access trusted headers
var latest = client.GetLatestBlock();
Console.WriteLine($"Latest block: {latest.BlockNumber}");
var finalized = client.GetFinalizedBlock();
Console.WriteLine($"Finalized block: {finalized.BlockNumber}");
Light clients require a trusted checkpoint to bootstrap securely:
512 validators selected for light client consensus:
Finalized:
Optimistic:
Light client maintains last 256 execution block hashes:
Required Trust:
Cryptographic Security:
Long-Range Attacks:
Eclipse Attacks:
Staleness Attacks:
Update Frequency:
Checkpoint Management:
Storage:
Error Handling:
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 net6.0 is compatible. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 2 NuGet packages that depend on Nethereum.Consensus.LightClient:
| Package | Downloads |
|---|---|
|
Nethereum.ChainStateVerification
Verified execution-state primitives (account/storage/receipt proofs rooted in the light client). |
|
|
Nethereum.Wallet
Core wallet services for managing accounts, vaults, and configuration across the Nethereum stack. |
This package is not used by any popular GitHub repositories.