Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ on:
push:
branches:
- main
pull_request:
workflow_dispatch:

concurrency:
group: pages
group: pages-${{ github.ref }}
cancel-in-progress: false

permissions: read-all
Expand All @@ -24,6 +25,7 @@ jobs:
- name: Setup Pages
id: pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
if: github.event_name != 'pull_request'

- name: Install dependencies
run: |
Expand All @@ -42,6 +44,7 @@ jobs:
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: doc/build
if: github.event_name != 'pull_request'

deploy:
name: Deploy
Expand Down
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,69 @@ unusual features like flushing, retracting, and tree segment serialisation.
assert(path->verify(root));


## Tiled storage (tlog-tiles)

The companion header `merklecpp_tiles.h` adds optional, header-only support for
persisting a tree as [tlog-tiles](https://c2sp.org/tlog-tiles) tile files
*progressively* (optionally dropping already-tiled leaves from memory) and for
retrieving inclusion and consistency proofs from those tiles, from the in-memory
tree, or from a combination of the two. The hashing is unchanged: tiles and tile-derived proofs are templated on
the tree's existing hash function, so a tile-derived inclusion proof is
byte-identical to one from `merkle::Tree::path()` and verifies with the same
`merkle::Path::verify()`.

#include <merklecpp_tiles.h>

merkle::tiles::TiledTree::Config cfg;
cfg.prefix = "/var/log/mylog"; // tile files live here
cfg.retention_margin = 1024; // keep the most recent leaves in memory
cfg.compact_on_flush = true; // opt in to dropping already-tiled leaves

merkle::tiles::TiledTree log(cfg);
for (const auto& leaf_hash : batch)
log.append(leaf_hash);

// Write newly-complete tiles. With compaction enabled
// this also drops from memory the leaves already covered by a full tile;
// otherwise the tree keeps every leaf and you can call log.compact() later.
log.flush();

// Proofs are served from tiles + the resident tree, even for flushed leaves.
auto inclusion = log.inclusion_proof(/*index=*/0, log.size());
assert(inclusion->verify(log.root()));

auto consistency = log.consistency_proof(/*m=*/100, /*n=*/log.size());

`TiledTree` creates a new tiled tree: the configured directory may exist, but
its `tile` subdirectory must be absent or empty. It deliberately rejects
existing tile data because tile files alone do not identify or restore the
tree that produced them. Applications with externally persisted tree state can
use the lower-level `TileStore` and `TileWriter` APIs to resume a store.

See the [tiled storage guide](doc/tiles-guide.md) for a how-to covering
flushing, compaction, rollback, proofs, and the lower-level building blocks,
and [doc/design/tlog-tiles.md](doc/design/tlog-tiles.md) for the full design,
file/directory layout, and the proof algorithms.


## Building and testing

Enable the test suite with CMake's `TESTS` option:

cmake -S . -B build -DTESTS=ON
cmake --build build
ctest --test-dir build

Some tile coverage is intentionally long-running. `LONG_TESTS` is off by
default for local builds; turn it on when you want the full tile stress suite,
including level-2 tile coverage and tile proof timing:

cmake -S . -B build -DTESTS=ON -DLONG_TESTS=ON

The repository CI enables `LONG_TESTS` so pull requests continue to exercise the
full tiled-storage matrix.


## Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Expand Down
35 changes: 35 additions & 0 deletions doc/design/tlog-tiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,30 @@ one-method core addition; README/docs updates.

---

## 11. Testing strategy

The existing library is the **oracle** — this is how we guarantee "proofs remain
compatible":

- **Equality, not just verification.** Assert `*inclusion_proof(i,size) ==
*tree.path(i)` using the existing `PathT::operator==`, and likewise against
`past_path`. This is stronger than `verify()` and pins byte-compatibility.
- **Root agreement.** `ProofEngineT::root(size)` == `tree.root()` /
`tree.past_root(size-1)` for many random sizes.
- **Spec vectors.** Exact full-tile counts and on-disk file sets for sizes 256
and 70 000; index-encoding strings (incl. `x001/x234/067`).
- **Flush/compaction.** Cross-check proofs for flushed indices against a twin
tree that was never flushed (same inserts) — roots must match and proofs must
verify.
- **Consistency proofs.** Standard RFC 6962 `verify_consistency` plus the
reconciliation-of-`past_root`s check; randomized `m < n`.
- **Templating.** Run a subset under `Tree`, `Tree384`, `Tree512` to confirm
hash-size independence.
- **Style.** Mirror existing standalone-`main()` tests (`test/util.h`,
`make_hashes`, `get_timeout`) and register via `add_merklecpp_test`.

---

## 12. Risks, edge cases, open questions

- **External interop (by design, no).** With the default combiner the tiles are
Expand Down Expand Up @@ -748,3 +772,14 @@ one-method core addition; README/docs updates.

---

## 13. Build & backwards-compatibility impact

- **Additive only.** New header + tests; existing `merklecpp.h` behaviour and
API are unchanged. Default builds (no tiles) are unaffected.
- **No new mandatory dependencies.** Roll-ups/proofs use the existing
`HASH_FUNCTION` (two-hash combiner), so `sha256_compress` suffices; OpenSSL
stays optional.
- **Optional core change** is a single read-only accessor that performs no
hashing and does not alter any existing code path.
- **CMake.** Add a `tiles` test group guarded like the others; no changes to the
`merklecpp` INTERFACE target are required for consumers that don't use tiles.
Loading
Loading