Skip to content
Closed
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/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ jobs:

- name: Run Merkle tree tests
run: |
docker run --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash
docker run --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash --hash-function=keccak256
docker run --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash --hash-function=sha256

- name: Run C API tests
run: |
Expand Down Expand Up @@ -379,7 +380,8 @@ jobs:

- name: Run Merkle tree tests
run: |
docker run --platform linux/arm64 --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash
docker run --platform linux/arm64 --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash --hash-function=keccak256
docker run --platform linux/arm64 --rm -t ${{ github.repository_owner }}/machine-emulator:tests test-merkle-tree-hash --log2-root-size=30 --log2-leaf-size=12 --input=/usr/bin/test-merkle-tree-hash --hash-function=sha256

- name: Run C API tests
run: |
Expand Down Expand Up @@ -633,7 +635,7 @@ jobs:

- name: Run tests with sanitizer
run: |
docker run --rm -t ${{ github.repository_owner }}/machine-emulator:sanitizer make sanitize=yes test-save-and-load test-machine test-hash test-lua test-jsonrpc test-c-api coverage-machine test-uarch-rv64ui test-uarch-interpreter coverage-uarch
docker run --rm -t ${{ github.repository_owner }}/machine-emulator:sanitizer make sanitize=yes test-save-and-load test-machine test-lua test-jsonrpc test-c-api coverage-machine test-uarch-rv64ui test-uarch-interpreter coverage-uarch

publish_artifacts:
name: Publish artifacts
Expand Down
1 change: 1 addition & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ stap = "stap"
wronly = "wronly"
optin = "optin"
sxl = "sxl"
nd = "nd"
1 change: 0 additions & 1 deletion LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ This project includes several submodules and dependencies, each with its own lic
- `third-party/riscv-arch-test`: Source code licensed under the Apache 2.0 and BSD 3-Clause licenses. Documentation under `CC-BY-4.0`. License information is provided in README.md and other COPYING.* files like [third-party/riscv-arch-test/COPYING.APACHE](third-party/riscv-arch-test/COPYING.APACHE).
- `third-party/riscv-tests`: Licensed under the BSD 3-Clause "New" or "Revised" License. See [third-party/riscv-tests/LICENSE](third-party/riscv-tests/LICENSE) for license details.
- `third-party/riscv-tests/env`: Licensed under the BSD 3-Clause "New" or "Revised" License. License details are in [third-party/riscv-tests/env/LICENSE](third-party/riscv-tests/env/LICENSE).
- `third-party/tiny_sha3`: Licensed under the MIT License. The license can be found at [third-party/tiny_sha3/LICENSE](third-party/tiny_sha3/LICENSE).
- `third-party/nlohmann-json`: Licensed under the MIT License. The license can be found at [third-party/nlohmann-json/LICENSE.MIT](third-party/nlohmann-json/LICENSE.MIT).

## Debian Packages
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ EMU_TO_BIN= src/cartesi-jsonrpc-machine src/cartesi-merkle-tree-hash
EMU_TO_LIB= src/$(LIBCARTESI_SO) src/$(LIBCARTESI_SO_JSONRPC)
EMU_TO_LIB_A= src/libcartesi.a src/libcartesi_jsonrpc.a src/libluacartesi.a src/libluacartesi_jsonrpc.a
EMU_LUA_TO_BIN= src/cartesi-machine.lua src/cartesi-machine-stored-hash.lua
EMU_TO_LUA_PATH= src/cartesi/util.lua src/cartesi/proof.lua src/cartesi/gdbstub.lua
EMU_TO_LUA_PATH= src/cartesi/util.lua src/cartesi/gdbstub.lua
EMU_TO_LUA_CPATH= src/cartesi.so
EMU_TO_LUA_CARTESI_CPATH= src/cartesi/jsonrpc.so
EMU_TO_INC= $(addprefix src/,jsonrpc-machine-c-api.h machine-c-api.h machine-c-version.h)
Expand Down
24 changes: 17 additions & 7 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ CLANG_TIDY_WARNS=-Wthread-safety -Wglobal-constructors
# Place our include directories before the system's
INCS+= \
-I../third-party/llvm-flang-uint128 \
-I../third-party/tiny_sha3 \
-I../third-party/nlohmann-json \
-I../third-party/downloads \
$(BOOST_INC)
Expand Down Expand Up @@ -221,8 +220,8 @@ ifneq ($(git_commit),)
DEFS+=-DGIT_COMMIT='"$(git_commit)"'
endif

