diff options
| author | cyan <cyjan@mrcyjanek.net> | 2026-03-09 18:05:16 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-09 18:05:16 +0100 |
| commit | 2c11591e02b907e63d8fd4fcb0a6559625934a95 (patch) | |
| tree | dab95d36703f314a8ee9d6277a160df16833c4e5 /patches/monero/0018-serialize-cache-to-JSON.patch | |
| parent | 411e8a1cdb3f4c2812d83f28c335d2a4eb18bd29 (diff) | |
reproducibility (#177)
* reproducibility
* wip: ci fixes, drop generate_translations_header.c
* minor fixes
* fix patch
* fix: toolchain
* bump hash
* fix: minor build issue fixes
* fix: x86_64-w64-mingw32
* wip
* wip
* all updated :o
* fix: reduce git size
* update checksum
remove CI
* chore, more optimal dockerfile
* update monero to v0.18.4.6
* update checksum
* update
* minor patch update
* fix: no command specified
* fix: correct path
* alpine
* stupid.
* AAWASTREYDRFUGTIHYJHGUTYFRDTFYVGUBHINJHGTYFRDSRTXDTCFHBJ
Diffstat (limited to 'patches/monero/0018-serialize-cache-to-JSON.patch')
| -rw-r--r-- | patches/monero/0018-serialize-cache-to-JSON.patch | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/patches/monero/0018-serialize-cache-to-JSON.patch b/patches/monero/0018-serialize-cache-to-JSON.patch deleted file mode 100644 index dbec2f2..0000000 --- a/patches/monero/0018-serialize-cache-to-JSON.patch +++ /dev/null @@ -1,463 +0,0 @@ -From 7c1d576901a56b7c315b2c54362f7985ff8df753 Mon Sep 17 00:00:00 2001 -From: Czarek Nakamoto <cyjan@mrcyjanek.net> -Date: Tue, 12 Aug 2025 07:09:14 -0400 -Subject: [PATCH] serialize cache to JSON - ---- - src/wallet/CMakeLists.txt | 1 + - src/wallet/api/wallet.cpp | 5 + - src/wallet/api/wallet.h | 2 + - src/wallet/api/wallet2_api.h | 3 + - src/wallet/wallet2.h | 6 + - src/wallet/wallet_cache_to_json.cpp | 368 ++++++++++++++++++++++++++++ - 6 files changed, 385 insertions(+) - create mode 100644 src/wallet/wallet_cache_to_json.cpp - -diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt -index b163212b7..196ad671f 100644 ---- a/src/wallet/CMakeLists.txt -+++ b/src/wallet/CMakeLists.txt -@@ -38,6 +38,7 @@ set(wallet_sources - message_store.cpp - message_transporter.cpp - wallet_rpc_payments.cpp -+ wallet_cache_to_json.cpp - ) - - monero_find_all_headers(wallet_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") -diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 7d7d0f922..effb6e719 100644 ---- a/src/wallet/api/wallet.cpp -+++ b/src/wallet/api/wallet.cpp -@@ -3475,4 +3475,9 @@ void Wallet::setLedgerCallback(void (*sendToLedgerDevice)(unsigned char *command - #endif - } - -+std::string WalletImpl::serializeCacheToJson() const -+{ -+ return std::string(m_wallet->serialize_cache_to_json()); -+} -+ - } // namespace -diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index bfe81c590..98c03b9c1 100644 ---- a/src/wallet/api/wallet.h -+++ b/src/wallet/api/wallet.h -@@ -335,6 +335,8 @@ private: - bool getWaitsForDeviceSend(); - - bool getWaitsForDeviceReceive(); -+ -+ virtual std::string serializeCacheToJson() const override; - }; - - -diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index fcb8187d4..3d11929f9 100644 ---- a/src/wallet/api/wallet2_api.h -+++ b/src/wallet/api/wallet2_api.h -@@ -1217,6 +1217,9 @@ struct Wallet - static void setDeviceReceivedData(unsigned char* data, size_t len); - static void setDeviceSendData(unsigned char* data, size_t len); - static void setLedgerCallback(void (*sendToLedgerDevice)(unsigned char *command, unsigned int cmd_len)); -+ -+ //! serialize wallet cache to JSON -+ virtual std::string serializeCacheToJson() const = 0; - }; - - /** -diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index 4f324c238..bc4abc672 100644 ---- a/src/wallet/wallet2.h -+++ b/src/wallet/wallet2.h -@@ -1429,6 +1429,12 @@ private: - FIELD(m_background_sync_data) - END_SERIALIZE() - -+ /*! -+ * \brief Serialize wallet cache fields to JSON -+ * \return const char* pointing to JSON string containing all cache fields -+ */ -+ const char* serialize_cache_to_json() const; -+ - /*! - * \brief Check if wallet keys and bin files exist - * \param file_path Wallet file path -diff --git a/src/wallet/wallet_cache_to_json.cpp b/src/wallet/wallet_cache_to_json.cpp -new file mode 100644 -index 000000000..64687a7a6 ---- /dev/null -+++ b/src/wallet/wallet_cache_to_json.cpp -@@ -0,0 +1,368 @@ -+#include "wallet2.h" -+#include "serialization/binary_archive.h" -+#include "serialization/json_archive.h" -+#include "serialization/serialization.h" -+#include <sstream> -+#include <iomanip> -+ -+namespace tools -+{ -+ -+static void write_escaped_json_string(std::ostream& os, const std::string& str) -+{ -+ for (char c : str) { -+ switch (c) { -+ case '"': os << "\\\""; break; -+ case '\\': os << "\\\\"; break; -+ case '\n': os << "\\n"; break; -+ case '\r': os << "\\r"; break; -+ case '\t': os << "\\t"; break; -+ case '\b': os << "\\b"; break; -+ case '\f': os << "\\f"; break; -+ default: os << c; break; -+ } -+ } -+} -+ -+static void post_process_json(std::string& json) -+{ -+ // ": ," --> ": null," -+ size_t pos = 0; -+ while ((pos = json.find(": ,", pos)) != std::string::npos) { -+ json.replace(pos, 3, ": null,"); -+ pos += 7; -+ } -+ -+ // ": }" --> ": null}" -+ pos = 0; -+ while ((pos = json.find(": }", pos)) != std::string::npos) { -+ json.replace(pos, 3, ": null}"); -+ pos += 7; -+ } -+ -+ // ": ]" --> ": null]" -+ pos = 0; -+ while ((pos = json.find(": ]", pos)) != std::string::npos) { -+ json.replace(pos, 3, ": null]"); -+ pos += 7; -+ } -+ -+ // "key": number"hexstring" --> "key": "numberhexstring" -+ pos = 0; -+ while (pos < json.length()) { -+ size_t colon_pos = json.find(": ", pos); -+ if (colon_pos == std::string::npos) break; -+ -+ size_t value_start = colon_pos + 2; -+ if (value_start >= json.length()) break; -+ -+ if (std::isdigit(json[value_start])) { -+ size_t quote_pos = json.find('"', value_start); -+ if (quote_pos != std::string::npos && quote_pos < json.find_first_of(",}]", value_start)) { -+ size_t closing_quote = json.find('"', quote_pos + 1); -+ if (closing_quote != std::string::npos && closing_quote < json.find_first_of(",}]", value_start)) { -+ std::string digits; -+ size_t digit_end = value_start; -+ while (digit_end < quote_pos && std::isdigit(json[digit_end])) { -+ digits += json[digit_end]; -+ digit_end++; -+ } -+ -+ if (digit_end == quote_pos && !digits.empty()) { -+ std::string hex_part = json.substr(quote_pos + 1, closing_quote - quote_pos - 1); -+ -+ std::string replacement = "\"" + digits + hex_part + "\""; -+ json.replace(value_start, closing_quote - value_start + 1, replacement); -+ pos = value_start + replacement.length(); -+ continue; -+ } -+ } -+ } -+ } -+ -+ pos = colon_pos + 1; -+ } -+} -+ -+const char* wallet2::serialize_cache_to_json() const -+{ -+ static std::string json_result; -+ -+ try -+ { -+ std::stringstream oss; -+ json_archive<true> ar(oss, true); // true for pretty printing -+ -+ ar.begin_object(); -+ -+ // MAGIC_FIELD("monero wallet cache") -+ std::string magic = "monero wallet cache"; -+ ar.tag("magic"); -+ ar.serialize_blob((void*)magic.data(), magic.size()); -+ if (!ar.good()) { -+ json_result = "{\"error\":\"Failed to serialize magic field\"}"; -+ return json_result.c_str(); -+ } -+ -+ // VERSION_FIELD(2) -+ uint32_t version = 2; -+ ar.tag("version"); -+ ar.serialize_varint(version); -+ if (!ar.good()) { -+ json_result = "{\"error\":\"Failed to serialize version field\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_blockchain) - hashchain type, has serialization support -+ ar.tag("m_blockchain"); -+ if (!::serialization::serialize(ar, const_cast<hashchain&>(m_blockchain))) { -+ json_result = "{\"error\":\"Failed to serialize m_blockchain\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_transfers) - transfer_container (std::vector<transfer_details>) -+ ar.tag("m_transfers"); -+ if (!::serialization::serialize(ar, const_cast<transfer_container&>(m_transfers))) { -+ json_result = "{\"error\":\"Failed to serialize m_transfers\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_account_public_address) - cryptonote::account_public_address -+ ar.tag("m_account_public_address"); -+ if (!::serialization::serialize(ar, const_cast<cryptonote::account_public_address&>(m_account_public_address))) { -+ json_result = "{\"error\":\"Failed to serialize m_account_public_address\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_key_images) - serializable_unordered_map<crypto::key_image, size_t> -+ ar.tag("m_key_images"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::key_image, size_t>&>(m_key_images))) { -+ json_result = "{\"error\":\"Failed to serialize m_key_images\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_unconfirmed_txs) - serializable_unordered_map<crypto::hash, unconfirmed_transfer_details> -+ ar.tag("m_unconfirmed_txs"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, unconfirmed_transfer_details>&>(m_unconfirmed_txs))) { -+ json_result = "{\"error\":\"Failed to serialize m_unconfirmed_txs\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_payments) - payment_container (serializable_unordered_multimap<crypto::hash, payment_details>) -+ ar.tag("m_payments"); -+ if (!::serialization::serialize(ar, const_cast<payment_container&>(m_payments))) { -+ json_result = "{\"error\":\"Failed to serialize m_payments\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_tx_keys) - serializable_unordered_map<crypto::hash, crypto::secret_key> -+ ar.tag("m_tx_keys"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, crypto::secret_key>&>(m_tx_keys))) { -+ json_result = "{\"error\":\"Failed to serialize m_tx_keys\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_confirmed_txs) - serializable_unordered_map<crypto::hash, confirmed_transfer_details> -+ ar.tag("m_confirmed_txs"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, confirmed_transfer_details>&>(m_confirmed_txs))) { -+ json_result = "{\"error\":\"Failed to serialize m_confirmed_txs\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_tx_notes) - serializable_unordered_map<crypto::hash, std::string> -+ ar.tag("m_tx_notes"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::string>&>(m_tx_notes))) { -+ json_result = "{\"error\":\"Failed to serialize m_tx_notes\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_unconfirmed_payments) - serializable_unordered_multimap<crypto::hash, pool_payment_details> -+ ar.tag("m_unconfirmed_payments"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_multimap<crypto::hash, pool_payment_details>&>(m_unconfirmed_payments))) { -+ json_result = "{\"error\":\"Failed to serialize m_unconfirmed_payments\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_pub_keys) - serializable_unordered_map<crypto::public_key, size_t> -+ ar.tag("m_pub_keys"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, size_t>&>(m_pub_keys))) { -+ json_result = "{\"error\":\"Failed to serialize m_pub_keys\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_address_book) - std::vector<tools::wallet2::address_book_row> -+ ar.tag("m_address_book"); -+ if (!::serialization::serialize(ar, const_cast<std::vector<tools::wallet2::address_book_row>&>(m_address_book))) { -+ json_result = "{\"error\":\"Failed to serialize m_address_book\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_scanned_pool_txs[0]) - std::unordered_set<crypto::hash> -+ ar.tag("m_scanned_pool_txs_0"); -+ if (!::serialization::serialize(ar, const_cast<std::unordered_set<crypto::hash>&>(m_scanned_pool_txs[0]))) { -+ json_result = "{\"error\":\"Failed to serialize m_scanned_pool_txs[0]\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_scanned_pool_txs[1]) - std::unordered_set<crypto::hash> -+ ar.tag("m_scanned_pool_txs_1"); -+ if (!::serialization::serialize(ar, const_cast<std::unordered_set<crypto::hash>&>(m_scanned_pool_txs[1]))) { -+ json_result = "{\"error\":\"Failed to serialize m_scanned_pool_txs[1]\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_subaddresses) - serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index> -+ ar.tag("m_subaddresses"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index>&>(m_subaddresses))) { -+ json_result = "{\"error\":\"Failed to serialize m_subaddresses\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_subaddress_labels) - std::vector<std::vector<std::string>> - manual JSON serialization -+ oss << ", \n \"m_subaddress_labels\": ["; -+ for (size_t i = 0; i < m_subaddress_labels.size(); ++i) { -+ if (i > 0) oss << ", "; -+ oss << "\n ["; -+ for (size_t j = 0; j < m_subaddress_labels[i].size(); ++j) { -+ if (j > 0) oss << ", "; -+ oss << "\""; -+ write_escaped_json_string(oss, m_subaddress_labels[i][j]); -+ oss << "\""; -+ } -+ oss << "]"; -+ } -+ oss << "\n ]"; -+ -+ // FIELD(m_additional_tx_keys) - serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>> -+ ar.tag("m_additional_tx_keys"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>>&>(m_additional_tx_keys))) { -+ json_result = "{\"error\":\"Failed to serialize m_additional_tx_keys\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_attributes) - serializable_unordered_map<std::string, std::string> - manual JSON serialization -+ oss << ", \n \"m_attributes\": {"; -+ bool first_attr = true; -+ for (const auto& attr : m_attributes) { -+ if (!first_attr) oss << ", "; -+ first_attr = false; -+ oss << "\n \""; -+ write_escaped_json_string(oss, attr.first); -+ oss << "\": \""; -+ write_escaped_json_string(oss, attr.second); -+ oss << "\""; -+ } -+ oss << "\n }"; -+ -+ // FIELD(m_account_tags) - std::pair<serializable_map<std::string, std::string>, std::vector<std::string>> - manual JSON serialization -+ oss << ", \n \"m_account_tags\": {"; -+ oss << "\n \"tags_map\": {"; -+ bool first_tag = true; -+ for (const auto& tag : m_account_tags.first) { -+ if (!first_tag) oss << ", "; -+ first_tag = false; -+ oss << "\n \""; -+ write_escaped_json_string(oss, tag.first); -+ oss << "\": \""; -+ write_escaped_json_string(oss, tag.second); -+ oss << "\""; -+ } -+ oss << "\n },"; -+ oss << "\n \"account_list\": ["; -+ for (size_t i = 0; i < m_account_tags.second.size(); ++i) { -+ if (i > 0) oss << ", "; -+ oss << "\n \""; -+ write_escaped_json_string(oss, m_account_tags.second[i]); -+ oss << "\""; -+ } -+ oss << "\n ]"; -+ oss << "\n }"; -+ -+ // FIELD(m_ring_history_saved) - bool -+ // ar.tag("m_ring_history_saved"); -+ // ar.serialize_blob(&m_ring_history_saved, sizeof(m_ring_history_saved)); -+ // if (!ar.good()) { -+ // json_result = "{\"error\":\"Failed to serialize m_ring_history_saved\"}"; -+ // return json_result.c_str(); -+ // } -+ -+ // FIELD(m_last_block_reward) - uint64_t -+ ar.tag("m_last_block_reward"); -+ ar.serialize_int(m_last_block_reward); -+ if (!ar.good()) { -+ json_result = "{\"error\":\"Failed to serialize m_last_block_reward\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_tx_device) - serializable_unordered_map<crypto::hash, std::string> -+ ar.tag("m_tx_device"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::string>&>(m_tx_device))) { -+ json_result = "{\"error\":\"Failed to serialize m_tx_device\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_device_last_key_image_sync) - uint64_t -+ ar.tag("m_device_last_key_image_sync"); -+ ar.serialize_int(m_device_last_key_image_sync); -+ if (!ar.good()) { -+ json_result = "{\"error\":\"Failed to serialize m_device_last_key_image_sync\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_cold_key_images) - serializable_unordered_map<crypto::public_key, crypto::key_image> -+ ar.tag("m_cold_key_images"); -+ if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, crypto::key_image>&>(m_cold_key_images))) { -+ json_result = "{\"error\":\"Failed to serialize m_cold_key_images\"}"; -+ return json_result.c_str(); -+ } -+ -+ // FIELD(m_rpc_client_secret_key) - crypto::secret_key -+ // ar.tag("m_rpc_client_secret_key"); -+ // ar.serialize_blob(&m_rpc_client_secret_key, sizeof(m_rpc_client_secret_key)); -+ // if (!ar.good()) { -+ // json_result = "{\"error\":\"Failed to serialize m_rpc_client_secret_key\"}"; -+ // return json_result.c_str(); -+ // } -+ -+ // Version-dependent fields -+ if (version >= 1) { -+ // FIELD(m_has_ever_refreshed_from_node) - bool -+ // ar.tag("m_has_ever_refreshed_from_node"); -+ // ar.serialize_blob(&m_has_ever_refreshed_from_node, sizeof(m_has_ever_refreshed_from_node)); -+ // if (!ar.good()) { -+ // json_result = "{\"error\":\"Failed to serialize m_has_ever_refreshed_from_node\"}"; -+ // return json_result.c_str(); -+ // } -+ } -+ -+ if (version >= 2) { -+ // FIELD(m_background_sync_data) - background_sync_data_t -+ ar.tag("m_background_sync_data"); -+ if (!::serialization::serialize(ar, const_cast<background_sync_data_t&>(m_background_sync_data))) { -+ json_result = "{\"error\":\"Failed to serialize m_background_sync_data\"}"; -+ return json_result.c_str(); -+ } -+ } -+ -+ ar.end_object(); -+ -+ if (!ar.good()) { -+ json_result = "{\"error\":\"Failed to finalize JSON serialization\"}"; -+ return json_result.c_str(); -+ } -+ -+ json_result = oss.str(); -+ -+ // Post-process to fix malformed JSON -+ post_process_json(json_result); -+ -+ return json_result.c_str(); -+ } -+ catch (const std::exception& e) -+ { -+ json_result = "{\"error\":\"Failed to serialize wallet cache: " + std::string(e.what()) + "\"}"; -+ return json_result.c_str(); -+ } -+} -+ -+} // namespace tools -\ No newline at end of file --- -2.50.1 - |
