Skip to content

Commit

Permalink
refactor: simplify machine hash computation in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
diegonehab committed Oct 6, 2023
1 parent f17ab80 commit 34547ee
Show file tree
Hide file tree
Showing 9 changed files with 323 additions and 692 deletions.
4 changes: 3 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,9 @@ TEST_MERKLE_TREE_HASH_OBJS:= \
test-merkle-tree-hash.o

TEST_MACHINE_C_API_OBJS:= \
test-machine-c-api.o
test-machine-c-api.o \
back-merkle-tree.o \
pristine-merkle-tree.o

PROTO_OBJS:= \
$(PROTOBUF_GEN_OBJS) \
Expand Down
53 changes: 50 additions & 3 deletions src/back-merkle-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
//

#include "back-merkle-tree.h"
#include <iomanip>
#include <iostream>
#include <limits>

/// \file
Expand Down Expand Up @@ -44,14 +46,14 @@ back_merkle_tree::back_merkle_tree(int log2_root_size, int log2_leaf_size, int l
if (log2_word_size > log2_leaf_size) {
throw std::out_of_range{"log2_word_size is greater than log2_word_size"};
}
if (log2_root_size >= std::numeric_limits<address_type>::digits) {
if (log2_root_size - m_log2_leaf_size >= std::numeric_limits<address_type>::digits) {
throw std::out_of_range{"tree is too large for address type"};
}
}

void back_merkle_tree::push_back(const hash_type &leaf_hash) {
void back_merkle_tree::push_back(const hash_type &new_leaf_hash) {
hasher_type h;
hash_type right = leaf_hash;
hash_type right = new_leaf_hash;
if (m_leaf_count >= m_max_leaves) {
throw std::out_of_range{"too many leaves"};
}
Expand All @@ -68,6 +70,51 @@ void back_merkle_tree::push_back(const hash_type &leaf_hash) {
++m_leaf_count;
}

void back_merkle_tree::pad_back(uint64_t new_leaf_count) {
hasher_type h;
if (new_leaf_count > m_max_leaves || m_leaf_count + new_leaf_count > m_max_leaves) {
throw std::invalid_argument("too many leaves");
}
const int depth = m_log2_root_size - m_log2_leaf_size;
int j = 0;
while (j <= depth) {
const uint64_t j_span = address_type{1} << j;
if (j_span > new_leaf_count) {
break;
}
// is our smallest tree at depth j?
if ((m_leaf_count & j_span) != 0) {
// if so, we can add 2^j pristine leaves directly
auto right = m_pristine_hashes.get_hash(m_log2_leaf_size + j);
for (int i = j; i <= depth; ++i) {
const uint64_t i_span = address_type{1} << i;
if ((m_leaf_count & i_span) != 0) {
const auto &left = m_context[i];
get_concat_hash(h, left, right, right);
} else {
m_context[i] = right;
// outer loop continues where we left off
j = i;
break;
}
}
new_leaf_count = new_leaf_count - j_span;
m_leaf_count = m_leaf_count + j_span;
} else {
++j;
}
}
// now add the rest of the padding directly to the context
for (int i = 0; i <= depth; ++i) {
const uint64_t i_span = address_type{1} << i;
if ((new_leaf_count & i_span) != 0) {
m_context[i] = m_pristine_hashes.get_hash(m_log2_leaf_size + i);
new_leaf_count = new_leaf_count - i_span;
m_leaf_count = m_leaf_count + i_span;
}
}
}

back_merkle_tree::hash_type back_merkle_tree::get_root_hash(void) const {
hasher_type h;
assert(m_leaf_count <= m_max_leaves);
Expand Down
30 changes: 25 additions & 5 deletions src/back-merkle-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ class back_merkle_tree {
/// \brief Constructor
/// \param log2_root_size Log<sub>2</sub> of root node
/// \param log2_leaf_size Log<sub>2</sub> of leaf node
/// \param log2_word_size Log<sub>2</sub> of word
/// \param log2_word_size Log<sub>2</sub> of word node
back_merkle_tree(int log2_root_size, int log2_leaf_size, int log2_word_size);

/// \brief Appends a new hash to the tree
/// \param hash Hash of leaf data
/// \param new_leaf_hash Hash of new leaf data
/// \details
/// Consider the tree down to the leaf level.
/// The tree is only complete after 2^(log2_root_size-log2_leaf_size) leaves
/// have been added.
/// The tree is only complete after 2^(log2_root_size-log2_leaf_size)
/// leaves have been added.
/// Before that, when leaf_count leaves have been added, we assume the rest
/// of the leaves are filled with zeros (i.e., they are pristine).
/// The trick is that we do not need to store the hashes of all leaf_count
Expand All @@ -85,7 +85,27 @@ class back_merkle_tree {
/// If the bit is not set, we simply store context[i] = right and break
/// In other words, we can update the context in
/// log time (log2_root_size-log2_leaf_size)
void push_back(const hash_type &leaf_hash);
void push_back(const hash_type &new_leaf_hash);

/// \brief Appends a number of padding hashes to the tree
/// \param leaf_count Number of padding hashes to append
/// \details
/// Recall that a bit i set in leaf_count represents a complete subtree
/// of size 2^i for which we have a hash in context[i].
/// The remaining entries in the context are unused.
/// The base case is when the least significant bit set in leaf_count is
/// bigger than new_leaf_count.
/// We can simply add to context[j] a pristine subtree of size 2^j
/// for each bit j set in new_leaf_count.
/// No used used entry in the context will be overwritten.
/// We can then simply add new_leaf_count to leaf_count and we are done.
/// In the general case, the least significant bit set i in leaf_count is
/// less than or equal to new_leaf_count.
/// Here, we add a pristine subtree of size 2^i to the context and
/// bubble up.
/// We add 2^i to leaf_count and subtract 2^i from new_leaf_count.
/// Then we repeat this process until we reach the base case.
void pad_back(uint64_t new_leaf_count);

/// \brief Returns the root tree hash
/// \returns Root tree hash
Expand Down
21 changes: 12 additions & 9 deletions src/rng-seed.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright 2023 Cartesi Pte. Ltd.
// Copyright Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at http://www.apache.org/licenses/LICENSE-2.0
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along
// with this program (see COPYING). If not, see <https://www.gnu.org/licenses/>.
//

#ifndef RNG_SEED_H
Expand Down
11 changes: 6 additions & 5 deletions src/test-machine-c-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@
#define BOOST_FIXTURE_TEST_CASE_NOLINT(...) BOOST_FIXTURE_TEST_CASE(__VA_ARGS__)

static hash_type get_verification_root_hash(cm_machine *machine) {
std::vector dump_list{
std::vector<std::string> dump_list{{
"0000000000000000--0000000000001000.bin", // shadow state
"0000000000001000--000000000000f000.bin", // dtb
"0000000000010000--0000000000001000.bin", // shadow pmas
"0000000000020000--0000000000006000.bin", // shadow tlb
"0000000002000000--00000000000c0000.bin", // clint
"0000000040008000--0000000000001000.bin", // htif
"000000007ff00000--0000000000100000.bin", // dtb
"0000000080000000--0000000000100000.bin", // ram
};
}};
char *err_msg{};

int error_code = cm_dump_pmas(machine, &err_msg);
Expand Down Expand Up @@ -232,6 +232,7 @@ class incomplete_machine_fixture : public default_machine_fixture {

target->uarch.ram.image_filename = new_cstr(source->uarch.ram.image_filename);
target->uarch.ram.length = source->uarch.ram.length;
target->uarch.processor = source->uarch.processor;
}

static void _cleanup_machine_config(cm_machine_config *config) {
Expand Down Expand Up @@ -1484,11 +1485,11 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(get_initial_config_flash_drive_test, flash_drive_
BOOST_FIXTURE_TEST_CASE_NOLINT(dump_pmas_null_placeholder_test, flash_drive_machine_fixture) {
std::array dump_list{
"0000000000000000--0000000000001000.bin", // shadow state
"0000000000001000--000000000000f000.bin", // dtb
"0000000000010000--0000000000001000.bin", // shadow pmas
"0000000000020000--0000000000006000.bin", // shadow tlb
"0000000002000000--00000000000c0000.bin", // clint
"0000000040008000--0000000000001000.bin", // htif
"000000007ff00000--0000000000100000.bin", // dtb
"0000000080000000--0000000000100000.bin", // ram
"0080000000000000--0000000003c00000.bin" // flash drive
};
Expand All @@ -1505,11 +1506,11 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(dump_pmas_null_placeholder_test, flash_drive_mach
BOOST_FIXTURE_TEST_CASE_NOLINT(dump_pmas_basic_test, flash_drive_machine_fixture) {
std::array dump_list{
"0000000000000000--0000000000001000.bin", // shadow state
"0000000000001000--000000000000f000.bin", // dtb
"0000000000010000--0000000000001000.bin", // shadow pmas
"0000000000020000--0000000000006000.bin", // shadow tlb
"0000000002000000--00000000000c0000.bin", // clint
"0000000040008000--0000000000001000.bin", // htif
"000000007ff00000--0000000000100000.bin", // dtb
"0000000080000000--0000000000100000.bin", // ram
"0080000000000000--0000000003c00000.bin" // flash drive
};
Expand Down
Loading

0 comments on commit 34547ee

Please sign in to comment.