# The SHA3 is third party library we always want to compile with O3
SHA3_CFLAGS=-O3
# Hashing libraries have special optimizations flags
HASH_CFLAGS=-O3 -DNDEBUG -funroll-loops -fno-stack-protector

# Optimization flags for the interpreter
ifneq (,$(filter yes,$(relwithdebinfo) $(release)))
Expand Down Expand Up @@ -370,7 +369,9 @@ LIBCARTESI_OBJS:= \
pristine-merkle-tree.o \
replay-step-state-access-interop.o \
send-cmio-response.o \
sha3.o \
keccak-256-hasher.o \
sha-256-hasher.o \
is-pristine.o \
uarch-pristine-hash.o \
uarch-pristine-ram.o \
uarch-pristine-state-hash.o \
Expand All @@ -397,7 +398,9 @@ LUACARTESI_OBJS:= \
$(CARTESI_CLUA_OBJS)

LIBCARTESI_MERKLE_TREE_OBJS:= \
sha3.o \
keccak-256-hasher.o \
sha-256-hasher.o \
is-pristine.o \
back-merkle-tree.o \
pristine-merkle-tree.o \
complete-merkle-tree.o \
Expand Down Expand Up @@ -555,8 +558,6 @@ jsonrpc-discover.cpp: jsonrpc-discover.json
@$(CC) $(CFLAGS) $< -MM -MT $@ -MF $@.d > /dev/null 2>&1
@touch $@

sha3.o: ../third-party/tiny_sha3/sha3.c
$(CC) $(CFLAGS) $(SHA3_CFLAGS) -c -o $@ $<

uarch-pristine-ram.o: $(UARCH_PRISTINE_RAM_C)
$(CC) $(CFLAGS) -c -o $@ $<
Expand All @@ -570,6 +571,15 @@ interpret-jump-table.h: ../tools/gen-interpret-jump-table.lua
interpret.o: interpret.cpp machine-c-version.h interpret-jump-table.h
$(CXX) $(CXXFLAGS) $(INTERPRET_CXXFLAGS) -c -o $@ $<

keccak-256-hasher.o: keccak-256-hasher.cpp
$(CXX) $(CXXFLAGS) $(HASH_CFLAGS) -c -o $@ $<

sha-256-hasher.o: sha-256-hasher.cpp
$(CXX) $(CXXFLAGS) $(HASH_CFLAGS) -c -o $@ $<

is-pristine.o: is-pristine.cpp
$(CXX) $(CXXFLAGS) $(HASH_CFLAGS) -c -o $@ $<

%.o: %.cpp machine-c-version.h
$(CXX) $(CXXFLAGS) -c -o $@ $<

Expand Down
4 changes: 2 additions & 2 deletions src/address-range.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ class address_range {
}

