Nethereum.Merkle.Patricia
7.0.0
Prefix Reserved
dotnet add package Nethereum.Merkle.Patricia --version 7.0.0
NuGet\Install-Package Nethereum.Merkle.Patricia -Version 7.0.0
<PackageReference Include="Nethereum.Merkle.Patricia" Version="7.0.0" />
<PackageVersion Include="Nethereum.Merkle.Patricia" Version="7.0.0" />
<PackageReference Include="Nethereum.Merkle.Patricia" />
paket add Nethereum.Merkle.Patricia --version 7.0.0
#r "nuget: Nethereum.Merkle.Patricia, 7.0.0"
#:package Nethereum.Merkle.Patricia@7.0.0
#addin nuget:?package=Nethereum.Merkle.Patricia&version=7.0.0
#tool nuget:?package=Nethereum.Merkle.Patricia&version=7.0.0
Nethereum.Merkle.Patricia
The Modified Merkle Patricia Trie — the data structure behind Ethereum account state, contract storage, and transaction and receipt roots. Build one, commit it, prove a key against its root, or verify someone else's proof without holding the state.
What you can do with it
- Compute a state, storage or transaction root from a set of key/value pairs.
- Prove a key — generate the root-first, EIP-1186 node list a light client or contract needs.
- Verify an account, a storage slot or a transaction against a trusted root, without the rest of the state.
- Serve and verify snap/1 range proofs — hand out a slice of the trie with edge proofs, and check one you were given.
- Store trie nodes by path instead of by hash, so an updated node overwrites its predecessor and the database does not grow with history.
- Keep many contract storage tries in one store, separated by owner, without slot-key collisions.
- Build a trie larger than memory, persisting and collapsing as you go.
Quick start
Compute a root, prove a key against it, and verify the proof.
From ProofVerificationFrontDoorTests.QuickStart_ComputeARootProveAKeyAndVerifyIt (use case quick-start) — a tagged, passing test.
var hashProvider = Sha3KeccackHashProvider.Instance;
var trie = new PatriciaTrie(new InMemoryContentNodeStore());
for (var i = 0; i < 128; i++)
trie.Put(hashProvider.ComputeHash(new[] { (byte)i }), new byte[] { (byte)i, 0xAB });
trie.SaveNodesToStorage();
var root = trie.Root.GetHash();
var key = hashProvider.ComputeHash(new byte[] { 7 });
var proof = ProofGenerator.GenerateProof(trie, key);
Assert.Equal(root, hashProvider.ComputeHash(proof[0]));
Assert.True(ProofVerification.Current.Range.VerifyEntry(root, key, new byte[] { 7, 0xAB }, proof));
Entry points
Start with PatriciaTrie. It holds its own node store, so Get, Put and Delete take no storage argument.
| I want to… | Reach for |
|---|---|
| Build a trie and get its root | new PatriciaTrie(store) → Put(key, value) → SaveNodesToStorage() → Root.GetHash() |
| Reload a trie from a root | new PatriciaTrie(rootHash, store) |
| Prove a key | ProofGenerator.GenerateProof(trie, key) |
| Verify an account or storage proof | ProofVerification.Current.Account.Verify(…) / .Storage.Verify(…) |
| Serve a snap/1 range | PatriciaRangeIterator.EnumerateRange(…) + PatriciaRangeProofGenerator.GenerateProof(…) |
| Verify a snap/1 range | ProofVerification.Current.Range.Verify(…) |
| Keep a contract's storage trie apart | new PatriciaTrie(store, owner: keccak(address)) |
| Build something bigger than memory | SaveDirtyNodesToStorageAndCollapse() every N writes |
Two node stores ship in the box: InMemoryContentNodeStore (keyed by hash — what proof verification uses) and InMemoryPathNodeStore (keyed by owner and path — what a node uses). Persistent RocksDB implementations live in Nethereum.CoreChain.RocksDB.
Installation
dotnet add package Nethereum.Merkle.Patricia
Architecture: the trie holds one node store
The trie holds a single node store (ITrieNodeStore) rather than threading a storage object through every Get/Put/Delete. Each node carries its own identity — its hash (GetHash()) and its location (Owner, Path) — and the store alone decides which of the two it keys on.
That one decision is the whole difference between the two storage models:
| Content-addressed store | Path-keyed (location-addressed) store | |
|---|---|---|
| Key | node.GetHash() |
Owner ‖ Path |
| Nodes stored | every node, including embedded ❤️2-byte ones | only nodes ≥32 bytes; shorter children are inlined in the parent and re-decoded on read |
| Effect of an update | a new key appears; the old node stays | the same key is overwritten — the trie does not grow with history |
| Deletions | nothing to do | need tombstones, emitted from an ITrieTracer |
| Integrity on read | implicit (the key is the hash) | explicit — the store verifies the blob against the reference hash it was asked for |
| In-box implementation | InMemoryContentNodeStore |
InMemoryPathNodeStore |
Owner is empty for the account trie and keccak(address) for a contract's storage trie, so many storage tries coexist in one path store without colliding on slot keys. This single-store model is what lets the same trie code run over an in-memory content store (proofs) or a persistent path-keyed database (a full node's state) with no API change.
Persistent RocksDB implementations of ITrieNodeStore — path-keyed and content-addressed, with node history — live in Nethereum.CoreChain.RocksDB (src/Nethereum.CoreChain.RocksDB/Stores/).
Key concepts
- Nodes —
LeafNode(path + value),ExtendedNode(shared-prefix path + one child),BranchNode(16 children + optional value),HashNode(a 32-byte reference that lazily decodes its inner node through the held store),EmptyNode. - Nibbles — keys are traversed a nibble (4 bits) at a time; leaves and extensions carry hex-prefix-encoded nibble paths.
- Node identity — every
NodehasGetHash()(keccak of its RLP), plusOwnerandPath. The store keys on one or the other. TrieNodeSet— the unit of a write: a batch of nodes to persist, plusTrieNodeDeletetombstones for removals. The trie collects dirty nodes into a set and callsstore.Commit(set).- Hash provider — every constructor has an overload taking an
IHashProvider; the default isSha3KeccackHashProvider.Instance(Nethereum.Util.HashProviders).
The node store
| Type | Role |
|---|---|
ITrieNodeStore |
The unified store the trie holds: Commit(TrieNodeSet nodes), Get(Node reference) (returns raw RLP; the store never decodes), Contains(Node reference), ContainsKey(byte[] stateRoot), Flush(), Clear(). |
InMemoryContentNodeStore |
Content-addressed in-memory store (keyed by keccak). Also implements INodeBlobStore. Stores all nodes; self-verifying. The accumulator every proof verifier uses. |
InMemoryPathNodeStore |
Location-addressed in-memory store (keyed by owner ‖ path). Skips ❤️2-byte nodes, verifies on read, applies tombstones. |
ContentAddressedNodeStore |
Adapter presenting a raw INodeBlobStore as a content-addressed ITrieNodeStore (ContentAddressedNodeStore.Wrap(INodeBlobStore storage)). |
INodeBlobStore |
The raw hash→blob byte store: Put(byte[] key, byte[] value), Get(byte[] key), Delete(byte[] key). |
IRawNodeReader |
TryGetRawNode(byte[] owner, byte[] path) — reattach a trie to a root read straight out of a path store (PatriciaTrie.ReattachFromRawRoot). |
ITrieTracer / TrieTracer |
Observes node removals (OnRemove(byte[] owner, byte[] path, byte[] prevBlob), Removals, Reset()) so a path-store commit can emit tombstones. Zero cost when absent (content mode). |
IContractStorageWipeable |
DeleteRange(byte[] owner) — wipes a whole contract's storage subtree (SELFDESTRUCT) on a path store. |
TransientFlushUnavailableException |
Raised by a store that cannot honour a Flush() at this moment. |
Storage declarations
These declarations are copied from the source files under src/Nethereum.Merkle.Patricia/Storage/.
ReadmeTraceabilityTests (tests/Nethereum.Merkle.Patricia.Tests/ReadmeTraceabilityTests.cs) checks that each tagged type is named in a README code block, and that every public member it declares — properties, fields and methods — is named somewhere in this file. Interfaces are covered by that: rename or remove TryGetRawNode, Put, DeleteRange or any member below and the test goes red naming the member.
Argument order is checked too, but only where this README writes the member with parentheses, and the check is a subsequence scan over the whole block rather than a signature parse. So a swapped pair is caught when the block names those parameters once, and can be masked when a neighbouring signature in the same block supplies the same names in the old order. Treat the suite as a reliable guard against renames and removals, and read the source file when the exact parameter order matters.
public interface ITrieNodeStore
{
void Commit(TrieNodeSet nodes);
byte[] Get(Node reference);
bool Contains(Node reference);
void Flush();
void Clear();
bool ContainsKey(byte[] stateRoot);
}
public interface INodeBlobStore
{
void Put(byte[] key, byte[] value);
byte[] Get(byte[] key);
void Delete(byte[] key);
}
public interface IRawNodeReader
{
byte[] TryGetRawNode(byte[] owner, byte[] path);
}
public interface IContractStorageWipeable
{
void DeleteRange(byte[] owner);
}
A commit carries removals as well as writes. TrieNodeSet.AddDelete(byte[] owner, byte[] path, byte[] prevBlob) records one:
public readonly struct TrieNodeDelete
{
public byte[] Owner { get; }
public byte[] Path { get; }
public byte[] PrevBlob { get; }
public TrieNodeDelete(byte[] owner, byte[] path, byte[] prevBlob);
}
A content store ignores those — its keys are hashes, so a superseded node is simply never referenced again. A path store must apply them, because the key would otherwise still resolve.
Usage
Every snippet below is extracted verbatim from a [NethereumDocExample(DocSection.ChainInfrastructure, …)]-tagged passing test in tests/Nethereum.Merkle.Patricia.Tests.
They are fragments, not programs. Extraction keeps the body of the test method, so a snippet may use variables built in the test's arrange step or private fixture helpers (KeyHash, Value, RefOf, keys, values, rootHash, …) that are not shown here, and it may end in Assert. Open the named test file for the surrounding setup before copying — only the Quick Start above is self-contained.
Build, commit, reload — the store is held, not threaded
From ProofVerificationFrontDoorTests.BuildCommitAndReloadThroughOneHeldStore (use case patricia-trie).
var keccak = new Sha3Keccack();
var store = new InMemoryContentNodeStore();
var trie = new PatriciaTrie(store);
var keys = new List<byte[]>();
var values = new List<byte[]>();
for (var i = 0; i < 200; i++)
{
var key = keccak.CalculateHash(new byte[] { (byte)i, (byte)(i >> 8) });
var value = Nethereum.RLP.RLP.EncodeElement(new byte[] { (byte)i });
keys.Add(key);
values.Add(value);
trie.Put(key, value);
}
trie.SaveNodesToStorage();
var rootHash = trie.Root.GetHash();
var reloaded = new PatriciaTrie(rootHash, store);
for (var i = 0; i < keys.Count; i++)
Assert.Equal(values[i], reloaded.Get(keys[i]));
HeldStoreTrieTests.Reads_Through_Held_Store_Without_Threading runs the same reload over both store kinds from one [Theory], which is the point: the trie code does not know which it is holding.
Get/Put/Delete take no storage parameter. PatriciaTrie.LoadFromStorage(rootHash, store) is the (rootHash, store) constructor plus an empty-root branch: a null or empty rootHash returns new PatriciaTrie(store, …) — an empty trie — where the constructor would build a HashNode over those bytes (PatriciaTrie.cs:120-125). Use LoadFromStorage when the root may not exist yet.
SaveNodesToStorage() commits the whole trie; SaveDirtyNodesToStorage() commits only what changed.
Account and contract-storage tries in one path store
From PathStoreAppliesTombstonesTests.Storage_Trie_Owner_Keyed_Deletes_Do_Not_Touch_Account_Trie (use case key-path-storage).
var store = new InMemoryPathNodeStore();
var keccak = new Sha3Keccack();
var owner = keccak.CalculateHash(new byte[] { 0xC0, 0xDE });
var account = new PatriciaTrie(store) { Tracer = new TrieTracer() };
var storage = new PatriciaTrie(store, owner) { Tracer = new TrieTracer() };
foreach (var k in keys)
{
account.Put(k, Nethereum.RLP.RLP.EncodeElement(new byte[] { 0xAC }));
storage.Put(k, Nethereum.RLP.RLP.EncodeElement(new byte[] { 0x57 }));
}
account.SaveDirtyNodesToStorage();
storage.SaveDirtyNodesToStorage();
Both tries use the same keys and the same store. Deleting every storage slot afterwards leaves the account trie intact, because the path store keys each node on owner ‖ path and owner differs. Attaching a TrieTracer is what lets the commit emit tombstones for the removed nodes.
A path store verifies what it hands back
From UnifiedITrieNodeStoreTests.Path_Store_Commit_Resolves_Referenceable_Nodes_And_Rejects_Tamper (use case key-path-storage).
var pathStore = new InMemoryPathNodeStore();
((ITrieNodeStore)pathStore).Commit(set);
foreach (var node in referenceable)
Assert.Equal(node.GetEncodedData(), ((ITrieNodeStore)pathStore).Get(RefOf(node)));
var victim = referenceable[0];
var wrongRef = new HashNode { Hash = new byte[32], Owner = victim.Owner, Path = victim.Path };
Assert.Throws<InvalidOperationException>(() => ((ITrieNodeStore)pathStore).Get(wrongRef));
A content store cannot be lied to — the key is the hash. A path store can, so it re-hashes the blob on every read and throws when the blob does not match the hash the caller asked for. The same check is exposed directly as ProofVerification.Current.TrieNode.Verify(expectedHash, blob, hashProvider).
Bounded memory on large builds — save and collapse
From PatriciaTrieSaveAndCollapseTests.RootHash_IsIdentical_WithPeriodicCollapse (use case patricia-trie).
var store = new InMemoryContentNodeStore();
var trie = new PatriciaTrie(store);
for (int i = 0; i < 2000; i++)
{
trie.Put(KeyHash(i), Value(i));
if (i % 250 == 249) trie.SaveDirtyNodesToStorageAndCollapse();
}
var actual = trie.Root.GetHash();
SaveDirtyNodesToStorageAndCollapse() persists the dirty nodes and then drops the materialised subtrees back to HashNodes, so a multi-million-key build does not have to fit in memory. The root is byte-for-byte the same as building without collapsing.
Proofs
Generating an account/storage proof (root-first, EIP-1186 order)
From ProofGeneratorRootFirstOrderingTests.FirstProofNode_HashesTo_StateRoot (use case state-proofs).
var proof = ProofGenerator.GenerateProof(trie, keys[0]);
Assert.NotNull(proof);
Assert.NotEmpty(proof);
Assert.Equal(rootHash, new Sha3Keccack().CalculateHash(proof[0]));
public static List<byte[]> GenerateProof(PatriciaTrie trie, byte[] key)
It returns a List<byte[]> of RLP node blobs, root first. It returns null when the key is not in the trie — there is no path to prove, so a caller must null-check rather than expect an empty list.
Verifying against a trusted root
All verifiers hang off the ProofVerification.Current front door — Account, Storage, Range, Transaction, TrieNode:
| Verifier | Signature |
|---|---|
IAccountProofVerifier |
bool Verify(byte[] stateRoot, IEnumerable<byte[]> proof, string accountAddress, Account account) |
IStorageProofVerifier |
bool Verify(byte[] stateRoot, IList<byte[]> proof, byte[] key, byte[] value) |
IRangeProofVerifier |
RangeProofResult Verify(byte[] rootHash, byte[] firstKey, IList<byte[]> keys, IList<byte[]> values, IList<byte[]> proofNodes) and bool VerifyEntry(byte[] root, byte[] keyHash, byte[] expectedValue, IList<byte[]> proof) |
ITransactionProofVerifier |
bool Verify(string transactionsRoot, List<IndexedSignedTransaction> transactions) |
ITrieNodeVerifier |
bool Verify(byte[] expectedHash, byte[] blob, IHashProvider hashProvider) |
Each concrete verifier also exposes its own Current singleton, and ProofVerification has a constructor taking all five so you can substitute one. The concrete class names do not follow one pattern — the range verifier is PatriciaRangeProofVerifier, not a RangeProofVerification:
| Front-door property | Concrete class with Current |
|---|---|
Account |
AccountProofVerification |
Storage |
StorageProofVerification |
Range |
PatriciaRangeProofVerifier |
Transaction |
TransactionProofVerification |
TrieNode |
TrieNodeVerification |
public interface IProofVerification
{
IAccountProofVerifier Account { get; }
IStorageProofVerifier Storage { get; }
IRangeProofVerifier Range { get; }
ITransactionProofVerifier Transaction { get; }
ITrieNodeVerifier TrieNode { get; }
}
From ProofVerificationFrontDoorTests.AccountProof_VerifiesAgainstTheStateRoot (use case state-proofs).
var stateRoot = accountTrie.Root.GetHash();
var proof = ProofGenerator.GenerateProof(accountTrie, accountKey);
Assert.True(ProofVerification.Current.Account.Verify(stateRoot, proof, TargetAddress, account));
Swapping the balance for a value the state root does not commit to makes the same call return false (AccountProof_WithATamperedBalance_IsRejected).
Storage slots go through AccountStorage.EncodeKeyForStorage / EncodeValueForStorage (from Nethereum.Model) — the verifier applies that encoding itself, so you pass the raw slot and value:
From ProofVerificationFrontDoorTests.StorageProof_VerifiesASetSlot_AndAnAbsentKeyYieldsNoProof (use case state-proofs).
var storageRoot = storageTrie.Root.GetHash();
var inclusion = ProofGenerator.GenerateProof(
storageTrie, AccountStorage.EncodeKeyForStorage(slot, hashProvider));
Assert.True(ProofVerification.Current.Storage.Verify(storageRoot, inclusion, slot, slotValue));
Under the hood a verifier loads the proof nodes into an InMemoryContentNodeStore and walks the key's path from the root through them — a proof that reconstructs the authentic root is unforgeable.
snap/1 range proofs
For snap sync, a range of the trie is served with edge proofs and verified without the full trie:
PatriciaRangeProofGenerator.GenerateProof(Node root, ITrieNodeStore store, byte[] startKey)and the four-argument overload(…, byte[] startKey, byte[] lastReturnedKey)— boundary proof for a served range.PatriciaRangeIterator.EnumerateRange(Node root, ITrieNodeStore store, byte[] startKey, int maxCount = int.MaxValue, long maxResponseBytes = long.MaxValue)— lexicographic enumeration yieldingPatriciaRangeIterator.RangeEntry { KeyBytes, Value }— a class nested insidePatriciaRangeIterator, not a top-level type — resolvingHashNodes lazily through the store.startKeymust be 32 bytes.ProofVerification.Current.Range.Verify(…)→RangeProofResult { Valid, HasMore }— the full snap/1 range-proof algorithm (proof-to-path, unset-internal, has-right-element).
public static IEnumerable<RangeEntry> EnumerateRange(
Node root,
ITrieNodeStore store,
byte[] startKey,
int maxCount = int.MaxValue,
long maxResponseBytes = long.MaxValue)
public class RangeEntry
{
public byte[] KeyBytes { get; set; }
public byte[] Value { get; set; }
}
public readonly struct RangeProofResult
{
public bool Valid { get; }
public bool HasMore { get; }
public RangeProofResult(bool valid, bool hasMore);
public static readonly RangeProofResult Invalid;
}
From PatriciaRangeProofVerifierTests.Verify_BoundedRange_RoundTrip_Succeeds_WithHasMore (use case snap-range-proofs).
var proof = PatriciaRangeProofGenerator.GenerateProof(trie.Root, storage, startKey, lastKey);
var r = ProofVerification.Current.Range.Verify(rootHash, startKey, keys, values, proof);
Assert.True(r.Valid);
Assert.True(r.HasMore);
HasMore tells the syncing peer whether another chunk follows. Tampering with a value, dropping a key, or presenting keys out of order all make Valid false — the companion tests in the same file assert each of those.
Node types (reference)
| Node | Members |
|---|---|
Node (abstract base) |
Owner, Path, GetHash(), GetEncodedData(), MarkDirty(), IsDirty, NeedsPersist, ClearNeedsPersist(), MarkPersisted() |
LeafNode |
Nibbles, Value, GetPrefixedNibbles() |
ExtendedNode |
Nibbles, InnerNode, CollapseInner(), GetPrefixedNibbles() |
BranchNode |
Children (16), Value, SetChild(int nibble, Node node), RemoveChild(int nibble), CollapseChild(int nibble) |
HashNode |
Hash, lazy InnerNode, DecodeInnerNode(ITrieNodeStore store, bool decodeInnerHashNodes), ReleaseInnerNode() |
EmptyNode |
the empty subtree; shared EmptyNode.Instance |
Decoding is one unified path through NodeDecoder, which threads Owner/Path onto each child reference — no storage-type sniffing. Both members are instance methods, so you construct a NodeDecoder first (Nodes/Rlp/NodeDecoder.cs:8,13):
public class NodeDecoder
{
public Node Decode(HashNode reference, ITrieNodeStore store, bool decodeHashNodes);
public Node DecodeFromRlpData(byte[] currentData, byte[] owner, byte[] path, bool decodeHashNodes, ITrieNodeStore store);
}
A 32-byte child becomes a HashNode carrying {Hash, Owner, Path}; a shorter child is decoded inline.
PatriciaPathWalker exposes the nibble/compact conversions the trie uses — CompactToNibbles(byte[] compact), NibblesToCompact(byte[] nibbles), WalkPath(Node root, ITrieNodeStore store, byte[] pathNibbles).
PatriciaTrie surface (reference)
| Member | Notes |
|---|---|
| Constructors | () (empty trie, Keccak), (IHashProvider), (byte[] hashRoot), (Node root), (ITrieNodeStore store), (byte[] hashRoot, ITrieNodeStore store), (Node root, ITrieNodeStore store), (ITrieNodeStore store, byte[] owner), (byte[] hashRoot, ITrieNodeStore store, byte[] owner), (Node root, ITrieNodeStore store, byte[] owner) — each with an extra IHashProvider overload |
LoadFromStorage |
(byte[] rootHash, ITrieNodeStore store[, byte[] owner][, IHashProvider]) |
ReattachFromRawRoot |
(IRawNodeReader rawReader, ITrieNodeStore store, byte[] owner[, IHashProvider]) |
| Properties | Root, Store, HashProvider, Tracer |
| Reads | Get(byte[] key) |
| Writes | Put(byte[] key, byte[] value), Delete(byte[] key) |
| Commits | SaveNodesToStorage(), SaveDirtyNodesToStorage(), SaveDirtyNodesToStorageAndCollapse() |
Related packages
Nethereum.Merkle.Binary— the EIP-7864 binary trie, the proposed replacement for this structure.Nethereum.CoreChain.RocksDB— persistent path-keyed and content-addressedITrieNodeStoreimplementations with node history and reorg rewind.Nethereum.Merkle— general-purpose Merkle trees (airdrops, whitelists, sparse trees), unrelated to the state trie.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net451 is compatible. net452 was computed. net46 was computed. net461 is compatible. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.5.1
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
.NETFramework 4.6.1
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
.NETStandard 2.0
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- NETStandard.Library (>= 2.0.3)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net10.0
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net6.0
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net8.0
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
-
net9.0
- Nethereum.Model (>= 7.0.0)
- Nethereum.RLP (>= 7.0.0)
- Nethereum.Util (>= 7.0.0)
- Newtonsoft.Json (>= 11.0.2 && < 14.0.0)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Nethereum.Merkle.Patricia:
| Package | Downloads |
|---|---|
|
Nethereum.RPC
Nethereum.RPC Ethereum Core RPC Class Library to interact via RPC with an Ethereum client, for example geth. |
|
|
Nethereum.CoreChain
Nethereum CoreChain - Core blockchain infrastructure for state, transactions, and receipts root management |
|
|
Nethereum.ChainStateVerification
Verified execution-state primitives (account/storage/receipt proofs rooted in the light client). |
|
|
web3.net
Web3 .Net package |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.0.0 | 4,555 | 10/2/2026 |
| 6.1.0 | 187,699 | 3/25/2026 |
| 6.0.4 | 19,790 | 3/18/2026 |
| 6.0.3 | 1,960 | 3/18/2026 |
| 6.0.1 | 3,383 | 3/17/2026 |
| 6.0.0 | 6,400 | 3/16/2026 |
| 5.8.0 | 112,371 | 1/6/2026 |
| 5.0.0 | 489,655 | 5/28/2025 |
| 4.29.0 | 353,434 | 2/10/2025 |
| 4.28.0 | 98,086 | 1/7/2025 |
| 4.27.1 | 15,795 | 12/24/2024 |
| 4.27.0 | 10,798 | 12/24/2024 |
| 4.26.0 | 113,546 | 10/1/2024 |
| 4.25.0 | 54,361 | 9/19/2024 |
| 4.21.4 | 155,223 | 8/9/2024 |
| 4.21.3 | 13,563 | 7/22/2024 |
| 4.21.2 | 77,725 | 6/26/2024 |
| 4.21.1 | 4,486 | 6/26/2024 |
| 4.21.0 | 25,679 | 6/18/2024 |
| 4.20.0 | 416,171 | 3/28/2024 |