Skip to content

Commit

Permalink
feat: Replace proof with sibling_hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcos Pernambuco Motta committed Nov 19, 2023
1 parent a971e95 commit 0ba60e6
Show file tree
Hide file tree
Showing 28 changed files with 556 additions and 445 deletions.
2 changes: 1 addition & 1 deletion lib/grpc-interfaces
7 changes: 5 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ PGO_WORKLOAD=\
whetstone 2500

# We ignore test-machine-c-api.cpp cause it takes too long.
LINTER_IGNORE_SOURCES=test-machine-c-api.cpp
# We ignore uarch-pristine-ram.c because it is generated by xxd.
# We ignore uarch-pristine-state-hash.cpp because it is generated by compute-uarch-pristine-hash.
LINTER_IGNORE_SOURCES=test-machine-c-api.cpp uarch-pristine-ram.c uarch-pristine-state-hash.cpp
LINTER_IGNORE_HEADERS=%.pb.h
LINTER_SOURCES=$(filter-out $(LINTER_IGNORE_SOURCES),$(strip $(wildcard *.cpp) $(wildcard *.c)))
LINTER_HEADERS=$(filter-out $(LINTER_IGNORE_HEADERS),$(strip $(wildcard *.hpp) $(wildcard *.h)))
Expand All @@ -269,7 +271,9 @@ CLANG_FORMAT=clang-format
CLANG_FORMAT_UARCH_FILES:=$(wildcard ../uarch/*.cpp)
CLANG_FORMAT_UARCH_FILES:=$(filter-out %uarch-printf%,$(strip $(CLANG_FORMAT_UARCH_FILES)))
CLANG_FORMAT_FILES:=$(wildcard *.cpp) $(wildcard *.c) $(wildcard *.h) $(wildcard *.hpp) $(CLANG_FORMAT_UARCH_FILES)
CLANG_FORMAT_IGNORE_FILES:=uarch-pristine-ram.c uarch-pristine-state-hash.cpp
CLANG_FORMAT_FILES:=$(filter-out %.pb.h,$(strip $(CLANG_FORMAT_FILES)))
CLANG_FORMAT_FILES:=$(filter-out $(CLANG_FORMAT_IGNORE_FILES),$(strip $(CLANG_FORMAT_FILES)))

STYLUA=stylua
STYLUA_FLAGS=--indent-type Spaces --collapse-simple-statement Always
Expand Down Expand Up @@ -755,7 +759,6 @@ jsonrpc-discover.cpp: jsonrpc-discover.json

uarch-pristine-state-hash.cpp: compute-uarch-pristine-hash
@echo '// This file is auto-generated and should not be modified' > $@
@echo '// clang-format off' >> $@
@echo '#include "uarch-pristine-state-hash.h"' >> $@
@echo 'namespace cartesi {' >> $@
@echo ' const machine_merkle_tree::hash_type uarch_pristine_state_hash{' >> $@
Expand Down
64 changes: 38 additions & 26 deletions src/access-log.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ static inline uint64_t get_word_access_data(const access_data &ad) {
/// NOLINTNEXTLINE(bugprone-exception-escape)
class access {

using proof_type = machine_merkle_tree::proof_type;
using hasher_type = machine_merkle_tree::hasher_type;

public:
using hash_type = machine_merkle_tree::hash_type;
using sibling_hashes_type = std::vector<hash_type>;
using proof_type = machine_merkle_tree::proof_type;

public:
void set_type(access_type type) {
Expand Down Expand Up @@ -158,38 +162,46 @@ class access {
return m_read_hash;
}

/// \brief Sets proof that data read at address was in
/// Merkle tree before access.
/// \param proof Corresponding Merkle tree proof.
void set_proof(const proof_type &proof) {
m_proof = proof;
}
void set_proof(proof_type &&proof) {
m_proof = std::move(proof);
/// \brief Constructs a proof using this access' data and a given root hash.
/// \param root_hash Hash to be used as the root of the proof.
/// \return The corresponding proof
proof_type make_proof(const hash_type root_hash) const {
if (!m_sibling_hashes.has_value()) {
throw std::runtime_error("can't make proof if access doesn't have sibling hashes");
}
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
const auto &sibiling_hashes = m_sibling_hashes.value();
auto log2_root_size = m_log2_size + sibiling_hashes.size();
proof_type proof(log2_root_size, m_log2_size);
proof.set_root_hash(root_hash);
proof.set_target_address(m_address);
proof.set_target_hash(m_read_hash);
for (size_t log2_size = m_log2_size; log2_size < log2_root_size; log2_size++) {
proof.set_sibling_hash(sibiling_hashes[log2_size - m_log2_size], log2_size);
}
return proof;
}

/// \brief Gets proof that data read at address was in
/// Merkle tree before access.
/// \returns Proof, if one is available.
const std::optional<proof_type> &get_proof(void) const {
return m_proof;
std::optional<sibling_hashes_type> &get_sibling_hashes() {
return m_sibling_hashes;
}
const std::optional<sibling_hashes_type> &get_sibling_hashes() const {
return m_sibling_hashes;
}

/// \brief Removes proof that data read at address was in
/// Merkle tree before access.
void clear_proof(void) {
m_proof = std::nullopt;
void set_sibling_hashes(const sibling_hashes_type &sibling_hashes) {
m_sibling_hashes = sibling_hashes;
}

private:
access_type m_type{0}; ///< Type of access
uint64_t m_address{0}; ///< Address of access
int m_log2_size{0}; ///< Log2 of size of access
std::optional<access_data> m_read{}; ///< Data before access
hash_type m_read_hash; ///< Hash of data before access
std::optional<access_data> m_written{}; ///< Written data
std::optional<hash_type> m_written_hash{}; ///< Hash of written data
std::optional<proof_type> m_proof{}; ///< Proof of data before access
access_type m_type{0}; ///< Type of access
uint64_t m_address{0}; ///< Address of access
int m_log2_size{0}; ///< Log2 of size of access
std::optional<access_data> m_read{}; ///< Data before access
hash_type m_read_hash; ///< Hash of data before access
std::optional<access_data> m_written{}; ///< Written data
std::optional<hash_type> m_written_hash{}; ///< Hash of written data
std::optional<sibling_hashes_type> m_sibling_hashes{}; ///< Hashes of siblings in path from address to root
};

/// \brief Log of state accesses
Expand Down
1 change: 0 additions & 1 deletion src/cartesi-machine-tests.lua
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,6 @@ local function print_machine(test_name, expected_cycles)
--ram-length=32Mi\
--ram-image='%s'\
--no-bootargs\
--uarch-ram-length=%d\
--uarch-ram-image=%s\
--max-mcycle=%d ",
test_path .. "/" .. test_name,
Expand Down
1 change: 0 additions & 1 deletion src/cartesi/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ function _M.dump_log(log, out)
j = j + 1
-- Otherwise, output access
elseif ai then
if ai.proof then indentout(out, indent, "hash %s\n", hexhash8(ai.proof.root_hash)) end
local read = accessdatastring(ai.read, ai.read_hash, ai.log2_size)
if ai.type == "read" then
indentout(out, indent, "%d: read %s@0x%x(%u): %s\n", i, notes[i] or "", ai.address, ai.address, read)
Expand Down
6 changes: 2 additions & 4 deletions src/clua-jsonrpc-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,8 @@ static int jsonrpc_machine_class_verify_uarch_step_state_transition(lua_State *L
clua_check_cm_hash(L, 3, &target_hash);
auto &managed_runtime_config = clua_push_to(L,
clua_managed_cm_ptr<cm_machine_runtime_config>(clua_opt_cm_machine_runtime_config(L, 4, {}, ctxidx)), ctxidx);
const bool one_based = lua_toboolean(L, 5);
TRY_EXECUTE(cm_jsonrpc_verify_uarch_step_state_transition(managed_jsonrpc_mg_mgr.get(), &root_hash,
managed_log.get(), &target_hash, managed_runtime_config.get(), one_based, err_msg));
managed_log.get(), &target_hash, managed_runtime_config.get(), true, err_msg));
managed_log.reset();
managed_runtime_config.reset();
lua_pop(L, 2);
Expand All @@ -122,9 +121,8 @@ static int jsonrpc_machine_class_verify_uarch_reset_state_transition(lua_State *
clua_check_cm_hash(L, 3, &target_hash);
auto &managed_runtime_config = clua_push_to(L,
clua_managed_cm_ptr<cm_machine_runtime_config>(clua_opt_cm_machine_runtime_config(L, 4, {}, ctxidx)), ctxidx);
const bool one_based = lua_toboolean(L, 5);
TRY_EXECUTE(cm_jsonrpc_verify_uarch_reset_state_transition(managed_jsonrpc_mg_mgr.get(), &root_hash,
managed_log.get(), &target_hash, managed_runtime_config.get(), one_based, err_msg));
managed_log.get(), &target_hash, managed_runtime_config.get(), true, err_msg));
managed_log.reset();
managed_runtime_config.reset();
lua_pop(L, 2);
Expand Down
42 changes: 32 additions & 10 deletions src/clua-machine-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ void cm_delete(cm_access_log *ptr) {
cm_delete_access_log(ptr);
}

/// \brief Deleter for C api access
template <>
void cm_delete(cm_access *ptr) {
cm_delete_access(ptr);
}

/// \brief Deleter for C api merkle tree proof
template <>
void cm_delete(cm_merkle_tree_proof *ptr) {
Expand Down Expand Up @@ -352,9 +358,9 @@ static void check_sibling_cm_hashes(lua_State *L, int idx, size_t log2_target_si
}
sibling_hashes->count = sibling_hashes_count;
sibling_hashes->entry = new cm_hash[sibling_hashes_count]{};
for (; log2_target_size < log2_root_size; ++log2_target_size) {
lua_rawgeti(L, idx, static_cast<lua_Integer>(log2_root_size - log2_target_size));
auto index = log2_root_size - 1 - log2_target_size;
for (size_t log2_size = log2_target_size; log2_size < log2_root_size; ++log2_size) {
lua_rawgeti(L, idx, static_cast<lua_Integer>(log2_size - log2_target_size) + 1);
auto index = log2_size - log2_target_size;
clua_check_cm_hash(L, -1, &sibling_hashes->entry[index]);
lua_pop(L, 1);
}
Expand Down Expand Up @@ -424,8 +430,7 @@ static unsigned char *opt_cm_access_data_field(lua_State *L, int tabidx, const c
/// \param a Pointer to receive access
/// \param ctxidx Index (or pseudo-index) of clua context
static void check_cm_access(lua_State *L, int tabidx, bool proofs, cm_access *a, int ctxidx) {
ctxidx = lua_absindex(L, ctxidx);
tabidx = lua_absindex(L, tabidx);
(void) ctxidx;
luaL_checktype(L, tabidx, LUA_TTABLE);
a->type = check_cm_access_type_field(L, tabidx, "type");
a->address = check_uint_field(L, tabidx, "address");
Expand All @@ -435,8 +440,9 @@ static void check_cm_access(lua_State *L, int tabidx, bool proofs, cm_access *a,
CM_TREE_LOG2_ROOT_SIZE);
}
if (proofs) {
lua_getfield(L, tabidx, "proof");
a->proof = clua_check_cm_merkle_tree_proof(L, -1, ctxidx);
lua_getfield(L, tabidx, "sibling_hashes");
a->sibling_hashes = new cm_hash_array{};
check_sibling_cm_hashes(L, -1, a->log2_size, CM_TREE_LOG2_ROOT_SIZE, a->sibling_hashes);
lua_pop(L, 1);
}

Expand All @@ -452,6 +458,18 @@ static void check_cm_access(lua_State *L, int tabidx, bool proofs, cm_access *a,
a->written_data = opt_cm_access_data_field(L, tabidx, "written", a->log2_size, &a->written_data_size);
}

cm_access *clua_check_cm_access(lua_State *L, int tabidx, int ctxidx) {
tabidx = lua_absindex(L, tabidx);
ctxidx = lua_absindex(L, ctxidx);
luaL_checktype(L, tabidx, LUA_TTABLE);
auto &managed = clua_push_to(L, clua_managed_cm_ptr<cm_access>(new cm_access{}), ctxidx);
cm_access *access = managed.get();
check_cm_access(L, tabidx, true, access, ctxidx);
managed.release();
lua_pop(L, 1); // cleanup managed log from stack
return access;
}

cm_access_log *clua_check_cm_access_log(lua_State *L, int tabidx, int ctxidx) {
tabidx = lua_absindex(L, tabidx);
ctxidx = lua_absindex(L, ctxidx);
Expand Down Expand Up @@ -651,9 +669,13 @@ void clua_push_cm_access_log(lua_State *L, const cm_access_log *log) {
lua_setfield(L, -2, "written");
}
}
if (log->log_type.proofs && a->proof != nullptr) {
clua_push_cm_proof(L, a->proof);
lua_setfield(L, -2, "proof");
if (log->log_type.proofs && a->sibling_hashes != nullptr) {
lua_newtable(L);
for (size_t log2_size = a->log2_size; log2_size < CM_TREE_LOG2_ROOT_SIZE; log2_size++) {
clua_push_cm_hash(L, &a->sibling_hashes->entry[log2_size - a->log2_size]);
lua_rawseti(L, -2, static_cast<lua_Integer>(log2_size - a->log2_size) + 1);
}
lua_setfield(L, -2, "sibling_hashes");
}
lua_rawseti(L, -2, static_cast<lua_Integer>(i) + 1);
}
Expand Down
8 changes: 8 additions & 0 deletions src/clua-machine-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,14 @@ cm_merkle_tree_proof *clua_check_cm_merkle_tree_proof(lua_State *L, int tabidx);
/// \returns The access log. Must be delete by the user with cm_delete_access_log
cm_access_log *clua_check_cm_access_log(lua_State *L, int tabidx, int ctxidx = lua_upvalueindex(1));

/// \brief Loads an cm_access from Lua
/// \param L Lua state
/// \param tabidx access stack index
/// \param a Pointer to receive access
/// \param ctxidx Index (or pseudo-index) of clua context
/// \returns The access. Must be delete by the user with cm_delete_access
cm_access *clua_check_cm_access(lua_State *L, int tabidx, int ctxidx = lua_upvalueindex(1));

/// \brief Loads a cm_machine_config object from a Lua table
/// \param L Lua state
/// \param tabidx Index of table in Lua stack
Expand Down
1 change: 1 addition & 0 deletions src/clua-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ int clua_machine_init(lua_State *L, int ctxidx) {
clua_createnewtype<clua_managed_cm_ptr<const cm_machine_config>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_machine_config>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_access_log>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_access>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_machine_runtime_config>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<cm_merkle_tree_proof>>(L, ctxidx);
clua_createnewtype<clua_managed_cm_ptr<char>>(L, ctxidx);
Expand Down
26 changes: 20 additions & 6 deletions src/json-util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,15 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, access &access, con
}
not_default_constructible<machine_merkle_tree::proof_type> proof;
ju_get_opt_field(jk, "proof"s, proof, new_path);
if (proof.has_value()) {
access.set_proof(std::move(proof).value());
if (contains(jk, "sibling_hashes")) {
access.get_sibling_hashes().emplace();
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
auto &sibling_hashes = access.get_sibling_hashes().value();
ju_get_vector_like_field(jk, "sibling_hashes"s, sibling_hashes, new_path);
auto expected_depth = static_cast<size_t>(machine_merkle_tree::get_log2_root_size() - access.get_log2_size());
if (sibling_hashes.size() != expected_depth) {
throw std::invalid_argument("field \""s + new_path + "sibling_hashes\" has wrong length");
}
}
}

Expand Down Expand Up @@ -754,8 +761,9 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, not_default_constru
ju_get_vector_like_field(jk, "accesses"s, accesses, new_path);
if (log_type.value().has_proofs()) {
for (unsigned i = 0; i < accesses.size(); ++i) {
if (!accesses[i].get_proof().has_value()) {
throw std::invalid_argument("field \""s + new_path + "accesses/" + to_string(i) + "\" missing proof");
if (!accesses[i].get_sibling_hashes().has_value()) {
throw std::invalid_argument(
"field \""s + new_path + "accesses/" + to_string(i) + "\" missing sibling hashes");
}
}
}
Expand Down Expand Up @@ -1159,9 +1167,15 @@ void to_json(nlohmann::json &j, const access &a) {
j["written"] = encode_base64(a.get_written().value());
}
}
if (a.get_proof().has_value()) {
if (a.get_sibling_hashes().has_value()) {
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
j["proof"] = a.get_proof().value();
const auto &sibling_hashes = a.get_sibling_hashes().value();
auto depth = machine_merkle_tree::get_log2_root_size() - a.get_log2_size();
nlohmann::json s = nlohmann::json::array();
for (int i = 0; i < depth; i++) {
s.push_back(encode_base64(sibling_hashes[i]));
}
j["sibling_hashes"] = s;
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/machine-c-api-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,16 @@ CM_API cm_access_log *convert_to_c(const cartesi::access_log &cpp_access_log);
/// \brief Helper function converts access log to C api structure
CM_API cartesi::access_log convert_from_c(const cm_access_log *c_acc_log);

/// \brief Helper function that parses access from C api structure
CM_API cm_access *convert_to_c(const cartesi::access &cpp_access);

/// \brief Helper function converts access to C api structure
CM_API cartesi::access convert_from_c(const cm_access *c_access);

/// \brief Helper function converts C++ string to allocated C string
CM_API char *convert_to_c(const std::string &cpp_str);

/// \brief Helper function converts C++ string to allocated C string
CM_API cm_merkle_tree_proof *convert_to_c(const cartesi::machine_merkle_tree::proof_type &proof);

#endif // CM_C_API_INTERNAL_H
Loading

0 comments on commit 0ba60e6

Please sign in to comment.