diff --git a/src/access-log.h b/src/access-log.h index 5d49a2f5b..4cf4246b0 100644 --- a/src/access-log.h +++ b/src/access-log.h @@ -224,31 +224,23 @@ class access_log { public: /// \brief Type of access log class type { - bool m_proofs; ///< Includes proofs bool m_annotations; ///< Includes annotations bool m_large_data; ///< Includes data bigger than 8 bytes public: /// \brief Default constructor - /// \param proofs Include proofs /// \param annotations Include annotations (default false) - explicit type(bool proofs, bool annotations = false, bool large_data = false) : - m_proofs(proofs), + /// \param large_data Include large data (default false) + explicit type(bool annotations = false, bool large_data = false) : m_annotations(annotations), m_large_data(large_data) { ; } explicit type(int log_type) : - m_proofs(static_cast(log_type & CM_ACCESS_LOG_TYPE_PROOFS)), m_annotations(static_cast(log_type & CM_ACCESS_LOG_TYPE_ANNOTATIONS)), m_large_data(static_cast(log_type & CM_ACCESS_LOG_TYPE_LARGE_DATA)) { ; } - /// \brief Returns whether log includes proofs - bool has_proofs(void) const { - return m_proofs; - } - /// \brief Returns whether log includes annotations bool has_annotations(void) const { return m_annotations; diff --git a/src/cartesi-machine.lua b/src/cartesi-machine.lua index d08b439c7..1e4e8c908 100755 --- a/src/cartesi-machine.lua +++ b/src/cartesi-machine.lua @@ -2150,17 +2150,11 @@ if gdb_stub then gdb_stub:close() end if log_step_uarch then assert(config.processor.iunrep == 0, "micro step proof is meaningless in unreproducible mode") stderr("Gathering micro step log: please wait\n") - util.dump_log( - machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS), - io.stderr - ) + util.dump_log(machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS), io.stderr) end if log_reset_uarch then stderr("Resetting microarchitecture state: please wait\n") - util.dump_log( - machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS), - io.stderr - ) + util.dump_log(machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS), io.stderr) end if dump_memory_ranges then dump_pmas(machine) end if final_hash then diff --git a/src/clua-cartesi.cpp b/src/clua-cartesi.cpp index d6d704ef3..b2542fc80 100644 --- a/src/clua-cartesi.cpp +++ b/src/clua-cartesi.cpp @@ -182,7 +182,6 @@ CM_API int luaopen_cartesi(lua_State *L) { clua_setintegerfield(L, CM_BREAK_REASON_REACHED_TARGET_MCYCLE, "BREAK_REASON_REACHED_TARGET_MCYCLE", -1); clua_setintegerfield(L, CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE, "UARCH_BREAK_REASON_REACHED_TARGET_CYCLE", -1); clua_setintegerfield(L, CM_UARCH_BREAK_REASON_UARCH_HALTED, "UARCH_BREAK_REASON_UARCH_HALTED", -1); - clua_setintegerfield(L, CM_ACCESS_LOG_TYPE_PROOFS, "ACCESS_LOG_TYPE_PROOFS", -1); clua_setintegerfield(L, CM_ACCESS_LOG_TYPE_ANNOTATIONS, "ACCESS_LOG_TYPE_ANNOTATIONS", -1); clua_setintegerfield(L, CM_ACCESS_LOG_TYPE_LARGE_DATA, "ACCESS_LOG_TYPE_LARGE_DATA", -1); clua_setintegerfield(L, CM_CMIO_YIELD_COMMAND_AUTOMATIC, "CMIO_YIELD_COMMAND_AUTOMATIC", -1); diff --git a/src/clua-jsonrpc-machine.cpp b/src/clua-jsonrpc-machine.cpp index b983f4997..962b1c84a 100644 --- a/src/clua-jsonrpc-machine.cpp +++ b/src/clua-jsonrpc-machine.cpp @@ -62,18 +62,12 @@ static int jsonrpc_machine_class_verify_step_uarch(lua_State *L) { lua_settop(L, 5); auto &managed_jsonrpc_mgr = clua_check>(L, stubidx, ctxidx); const char *log = clua_check_schemed_json_string(L, 2, "AccessLog", ctxidx); - if (!lua_isnil(L, 1) || !lua_isnil(L, 3)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 1, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 3, &target_hash); - if (cm_jsonrpc_verify_step_uarch(managed_jsonrpc_mgr.get(), &root_hash, log, &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_jsonrpc_verify_step_uarch(managed_jsonrpc_mgr.get(), nullptr, log, nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 1, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 3, &target_hash); + if (cm_jsonrpc_verify_step_uarch(managed_jsonrpc_mgr.get(), &root_hash, log, &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } @@ -86,18 +80,12 @@ static int jsonrpc_machine_class_verify_reset_uarch(lua_State *L) { lua_settop(L, 5); auto &managed_jsonrpc_mgr = clua_check>(L, stubidx, ctxidx); const char *log = clua_check_schemed_json_string(L, 2, "AccessLog", ctxidx); - if (!lua_isnil(L, 1) || !lua_isnil(L, 3)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 1, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 3, &target_hash); - if (cm_jsonrpc_verify_reset_uarch(managed_jsonrpc_mgr.get(), &root_hash, log, &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_jsonrpc_verify_reset_uarch(managed_jsonrpc_mgr.get(), nullptr, log, nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 1, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 3, &target_hash); + if (cm_jsonrpc_verify_reset_uarch(managed_jsonrpc_mgr.get(), &root_hash, log, &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } @@ -114,20 +102,13 @@ static int jsonrpc_machine_class_verify_send_cmio_response(lua_State *L) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const auto *data = reinterpret_cast(luaL_checklstring(L, 2, &length)); const char *log = clua_check_schemed_json_string(L, 4, "AccessLog", ctxidx); - if (!lua_isnil(L, 3) || !lua_isnil(L, 5)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 3, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 5, &target_hash); - if (cm_jsonrpc_verify_send_cmio_response(managed_jsonrpc_mgr.get(), reason, data, length, &root_hash, log, - &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_jsonrpc_verify_send_cmio_response(managed_jsonrpc_mgr.get(), reason, data, length, nullptr, log, - nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 3, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 5, &target_hash); + if (cm_jsonrpc_verify_send_cmio_response(managed_jsonrpc_mgr.get(), reason, data, length, &root_hash, log, + &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } diff --git a/src/clua-machine.cpp b/src/clua-machine.cpp index 271a9b7c9..c1db6e2f2 100644 --- a/src/clua-machine.cpp +++ b/src/clua-machine.cpp @@ -43,18 +43,12 @@ static int machine_class_index_get_reg_address(lua_State *L) { static int machine_class_index_verify_step_uarch(lua_State *L) { lua_settop(L, 4); const char *log = clua_check_schemed_json_string(L, 2, "AccessLog"); - if (!lua_isnil(L, 1) || !lua_isnil(L, 3)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 1, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 3, &target_hash); - if (cm_verify_step_uarch(&root_hash, log, &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_verify_step_uarch(nullptr, log, nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 1, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 3, &target_hash); + if (cm_verify_step_uarch(&root_hash, log, &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } @@ -63,18 +57,12 @@ static int machine_class_index_verify_step_uarch(lua_State *L) { static int machine_class_index_verify_reset_uarch(lua_State *L) { lua_settop(L, 4); const char *log = clua_check_schemed_json_string(L, 2, "AccessLog"); - if (!lua_isnil(L, 1) || !lua_isnil(L, 3)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 1, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 3, &target_hash); - if (cm_verify_reset_uarch(&root_hash, log, &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_verify_reset_uarch(nullptr, log, nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 1, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 3, &target_hash); + if (cm_verify_reset_uarch(&root_hash, log, &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } @@ -87,18 +75,12 @@ static int machine_class_index_verify_send_cmio_response(lua_State *L) { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) const auto *data = reinterpret_cast(luaL_checklstring(L, 2, &length)); const char *log = clua_check_schemed_json_string(L, 4, "AccessLog"); - if (!lua_isnil(L, 3) || !lua_isnil(L, 5)) { - cm_hash root_hash{}; - clua_check_cm_hash(L, 3, &root_hash); - cm_hash target_hash{}; - clua_check_cm_hash(L, 5, &target_hash); - if (cm_verify_send_cmio_response(reason, data, length, &root_hash, log, &target_hash) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } - } else { - if (cm_verify_send_cmio_response(reason, data, length, nullptr, log, nullptr) != 0) { - return luaL_error(L, "%s", cm_get_last_error_message()); - } + cm_hash root_hash{}; + clua_check_cm_hash(L, 3, &root_hash); + cm_hash target_hash{}; + clua_check_cm_hash(L, 5, &target_hash); + if (cm_verify_send_cmio_response(reason, data, length, &root_hash, log, &target_hash) != 0) { + return luaL_error(L, "%s", cm_get_last_error_message()); } return 0; } diff --git a/src/json-util.cpp b/src/json-util.cpp index 62a4f15b0..7e0ae792a 100644 --- a/src/json-util.cpp +++ b/src/json-util.cpp @@ -1082,13 +1082,11 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, not_default_constru } const auto &jk = j[key]; const auto new_path = path + to_string(key) + "/"; - bool has_proofs = false; - ju_get_field(jk, "has_proofs"s, has_proofs, new_path); bool has_annotations = false; ju_get_field(jk, "has_annotations"s, has_annotations, new_path); bool has_large_data = false; ju_get_field(jk, "has_large_data"s, has_large_data, new_path); - optional.emplace(has_proofs, has_annotations, has_large_data); + optional.emplace(has_annotations, has_large_data); } template void ju_get_opt_field(const nlohmann::json &j, const uint64_t &key, @@ -1113,12 +1111,10 @@ void ju_get_opt_field(const nlohmann::json &j, const K &key, not_default_constru } std::vector accesses; 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_sibling_hashes().has_value()) { - throw std::invalid_argument( - "field \""s + new_path + "accesses/" + to_string(i) + "\" missing sibling hashes"); - } + for (unsigned i = 0; i < accesses.size(); ++i) { + if (!accesses[i].get_sibling_hashes().has_value()) { + throw std::invalid_argument( + "field \""s + new_path + "accesses/" + to_string(i) + "\" missing sibling hashes"); } } std::vector brackets; @@ -1745,8 +1741,7 @@ void to_json(nlohmann::json &j, const std::vector &as) { } void to_json(nlohmann::json &j, const access_log::type &log_type) { - j = nlohmann::json{{"has_proofs", log_type.has_proofs()}, {"has_annotations", log_type.has_annotations()}, - {"has_large_data", log_type.has_large_data()}}; + j = nlohmann::json{{"has_annotations", log_type.has_annotations()}, {"has_large_data", log_type.has_large_data()}}; } void to_json(nlohmann::json &j, const access_log &log) { diff --git a/src/jsonrpc-discover.json b/src/jsonrpc-discover.json index dd8dbdf5e..a28928611 100644 --- a/src/jsonrpc-discover.json +++ b/src/jsonrpc-discover.json @@ -235,29 +235,8 @@ }, { - "name": "machine.verify_step_uarch_log", - "summary": "Verifies an access log", - "params": [ { - "name":"log", - "description": "Access log to verify", - "required": true, - "schema": { - "$ref": "#/components/schemas/AccessLog" - } - } - ], - "result": { - "name": "status", - "description": "True when operation succeeded", - "schema": { - "type": "boolean" - } - } - }, - - { - "name": "machine.verify_step_uarch_state_transition", - "summary": "Verifies a state transition", + "name": "machine.verify_step_uarch", + "summary": "Verifies a state transition caused by log_step_uarch", "params": [ { "name":"root_hash_before", "description": "State hash before transition described by access log", @@ -291,28 +270,7 @@ }, { - "name": "machine.verify_reset_uarch_log", - "summary": "Verifies an access log produced by a log_reset_uarch", - "params": [ { - "name":"log", - "description": "Access log to verify", - "required": true, - "schema": { - "$ref": "#/components/schemas/AccessLog" - } - } - ], - "result": { - "name": "status", - "description": "True when operation succeeded", - "schema": { - "type": "boolean" - } - } - }, - - { - "name": "machine.verify_reset_uarch_state_transition", + "name": "machine.verify_reset_uarch", "summary": "Verifies a state transition caused by log_reset_uarch", "params": [ { "name":"root_hash_before", @@ -795,43 +753,8 @@ }, { - "name": "machine.verify_send_cmio_response_log", - "summary": "Checks the internal consistency of an access log produced by send_cmio_response", - "params": [ { - "name":"reason", - "description": "Reason for sending response", - "required": true, - "schema": { - "$ref": "#/components/schemas/UnsignedInteger" - } - }, { - "name":"data", - "description": "Response data sent when the log was generated.", - "required": true, - "schema": { - "$ref": "#/components/schemas/Base64String" - } - }, { - "name":"log", - "description": "Access log to verify", - "required": true, - "schema": { - "$ref": "#/components/schemas/AccessLog" - } - } - ], - "result": { - "name": "status", - "description": "True when operation succeeded", - "schema": { - "type": "boolean" - } - } - }, - - { - "name": "machine.verify_send_cmio_response_state_transition", - "summary": "Checks the validity of state transitions caused by send_cmio_response", + "name": "machine.verify_send_cmio_response", + "summary": "Verifies a state transition caused by log_send_cmio_response", "params": [ { "name":"reason", "description": "Reason for sending response", @@ -1541,9 +1464,6 @@ "title": "AccessLogType", "type": "object", "properties": { - "has_proofs": { - "type": "boolean" - }, "has_annotations": { "type": "boolean" }, @@ -1552,7 +1472,6 @@ } }, "required": [ - "has_proofs", "has_annotations", "has_large_data" ] diff --git a/src/jsonrpc-machine-c-api.cpp b/src/jsonrpc-machine-c-api.cpp index 848f21f11..ac174a8c0 100644 --- a/src/jsonrpc-machine-c-api.cpp +++ b/src/jsonrpc-machine-c-api.cpp @@ -124,14 +124,9 @@ cm_error cm_jsonrpc_verify_step_uarch(const cm_jsonrpc_mgr *mgr, const cm_hash * const auto *cpp_mgr = convert_from_c(mgr); const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::jsonrpc_virtual_machine::verify_step_uarch_state_transition(*cpp_mgr, cpp_root_hash_before, cpp_log, - cpp_root_hash_after); - } else { - cartesi::jsonrpc_virtual_machine::verify_step_uarch_log(*cpp_mgr, cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::jsonrpc_virtual_machine::verify_step_uarch(*cpp_mgr, cpp_root_hash_before, cpp_log, cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); @@ -143,17 +138,11 @@ cm_error cm_jsonrpc_verify_reset_uarch(const cm_jsonrpc_mgr *mgr, const cm_hash throw std::invalid_argument("invalid access log"); } const auto *cpp_mgr = convert_from_c(mgr); - const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::jsonrpc_virtual_machine::verify_reset_uarch_state_transition(*cpp_mgr, cpp_root_hash_before, cpp_log, - cpp_root_hash_after); - } else { - cartesi::jsonrpc_virtual_machine::verify_reset_uarch_log(*cpp_mgr, cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::jsonrpc_virtual_machine::verify_reset_uarch(*cpp_mgr, cpp_root_hash_before, cpp_log, cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); @@ -240,14 +229,10 @@ cm_error cm_jsonrpc_verify_send_cmio_response(const cm_jsonrpc_mgr *mgr, uint16_ const auto *cpp_mgr = convert_from_c(mgr); const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::jsonrpc_virtual_machine::verify_send_cmio_response_state_transition(*cpp_mgr, reason, data, length, - cpp_root_hash_before, cpp_log, cpp_root_hash_after); - } else { - cartesi::jsonrpc_virtual_machine::verify_send_cmio_response_log(*cpp_mgr, reason, data, length, cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::jsonrpc_virtual_machine::verify_send_cmio_response(*cpp_mgr, reason, data, length, cpp_root_hash_before, + cpp_log, cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); diff --git a/src/jsonrpc-machine-c-api.h b/src/jsonrpc-machine-c-api.h index 05ac05ffb..00ebff752 100644 --- a/src/jsonrpc-machine-c-api.h +++ b/src/jsonrpc-machine-c-api.h @@ -114,29 +114,25 @@ CM_API cm_error cm_jsonrpc_get_machine(const cm_jsonrpc_mgr *mgr, cm_machine **n // ------------------------------------- // Verifying -/// \brief Checks the validity of a state transition for one micro cycle. +/// \brief Checks the validity of a state transition produced by cm_log_step_uarch. /// \param mgr Pointer to a valid JSONRPC connection manager. /// \param root_hash_before State hash before load. /// \param log State access log to be verified as a JSON string. /// \param root_hash_after State hash after load. /// \returns 0 for success, non zero code for error. -/// \details In case both root_hash_before and root_hash_after are NULL, -/// then it just verifies the access log integrity. CM_API cm_error cm_jsonrpc_verify_step_uarch(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); -/// \brief Checks the validity of a state transition produced by a microarchitecture state reset. +/// \brief Checks the validity of a state transition produced by cm_log_verify_reset_uarch. /// \param mgr Pointer to a valid JSONRPC connection manager. /// \param root_hash_before State hash before load. /// \param log State access log to be verified as a JSON string. /// \param root_hash_after State hash after load. /// \returns 0 for success, non zero code for error. -/// \details In case both root_hash_before and root_hash_after are NULL, -/// then it just verifies the access log integrity. CM_API cm_error cm_jsonrpc_verify_reset_uarch(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); -/// \brief Checks the validity of state transitions produced by a send cmio response. +/// \brief Checks the validity of a state transition produced by cm_log_send_cmio_response. /// \param mgr Pointer to a valid JSONRPC connection manager. /// \param reason Reason for sending the response. /// \param data The response sent when the log was generated. @@ -145,8 +141,6 @@ CM_API cm_error cm_jsonrpc_verify_reset_uarch(const cm_jsonrpc_mgr *mgr, const c /// \param log State access log to be verified as a JSON string. /// \param root_hash_after State hash after load. /// \returns 0 for success, non zero code for error. -/// \details In case both root_hash_before and root_hash_after are NULL, -/// then it just verifies the access log integrity. CM_API cm_error cm_jsonrpc_verify_send_cmio_response(const cm_jsonrpc_mgr *mgr, uint16_t reason, const uint8_t *data, uint64_t length, const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); diff --git a/src/jsonrpc-remote-machine.cpp b/src/jsonrpc-remote-machine.cpp index 93b2b22fa..8ebcc3716 100644 --- a/src/jsonrpc-remote-machine.cpp +++ b/src/jsonrpc-remote-machine.cpp @@ -966,33 +966,6 @@ static json jsonrpc_machine_log_step_uarch_handler(const json &j, const std::sha return jsonrpc_response_ok(j, session->handler->machine->log_step_uarch(std::get<0>(args).value())); } -/// \brief JSONRPC handler for the machine.verify_step_uarch_log method -/// \param j JSON request object -/// \param session HTTP session -/// \returns JSON response object -static json jsonrpc_machine_verify_step_uarch_log_handler(const json &j, const std::shared_ptr &session) { - (void) session; - static const char *param_name[] = {"log"}; - auto args = parse_args>(j, param_name); - // NOLINTNEXTLINE(bugprone-unchecked-optional-access) - cartesi::machine::verify_step_uarch_log(std::get<0>(args).value()); - return jsonrpc_response_ok(j); -} - -/// \brief JSONRPC handler for the machine.verify_reset_uarch_log method -/// \param j JSON request object -/// \param session HTTP session -/// \returns JSON response object -static json jsonrpc_machine_verify_reset_uarch_log_handler(const json &j, - const std::shared_ptr &session) { - (void) session; - static const char *param_name[] = {"log"}; - auto args = parse_args>(j, param_name); - // NOLINTNEXTLINE(bugprone-unchecked-optional-access) - cartesi::machine::verify_reset_uarch_log(std::get<0>(args).value()); - return jsonrpc_response_ok(j); -} - /// \brief JSONRPC handler for the machine.log_step_uarch method /// \param j JSON request object /// \param session HTTP session @@ -1007,37 +980,33 @@ static json jsonrpc_machine_log_reset_uarch_handler(const json &j, const std::sh return jsonrpc_response_ok(j, session->handler->machine->log_reset_uarch(std::get<0>(args).value())); } -/// \brief JSONRPC handler for the machine.verify_step_uarch_state_transition method +/// \brief JSONRPC handler for the machine.verify_step_uarch method /// \param j JSON request object /// \param session HTTP session /// \returns JSON response object -static json jsonrpc_machine_verify_step_uarch_state_transition_handler(const json &j, - const std::shared_ptr &session) { +static json jsonrpc_machine_verify_step_uarch_handler(const json &j, const std::shared_ptr &session) { (void) session; static const char *param_name[] = {"root_hash_before", "log", "root_hash_after"}; auto args = parse_args, cartesi::machine_merkle_tree::hash_type>(j, param_name); // NOLINTNEXTLINE(bugprone-unchecked-optional-access) - cartesi::machine::verify_step_uarch_state_transition(std::get<0>(args), std::get<1>(args).value(), - std::get<2>(args)); + cartesi::machine::verify_step_uarch(std::get<0>(args), std::get<1>(args).value(), std::get<2>(args)); return jsonrpc_response_ok(j); } -/// \brief JSONRPC handler for the machine.verify_reset_uarch_state_transition method +/// \brief JSONRPC handler for the machine.verify_reset_uarch method /// \param j JSON request object /// \param session HTTP session /// \returns JSON response object -static json jsonrpc_machine_verify_reset_uarch_state_transition_handler(const json &j, - const std::shared_ptr &session) { +static json jsonrpc_machine_verify_reset_uarch_handler(const json &j, const std::shared_ptr &session) { (void) session; static const char *param_name[] = {"root_hash_before", "log", "root_hash_after"}; auto args = parse_args, cartesi::machine_merkle_tree::hash_type>(j, param_name); // NOLINTNEXTLINE(bugprone-unchecked-optional-access) - cartesi::machine::verify_reset_uarch_state_transition(std::get<0>(args), std::get<1>(args).value(), - std::get<2>(args)); + cartesi::machine::verify_reset_uarch(std::get<0>(args), std::get<1>(args).value(), std::get<2>(args)); return jsonrpc_response_ok(j); } @@ -1328,31 +1297,11 @@ static json jsonrpc_machine_log_send_cmio_response_handler(const json &j, // NOLINTEND(bugprone-unchecked-optional-access) } -/// \brief JSONRPC handler for the machine.verify_send_cmio_response_log method -/// \param j JSON request object -/// \param session HTTP session -/// \returns JSON response object -static json jsonrpc_machine_verify_send_cmio_response_log_handler(const json &j, - const std::shared_ptr &session) { - (void) session; - static const char *param_name[] = {"reason", "data", "log"}; - auto args = - parse_args>(j, param_name); - auto bin = cartesi::decode_base64(std::get<1>(args)); - // NOLINTBEGIN(bugprone-unchecked-optional-access) - // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) - cartesi::machine::verify_send_cmio_response_log(std::get<0>(args), reinterpret_cast(bin.data()), - bin.size(), std::get<2>(args).value()); - // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) - // NOLINTEND(bugprone-unchecked-optional-access) - return jsonrpc_response_ok(j); -} - -/// \brief JSONRPC handler for the machine.verify_send_cmio_response_state_transition method +/// \brief JSONRPC handler for the machine.verify_send_cmio_response method /// \param j JSON request object /// \param session HTTP session /// \returns JSON response object -static json jsonrpc_machine_verify_send_cmio_response_state_transition_handler(const json &j, +static json jsonrpc_machine_verify_send_cmio_response_handler(const json &j, const std::shared_ptr &session) { (void) session; static const char *param_name[] = {"reason", "data", "root_hash_before", "log", "root_hash_after"}; @@ -1363,9 +1312,8 @@ static json jsonrpc_machine_verify_send_cmio_response_state_transition_handler(c auto bin = cartesi::decode_base64(std::get<1>(args)); // NOLINTBEGIN(bugprone-unchecked-optional-access) // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) - cartesi::machine::verify_send_cmio_response_state_transition(std::get<0>(args), - reinterpret_cast(bin.data()), bin.size(), std::get<2>(args), std::get<3>(args).value(), - std::get<4>(args)); + cartesi::machine::verify_send_cmio_response(std::get<0>(args), reinterpret_cast(bin.data()), + bin.size(), std::get<2>(args), std::get<3>(args).value(), std::get<4>(args)); // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) // NOLINTEND(bugprone-unchecked-optional-access) return jsonrpc_response_ok(j); @@ -1428,10 +1376,8 @@ static json jsonrpc_dispatch_method(const json &j, const std::shared_ptr(); SLOG(debug) << session->handler->local_endpoint << " handling \"" << method << "\" method"; diff --git a/src/jsonrpc-virtual-machine.cpp b/src/jsonrpc-virtual-machine.cpp index 968f155f3..30ae5197a 100644 --- a/src/jsonrpc-virtual-machine.cpp +++ b/src/jsonrpc-virtual-machine.cpp @@ -400,33 +400,21 @@ void jsonrpc_virtual_machine::shutdown(const jsonrpc_mgr_ptr &mgr) { mgr->shutdown(); } -void jsonrpc_virtual_machine::verify_step_uarch_log(const jsonrpc_mgr_ptr &mgr, const access_log &log) { - bool result = false; - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_step_uarch_log", std::tie(log), - result); -} - -void jsonrpc_virtual_machine::verify_step_uarch_state_transition(const jsonrpc_mgr_ptr &mgr, - const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { +void jsonrpc_virtual_machine::verify_step_uarch(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, + const access_log &log, const hash_type &root_hash_after) { bool result = false; auto b64_root_hash_before = encode_base64(root_hash_before); auto b64_root_hash_after = encode_base64(root_hash_after); - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_step_uarch_state_transition", + jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_step_uarch", std::tie(b64_root_hash_before, log, b64_root_hash_after), result); } -void jsonrpc_virtual_machine::verify_reset_uarch_log(const jsonrpc_mgr_ptr &mgr, const access_log &log) { - bool result = false; - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_reset_uarch_log", std::tie(log), - result); -} - -void jsonrpc_virtual_machine::verify_reset_uarch_state_transition(const jsonrpc_mgr_ptr &mgr, - const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { +void jsonrpc_virtual_machine::verify_reset_uarch(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, + const access_log &log, const hash_type &root_hash_after) { bool result = false; auto b64_root_hash_before = encode_base64(root_hash_before); auto b64_root_hash_after = encode_base64(root_hash_after); - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_reset_uarch_state_transition", + jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_reset_uarch", std::tie(b64_root_hash_before, log, b64_root_hash_after), result); } @@ -626,22 +614,14 @@ access_log jsonrpc_virtual_machine::do_log_send_cmio_response(uint16_t reason, c return std::move(result).value(); } -void jsonrpc_virtual_machine::verify_send_cmio_response_log(const jsonrpc_mgr_ptr &mgr, uint16_t reason, - const unsigned char *data, uint64_t length, const access_log &log) { - bool result = false; - std::string b64_data = cartesi::encode_base64(data, length); - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_send_cmio_response_log", - std::tie(reason, b64_data, log), result); -} - -void jsonrpc_virtual_machine::verify_send_cmio_response_state_transition(const jsonrpc_mgr_ptr &mgr, uint16_t reason, +void jsonrpc_virtual_machine::verify_send_cmio_response(const jsonrpc_mgr_ptr &mgr, uint16_t reason, const unsigned char *data, uint64_t length, const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { bool result = false; std::string b64_data = cartesi::encode_base64(data, length); auto b64_root_hash_before = encode_base64(root_hash_before); auto b64_root_hash_after = encode_base64(root_hash_after); - jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_send_cmio_response_state_transition", + jsonrpc_request(mgr->get_stream(), mgr->get_remote_address(), "machine.verify_send_cmio_response", std::tie(reason, b64_data, b64_root_hash_before, log, b64_root_hash_after), result); } diff --git a/src/jsonrpc-virtual-machine.h b/src/jsonrpc-virtual-machine.h index 7d3fa06ad..ca0a8f987 100644 --- a/src/jsonrpc-virtual-machine.h +++ b/src/jsonrpc-virtual-machine.h @@ -58,23 +58,15 @@ class jsonrpc_virtual_machine final : public i_virtual_machine { static machine_config get_default_config(const jsonrpc_mgr_ptr &mgr); - static void verify_step_uarch_log(const jsonrpc_mgr_ptr &mgr, const access_log &log); - - static void verify_step_uarch_state_transition(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, - const access_log &log, const hash_type &root_hash_after); - - static void verify_reset_uarch_log(const jsonrpc_mgr_ptr &mgr, const access_log &log); - - static void verify_reset_uarch_state_transition(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, - const access_log &log, const hash_type &root_hash_after); - - static void verify_send_cmio_response_log(const jsonrpc_mgr_ptr &mgr, uint16_t reason, const unsigned char *data, - uint64_t length, const access_log &log); + static void verify_step_uarch(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, const access_log &log, + const hash_type &root_hash_after); - static void verify_send_cmio_response_state_transition(const jsonrpc_mgr_ptr &mgr, uint16_t reason, - const unsigned char *data, uint64_t length, const hash_type &root_hash_before, const access_log &log, + static void verify_reset_uarch(const jsonrpc_mgr_ptr &mgr, const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after); + static void verify_send_cmio_response(const jsonrpc_mgr_ptr &mgr, uint16_t reason, const unsigned char *data, + uint64_t length, const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after); + static fork_result fork(const jsonrpc_mgr_ptr &mgr); static std::string rebind(const jsonrpc_mgr_ptr &mgr, const std::string &address); static uint64_t get_reg_address(const jsonrpc_mgr_ptr &mgr, reg r); diff --git a/src/machine-c-api.cpp b/src/machine-c-api.cpp index a256d9cd5..d5600a9cc 100644 --- a/src/machine-c-api.cpp +++ b/src/machine-c-api.cpp @@ -276,13 +276,9 @@ cm_error cm_verify_step_uarch(const cm_hash *root_hash_before, const char *log, } const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::machine::verify_step_uarch_state_transition(cpp_root_hash_before, cpp_log, cpp_root_hash_after); - } else { - cartesi::machine::verify_step_uarch_log(cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::machine::verify_step_uarch(cpp_root_hash_before, cpp_log, cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); @@ -294,13 +290,9 @@ cm_error cm_verify_reset_uarch(const cm_hash *root_hash_before, const char *log, } const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::machine::verify_reset_uarch_state_transition(cpp_root_hash_before, cpp_log, cpp_root_hash_after); - } else { - cartesi::machine::verify_reset_uarch_log(cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::machine::verify_reset_uarch(cpp_root_hash_before, cpp_log, cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); @@ -680,14 +672,10 @@ cm_error cm_verify_send_cmio_response(uint16_t reason, const uint8_t *data, uint } const auto cpp_log = // NOLINTNEXTLINE(bugprone-unchecked-optional-access) cartesi::from_json>(log).value(); - if (root_hash_before || root_hash_after) { - const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); - const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); - cartesi::machine::verify_send_cmio_response_state_transition(reason, data, length, cpp_root_hash_before, - cpp_log, cpp_root_hash_after); - } else { - cartesi::machine::verify_send_cmio_response_log(reason, data, length, cpp_log); - } + const cartesi::machine::hash_type cpp_root_hash_before = convert_from_c(root_hash_before); + const cartesi::machine::hash_type cpp_root_hash_after = convert_from_c(root_hash_after); + cartesi::machine::verify_send_cmio_response(reason, data, length, cpp_root_hash_before, cpp_log, + cpp_root_hash_after); return cm_result_success(); } catch (...) { return cm_result_failure(); diff --git a/src/machine-c-api.h b/src/machine-c-api.h index abec236b7..2b4f7a802 100644 --- a/src/machine-c-api.h +++ b/src/machine-c-api.h @@ -105,9 +105,8 @@ typedef enum cm_uarch_break_reason { /// \brief Access log types. typedef enum cm_access_log_type { - CM_ACCESS_LOG_TYPE_PROOFS = 1, ///< Includes proofs - CM_ACCESS_LOG_TYPE_ANNOTATIONS = 2, ///< Includes annotations - CM_ACCESS_LOG_TYPE_LARGE_DATA = 4, ///< Includes data larger than 8 bytes + CM_ACCESS_LOG_TYPE_ANNOTATIONS = 1, ///< Includes annotations + CM_ACCESS_LOG_TYPE_LARGE_DATA = 2, ///< Includes data larger than 8 bytes } cm_access_log_type; /// \brief Yield device commands. @@ -641,23 +640,21 @@ CM_API cm_error cm_log_send_cmio_response(cm_machine *m, uint16_t reason, const // Verifying // ------------------------------------ -/// \brief Checks the validity of a state transition for one microarchitecture cycle. +/// \brief Checks the validity of a state transition produced by cm_log_step_uarch. /// \param root_hash_before State hash before step. /// \param log State access log to be verified as a JSON object in a string. /// \param root_hash_after State hash after step. /// \returns 0 for success, non zero code for error. -/// \details If both root_hash_before and root_hash_after are NULL, no proofs are taken into account. CM_API cm_error cm_verify_step_uarch(const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); -/// \brief Checks the validity of a state transition produced by a microarchitecture reset. +/// \brief Checks the validity of a state transition produced by cm_log_verify_reset_uarch. /// \param root_hash_before State hash before reset. /// \param log State access log to be verified as a JSON object in a string. /// \param root_hash_after State hash after reset. /// \returns 0 for success, non zero code for error. -/// \details If both root_hash_before and root_hash_after are NULL, no proofs are taken into account. CM_API cm_error cm_verify_reset_uarch(const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); -/// \brief Checks the validity of state transitions produced by a send cmio response. +/// \brief Checks the validity of a state transition produced by cm_log_send_cmio_response. /// \param reason Reason for sending the response. /// \param data The response sent when the log was generated. /// \param length Length of response. @@ -665,7 +662,6 @@ CM_API cm_error cm_verify_reset_uarch(const cm_hash *root_hash_before, const cha /// \param log State access log to be verified as a JSON object in a string. /// \param root_hash_after State hash after response. /// \returns 0 for success, non zero code for error. -/// \details If both root_hash_before and root_hash_after are NULL, no proofs are taken into account. CM_API cm_error cm_verify_send_cmio_response(uint16_t reason, const uint8_t *data, uint64_t length, const cm_hash *root_hash_before, const char *log, const cm_hash *root_hash_after); diff --git a/src/machine.cpp b/src/machine.cpp index da053cc7d..cef2063b7 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2631,51 +2631,29 @@ void machine::send_cmio_response(uint16_t reason, const unsigned char *data, uin access_log machine::log_send_cmio_response(uint16_t reason, const unsigned char *data, uint64_t length, const access_log::type &log_type) { hash_type root_hash_before; - if (log_type.has_proofs()) { - get_root_hash(root_hash_before); - } + get_root_hash(root_hash_before); // Call send_cmio_response with the recording state accessor record_state_access a(*this, log_type); a.push_bracket(bracket_type::begin, "send cmio response"); cartesi::send_cmio_response(a, reason, data, length); a.push_bracket(bracket_type::end, "send cmio response"); // Verify access log before returning - if (log_type.has_proofs()) { - hash_type root_hash_after; - update_merkle_tree(); - get_root_hash(root_hash_after); - verify_send_cmio_response_state_transition(reason, data, length, root_hash_before, *a.get_log(), - root_hash_after); - } else { - verify_send_cmio_response_log(reason, data, length, *a.get_log()); - } + hash_type root_hash_after; + update_merkle_tree(); + get_root_hash(root_hash_after); + verify_send_cmio_response(reason, data, length, root_hash_before, *a.get_log(), root_hash_after); return std::move(*a.get_log()); } -void machine::verify_send_cmio_response_log(uint16_t reason, const unsigned char *data, uint64_t length, - const access_log &log) { - // There must be at least one access in log - if (log.get_accesses().empty()) { - throw std::invalid_argument{"too few accesses in log"}; - } - replay_state_access a(log, false /* verify_proofs */, {} /* initial_hash */); - cartesi::send_cmio_response(a, reason, data, length); - a.finish(); -} - -void machine::verify_send_cmio_response_state_transition(uint16_t reason, const unsigned char *data, uint64_t length, +void machine::verify_send_cmio_response(uint16_t reason, const unsigned char *data, uint64_t length, const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { - // We need proofs in order to verify the state transition - if (!log.get_log_type().has_proofs()) { - throw std::invalid_argument{"log has no proofs"}; - } // There must be at least one access in log if (log.get_accesses().empty()) { throw std::invalid_argument{"too few accesses in log"}; } // Verify all intermediate state transitions - replay_state_access a(log, true /* verify_proofs */, root_hash_before); + replay_state_access a(log, root_hash_before); cartesi::send_cmio_response(a, reason, data, length); a.finish(); @@ -2698,48 +2676,28 @@ void machine::reset_uarch() { access_log machine::log_reset_uarch(const access_log::type &log_type) { hash_type root_hash_before; - if (log_type.has_proofs()) { - get_root_hash(root_hash_before); - } + get_root_hash(root_hash_before); // Call uarch_reset_state with a uarch_record_state_access object uarch_record_state_access a(m_uarch.get_state(), *this, log_type); a.push_bracket(bracket_type::begin, "reset uarch state"); uarch_reset_state(a); a.push_bracket(bracket_type::end, "reset uarch state"); // Verify access log before returning - if (log_type.has_proofs()) { - hash_type root_hash_after; - update_merkle_tree(); - get_root_hash(root_hash_after); - verify_reset_uarch_state_transition(root_hash_before, *a.get_log(), root_hash_after); - } else { - verify_reset_uarch_log(*a.get_log()); - } + hash_type root_hash_after; + update_merkle_tree(); + get_root_hash(root_hash_after); + verify_reset_uarch(root_hash_before, *a.get_log(), root_hash_after); return std::move(*a.get_log()); } -void machine::verify_reset_uarch_log(const access_log &log) { - // There must be at least one access in log - if (log.get_accesses().empty()) { - throw std::invalid_argument{"too few accesses in log"}; - } - uarch_replay_state_access a(log, false /* verify_proofs */, {} /* initial_hash */); - uarch_reset_state(a); - a.finish(); -} - -void machine::verify_reset_uarch_state_transition(const hash_type &root_hash_before, const access_log &log, +void machine::verify_reset_uarch(const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { - // We need proofs in order to verify the state transition - if (!log.get_log_type().has_proofs()) { - throw std::invalid_argument{"log has no proofs"}; - } // There must be at least one access in log if (log.get_accesses().empty()) { throw std::invalid_argument{"too few accesses in log"}; } // Verify all intermediate state transitions - uarch_replay_state_access a(log, true /* verify_proofs */, root_hash_before); + uarch_replay_state_access a(log, root_hash_before); uarch_reset_state(a); a.finish(); // Make sure the access log ends at the same root hash as the state @@ -2755,47 +2713,27 @@ access_log machine::log_step_uarch(const access_log::type &log_type) { throw std::runtime_error("microarchitecture RAM is not present"); } hash_type root_hash_before; - if (log_type.has_proofs()) { - get_root_hash(root_hash_before); - } + get_root_hash(root_hash_before); // Call interpret with a logged state access object uarch_record_state_access a(m_uarch.get_state(), *this, log_type); a.push_bracket(bracket_type::begin, "step"); uarch_step(a); a.push_bracket(bracket_type::end, "step"); // Verify access log before returning - if (log_type.has_proofs()) { - hash_type root_hash_after; - get_root_hash(root_hash_after); - verify_step_uarch_state_transition(root_hash_before, *a.get_log(), root_hash_after); - } else { - verify_step_uarch_log(*a.get_log()); - } + hash_type root_hash_after; + get_root_hash(root_hash_after); + verify_step_uarch(root_hash_before, *a.get_log(), root_hash_after); return std::move(*a.get_log()); } -void machine::verify_step_uarch_log(const access_log &log) { - // There must be at least one access in log - if (log.get_accesses().empty()) { - throw std::invalid_argument{"too few accesses in log"}; - } - uarch_replay_state_access a(log, false /* verify proofs */, {} /* initial hash */); - uarch_step(a); - a.finish(); -} - -void machine::verify_step_uarch_state_transition(const hash_type &root_hash_before, const access_log &log, +void machine::verify_step_uarch(const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after) { - // We need proofs in order to verify the state transition - if (!log.get_log_type().has_proofs()) { - throw std::invalid_argument{"log has no proofs"}; - } // There must be at least one access in log if (log.get_accesses().empty()) { throw std::invalid_argument{"too few accesses in log"}; } // Verify all intermediate state transitions - uarch_replay_state_access a(log, true /* verify proofs! */, root_hash_before); + uarch_replay_state_access a(log, root_hash_before); uarch_step(a); a.finish(); // Make sure the access log ends at the same root hash as the state diff --git a/src/machine.h b/src/machine.h index 083095ee6..edf835097 100644 --- a/src/machine.h +++ b/src/machine.h @@ -335,26 +335,18 @@ class machine final { /// \returns The state access log. access_log log_reset_uarch(const access_log::type &log_type); - /// \brief Checks the internal consistency of an access log. - /// \param log State access log to be verified. - static void verify_step_uarch_log(const access_log &log); - - /// \brief Checks the validity of a state transition. + /// \brief Checks the validity of a state transition caused by log_step_uarch. /// \param root_hash_before State hash before step. /// \param log Step state access log. /// \param root_hash_after State hash after step. - static void verify_step_uarch_state_transition(const hash_type &root_hash_before, const access_log &log, + static void verify_step_uarch(const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after); - /// \brief Checks the internal consistency of an access log produced by log_reset_uarch - /// \param log State access log to be verified. - static void verify_reset_uarch_log(const access_log &log); - - /// \brief Checks the validity of a state transition. caused by log_reset_uarch + /// \brief Checks the validity of a state transition caused by log_reset_uarch. /// \param root_hash_before State hash before uarch reset /// \param log Step state access log. /// \param root_hash_after State hash after uarch reset. - static void verify_reset_uarch_state_transition(const hash_type &root_hash_before, const access_log &log, + static void verify_reset_uarch(const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after); static machine_config get_default_config(void); @@ -1018,22 +1010,14 @@ class machine final { access_log log_send_cmio_response(uint16_t reason, const unsigned char *data, uint64_t length, const access_log::type &log_type); - /// \brief Checks the internal consistency of an access log produced by log_send_cmio_response - /// \param reason Reason for sending response. - /// \param data The response sent when the log was generated. - /// \param length Length of response data. - /// \param log State access log to be verified. - static void verify_send_cmio_response_log(uint16_t reason, const unsigned char *data, uint64_t length, - const access_log &log); - - /// \brief Checks the validity of state transitions caused by log_send_cmio_response + /// \brief Checks the validity of state transitions caused by log_send_cmio_response. /// \param reason Reason for sending response. /// \param data The response sent when the log was generated. /// \param length Length of response /// \param root_hash_before State hash before response was sent. /// \param log Log containing the state accesses performed by the load operation /// \param root_hash_after State hash after response was sent. - static void verify_send_cmio_response_state_transition(uint16_t reason, const unsigned char *data, uint64_t length, + static void verify_send_cmio_response(uint16_t reason, const unsigned char *data, uint64_t length, const hash_type &root_hash_before, const access_log &log, const hash_type &root_hash_after); /// \brief Reads the value of a microarchitecture register. diff --git a/src/record-state-access.h b/src/record-state-access.h index de2ed036d..193e704d2 100644 --- a/src/record-state-access.h +++ b/src/record-state-access.h @@ -90,16 +90,16 @@ class record_state_access : public i_state_accessget_log_type().has_proofs()) { - // We can skip updating the merkle tree while getting the proof because we assume that: - // 1) A full merkle tree update was called at the beginning of machine::log_load_cmio_input() - // 2) We called update_merkle_tree_page on all write accesses - const auto proof = - m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We can skip updating the merkle tree while getting the proof because we assume that: + // 1) A full merkle tree update was called at the beginning of machine::log_load_cmio_input() + // 2) We called update_merkle_tree_page on all write accesses + const auto proof = + m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + a.set_type(access_type::read); a.set_address(paligned); a.set_log2_size(log2_size::value); @@ -127,16 +127,16 @@ class record_state_access : public i_state_accessget_log_type().has_proofs()) { - // We can skip updating the merkle tree while getting the proof because we assume that: - // 1) A full merkle tree update was called at the beginning of machine::log_load_cmio_input() - // 2) We called update_merkle_tree_page on all write accesses - const auto proof = - m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We can skip updating the merkle tree while getting the proof because we assume that: + // 1) A full merkle tree update was called at the beginning of machine::log_load_cmio_input() + // 2) We called update_merkle_tree_page on all write accesses + const auto proof = + m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + a.set_type(access_type::write); a.set_address(paligned); a.set_log2_size(log2_size::value); @@ -161,11 +161,9 @@ class record_state_access : public i_state_accessget_log_type().has_proofs()) { - const bool updated = m_m.update_merkle_tree_page(paligned); - (void) updated; - assert(updated); - } + const bool updated = m_m.update_merkle_tree_page(paligned); + (void) updated; + assert(updated); } /// \brief Logs a write access before it happens, writes, and then update the Merkle tree. @@ -247,11 +245,11 @@ class record_state_access : public i_state_accessget_log_type().has_proofs()) { - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + // write data to memory m_m.write_memory(paddr, data, data_length); if (write_length > data_length) { diff --git a/src/replay-state-access.h b/src/replay-state-access.h index 2a7a790b5..8e0b137e4 100644 --- a/src/replay-state-access.h +++ b/src/replay-state-access.h @@ -43,8 +43,6 @@ class replay_state_access : public i_state_access &m_accesses; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - ///< Whether to verify proofs in access log - bool m_verify_proofs; ///< Index of next access to ne consumed unsigned m_next_access; ///< Root hash before next access @@ -55,22 +53,15 @@ class replay_state_access : public i_state_access(paligned - pleaf_aligned); @@ -257,14 +247,12 @@ class replay_state_access : public i_state_accessget_log_type().has_proofs()) { - // We can skip updating the merkle tree while getting the proof because we assume that: - // 1) A full merkle tree update was called at the beginning of machine::log_step_uarch() - // 2) We called update_merkle_tree_page on all write accesses - const auto proof = - m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We can skip updating the merkle tree while getting the proof because we assume that: + // 1) A full merkle tree update was called at the beginning of machine::log_step_uarch() + // 2) We called update_merkle_tree_page on all write accesses + const auto proof = + m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + a.set_type(access_type::read); a.set_address(paligned); a.set_log2_size(log2_size::value); @@ -210,16 +210,16 @@ class uarch_record_state_access : public i_uarch_state_accessget_log_type().has_proofs()) { - // We can skip updating the merkle tree while getting the proof because we assume that: - // 1) A full merkle tree update was called at the beginning of machine::log_step_uarch() - // 2) We called update_merkle_tree_page on all write accesses - const auto proof = - m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We can skip updating the merkle tree while getting the proof because we assume that: + // 1) A full merkle tree update was called at the beginning of machine::log_step_uarch() + // 2) We called update_merkle_tree_page on all write accesses + const auto proof = + m_m.get_proof(pleaf_aligned, machine_merkle_tree::get_log2_word_size(), skip_merkle_tree_update); + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + a.set_type(access_type::write); a.set_address(paligned); a.set_log2_size(log2_size::value); @@ -244,11 +244,9 @@ class uarch_record_state_access : public i_uarch_state_accessget_log_type().has_proofs()) { - const bool updated = m_m.update_merkle_tree_page(paligned); - (void) updated; - assert(updated); - } + const bool updated = m_m.update_merkle_tree_page(paligned); + (void) updated; + assert(updated); } /// \brief Logs a write access before it happens, writes, and then update the Merkle tree. @@ -376,15 +374,8 @@ class uarch_record_state_access : public i_uarch_state_access(hdata, data); - // Finally, update Merkle tree or mark the page dirty, depending on whether proofs are being requested or not - if (m_log->get_log_type().has_proofs()) { - // When proofs are requested, we always want to update the Merkle tree - update_after_write(paddr); - } else { - // Marking the page dirty is only needed for pages of memory PMAs, when proofs are not requested - const uint64_t paddr_page = paddr & ~PAGE_OFFSET_MASK; - pma.mark_dirty_page(paddr_page - pma.get_start()); - } + // When proofs are requested, we always want to update the Merkle tree + update_after_write(paddr); } /// \brief Writes a uint64 machine state register mapped to a memory address @@ -425,11 +416,11 @@ class uarch_record_state_access : public i_uarch_state_accessget_log_type().has_proofs()) { - // We just store the sibling hashes in the access because this is the only missing piece of data needed to - // reconstruct the proof - a.set_sibling_hashes(proof.get_sibling_hashes()); - } + + // We just store the sibling hashes in the access because this is the only missing piece of data needed to + // reconstruct the proof + a.set_sibling_hashes(proof.get_sibling_hashes()); + a.set_written_hash(uarch_pristine_state_hash); // Restore uarch to pristine state diff --git a/src/uarch-replay-state-access.h b/src/uarch-replay-state-access.h index 54375bf88..26fecd129 100644 --- a/src/uarch-replay-state-access.h +++ b/src/uarch-replay-state-access.h @@ -41,8 +41,6 @@ class uarch_replay_state_access : public i_uarch_state_access &m_accesses; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - ///< Whether to verify proofs in access log - bool m_verify_proofs; ///< Next access unsigned m_next_access; @@ -54,22 +52,15 @@ class uarch_replay_state_access : public i_uarch_state_access UArchStepStatus uarch_step(UarchState &a) { - // This must be the first read in order to match the first log access in machine::verify_step_uarch_state_transition + // This must be the first read in order to match the first log access in machine::verify_step_uarch uint64 cycle = readCycle(a); // do not advance if cycle will overflow if (cycle == UINT64_MAX) { diff --git a/tests/Makefile b/tests/Makefile index c2ab0f433..7dac34fe0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -218,7 +218,7 @@ test-yield-and-save: | $(CARTESI_IMAGES) test-misc: test-c-api test-hash test-save-and-load test-yield-and-save test-generate-uarch-logs: $(BUILDDIR)/uarch-riscv-tests-json-logs - $(LUA) ./lua/uarch-riscv-tests.lua --output-dir=$(BUILDDIR)/uarch-riscv-tests-json-logs --proofs --proofs-frequency=1 --create-reset-uarch-log --create-send-cmio-response-log --jobs=$(NUM_JOBS) json-step-logs + $(LUA) ./lua/uarch-riscv-tests.lua --output-dir=$(BUILDDIR)/uarch-riscv-tests-json-logs --create-reset-uarch-log --create-send-cmio-response-log --jobs=$(NUM_JOBS) json-step-logs tar -czf uarch-riscv-tests-json-logs.tar.gz -C $(BUILDDIR) uarch-riscv-tests-json-logs coverage-machine: diff --git a/tests/lua/cartesi-machine-tests.lua b/tests/lua/cartesi-machine-tests.lua index 4389c1220..36b7958bb 100755 --- a/tests/lua/cartesi-machine-tests.lua +++ b/tests/lua/cartesi-machine-tests.lua @@ -294,7 +294,6 @@ local riscv_tests = { { "compressed.bin", 410 }, } -local log_proofs = false local log_annotations = false -- Microarchitecture configuration @@ -322,9 +321,6 @@ where options are: run N tests in parallel (default: 1, i.e., run tests sequentially) - --log-proofs - include proofs in logs - --log-annotations include annotations in logs @@ -494,16 +490,6 @@ local options = { return true end, }, - { - "^%-%-log%-proofs$", - function(o) - if not o then - return false - end - log_proofs = true - return true - end, - }, { "^%-%-log%-annotations$", function(o) @@ -781,7 +767,6 @@ local function step(tests) end local indentout = util.indentout local log_type = (log_annotations and cartesi.ACCESS_LOG_TYPE_ANNOTATIONS or 0) - | (log_proofs and cartesi.ACCESS_LOG_TYPE_PROOFS or 0) out:write("[\n") for i, test in ipairs(tests) do local ram_image = test[1] diff --git a/tests/lua/log-with-mtime-transition.lua b/tests/lua/log-with-mtime-transition.lua index 37046c462..a766ba42a 100755 --- a/tests/lua/log-with-mtime-transition.lua +++ b/tests/lua/log-with-mtime-transition.lua @@ -13,7 +13,7 @@ local config = { local machine = cartesi.machine(config) local old_hash = machine:get_root_hash() -local access_log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS) +local access_log = machine:log_step_uarch() local new_hash = machine:get_root_hash() cartesi.machine.verify_step_uarch(old_hash, access_log, new_hash, {}) print("ok") diff --git a/tests/lua/machine-bind.lua b/tests/lua/machine-bind.lua index 86d5ac0a6..979a527af 100755 --- a/tests/lua/machine-bind.lua +++ b/tests/lua/machine-bind.lua @@ -717,10 +717,9 @@ do_test("machine step should pass verifications", function(machine) module = remote end local initial_hash = machine:get_root_hash() - local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) + local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) local final_hash = machine:get_root_hash() module.machine.verify_step_uarch(initial_hash, log, final_hash) - module.machine.verify_step_uarch(nil, log, nil) end) print("\n\ntesting step and verification") @@ -733,14 +732,16 @@ do_test("Step log must contain conssitent data hashes", function(machine) end module = remote end + local initial_hash = machine:get_root_hash() local log = machine:log_step_uarch() - module.machine.verify_step_uarch(nil, log, nil) + local final_hash = machine:get_root_hash() + module.machine.verify_step_uarch(initial_hash, log, final_hash) local read_access = log.accesses[1] assert(read_access.type == "read") local read_hash = read_access.read_hash -- ensure that verification fails with wrong read hash read_access.read_hash = wrong_hash - local _, err = pcall(module.machine.verify_step_uarch, nil, log, nil) + local _, err = pcall(module.machine.verify_step_uarch, initial_hash, log, final_hash) assert(err:match("logged read data of uarch.uarch_cycle data does not hash to the logged read hash at 1st access")) read_access.read_hash = read_hash -- restore correct value @@ -749,13 +750,13 @@ do_test("Step log must contain conssitent data hashes", function(machine) assert(write_access.type == "write") read_hash = write_access.read_hash write_access.read_hash = wrong_hash - _, err = pcall(module.machine.verify_step_uarch, nil, log, nil) + _, err = pcall(module.machine.verify_step_uarch, initial_hash, log, final_hash) assert(err:match("logged read data of uarch.cycle does not hash to the logged read hash at 8th access")) write_access.read_hash = read_hash -- restore correct value -- ensure that verification fails with wrong written hash write_access.written_hash = wrong_hash - _, err = pcall(module.machine.verify_step_uarch, nil, log, nil) + _, err = pcall(module.machine.verify_step_uarch, initial_hash, log, final_hash) assert(err:match("logged written data of uarch.cycle does not hash to the logged written hash at 8th access")) end) @@ -770,12 +771,11 @@ do_test("step when uarch cycle is max", function(machine) machine:write_reg("uarch_cycle", MAX_UARCH_CYCLE) assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) local initial_hash = machine:get_root_hash() - local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) + local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) local final_hash = machine:get_root_hash() assert(final_hash == initial_hash) module.machine.verify_step_uarch(initial_hash, log, final_hash) - module.machine.verify_step_uarch(nil, log, nil) end) local uarch_proof_step_program = { @@ -797,18 +797,17 @@ test_util.make_do_test(build_machine, machine_type, { local t1 = 6 local t2 = 7 local uarch_ram_start = cartesi.UARCH_RAM_START_ADDRESS - local log_type = cartesi.ACCESS_LOG_TYPE_PROOFS - machine:log_step_uarch(log_type) -- auipc t0,0x0 - machine:log_step_uarch(log_type) -- addi t0,t0,256 # 0x100 + machine:log_step_uarch() -- auipc t0,0x0 + machine:log_step_uarch() -- addi t0,t0,256 # 0x100 assert(machine:read_reg("uarch_x" .. t0) == uarch_ram_start + 0x100) - machine:log_step_uarch(log_type) -- li t1,0xca + machine:log_step_uarch() -- li t1,0xca assert(machine:read_reg("uarch_x" .. t1) == 0xca) - machine:log_step_uarch(log_type) -- li t2,0xfe + machine:log_step_uarch() -- li t2,0xfe assert(machine:read_reg("uarch_x" .. t2) == 0xfe) -- sd and assert stored correctly - machine:log_step_uarch(log_type) -- sd t1,0(t0) [0xca] + machine:log_step_uarch() -- sd t1,0(t0) [0xca] assert(string.unpack("I8", machine:read_memory(uarch_ram_start + 0x100, 8)) == 0xca) -- sd and assert stored correctly @@ -818,7 +817,7 @@ test_util.make_do_test(build_machine, machine_type, { -- This step should run successfully -- The previous unproven step should have marked the updated pages dirty, allowing -- the tree to be updated correctly in the next proved step - machine:log_step_uarch(log_type) -- sd t1,0(t0) [0xca] + machine:log_step_uarch() -- sd t1,0(t0) [0xca] assert(string.unpack("I8", machine:read_memory(uarch_ram_start + 0x100, 8)) == 0xca) end) @@ -892,7 +891,7 @@ for i = 0, 31 do test_reset_uarch_config.processor["x" .. i] = 0x10000 + (i * 8) end -local function test_reset_uarch(machine, with_log, with_proofs, with_annotations) +local function test_reset_uarch(machine, with_log, with_annotations) -- assert initial fixture state assert(machine:read_uarch_halt_flag() == true) assert(machine:read_uarch_cycle() == 1) @@ -909,16 +908,11 @@ local function test_reset_uarch(machine, with_log, with_proofs, with_annotations assert(uarch_state_hash ~= cartesi.UARCH_PRISTINE_STATE_HASH) -- reset uarch state if with_log then - local log_type = (with_proofs and cartesi.ACCESS_LOG_TYPE_PROOFS or 0) - | (with_annotations and cartesi.ACCESS_LOG_TYPE_ANNOTATIONS or 0) + local log_type = (with_annotations and cartesi.ACCESS_LOG_TYPE_ANNOTATIONS or 0) local log = machine:log_reset_uarch(log_type) assert(#log.accesses == 1) local access = log.accesses[1] - if with_proofs then - assert(access.sibling_hashes ~= nil) - else - assert(access.sibling_hashes == nil) - end + assert(access.sibling_hashes ~= nil) assert(access.address == cartesi.UARCH_SHADOW_START_ADDRESS) assert(access.log2_size == cartesi.UARCH_STATE_LOG2_SIZE) assert(access.written_hash == cartesi.UARCH_PRISTINE_STATE_HASH) @@ -946,22 +940,17 @@ end test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_config })( "Testing reset_uarch without logging", function(machine) - test_reset_uarch(machine, false, false, false) + test_reset_uarch(machine, false, false) end ) -for _, with_proofs in ipairs({ true, false }) do - for _, with_annotations in ipairs({ true, false }) do - test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_config })( - "Testing reset_uarch with logging, proofs=" - .. tostring(with_proofs) - .. ", annotations=" - .. tostring(with_annotations), - function(machine) - test_reset_uarch(machine, true, with_proofs, with_annotations) - end - ) - end +for _, with_annotations in ipairs({ true, false }) do + test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_config })( + "Testing reset_uarch with logging, annotations=" .. tostring(with_annotations), + function(machine) + test_reset_uarch(machine, true, with_annotations) + end + ) end test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_config })( @@ -972,7 +961,7 @@ test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_c module = remote end local initial_hash = machine:get_root_hash() - local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) + local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) local final_hash = machine:get_root_hash() -- verify happy path module.machine.verify_reset_uarch(initial_hash, log, final_hash) @@ -993,15 +982,17 @@ test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_c if machine_type ~= "local" then module = remote end - local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) - module.machine.verify_reset_uarch(nil, log, nil) + local initial_hash = machine:get_root_hash() + local log = machine:log_reset_uarch() + local final_hash = machine:get_root_hash() + module.machine.verify_reset_uarch(initial_hash, log, final_hash) end ) test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_config })( "Dump of log produced by log_reset_uarch should match", function(machine) - local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) + local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) local expected_dump_pattern = "begin reset uarch state\n" .. " 1: write uarch_state@0x400000%(4194304%): " .. 'hash:"[0-9a-f]+"%(2%^22 bytes%) %-> hash:"[0-9a-fA-F]+"%(2%^22 bytes%)\n' @@ -1038,27 +1029,27 @@ test_util.make_do_test(build_machine, machine_type, { uarch = test_reset_uarch_c module = remote end -- reset uarch and get log - local log = machine:log_reset_uarch( - cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS | cartesi.ACCESS_LOG_TYPE_LARGE_DATA - ) + local initial_hash = machine:get_root_hash() + local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS | cartesi.ACCESS_LOG_TYPE_LARGE_DATA) + local final_hash = machine:get_root_hash() assert(#log.accesses == 1, "log should have 1 access") local access = log.accesses[1] -- in debug mode, the log must include read and written data assert(access.read ~= nil, "read data should not be nil") assert(access.written ~= nil, "written data should not be nil") -- verify returned log - module.machine.verify_reset_uarch(nil, log, nil) + module.machine.verify_reset_uarch(initial_hash, log, final_hash) -- save logged read and written data local original_read = access.read -- tamper with read data to produce a hash mismatch access.read = "X" .. access.read:sub(2) - local _, err = pcall(module.machine.verify_reset_uarch, nil, log, nil) + local _, err = pcall(module.machine.verify_reset_uarch, initial_hash, log, final_hash) assert(err:match("hash of read data and read hash at 1st access does not match read hash")) -- restore correct read access.read = original_read -- change written data to produce a hash mismatch access.written = "X" .. access.written:sub(2) - _, err = pcall(module.machine.verify_reset_uarch, nil, log, nil) + _, err = pcall(module.machine.verify_reset_uarch, initial_hash, log, final_hash) assert(err:match("written hash and written data mismatch at 1st access")) end ) @@ -1075,7 +1066,7 @@ do_test("Test unhappy paths of verify_reset_uarch", function(machine) local function assert_error(expected_error, callback) machine:reset_uarch() local initial_hash = machine:get_root_hash() - local log = machine:log_reset_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS) + local log = machine:log_reset_uarch() local final_hash = machine:get_root_hash() callback(log) local _, err = pcall(module.machine.verify_reset_uarch, initial_hash, log, final_hash) @@ -1130,7 +1121,7 @@ do_test("Test unhappy paths of verify_step_uarch", function(machine) local function assert_error(expected_error, callback) machine:reset_uarch() local initial_hash = machine:get_root_hash() - local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS) + local log = machine:log_step_uarch() local final_hash = machine:get_root_hash() callback(log) local _, err = pcall(module.machine.verify_step_uarch, initial_hash, log, final_hash) @@ -1299,81 +1290,73 @@ local function test_send_cmio_input_with_different_arguments() machine:send_cmio_response(reason, data) assert_after_cmio_response_sent(machine) end) - for _, proofs in ipairs({ false, true }) do - for _, large_data in ipairs({ false, true }) do - local annotations = true - do_test( - string.format( - "log_send_cmio_response happy path with proofs=%s, annotations=%s, large_data=%s", - proofs, - annotations, - large_data - ), - function(machine) - local log_type = (proofs and cartesi.ACCESS_LOG_TYPE_PROOFS or 0) - | (annotations and cartesi.ACCESS_LOG_TYPE_ANNOTATIONS or 0) - | (large_data and cartesi.ACCESS_LOG_TYPE_LARGE_DATA or 0) - local module = cartesi - if machine_type ~= "local" then - if not remote then - remote = connect() - end - module = remote - end - assert_before_cmio_response_sent(machine) - local root_hash_before = proofs and machine:get_root_hash() or nil - local log = machine:log_send_cmio_response(reason, data, log_type) - assert_after_cmio_response_sent(machine) - local root_hash_after = proofs and machine:get_root_hash() or nil - -- check log - local accesses = log.accesses - assert(#accesses == 5) - assert_access(accesses, 1, { - type = "read", - address = module.machine.get_reg_address("iflags"), - log2_size = 3, - }) - assert_access(accesses, 2, { - type = "write", - address = cartesi.PMA_CMIO_RX_BUFFER_START, - log2_size = cartesi.PMA_CMIO_RX_BUFFER_LOG2_SIZE, - read_hash = all_zeros_hash, - read = large_data and all_zeros or nil, - written_hash = data_hash, - written = large_data and data or nil, - }) - assert_access(accesses, 3, { - type = "write", - address = module.machine.get_reg_address("htif_fromhost"), - log2_size = 3, - }) - assert_access(accesses, 4, { - type = "read", - address = module.machine.get_reg_address("iflags"), - log2_size = 3, - }) - assert_access(accesses, 5, { - type = "write", - address = module.machine.get_reg_address("iflags"), - log2_size = 3, - }) - -- ask machine to verify the log - module.machine.verify_send_cmio_response(reason, data, nil, log, nil) - if proofs then - -- ask machine to verify state transitions - module.machine.verify_send_cmio_response( - reason, - data, - root_hash_before, - log, - root_hash_after, - log_type, - {} - ) + for _, large_data in ipairs({ false, true }) do + local annotations = true + do_test( + string.format( + "log_send_cmio_response happy path with annotations=%s, large_data=%s", + annotations, + large_data + ), + function(machine) + local log_type = (annotations and cartesi.ACCESS_LOG_TYPE_ANNOTATIONS or 0) + | (large_data and cartesi.ACCESS_LOG_TYPE_LARGE_DATA or 0) + local module = cartesi + if machine_type ~= "local" then + if not remote then + remote = connect() end + module = remote end - ) - end + assert_before_cmio_response_sent(machine) + local root_hash_before = machine:get_root_hash() + local log = machine:log_send_cmio_response(reason, data, log_type) + assert_after_cmio_response_sent(machine) + local root_hash_after = machine:get_root_hash() + -- check log + local accesses = log.accesses + assert(#accesses == 5) + assert_access(accesses, 1, { + type = "read", + address = module.machine.get_reg_address("iflags"), + log2_size = 3, + }) + assert_access(accesses, 2, { + type = "write", + address = cartesi.PMA_CMIO_RX_BUFFER_START, + log2_size = cartesi.PMA_CMIO_RX_BUFFER_LOG2_SIZE, + read_hash = all_zeros_hash, + read = large_data and all_zeros or nil, + written_hash = data_hash, + written = large_data and data or nil, + }) + assert_access(accesses, 3, { + type = "write", + address = module.machine.get_reg_address("htif_fromhost"), + log2_size = 3, + }) + assert_access(accesses, 4, { + type = "read", + address = module.machine.get_reg_address("iflags"), + log2_size = 3, + }) + assert_access(accesses, 5, { + type = "write", + address = module.machine.get_reg_address("iflags"), + log2_size = 3, + }) + -- ask machine to verify state transitions + module.machine.verify_send_cmio_response( + reason, + data, + root_hash_before, + log, + root_hash_after, + log_type, + {} + ) + end + ) end end test_send_cmio_input_with_different_arguments() @@ -1382,11 +1365,7 @@ do_test("Dump of log produced by send_cmio_response should match", function(mach machine:set_iflags_Y() local data = "0123456789" local reason = 7 - local log = machine:log_send_cmio_response( - reason, - data, - cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS - ) + local log = machine:log_send_cmio_response(reason, data, cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) -- luacheck: push no max line length local expected_dump = "begin send cmio response\n" .. " 1: read iflags.Y@0x2e8(744): 0x1a(26)\n" @@ -1484,10 +1463,9 @@ do_test("send_cmio_response of zero bytes", function(machine) -- log and verify machine:set_iflags_Y() local hash_before = machine:get_root_hash() - local log = machine:log_send_cmio_response(reason, data, cartesi.ACCESS_LOG_TYPE_PROOFS) + local log = machine:log_send_cmio_response(reason, data) assert(#log.accesses == 4, "log should have 4 accesses") local hash_after = machine:get_root_hash() - module.machine.verify_send_cmio_response(reason, data, nil, log, nil) module.machine.verify_send_cmio_response(reason, data, hash_before, log, hash_after) end) @@ -1584,7 +1562,7 @@ test_util.make_do_test(build_machine, machine_type, { -- step and log one instruction that stores the word in t0 to the address in t1 -- returns raw and formatted log local function log_step() - local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_PROOFS | cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) + local log = machine:log_step_uarch(cartesi.ACCESS_LOG_TYPE_ANNOTATIONS) local temp_file = test_util.new_temp_file() util.dump_log(log, temp_file) return log, temp_file:read_all() diff --git a/tests/lua/mcycle-overflow.lua b/tests/lua/mcycle-overflow.lua index 7abc56f18..ca89e05c5 100755 --- a/tests/lua/mcycle-overflow.lua +++ b/tests/lua/mcycle-overflow.lua @@ -74,19 +74,17 @@ do_test("run_uarch shouldn't change state at max uarch_cycle", function(machine) assert(hash_before == hash_after) end) -for _, log_type in ipairs({ cartesi.ACCESS_LOG_TYPE_PROOFS, 0 }) do - do_test("machine step should do nothing on max mcycle [log_type=" .. tostring(log_type) .. "]", function(machine) - machine:write_reg("uarch_cycle", MAX_UARCH_CYCLE) - local log = machine:log_step_uarch(log_type) - assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) - assert(#log.accesses == 1) - assert(log.accesses[1].type == "read") - assert(log.accesses[1].address == cartesi.UARCH_SHADOW_START_ADDRESS + 8) -- address of uarch_cycle - assert(#log.accesses[1].read == 32) - -- log data has 32 bytes. The uarch_cycle is the 2nd 8-byte word - assert(log.accesses[1].read:sub(9, 16) == string.pack("J", MAX_UARCH_CYCLE)) - assert((log.accesses[1].sibling_hashes ~= nil) == (log_type == cartesi.ACCESS_LOG_TYPE_PROOFS)) - end) -end +do_test("machine step should do nothing on max mcycle", function(machine) + machine:write_reg("uarch_cycle", MAX_UARCH_CYCLE) + local log = machine:log_step_uarch() + assert(machine:read_uarch_cycle() == MAX_UARCH_CYCLE) + assert(#log.accesses == 1) + assert(log.accesses[1].type == "read") + assert(log.accesses[1].address == cartesi.UARCH_SHADOW_START_ADDRESS + 8) -- address of uarch_cycle + assert(#log.accesses[1].read == 32) + -- log data has 32 bytes. The uarch_cycle is the 2nd 8-byte word + assert(log.accesses[1].read:sub(9, 16) == string.pack("J", MAX_UARCH_CYCLE)) + assert(log.accesses[1].sibling_hashes ~= nil) +end) print("passed all") diff --git a/tests/lua/uarch-riscv-tests.lua b/tests/lua/uarch-riscv-tests.lua index d2227bdae..0339981cd 100755 --- a/tests/lua/uarch-riscv-tests.lua +++ b/tests/lua/uarch-riscv-tests.lua @@ -98,11 +98,6 @@ where options are: (default: 1, i.e., run tests sequentially) --output-dir= write json logs to this directory - --proofs - include proofs in the log - --proofs-frequency= - write proof of every uarch cycles - (default: 1, i.e., all accesses) --create-reset-uarch-log create a json log file for a uarch reset operation valid only for the json-step-logs command @@ -130,11 +125,8 @@ local test_path = test_util.tests_uarch_path local test_pattern = ".*" local output_dir local jobs = 1 -local proofs = false local create_uarch_reset_log = false local create_send_cmio_response_log = false -local proofs_frequency = 1 -local total_steps_counter = 0 local options = { { @@ -216,27 +208,6 @@ local options = { return true end, }, - { - "^%-%-proofs$", - function(o) - if not o or #o < 1 then - return false - end - proofs = true - return true - end, - }, - { - "^%-%-proofs%-frequency%=(.+)$", - function(n) - if not n then - return false - end - proofs_frequency = assert(util.parse_number(n), "invalid proofs frequency " .. n) - assert(proofs_frequency > 0, "proofs frequency must be > 0") - return true - end, - }, { ".*", function(all) @@ -482,13 +453,11 @@ local function write_catalog_json_log_entry(out, logFilename, ctx) util.indentout( out, 1, - '{"logFilename": "%s", "binaryFilename": "%s", "steps": %d, "proofs":%s, "proofsFrequency":%d, ' + '{"logFilename": "%s", "binaryFilename": "%s", "steps": %d, ' .. '"initialRootHash": "%s", "finalRootHash": "%s"}', logFilename, ctx.ram_image or "", ctx.step_count, - proofs, - proofs_frequency, util.hexhash(ctx.initial_root_hash), util.hexhash(ctx.final_root_hash) ) @@ -501,13 +470,6 @@ local function create_catalog_json_log_entry(ctx) out:close() end -local function should_log_proofs() - if not proofs then - return false - end - return (total_steps_counter % proofs_frequency) == 0 -end - local function run_machine_writing_json_logs(machine, ctx) local test_name = ctx.test_name local max_cycle = ctx.expected_cycles * 2 @@ -516,9 +478,7 @@ local function run_machine_writing_json_logs(machine, ctx) util.indentout(out, indent, '{ "steps":[\n') local step_count = 0 while math.ult(machine:read_uarch_cycle(), max_cycle) do - local log_type = should_log_proofs() and cartesi.ACCESS_LOG_TYPE_PROOFS or 0 - local log = machine:log_step_uarch(log_type) - total_steps_counter = total_steps_counter + 1 + local log = machine:log_step_uarch() step_count = step_count + 1 local halted = machine:read_uarch_halt_flag() write_log_to_file(log, out, indent + 1, halted) @@ -537,8 +497,7 @@ local function create_json_reset_log() local test_name = "reset-uarch" machine:set_uarch_halt_flag() local initial_root_hash = machine:get_root_hash() - local log_type = proofs and cartesi.ACCESS_LOG_TYPE_PROOFS or 0 - local log = machine:log_reset_uarch(log_type) + local log = machine:log_reset_uarch() local out = create_json_log_file(test_name .. "-steps") write_log_to_file(log, out, 0, true) out:close() @@ -562,8 +521,7 @@ local function create_json_send_cmio_response_log() local reason = 1 machine:set_iflags_Y() local initial_root_hash = machine:get_root_hash() - local log_type = proofs and cartesi.ACCESS_LOG_TYPE_PROOFS or 0 - local log = machine:log_send_cmio_response(reason, response_data, log_type) + local log = machine:log_send_cmio_response(reason, response_data) local out = create_json_log_file(test_name .. "-steps") write_log_to_file(log, out, 0, true) out:close() diff --git a/tests/misc/test-machine-c-api.cpp b/tests/misc/test-machine-c-api.cpp index 3324008ac..13dd624b8 100644 --- a/tests/misc/test-machine-c-api.cpp +++ b/tests/misc/test-machine-c-api.cpp @@ -1135,7 +1135,7 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(verify_step_uarch_log_null_log_test, default_mach class access_log_machine_fixture : public incomplete_machine_fixture { public: access_log_machine_fixture() { - _log_type = CM_ACCESS_LOG_TYPE_PROOFS | CM_ACCESS_LOG_TYPE_ANNOTATIONS; + _log_type = CM_ACCESS_LOG_TYPE_ANNOTATIONS; _machine_dir_path = (std::filesystem::temp_directory_path() / "661b6096c377cdc07756df488059f4407c8f4").string(); uint32_t test_uarch_ram[] = { @@ -1245,8 +1245,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix // step 1 error_code = cm_log_step_uarch(_machine, _log_type, &_access_log); BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - error_code = cm_verify_step_uarch(nullptr, _access_log, nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); // get hash after step error_code = cm_get_root_hash(_machine, &hash1); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); @@ -1257,8 +1255,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix // step 2 error_code = cm_log_step_uarch(_machine, _log_type, &_access_log); BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - error_code = cm_verify_step_uarch(nullptr, _access_log, nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); // get hash after step error_code = cm_get_root_hash(_machine, &hash2); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); @@ -1269,8 +1265,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix // step 3 error_code = cm_log_step_uarch(_machine, _log_type, &_access_log); BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - error_code = cm_verify_step_uarch(nullptr, _access_log, nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); // get hash after step error_code = cm_get_root_hash(_machine, &hash3); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); @@ -1280,8 +1274,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(log_step_uarch_until_halt, access_log_machine_fix // step 4 error_code = cm_log_step_uarch(_machine, _log_type, &_access_log); BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - error_code = cm_verify_step_uarch(nullptr, _access_log, nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); // get hash after step error_code = cm_get_root_hash(_machine, &hash4); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); @@ -1312,10 +1304,6 @@ BOOST_FIXTURE_TEST_CASE_NOLINT(step_complex_test, access_log_machine_fixture) { BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - error_code = cm_verify_step_uarch(nullptr, _access_log, nullptr); - BOOST_CHECK_EQUAL(error_code, CM_ERROR_OK); - BOOST_CHECK_EQUAL(std::string(""), std::string(cm_get_last_error_message())); - error_code = cm_get_root_hash(_machine, &hash1); BOOST_REQUIRE_EQUAL(error_code, CM_ERROR_OK); BOOST_REQUIRE_EQUAL(std::string(cm_get_last_error_message()), std::string("")); diff --git a/tests/scripts/collect-uarch-test-logs.sh b/tests/scripts/collect-uarch-test-logs.sh index 21c52dac5..4fe554e1f 100755 --- a/tests/scripts/collect-uarch-test-logs.sh +++ b/tests/scripts/collect-uarch-test-logs.sh @@ -17,5 +17,5 @@ # set -e mkdir -m 755 -p /tmp/uarch-riscv-tests-json-logs -uarch-riscv-tests --output-dir=/tmp/uarch-riscv-tests-json-logs --proofs --proofs-frequency=1 --create-reset-uarch-log --create-send-cmio-response-log --jobs=$(nproc) json-step-logs +uarch-riscv-tests --output-dir=/tmp/uarch-riscv-tests-json-logs --create-reset-uarch-log --create-send-cmio-response-log --jobs=$(nproc) json-step-logs tar -czf uarch-riscv-tests-json-logs.tar.gz -C /tmp uarch-riscv-tests-json-logs