-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
58 additions
and
5,531 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,64 @@ | ||
<div align="center"> | ||
# Merkle Patricia Forestry | ||
|
||
<h1 align="center">Merkle Patricia Forestry</h1> | ||
<img alt="Merkle Patricia Forestry" src=".github/logo.png" height="250"> | ||
<p align="center" style="border-bottom: none">A set of (on-chain & off-chain) libraries for working with <strong>Merkle Patricia Tries</strong> on Cardano.</p> | ||
This package provides an Aiken library for working with an authenticated key/value store: a.k.a [Merkle Patricia Forestry](../README.md). It comes with a [companion off-chain package](../off-chain) for generating proofs and actually maintaining the raw data-structure since on-chain, we only ever deal with hashes. | ||
|
||
<hr/> | ||
## Installation | ||
|
||
[](https://github.com/aiken-lang/merkle-patricia-forestry/blob/main/LICENSE) | ||
[](https://github.com/aiken-lang/merkle-patricia-forestry/actions/workflows/continuous-integration.yml) | ||
[](https://www.npmjs.com/package/@aiken-lang/merkle-patricia-forestry) | ||
|
||
<hr/> | ||
</div> | ||
|
||
## Overview | ||
|
||
A Merkle Patricia Trie is a persistent & authenticated data structure to map between arbitrary keys and values. It's like a hashmap on steroids, which isn't tamperable. The items are represented in a space-optimized trie (a.k.a prefix tree) of radix 16. The hash digest of their keys gives the path to values in the trie. For more details, read [the wiki](https://github.com/aiken-lang/merkle-patricia-forestry/wiki/Technical-analysis). | ||
|
||
The use cases are numerous, such as maintaining large on-chain registries (e.g. domains) or providing unreasonably large oracled datasets of intrinsic data (e.g. a map of delegators/delegatees) or extrinsic data (e.g. GitHub data pertaining to an ecosystem of projects). It's also perfectly suited for long-running datasets that grow at a _slow_ rate (e.g. a PoW blockchain). | ||
|
||
### Features | ||
|
||
Using only a root hash digest (32 bytes) and a succinct proof (<1KB), Merkle Patricia Tries provides rapid: | ||
|
||
- [x] membership | ||
- [x] insertion | ||
- [x] deletion | ||
|
||
...of any key/value item in a large (billions) store. | ||
|
||
## Getting Started | ||
|
||
### Off-chain (JavaScript / Node.js) | ||
|
||
```bash | ||
yarn add @aiken-lang/merkle-patricia-forestry | ||
``` | ||
|
||
See [off-chain](./off-chain#readme) for usage. | ||
|
||
### On-chain (Aiken) | ||
|
||
```bash | ||
aiken add --version 1.1.0 aiken-lang/merkle-patricia-forestry | ||
aiken add aiken-lang/merkle-patricia-forestry --version 2.0.0 | ||
``` | ||
|
||
See [on-chain](./on-chain#readme) for usage. | ||
|
||
## Performances | ||
|
||
This library implements a few optimizations. We borrow ideas from the [Ethereum's Modified Merkle Patricia Trie (MPT)](https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/) and also introduce a novel approach for organizing nodes as tiny [Sparse Merkle Trees](https://eprint.iacr.org/2016/683.pdf) that result in much smaller proof sizes, and gives the name to the structure: Merkle Patricia Forestry. This optimization and overall approach are covered in more detail [in the wiki](https://github.com/aiken-lang/merkle-patricia-forestry/wiki/Technical-analysis#forestry). | ||
|
||
While this optimization sacrifices some memory and CPU execution units for smaller proof sizes, the library ultimately achieves a good trade-off. The table below summarizes the proof size, memory units, and CPU units for various sizes of tries. Note that the numbers in the table correspond to _one proof verification_ (e.g., membership). Insertion and deletion in the trie both require _two proof verifications_, so double the numbers! | ||
|
||
trie size | avg proof size (bytes) | avg proof mem units | avg proof cpu units | | ||
---: | -------------: | ------------: | ------------: | | ||
10² | 250 | 70K <sup>(0.70%)</sup> | 18M <sup>(0.12%)</sup> | | ||
10³ | 350 | 100K <sup>(1.00%)</sup> | 26M <sup>(0.19%)</sup> | | ||
10⁴ | 460 | 130K <sup>(1.30%)</sup> | 35M <sup>(0.25%)</sup> | | ||
10⁵ | 560 | 160K <sup>(1.60%)</sup> | 44M <sup>(0.31%)</sup> | | ||
10⁶ | 670 | 190K <sup>(1.90%)</sup> | 53M <sup>(0.38%)</sup> | | ||
10⁷ | 780 | 220K <sup>(2.20%)</sup> | 62M <sup>(0.44%)</sup> | | ||
10⁸ | 880 | 250K <sup>(2.50%)</sup> | 71M <sup>(0.51%)</sup> | | ||
10⁹ | 990 | 280K <sup>(2.80%)</sup> | 79M <sup>(0.56%)</sup> | | ||
## Documentation | ||
|
||
The documentation is generated from `aiken docs` and [available here](https://aiken-lang.github.io/merkle-patricia-forestry/aiken/merkle_patricia_forestry.html). | ||
|
||
### Examples | ||
|
||
A non-trivial example of a [fruit map](https://github.com/aiken-lang/merkle-patricia-forestry/blob/main/on-chain/lib/aiken/merkle-patricia-forestry.tests.ak#L90) is available in the source. It illustrate how to use the various `from_root`, `has`, `insert` and `delete` primitives. | ||
|
||
```aiken | ||
test insert_bitcoin_block_845602() { | ||
let trie = | ||
mpf.from_root( | ||
#"225a4599b804ba53745538c83bfa699ecf8077201b61484c91171f5910a4a8f9", | ||
) | ||
let block_hash = | ||
#"0000000000000000000261a131bf48cc5a19658ade8cfede99dc1c3933300d60" | ||
let block_body = | ||
#"26f711634eb26999169bb927f629870938bb4b6b4d1a078b44a6b4ec54f9e8df" | ||
mpf.insert(trie, block_hash, block_body, proof_bitcoin_845602()) == mpf.from_root( | ||
#"507c03bc4a25fd1cac2b03592befa4225c5f3488022affa0ab059ca350de2353", | ||
) | ||
} | ||
fn proof_bitcoin_845602() -> Proof { | ||
[ | ||
Branch { | ||
skip: 0, | ||
neighbors: #"bc13df27a19f8caf0bf922c900424025282a892ba8577095fd35256c9d553ca120b8645121ebc9057f7b28fa4c0032b1f49e616dfb8dbd88e4bffd7c0844d29b011b1af0993ac88158342583053094590c66847acd7890c86f6de0fde0f7ae2479eafca17f9659f252fa13ee353c879373a65ca371093525cf359fae1704cf4a", | ||
}, | ||
Branch { | ||
skip: 0, | ||
neighbors: #"255753863960985679b4e752d4b133322ff567d210ffbb10ee56e51177db057460b547fe42c6f44dfef8b3ecee35dfd4aa105d28b94778a3f1bb8211cf2679d7434b40848aebdd6565b59efdc781ffb5ca8a9f2b29f95a47d0bf01a09c38fa39359515ddb9d2d37a26bccb022968ef4c8e29a95c7c82edcbe561332ff79a51af", | ||
}, | ||
Branch { | ||
skip: 0, | ||
neighbors: #"9d95e34e6f74b59d4ea69943d2759c01fe9f986ff0c03c9e25ab561b23a413b77792fa78d9fbcb98922a4eed2df0ed70a2852ae8dbac8cff54b9024f229e66629136cfa60a569c464503a8b7779cb4a632ae052521750212848d1cc0ebed406e1ba4876c4fd168988c8fe9e226ed283f4d5f17134e811c3b5322bc9c494a598b", | ||
}, | ||
Branch { | ||
skip: 0, | ||
neighbors: #"b93c3b90e647f90beb9608aecf714e3fbafdb7f852cfebdbd8ff435df84a4116d10ccdbe4ea303efbf0f42f45d8dc4698c3890595be97e4b0f39001bde3f2ad95b8f6f450b1e85d00dacbd732b0c5bc3e8c92fc13d43028777decb669060558821db21a9b01ba5ddf6932708cd96d45d41a1a4211412a46fe41870968389ec96", | ||
}, | ||
Branch { | ||
skip: 0, | ||
neighbors: #"f89f9d06b48ecc0e1ea2e6a43a9047e1ff02ecf9f79b357091ffc0a7104bbb260908746f8e61ecc60dfe26b8d03bcc2f1318a2a95fa895e4d1aadbb917f9f2936b900c75ffe49081c265df9c7c329b9036a0efb46d5bac595a1dcb7c200e7d590000000000000000000000000000000000000000000000000000000000000000", | ||
}, | ||
] | ||
} | ||
``` | ||
|
||
> [!NOTE] | ||
> | ||
> On current mainnet, 140K mem units and 100M cpu units corresponds respectively to 1% of the maximum transaction mem and cpu budgets. | ||
> [!WARNING] | ||
> The proofs themselves have been generated from a trie built with the [off-chain package](../off-chain). While theoretically possible, the Aiken library doesn't contain any primitives for constructing tries _on-chain_, even for debugging. |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.