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
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ jobs:
working-directory: ${{github.workspace}}/build/${{ matrix.build_type }}
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
cmake $GITHUB_WORKSPACE -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DTESTS=ON -DOPENSSL=ON -DCLANG_TIDY=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake $GITHUB_WORKSPACE -DCMAKE_CXX_COMPILER=${{ matrix.compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DTESTS=ON -DLONG_TESTS=ON -DOPENSSL=ON -DCLANG_TIDY=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
else
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DTESTS=ON
cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DTESTS=ON -DLONG_TESTS=ON
fi

- name: Build
Expand All @@ -64,7 +64,9 @@ jobs:
- name: Clang-Tidy Header
if: matrix.os == 'ubuntu-latest'
shell: bash
run: clang-tidy merklecpp.h -p build/${{ matrix.build_type }} --warnings-as-errors='*'
run: |
clang-tidy merklecpp.h -p build/${{ matrix.build_type }} --warnings-as-errors='*'
clang-tidy merklecpp_tiles.h -p build/${{ matrix.build_type }} --warnings-as-errors='*'

- name: Test
working-directory: ${{github.workspace}}/build/${{ matrix.build_type }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

- name: Configure merklecpp
working-directory: ${{github.workspace}}/build
run: cmake -DCMAKE_BUILD_TYPE=Debug -DTESTS=ON $GITHUB_WORKSPACE
run: cmake -DCMAKE_BUILD_TYPE=Debug -DTESTS=ON -DLONG_TESTS=ON $GITHUB_WORKSPACE

- name: Build merklecpp
working-directory: ${{github.workspace}}/build
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ option(EVERCRYPT "enable comparison with EverCrypt Merkle trees" OFF)
option(OPENSSL "enable OpenSSL" OFF)
option(TRACE "enable debug traces" OFF)
option(CLANG_TIDY "enable clang-tidy checks during build" OFF)
option(LONG_TESTS "enable long-running tests" OFF)

if(CLANG_TIDY)
find_program(CLANG_TIDY_PROGRAM clang-tidy)
Expand Down
3 changes: 2 additions & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,8 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.

INPUT = merklecpp.h
INPUT = merklecpp.h \
merklecpp_tiles.h

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down
750 changes: 750 additions & 0 deletions doc/design/tlog-tiles.md

Large diffs are not rendered by default.

77 changes: 77 additions & 0 deletions merklecpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <cstdint>
#include <cstring>
#include <functional>
#include <limits>
#include <list>
#include <memory>
#include <sstream>
Expand Down Expand Up @@ -1316,6 +1317,82 @@ namespace merkle
leaf_node(index)->hash, index, std::move(path), as_of);
}

/// @brief Extracts the root hash of a complete subtree resident in memory
/// @param level The height of the subtree (it spans 2**level leaves)
/// @param index The index of the subtree at that height
/// @param out Set to the subtree root hash on success
/// @return Whether the subtree is a complete (balanced) subtree fully
/// resident in memory
/// @note This is read-only and does not change the hashing of the tree: it
/// returns an existing node hash (computing it on demand exactly as root()
/// and path() do). It returns false if any leaf of the subtree has been
/// flushed, if the subtree extends past the last leaf, or if the node at
/// that position is not a full subtree. The subtree spans leaf indices
/// [index << level, (index + 1) << level).
bool subtree_root(uint8_t level, size_t index, Hash& out)
{
const size_t leaves = num_leaves();
if (leaves == 0 || level >= std::numeric_limits<size_t>::digits)
{
return false;
}
if (index > (std::numeric_limits<size_t>::max() >> level))
{
return false;
}

const size_t lo = index << level;
const size_t count = (size_t)1 << level;

if (lo < min_index() || count > leaves || lo > leaves - count)
{
return false;
}

if (level == 0)
{
out = leaf(lo);
return true;
}

compute_root();

const uint8_t target_height = level + 1;
if (!_root || _root->height < target_height)
{
return false;
}

Node* cur = _root;
size_t it = lo << (sizeof(lo) * 8 - _root->height + 1);
for (uint8_t height = _root->height; height > target_height;)
{
const bool go_right = ((it >> (8 * sizeof(it) - 1)) & 0x01) != 0U;
if (cur->height == height)
{
Node* next = go_right ? cur->right : cur->left;
if (!next)
{
return false; // conflated/flushed: not resident
}
cur = next;
}
it <<= 1;
height--;
}

if (cur->height != target_height || !cur->is_full())
{
return false;
}
if (cur->dirty)
{
hash(cur);
}
out = cur->hash;
return true;
}

/// @brief Serialises the tree
/// @param bytes The vector of bytes to serialise to
void serialise(std::vector<uint8_t>& bytes)
Expand Down
Loading
Loading