#ifndef MICROARCHITECTURE
// Defaul implemenation returns always dirty tree
// Default implementation returns always dirty tree
virtual const i_dirty_page_tree &do_get_dirty_page_tree() const noexcept {
const static empty_dirty_page_tree no_dirty{};
return no_dirty;
Expand All @@ -363,7 +363,7 @@ class address_range {
return const_cast<i_dirty_page_tree &>(std::as_const(*this).do_get_dirty_page_tree());
}

// Defaul implemenation returns no hashes
// Default implementation returns no hashes
virtual const i_dense_hash_tree &do_get_dense_hash_tree() const noexcept {
const static empty_dense_hash_tree no_hashes{};
return no_hashes;
Expand Down
31 changes: 31 additions & 0 deletions src/array2d.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// 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.
//
// 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 ARRAY2D_H
#define ARRAY2D_H

#include <array>
#include <cstddef>

namespace cartesi {

//??(edubart): In future C++ standards we should switch to `std::mdarray` or `std::mdspan`
template <class T, std::size_t M, std::size_t N>
using array2d = std::array<std::array<T, N>, M>;

} // namespace cartesi

#endif // ARRAY2D_H
14 changes: 8 additions & 6 deletions src/back-merkle-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,14 @@

namespace cartesi {

back_merkle_tree::back_merkle_tree(int log2_root_size, int log2_leaf_size, int log2_word_size) :
back_merkle_tree::back_merkle_tree(int log2_root_size, int log2_leaf_size, int log2_word_size,
hash_function_type hash_function) :
m_log2_root_size{log2_root_size},
m_log2_leaf_size{log2_leaf_size},
m_max_leaves{UINT64_C(1) << (log2_root_size - log2_leaf_size)},
m_context(std::max(1, log2_root_size - log2_leaf_size + 1)),
m_pristine_hashes{log2_root_size, log2_word_size} {
m_pristine_hashes{log2_root_size, log2_word_size, hash_function},
m_hash_function(hash_function) {
if (log2_root_size < 0) {
throw std::out_of_range{"log2_root_size is negative"};
}
Expand All @@ -56,7 +58,7 @@ back_merkle_tree::back_merkle_tree(int log2_root_size, int log2_leaf_size, int l
}

void back_merkle_tree::push_back(const machine_hash &new_leaf_hash) {
hasher_type h;
variant_hasher h{m_hash_function};
machine_hash right = new_leaf_hash;
if (m_leaf_count >= m_max_leaves) {
throw std::out_of_range{"too many leaves"};
Expand All @@ -75,7 +77,7 @@ void back_merkle_tree::push_back(const machine_hash &new_leaf_hash) {
}

void back_merkle_tree::pad_back(uint64_t new_leaf_count) {
hasher_type h;
variant_hasher h{m_hash_function};
if (new_leaf_count > m_max_leaves || m_leaf_count + new_leaf_count > m_max_leaves) {
throw std::invalid_argument("too many leaves");
}
Expand Down Expand Up @@ -120,7 +122,7 @@ void back_merkle_tree::pad_back(uint64_t new_leaf_count) {
}

machine_hash back_merkle_tree::get_root_hash() const {
hasher_type h;
variant_hasher h{m_hash_function};
assert(m_leaf_count <= m_max_leaves);
const int depth = m_log2_root_size - m_log2_leaf_size;
if (m_leaf_count < m_max_leaves) {
Expand All @@ -144,7 +146,7 @@ back_merkle_tree::proof_type back_merkle_tree::get_next_leaf_proof() const {
if (m_leaf_count >= m_max_leaves) {
throw std::out_of_range{"tree is full"};
}
hasher_type h;
variant_hasher h{m_hash_function};
proof_type proof{m_log2_root_size, m_log2_leaf_size};
proof.set_target_address(m_leaf_count << m_log2_leaf_size);
proof.set_target_hash(m_pristine_hashes.get_hash(m_log2_leaf_size));
Expand Down
17 changes: 6 additions & 11 deletions src/back-merkle-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
#include <vector>

#include "hash-tree-proof.h"
#include "keccak-256-hasher.h"
#include "machine-hash.h"
#include "pristine-merkle-tree.h"
#include "variant-hasher.h"

/// \file
/// \brief Back Merkle tree interface.
Expand All @@ -40,20 +40,14 @@ namespace cartesi {
/// The class only ever stores log(n) hashes (1 for each tree level).
class back_merkle_tree {
public:
/// \brief Hasher class.
using hasher_type = keccak_256_hasher;

/// \brief Hasher class.
using hash_type = machine_hash;

/// \brief Storage for the proof of a word value.
using proof_type = hash_tree_proof;

/// \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 node
back_merkle_tree(int log2_root_size, int log2_leaf_size, int log2_word_size);
back_merkle_tree(int log2_root_size, int log2_leaf_size, int log2_word_size, hash_function_type hash_function);

/// \brief Appends a new hash to the tree
/// \param new_leaf_hash Hash of new leaf data
Expand All @@ -76,7 +70,7 @@ class back_merkle_tree {
/// If the bit i is set in leaf_count, we replace context[i] = hash(context[i], right) and move up a bit.
/// 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 &new_leaf_hash);
void push_back(const machine_hash &new_leaf_hash);

/// \brief Appends a number of padding hashes to the tree
/// \param leaf_count Number of padding hashes to append
Expand Down Expand Up @@ -107,7 +101,7 @@ class back_merkle_tree {
/// are growing is to the right of what is in the context)
/// If bit i is not set, we set root = hash(root, pristine[i+log2_leaf_size]) and move up a bit
/// (i.e., to grow our subtree, we need to pad it on the right with a pristine subtree of the same size)
hash_type get_root_hash() const;
machine_hash get_root_hash() const;

/// \brief Returns proof for the next pristine leaf
/// \returns Proof for leaf at given index, or throws exception
Expand All @@ -120,8 +114,9 @@ class back_merkle_tree {
int m_log2_leaf_size; ///< Log<sub>2</sub> of leaf size
uint64_t m_leaf_count{0}; ///< Number of leaves already added
uint64_t m_max_leaves; ///< Maximum number of leaves
std::vector<hash_type> m_context; ///< Hashes of bits set in leaf_count
std::vector<machine_hash> m_context; ///< Hashes of bits set in leaf_count
pristine_merkle_tree m_pristine_hashes; ///< Hash of pristine subtrees of all sizes
hash_function_type m_hash_function; ///< Hash function
};

} // namespace cartesi
Expand Down
14 changes: 8 additions & 6 deletions src/cartesi-machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,13 @@ where options are:
configures the global hash tree the the machine

<key>:<value> is one of
hasher:<string>
hash_function:<string>
sht_filename:<filename>
phtc_filename:<filename>
phtc_size:<number>
shared

hasher (default: "keccak")
hash_function (default: "keccak256")
hashing algorithm used for the tree

sht_filename (optional)
Expand Down Expand Up @@ -678,7 +678,7 @@ local uarch = {
}
local pmas = {}
local hash_tree = {
hasher = default_config.hash_tree.hasher,
hash_function = default_config.hash_tree.hash_function,
}
local concurrency_update_hash_tree = 0
local skip_root_hash_check = false
Expand Down Expand Up @@ -1063,18 +1063,20 @@ local options = {
"^(%-%-hash%-tree%=(.+))$",
function(all, opts)
local h = util.parse_options(opts, {
hasher = true,
hash_function = true,
sht_filename = true,
phtc_filename = true,
phtc_size = true,
shared = true,
})
if h.sht_filename == true then h.sht_filename = "" end
if h.phtc_filename == true then h.phtc_filename = "" end
if h.hasher == true then h.hasher = "keccak" end
if h.hash_function == true then h.hash_function = "keccak256" end
if h.shared == nil or h.shared == "false" then h.shared = false end
if h.shared == "true" then h.shared = true end
h.phtc_size = assert(util.parse_number(h.phtc_size), "invalid page hash cache size in " .. all)
if h.phtc_size ~= nil then
assert(util.parse_number(h.phtc_size), "invalid page hash cache size in " .. all)
end
assert(type(h.shared) == "boolean", "invalid hash tree shared value in " .. all)
for i, v in pairs(h) do
hash_tree[i] = v
Expand Down
43 changes: 0 additions & 43 deletions src/cartesi/proof.lua

This file was deleted.

Loading