Skip to content

Commit aab3e3e

Browse files
[docs] Release adb::any (#700)
1 parent 3300f01 commit aab3e3e

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

docs/blogs/adb-any.html

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
7+
<link rel="icon" href="../favicon.ico" type="image/x-icon">
8+
9+
<title>commonware > The Simplest Database You Need</title>
10+
<meta name="description" content="The primary limitation of the MMR compared to a more typical Merkle tree structure is its lack of support for removing elements from the list over which inclusion proofs can be provided. This restriction, at first glance, might appear to prohibit an MMR from being used to build a mutable database where keys take on values that change over time. However, append-only MMRs are a natural fit for authenticating log data. Instead of viewing our database as only a snapshot in time, the basic idea we'll build on is to maintain an MMR over the historical log of all database operations performed up until the present state.">
11+
<meta name="author" content="Roberto Bayardo, Patrick O'Grady">
12+
<meta name="keywords" content="commonware, open source, common goods, software, internet, ownership, trust, blockchain, decentralization, crypto">
13+
14+
<meta property="og:url" content="https://commonware.xyz/blogs/adb-any.html" />
15+
<meta property="og:type" content="article" />
16+
<meta property="og:site_name" content="commonware" />
17+
<meta property="og:image" content="https://commonware.xyz/imgs/adb-any.png" />
18+
<meta property="og:title" content="The Simplest Database You Need" />
19+
<meta property="og:description" content="The primary limitation of the MMR compared to a more typical Merkle tree structure is its lack of support for removing elements from the list over which inclusion proofs can be provided. This restriction, at first glance, might appear to prohibit an MMR from being used to build a mutable database where keys take on values that change over time. However, append-only MMRs are a natural fit for authenticating log data. Instead of viewing our database as only a snapshot in time, the basic idea we'll build on is to maintain an MMR over the historical log of all database operations performed up until the present state." />
20+
<meta property="article:author" content="https://x.com/roberto_bayardo" />
21+
<meta property="article:author" content="https://x.com/_patrickogrady" />
22+
<meta property="article:published_time" content="2025-04-09T00:00:00Z" />
23+
<meta property="article:modified_time" content="2025-04-09T00:00:00Z" />
24+
25+
<meta name="twitter:card" content="summary_large_image" />
26+
<meta property="twitter:domain" content="commonware.xyz" />
27+
<meta property="twitter:url" content="https://commonware.xyz/blogs/adb-any.html" />
28+
<meta property="twitter:title" content="The Simplest Database You Need" />
29+
<meta property="twitter:description" content="The primary limitation of the MMR compared to a more typical Merkle tree structure is its lack of support for removing elements from the list over which inclusion proofs can be provided. This restriction, at first glance, might appear to prohibit an MMR from being used to build a mutable database where keys take on values that change over time. However, append-only MMRs are a natural fit for authenticating log data. Instead of viewing our database as only a snapshot in time, the basic idea we'll build on is to maintain an MMR over the historical log of all database operations performed up until the present state." />
30+
<meta property="twitter:image" content="https://commonware.xyz/imgs/adb-any.png" />
31+
<meta property="twitter:site" content="@commonwarexyz" />
32+
<meta property="twitter:creator" content="@roberto_bayardo" />
33+
34+
<link rel="stylesheet" type="text/css" href="../style.css">
35+
</head>
36+
37+
<body>
38+
<div id="logo-placeholder">
39+
<div class="logo-line">
40+
<span class="edge-logo-symbol">+</span>
41+
<span class="horizontal-logo-symbol">~</span>
42+
<span class="horizontal-logo-symbol"> </span>
43+
<span class="horizontal-logo-symbol">-</span>
44+
<span class="horizontal-logo-symbol">+</span>
45+
<span class="horizontal-logo-symbol">-</span>
46+
<span class="horizontal-logo-symbol">+</span>
47+
<span class="horizontal-logo-symbol"> </span>
48+
<span class="horizontal-logo-symbol">-</span>
49+
<span class="horizontal-logo-symbol">+</span>
50+
<span class="horizontal-logo-symbol">-</span>
51+
<span class="horizontal-logo-symbol">~</span>
52+
<span class="horizontal-logo-symbol">~</span>
53+
<span class="edge-logo-symbol">*</span>
54+
</div>
55+
<div class="logo-line">
56+
<span class="vertical-logo-symbol">|</span>
57+
<span class="logo-text"> commonware </span>
58+
<span class="vertical-logo-symbol"> </span>
59+
</div>
60+
<div class="logo-line">
61+
<span class="edge-logo-symbol">*</span>
62+
<span class="horizontal-logo-symbol">~</span>
63+
<span class="horizontal-logo-symbol">+</span>
64+
<span class="horizontal-logo-symbol">+</span>
65+
<span class="horizontal-logo-symbol">-</span>
66+
<span class="horizontal-logo-symbol"> </span>
67+
<span class="horizontal-logo-symbol">~</span>
68+
<span class="horizontal-logo-symbol">-</span>
69+
<span class="horizontal-logo-symbol">+</span>
70+
<span class="horizontal-logo-symbol"> </span>
71+
<span class="horizontal-logo-symbol">-</span>
72+
<span class="horizontal-logo-symbol">*</span>
73+
<span class="horizontal-logo-symbol">-</span>
74+
<span class="edge-logo-symbol">+</span>
75+
</div>
76+
</div>
77+
<div class="content">
78+
<h1>The Simplest Database You Need</h1>
79+
<div class="meta">
80+
<div class="author">By <a href="https://x.com/roberto_bayardo">Roberto Bayardo</a> and <a href="https://x.com/_patrickogrady">Patrick O'Grady</a></div>
81+
<div class="date">April 9, 2025</div>
82+
</div>
83+
<p>In a <a href="https://commonware.xyz/blogs/mmr.html">previous article</a>, we detailed the unique properties of the Merkle Mountain Ranges (MMR) that makes it an excellent fit for authenticating data in high-performance blockchains. Recall that MMRs are an authenticated data structure (ADS) from which an untrusted server can efficiently prove inclusion of any element within a growing ordered list, as depicted below:</p>
84+
<div class="image-container">
85+
<img src="../imgs/mmr.png" alt="Appending new elements to an MMR">
86+
<div class="image-caption">Figure 1: Appending new elements to an MMR</div>
87+
</div>
88+
<p>Here, we'll dive into how the construction can be extended to create a lightweight <i>authenticated database</i> (ADB) capable of storing and proving mutable blockchain state with minimal amplification. We call the first of these MMR-powered ADBs <a href="https://docs.rs/commonware-storage/latest/commonware_storage/adb/any/index.html">adb::any</a>, and are excited to share that it is now available under an MIT/Apache-2 license.</p>
89+
<p>The primary limitation of the MMR compared to a more typical Merkle tree structure is its lack of support for removing elements from the list over which inclusion proofs can be provided. This restriction, at first glance, might appear to prohibit an MMR from being used to build a mutable database where keys take on values that change over time. However, append-only MMRs are a natural fit for authenticating log data. Instead of viewing our database as only a snapshot in time, the basic idea we'll build on is to maintain an MMR over the <i>historical log</i> of all database <i>operations</i> performed up until the present state.</p>
90+
<p>Let us consider two basic operations, <i>assigning</i> a key a value and <i>deleting</i> a key's value. Each operation applied to the database gets added to a persistent log, and its digest added to an MMR. To provide efficient lookups of a key's value, we employ a <a href="https://docs.rs/commonware-storage/latest/commonware_storage/index/index.html">memory-efficient index</a> that maps a compressed representation of each key to its latest value in the log.</p>
91+
<p>The figure below depicts a small example of this kind of ADB, showing only the updates for key “foo” which is assigned value 5 in log operation 3, deleted at operation 6, and later updated to value 6 at operation 9, which contains its active state. While the contents of the log are durably persisted to disk, the index depicted to the right is memory resident, mapping a key to the location of its currently active operation. Because keys in some applications may be large (e.g. 32 byte hashes), keys are transformed by a user-provided function into a more compact representation (e.g. an 8 byte hash prefix) for memory efficiency. (There is some additional complexity we don't describe here required for handling a small but non-negligible chance of collisions among these transformed keys.)</p>
92+
<div class="image-container">
93+
<img src="../imgs/adb-any.png" alt="Appending new elements to adb::any">
94+
<div class="image-caption">Figure 2: Appending new elements to adb::any</div>
95+
</div>
96+
<p>One challenge with this solution is the endlessly growing log of data which needs to be replayed to derive the current state of the database. Consider the MMR in the diagram above: it stores the old value for key "foo" in operation 3 even though its value is later reassigned in operations 6 and 9. To overcome this, we apply a <i>compaction</i> process that advances the inactivity floor, the index before which all operations are <i>inactive</i> (and therefore don't need to be stored to compute the current state). Starting from the old inactivity floor, we advance over the next n operations, where n is configurable. If the operation is already inactive, we simply drop the data. If it's active, we make it inactive by reapplying the same key-value in a new operation. This process guarantees that the number of inactive operations remaining ahead of the floor is never more than a small constant multiple of the number of active operations. Operations preceding the inactivity floor can be efficiently discarded from disk while still retaining the ability to authenticate any historical operation against the current root. Much as the log supports re-derivation of the database's state, it also allows us to re-derive the state of the pruned MMR as long as we durably persist (aka <i>pin</i>) a small (logarithmically sized) set of historical nodes.</p>
97+
<p>A variety of designs are possible within this general framework for an authenticated database, each involving differing trade-offs between performance, memory efficiency, and authentication expressivity. Our initial release, <a href="https://docs.rs/commonware-storage/latest/commonware_storage/adb/any/index.html">adb::any</a>, implements the minimal construction described above over the existing <a href="https://docs.rs/commonware-storage/latest/commonware_storage/mmr/journaled/index.html">mmr::journaled</a> primitive. To limit the IO of both updates and deletes to a minimum, adb::any <b>only</b> supports proving that some key was assigned to a specific value at some point in its history (not that a key has some value now nor that a key has no value). This (lack of capability) achieves a unique balance between performance and functionality that we believe applications will find just useful enough. For example, adb::any can be used to power efficient state sync over the active range (indicated by the inactivity floor), drive message-based interoperability (where emitted messages are forever persisted), and equip users to verify the balance served to them by centralized infrastructure (constraining any future proof to be at an index higher than the last).</p>
98+
<p>Another variant, which remains under development, augments this construction with <a href="https://docs.rs/commonware-storage/latest/commonware_storage/mmr/bitmap/index.html">an authenticated bitmap</a> over the activity status of each operation. This extension allows the ADB to additionally authenticate that a specific value is a key's <i>current</i> value – useful for applications requiring, for example, proving someone's account contains some balance, or that a user currently has the permission to execute some contract. <a href="https://arxiv.org/abs/2501.05262">QMDB</a>, the primary inspiration for this work, extends these concepts even further, adding the ability to prove <i>exclusion</i> (that some key is not currently assigned any value).</p>
99+
<p>In addition to <i>assign</i> and <i>delete</i> over keys, our implementation offers one additional database operation, <i>commit</i>, that synchronizes the compaction process with each batch update. In the context of a blockchain, the set of updates from executing all transactions in a block can be atomically committed to the database along with raising the inactivity floor a number of times necessary to prevent it from falling indefinitely behind (a useful marker in the log to inform state syncing clients where to start fetching from the log). This compaction process could be extended to charge any rewritten (still active) account at the inactivity floor some rent or to drop said accounts altogether from “hot” storage (requiring a proof to resurrect when needed again).</p>
100+
<p><a href="https://docs.rs/commonware-storage/latest/commonware_storage/adb/any/index.html">adb::any</a> is available today with work ongoing to both deliver additional feature variants and a benchmarking suite to evaluate the impact of said variants. Like other primitives, adb::any is exhaustively tested with <a href="https://docs.rs/commonware-runtime/latest/commonware_runtime/deterministic/index.html">runtime::deterministic</a> over a number of failure scenarios (like unclean shutdown).</p>
101+
<p>We look forward to releasing a production-ready version of adb::any later this year.</p>
102+
</div>
103+
104+
<div id="footer-placeholder"></div>
105+
<script src="../shared.js"></script>
106+
<script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "07159b86f75b4af18e54dd0cda2fb4a7"}'></script>
107+
</body>
108+
109+
</html>

docs/imgs/adb-any.png

66.4 KB
Loading

docs/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ <h3><a href="https://docs.rs/commonware-vrf">vrf</a></h3>
108108
<p>Generate bias-resistant randomness with untrusted contributors.</p>
109109

110110
<h2>Blogs</h2>
111+
<h3><a href="./blogs/adb-any.html">The Simplest Database You Need</a></h3>
112+
<div class="meta">
113+
<div class="author">By <a href="https://x.com/roberto_bayardo">Roberto Bayardo</a> and <a href="https://x.com/_patrickogrady">Patrick O'Grady</a></div>
114+
<div class="date">April 9, 2025</div>
115+
</div>
116+
<p>The primary limitation of the MMR compared to a more typical Merkle tree structure is its lack of support for removing elements from the list over which inclusion proofs can be provided. This restriction, at first glance, might appear to prohibit an MMR from being used to build a mutable database where keys take on values that change over time. However, append-only MMRs are a natural fit for authenticating log data. Instead of viewing our database as only a snapshot in time, the basic idea we'll build on is to maintain an MMR over the historical log of all database operations performed up until the present state.</p>
111117
<h3><a href="./blogs/commonware-deployer.html">Your p2p demo runs locally. Now what?</a></h3>
112118
<div class="meta">
113119
<div class="author">By <a href="https://x.com/_patrickogrady">Patrick O'Grady</a></div>

0 commit comments

Comments
 (0)