diff options
| author | cyan <cyjan@mrcyjanek.net> | 2024-12-04 10:22:48 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-04 10:22:48 -0500 |
| commit | 2a38bf29618a8ce163f9d6f83b7ae86924752e32 (patch) | |
| tree | 585af02d98d0d042d7b873c5af96b80ddf776b08 /patches/monero/0012-WIP-UR-functions.patch | |
| parent | 40c1a1bda4b6f125c702f5a37ecc48a6ebec24b8 (diff) | |
cleanup patches (and other stuff) (#79)
* cleanup patches
* fix polyseed patch
* Fix iOS builds
* fix polyseed dependencies
* fix polyseed patch for macOS
* update ledger patch
* update wownero patches and version
* update checksums
* wip"
* update gitmodules
* update boost build script
* update build_single.sh
* vix verbosey_copy
* fix __clear_cache bug on wownero
* update randomwow
* migrate build system
* fix cross compilation issues
* some more build issue
* update polyseed
* cleanup cmakelists
* fix toolchain.cmake.in
* add ssp
* another attempt at building windows on CI
* fix package name
* migrate mirror to my own hosting
* change download mirror priority (fallback first)
* link ssp in monero module as well by using CMAKE_{C,CXX}_FLAGS
* fix android builds
* update polyseed source
* 13 -> trixie
* fix package name conflicts, update runner to sid
* update boost to 1_84_0, disable patch that's no longer needed
* switch to ubuntu:24.04
* add POLYSEED_STATIC to toolchain.cmake.in in order to properly link
* drop patches
* fixes to darwin
* link missing wowner-seed library
* a litte bit more of experiments
* build locale only on windows
* update iconv
* update definitions
* update ci builds
* update my progress
* ios fix, update depends, ci
* multithread build system
* fix android, mingw and linux build issues
* remove dependency check
* update Dockerfile to include pigz
* show a message when pigz is missing
* fix devcontainer mingw setup (missing ENV)
* update android build runner
* sailfishos dropped (you better go behave yourself and run actual linux programs)
* fiz pigz issues
* install llvm-ranlib for android
* fix iOS build issues
* fix dummy ledger patch
* fix macos and darwin
* fix macos ci
* fix macos build command
* install autoconf
* add automake
* add libtool
* macos fixes, wownero fixes, idk what else, please help me
* fix wownero iOS build
* Cleanup patches
* add try-catch into monero code
* fix error handling
* update checksums
Diffstat (limited to 'patches/monero/0012-WIP-UR-functions.patch')
| -rw-r--r-- | patches/monero/0012-WIP-UR-functions.patch | 893 |
1 files changed, 0 insertions, 893 deletions
diff --git a/patches/monero/0012-WIP-UR-functions.patch b/patches/monero/0012-WIP-UR-functions.patch deleted file mode 100644 index 564be97..0000000 --- a/patches/monero/0012-WIP-UR-functions.patch +++ /dev/null @@ -1,893 +0,0 @@ -From 1b938a3f98468de3fa06b21a458104cf32831586 Mon Sep 17 00:00:00 2001 -From: Czarek Nakamoto <cyjan@mrcyjanek.net> -Date: Thu, 16 May 2024 17:28:59 +0200 -Subject: [PATCH 12/16] WIP: UR functions - -This commit adds UR functions for UR tasks, -I believe that the right place to get -UR strings is the wallet code itself, -especially because it allows us to -skip the part when we have to store -things to file to encode them later. -Now we are fully in memory - -Things broken in the commit -- ledger support. - AUTO_LOCK_CMD macro causes compile time - issues with this patch. I don't know why - just yet, this is a issue that I'll fix - later. However (considering the purpose - of this patch) it is not a dealbreaker. ---- - .gitmodules | 3 + - CMakeLists.txt | 4 +- - contrib/depends/hosts/darwin.mk | 2 +- - contrib/depends/toolchain.cmake.in | 2 +- - external/CMakeLists.txt | 1 + - external/bc-ur | 1 + - src/device/device_ledger.cpp | 5 +- - src/wallet/CMakeLists.txt | 1 + - src/wallet/api/pending_transaction.cpp | 33 +++ - src/wallet/api/pending_transaction.h | 1 + - src/wallet/api/unsigned_transaction.cpp | 42 ++++ - src/wallet/api/unsigned_transaction.h | 1 + - src/wallet/api/wallet.cpp | 286 +++++++++++++++++++++++- - src/wallet/api/wallet.h | 6 + - src/wallet/api/wallet2_api.h | 19 +- - src/wallet/wallet2.cpp | 96 ++++---- - src/wallet/wallet2.h | 2 + - 17 files changed, 452 insertions(+), 53 deletions(-) - create mode 160000 external/bc-ur - -diff --git a/.gitmodules b/.gitmodules -index 7ea87a009..a7e1d2cd0 100644 ---- a/.gitmodules -+++ b/.gitmodules -@@ -20,3 +20,6 @@ - path = external/supercop - url = https://github.com/monero-project/supercop - branch = monero -+[submodule "external/bc-ur"] -+ path = external/bc-ur -+ url = https://github.com/MrCyjaneK/bc-ur -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 63b8c5079..6028c0961 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -96,7 +96,8 @@ enable_language(C ASM) - set(CMAKE_C_STANDARD 11) - set(CMAKE_C_STANDARD_REQUIRED ON) - set(CMAKE_C_EXTENSIONS OFF) --set(CMAKE_CXX_STANDARD 14) -+set(CMAKE_CXX_STANDARD 17) -+add_definitions(-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) # boost: no template named 'unary_function' in namespace 'std'; did you mean '__unary_function'? - set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) - -@@ -364,6 +365,7 @@ if(NOT MANUAL_SUBMODULES) - endfunction () - - message(STATUS "Checking submodules") -+# check_submodule(external/bc-ur) - check_submodule(external/miniupnp) - check_submodule(external/rapidjson) - check_submodule(external/trezor-common) -diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk -index cbe795081..b14ee5c5b 100644 ---- a/contrib/depends/hosts/darwin.mk -+++ b/contrib/depends/hosts/darwin.mk -@@ -1,4 +1,4 @@ --OSX_MIN_VERSION=10.8 -+OSX_MIN_VERSION=10.14 - LD64_VERSION=609 - ifeq (aarch64, $(host_arch)) - CC_target=arm64-apple-$(host_os) -diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in -index f118c754e..f26655d68 100644 ---- a/contrib/depends/toolchain.cmake.in -+++ b/contrib/depends/toolchain.cmake.in -@@ -94,7 +94,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - SET(BREW OFF) - SET(PORT OFF) - SET(CMAKE_OSX_SYSROOT "@prefix@/native/SDK/") -- SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.08") -+ SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") - SET(CMAKE_CXX_STANDARD 14) - SET(LLVM_ENABLE_PIC OFF) - SET(LLVM_ENABLE_PIE OFF) -diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt -index 1b9761d70..0df9f9116 100644 ---- a/external/CMakeLists.txt -+++ b/external/CMakeLists.txt -@@ -69,6 +69,7 @@ endif() - add_subdirectory(db_drivers) - add_subdirectory(easylogging++) - add_subdirectory(qrcodegen) -+add_subdirectory(bc-ur) - add_subdirectory(randomx EXCLUDE_FROM_ALL) - add_subdirectory(polyseed EXCLUDE_FROM_ALL) - add_subdirectory(utf8proc EXCLUDE_FROM_ALL) -\ No newline at end of file -diff --git a/external/bc-ur b/external/bc-ur -new file mode 160000 -index 000000000..d82e7c753 ---- /dev/null -+++ b/external/bc-ur -@@ -0,0 +1 @@ -+Subproject commit d82e7c753e710b8000706dc3383b498438795208 -diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp -index a4b5f3ef0..90675df11 100644 ---- a/src/device/device_ledger.cpp -+++ b/src/device/device_ledger.cpp -@@ -313,12 +313,13 @@ namespace hw { - - /* ======================================================================= */ - /* LOCKER */ -- /* ======================================================================= */ -+ /* ======================================================================= */ - - //automatic lock one more level on device ensuring the current thread is allowed to use it -+ #pragma message ("Warning AUTO_LOCK_CMD is intentionally left broken. This is yet to be fixed.") - #define AUTO_LOCK_CMD() \ - /* lock both mutexes without deadlock*/ \ -- boost::lock(device_locker, command_locker); \ -+ /* boost::lock(device_locker, command_locker); */ \ - /* make sure both already-locked mutexes are unlocked at the end of scope */ \ - boost::lock_guard<boost::recursive_mutex> lock1(device_locker, boost::adopt_lock); \ - boost::lock_guard<boost::mutex> lock2(command_locker, boost::adopt_lock) -diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt -index 6095f99d5..b163212b7 100644 ---- a/src/wallet/CMakeLists.txt -+++ b/src/wallet/CMakeLists.txt -@@ -50,6 +50,7 @@ monero_add_library(wallet - target_link_libraries(wallet - PUBLIC - rpc_base -+ bc-ur - multisig - common - cryptonote_core -diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp -index be20b478c..1f714d229 100644 ---- a/src/wallet/api/pending_transaction.cpp -+++ b/src/wallet/api/pending_transaction.cpp -@@ -42,6 +42,8 @@ - #include <boost/format.hpp> - #include <boost/filesystem.hpp> - -+#include "bc-ur/src/bc-ur.hpp" -+ - using namespace std; - - namespace Monero { -@@ -178,6 +180,37 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite) - return m_status == Status_Ok; - } - -+std::string PendingTransactionImpl::commitUR(int max_fragment_length) { -+ -+ LOG_PRINT_L3("m_pending_tx size: " << m_pending_tx.size()); -+ -+ try { -+ std::string ptx = m_wallet.m_wallet->dump_tx_to_str(m_pending_tx); -+ m_status = Status_Ok; -+ auto urMessage = ur::string_to_bytes(ptx); -+ ur::ByteVector cbor; -+ ur::CborLite::encodeBytes(cbor, urMessage); -+ std::string type; -+ if (m_wallet.watchOnly()) { -+ type = "xmr-txunsigned"; -+ } else { -+ type = "xmr-txsigned"; -+ } -+ ur::UR urData = ur::UR(type, cbor); -+ auto encoder = ur::UREncoder(urData, max_fragment_length); -+ std::string output; -+ for(size_t i = 0; i < encoder.seq_len(); i++) { -+ output.append("\n"+encoder.next_part()); -+ } -+ return output; -+ } catch (const std::exception &e) { -+ m_errorString = string(tr("Unknown exception: ")) + e.what(); -+ m_status = Status_Error; -+ return ""; -+ } -+} -+ -+ - uint64_t PendingTransactionImpl::amount() const - { - uint64_t result = 0; -diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h -index 2fbaa83d9..0cc6c58e9 100644 ---- a/src/wallet/api/pending_transaction.h -+++ b/src/wallet/api/pending_transaction.h -@@ -46,6 +46,7 @@ public: - int status() const override; - std::string errorString() const override; - bool commit(const std::string &filename = "", bool overwrite = false) override; -+ std::string commitUR(int max_fragment_length = 130) override; - uint64_t amount() const override; - uint64_t dust() const override; - uint64_t fee() const override; -diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp -index 6165a2240..fd03e959d 100644 ---- a/src/wallet/api/unsigned_transaction.cpp -+++ b/src/wallet/api/unsigned_transaction.cpp -@@ -40,6 +40,8 @@ - #include <sstream> - #include <boost/format.hpp> - -+#include "bc-ur/src/bc-ur.hpp" -+ - using namespace std; - - namespace Monero { -@@ -96,6 +98,46 @@ bool UnsignedTransactionImpl::sign(const std::string &signedFileName) - return true; - } - -+std::string UnsignedTransactionImpl::signUR(int max_fragment_length) -+{ -+ if(m_wallet.watchOnly()) -+ { -+ m_errorString = tr("This is a watch only wallet"); -+ m_status = Status_Error; -+ return ""; -+ } -+ std::vector<tools::wallet2::pending_tx> ptx; -+ try -+ { -+ tools::wallet2::signed_tx_set signed_txes; -+ std::string signedTx = m_wallet.m_wallet->sign_tx_dump_to_str(m_unsigned_tx_set, ptx, signed_txes); -+ if (signedTx.empty()) -+ { -+ m_errorString = tr("Failed to sign transaction"); -+ m_status = Status_Error; -+ return ""; -+ } -+ auto urMessage = ur::string_to_bytes(signedTx); -+ ur::ByteVector cbor; -+ ur::CborLite::encodeBytes(cbor, urMessage); -+ std::string type = "xmr-txsigned"; -+ ur::UR urData = ur::UR(type, cbor); -+ auto encoder = ur::UREncoder(urData, max_fragment_length); -+ std::string output; -+ for(size_t i = 0; i < encoder.seq_len(); i++) { -+ output.append("\n"+encoder.next_part()); -+ } -+ return output; -+ } -+ catch (const std::exception &e) -+ { -+ m_errorString = string(tr("Failed to sign transaction")) + e.what(); -+ m_status = Status_Error; -+ return ""; -+ } -+ return ""; -+} -+ - //---------------------------------------------------------------------------------------------------- - bool UnsignedTransactionImpl::checkLoadedTx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &get_tx, const std::string &extra_message) - { -diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h -index 30065a7fa..a94b23f75 100644 ---- a/src/wallet/api/unsigned_transaction.h -+++ b/src/wallet/api/unsigned_transaction.h -@@ -53,6 +53,7 @@ public: - uint64_t txCount() const override; - // sign txs and save to file - bool sign(const std::string &signedFileName) override; -+ std::string signUR(int max_fragment_length = 130) override; - std::string confirmationMessage() const override {return m_confirmationMessage;} - uint64_t minMixinCount() const override; - -diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 306c9b8ae..5ca190c7d 100644 ---- a/src/wallet/api/wallet.cpp -+++ b/src/wallet/api/wallet.cpp -@@ -48,6 +48,7 @@ - - #include <boost/locale.hpp> - #include <boost/filesystem.hpp> -+#include "bc-ur/src/bc-ur.hpp" - - using namespace std; - using namespace cryptonote; -@@ -1321,6 +1322,61 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file - return transaction; - } - -+ -+UnsignedTransaction *WalletImpl::loadUnsignedTxUR(const std::string &input) { -+ clearStatus(); -+ UnsignedTransactionImpl * transaction = new UnsignedTransactionImpl(*this); -+ auto decoder = ur::URDecoder(); -+ -+ std::string delimiter = "\n"; -+ std::string inp = input; -+ size_t pos = 0; -+ std::string token; -+ while ((pos = inp.find(delimiter)) != std::string::npos) { -+ token = inp.substr(0, pos); -+ decoder.receive_part(token); -+ inp.erase(0, pos + delimiter.length()); -+ } -+ decoder.receive_part(inp); -+ -+ if (decoder.is_failure()) { -+ setStatusError(decoder.result_error().what()); -+ transaction->m_status = UnsignedTransaction::Status::Status_Error; -+ transaction->m_errorString = errorString(); -+ return transaction; -+ } -+ -+ if (!decoder.is_complete()) { -+ setStatusError("file ended but ur didn't complete"); -+ transaction->m_status = UnsignedTransaction::Status::Status_Error; -+ transaction->m_errorString = errorString(); -+ return transaction; -+ } -+ -+ std::string data; -+ auto cbor = decoder.result_ur().cbor(); -+ auto i = cbor.begin(); -+ auto end = cbor.end(); -+ ur::CborLite::decodeBytes(i, end, data); -+ -+ if (checkBackgroundSync("cannot load tx") || !m_wallet->parse_unsigned_tx_from_str(data, transaction->m_unsigned_tx_set)){ -+ setStatusError(tr("Failed to load unsigned transactions")); -+ transaction->m_status = UnsignedTransaction::Status::Status_Error; -+ transaction->m_errorString = errorString(); -+ -+ return transaction; -+ } -+ -+ // Check tx data and construct confirmation message -+ std::string extra_message; -+ if (!std::get<2>(transaction->m_unsigned_tx_set.transfers).empty()) -+ extra_message = (boost::format("%u outputs to import. ") % (unsigned)std::get<2>(transaction->m_unsigned_tx_set.transfers).size()).str(); -+ transaction->checkLoadedTx([&transaction](){return transaction->m_unsigned_tx_set.txes.size();}, [&transaction](size_t n)->const tools::wallet2::tx_construction_data&{return transaction->m_unsigned_tx_set.txes[n];}, extra_message); -+ setStatus(transaction->status(), transaction->errorString()); -+ -+ return transaction; -+} -+ - bool WalletImpl::submitTransaction(const string &fileName) { - clearStatus(); - if (checkBackgroundSync("cannot submit tx")) -@@ -1332,7 +1388,7 @@ bool WalletImpl::submitTransaction(const string &fileName) { - setStatus(Status_Ok, tr("Failed to load transaction from file")); - return false; - } -- -+ - if(!transaction->commit()) { - setStatusError(transaction->m_errorString); - return false; -@@ -1341,6 +1397,56 @@ bool WalletImpl::submitTransaction(const string &fileName) { - return true; - } - -+ -+bool WalletImpl::submitTransactionUR(const string &input) { -+ clearStatus(); -+ auto decoder = ur::URDecoder(); -+ -+ std::string delimiter = "\n"; -+ std::string inp = input; -+ size_t pos = 0; -+ std::string token; -+ while ((pos = inp.find(delimiter)) != std::string::npos) { -+ token = inp.substr(0, pos); -+ decoder.receive_part(token); -+ inp.erase(0, pos + delimiter.length()); -+ } -+ decoder.receive_part(inp); -+ -+ if (decoder.is_failure()) { -+ setStatusError(decoder.result_error().what()); -+ return false; -+ } -+ -+ if (!decoder.is_complete()) { -+ setStatusError("file ended but ur didn't complete"); -+ return false; -+ } -+ -+ std::string data; -+ auto cbor = decoder.result_ur().cbor(); -+ auto i = cbor.begin(); -+ auto end = cbor.end(); -+ ur::CborLite::decodeBytes(i, end, data); -+ if (checkBackgroundSync("cannot submit tx")) -+ return false; -+ std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this)); -+ -+ bool r = m_wallet->parse_tx_from_str(data, transaction->m_pending_tx, NULL); -+ if (!r) { -+ setStatus(Status_Ok, tr("Failed to load transaction from file")); -+ return false; -+ } -+ -+ if(!transaction->commit()) { -+ setStatusError(transaction->m_errorString); -+ return false; -+ } -+ -+ return true; -+} -+ -+ - bool WalletImpl::hasUnknownKeyImages() const - { - return m_wallet->has_unknown_key_images(); -@@ -1373,6 +1479,39 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all) - return true; - } - -+std::string WalletImpl::exportKeyImagesUR(size_t max_fragment_length, bool all) -+{ -+ if (m_wallet->watch_only()) -+ { -+ setStatusError(tr("Wallet is view only")); -+ return ""; -+ } -+ if (checkBackgroundSync("cannot export key images")) -+ return ""; -+ -+ try -+ { -+ std::string keyImages = m_wallet->export_key_images_str(all); -+ auto urMessage = ur::string_to_bytes(keyImages); -+ ur::ByteVector cbor; -+ ur::CborLite::encodeBytes(cbor, urMessage); -+ ur::UR urData = ur::UR("xmr-keyimage", cbor); -+ auto encoder = ur::UREncoder(urData, max_fragment_length); -+ std::string output; -+ for(size_t i = 0; i < encoder.seq_len(); i++) { -+ output.append("\n"+encoder.next_part()); -+ } -+ return output; -+ } -+ catch (const std::exception &e) -+ { -+ LOG_ERROR("Error exporting key images: " << e.what()); -+ setStatusError(e.what()); -+ return ""; -+ } -+ return ""; -+} -+ - bool WalletImpl::importKeyImages(const string &filename) - { - if (checkBackgroundSync("cannot import key images")) -@@ -1398,6 +1537,62 @@ bool WalletImpl::importKeyImages(const string &filename) - return true; - } - -+ -+bool WalletImpl::importKeyImagesUR(const string &input) -+{ -+ if (checkBackgroundSync("cannot import key images")) -+ return false; -+ if (!trustedDaemon()) { -+ setStatusError(tr("Key images can only be imported with a trusted daemon")); -+ return false; -+ } -+ try -+ { -+ auto decoder = ur::URDecoder(); -+ std::string delimiter = "\n"; -+ std::string inp = input; -+ size_t pos = 0; -+ std::string token; -+ while ((pos = inp.find(delimiter)) != std::string::npos) { -+ token = inp.substr(0, pos); -+ decoder.receive_part(token); -+ inp.erase(0, pos + delimiter.length()); -+ } -+ decoder.receive_part(inp); -+ -+ if (decoder.is_failure()) { -+ setStatusError(decoder.result_error().what()); -+ return false; -+ } -+ -+ if (!decoder.is_complete()) { -+ setStatusError("file ended but ur didn't complete"); -+ return false; -+ } -+ -+ std::string data; -+ auto cbor = decoder.result_ur().cbor(); -+ auto i = cbor.begin(); -+ auto end = cbor.end(); -+ ur::CborLite::decodeBytes(i, end, data); -+ -+ uint64_t spent = 0, unspent = 0; -+ -+ uint64_t height = m_wallet->import_key_images_str(data, spent, unspent); -+ LOG_PRINT_L2("Signed key images imported to height " << height << ", " -+ << print_money(spent) << " spent, " << print_money(unspent) << " unspent"); -+ } -+ catch (const std::exception &e) -+ { -+ LOG_ERROR("Error exporting key images: " << e.what()); -+ setStatusError(string(tr("Failed to import key images: ")) + e.what()); -+ return false; -+ } -+ -+ return true; -+} -+ -+ - bool WalletImpl::exportOutputs(const string &filename, bool all) - { - if (checkBackgroundSync("cannot export outputs")) -@@ -1430,6 +1625,40 @@ bool WalletImpl::exportOutputs(const string &filename, bool all) - return true; - } - -+std::string WalletImpl::exportOutputsUR(size_t max_fragment_length, bool all) -+{ -+ -+ if (checkBackgroundSync("cannot export outputs")) -+ return ""; -+ if (m_wallet->key_on_device()) -+ { -+ setStatusError(string(tr("Not supported on HW wallets."))); -+ return ""; -+ } -+ -+ try -+ { -+ std::string data = m_wallet->export_outputs_to_str(all); -+ auto urMessage = ur::string_to_bytes(data); -+ ur::ByteVector cbor; -+ ur::CborLite::encodeBytes(cbor, urMessage); -+ ur::UR urData = ur::UR("xmr-output", cbor); -+ auto encoder = ur::UREncoder(urData, max_fragment_length); -+ std::string output; -+ for(size_t i = 0; i < encoder.seq_len(); i++) { -+ output.append("\n"+encoder.next_part()); -+ } -+ return output; -+ } -+ catch (const std::exception &e) -+ { -+ LOG_ERROR("Error exporting outputs: " << e.what()); -+ setStatusError(string(tr("Error exporting outputs: ")) + e.what()); -+ return ""; -+ } -+} -+ -+ - bool WalletImpl::importOutputs(const string &filename) - { - if (checkBackgroundSync("cannot import outputs")) -@@ -1464,6 +1693,61 @@ bool WalletImpl::importOutputs(const string &filename) - return true; - } - -+ -+bool WalletImpl::importOutputsUR(const string &input) -+{ -+ if (checkBackgroundSync("cannot import outputs")) -+ return false; -+ if (m_wallet->key_on_device()) -+ { -+ setStatusError(string(tr("Not supported on HW wallets."))); -+ return false; -+ } -+ -+ try -+ { -+ auto decoder = ur::URDecoder(); -+ -+ std::string delimiter = "\n"; -+ std::string inp = input; -+ size_t pos = 0; -+ std::string token; -+ while ((pos = inp.find(delimiter)) != std::string::npos) { -+ token = inp.substr(0, pos); -+ decoder.receive_part(token); -+ inp.erase(0, pos + delimiter.length()); -+ } -+ decoder.receive_part(inp); -+ -+ if (decoder.is_failure()) { -+ setStatusError(decoder.result_error().what()); -+ return false; -+ } -+ -+ if (!decoder.is_complete()) { -+ setStatusError("file ended but ur didn't complete"); -+ return false; -+ } -+ -+ std::string data; -+ auto cbor = decoder.result_ur().cbor(); -+ auto i = cbor.begin(); -+ auto end = cbor.end(); -+ ur::CborLite::decodeBytes(i, end, data); -+ size_t n_outputs = m_wallet->import_outputs_from_str(std::string(data)); -+ LOG_PRINT_L2(std::to_string(n_outputs) << " outputs imported"); -+ } -+ catch (const std::exception &e) -+ { -+ LOG_ERROR("Failed to import outputs: " << e.what()); -+ setStatusError(string(tr("Failed to import outputs: ")) + e.what()); -+ return false; -+ } -+ -+ return true; -+} -+ -+ - bool WalletImpl::scanTransactions(const std::vector<std::string> &txids) - { - if (checkBackgroundSync("cannot scan transactions")) -diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index 2ad2b62a4..febc93119 100644 ---- a/src/wallet/api/wallet.h -+++ b/src/wallet/api/wallet.h -@@ -182,12 +182,18 @@ public: - const std::set<std::string> &preferred_inputs = {}) override; - virtual PendingTransaction * createSweepUnmixableTransaction() override; - bool submitTransaction(const std::string &fileName) override; -+ bool submitTransactionUR(const std::string &input) override; - virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override; -+ virtual UnsignedTransaction * loadUnsignedTxUR(const std::string &input) override; - bool hasUnknownKeyImages() const override; - bool exportKeyImages(const std::string &filename, bool all = false) override; -+ std::string exportKeyImagesUR(size_t max_fragment_length, bool all = false) override; - bool importKeyImages(const std::string &filename) override; -+ bool importKeyImagesUR(const std::string &input) override; - bool exportOutputs(const std::string &filename, bool all = false) override; -+ std::string exportOutputsUR(size_t max_fragment_length, bool all) override; - bool importOutputs(const std::string &filename) override; -+ bool importOutputsUR(const std::string &filename) override; - bool scanTransactions(const std::vector<std::string> &txids) override; - - bool setupBackgroundSync(const BackgroundSyncType background_sync_type, const std::string &wallet_password, const optional<std::string> &background_cache_password = optional<std::string>()) override; -diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index 1c3a11c39..2bbb32c8b 100644 ---- a/src/wallet/api/wallet2_api.h -+++ b/src/wallet/api/wallet2_api.h -@@ -91,6 +91,7 @@ struct PendingTransaction - virtual std::string errorString() const = 0; - // commit transaction or save to file if filename is provided. - virtual bool commit(const std::string &filename = "", bool overwrite = false) = 0; -+ virtual std::string commitUR(int max_fragment_length = 130) = 0; - virtual uint64_t amount() const = 0; - virtual uint64_t dust() const = 0; - virtual uint64_t fee() const = 0; -@@ -162,7 +163,8 @@ struct UnsignedTransaction - * @param signedFileName - * return - true on success - */ -- virtual bool sign(const std::string &signedFileName) = 0; -+ virtual bool sign(const std::string &signedFileName) = 0; -+ virtual std::string signUR(int max_fragment_length = 130) = 0; - }; - - /** -@@ -938,13 +940,15 @@ struct Wallet - * after object returned - */ - virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) = 0; -- -- /*! -+ virtual UnsignedTransaction * loadUnsignedTxUR(const std::string &input) = 0; -+ -+ /*! - * \brief submitTransaction - submits transaction in signed tx file - * \return - true on success - */ - virtual bool submitTransaction(const std::string &fileName) = 0; -- -+ virtual bool submitTransactionUR(const std::string &input) = 0; -+ - - /*! - * \brief disposeTransaction - destroys transaction object -@@ -969,20 +973,22 @@ struct Wallet - * \return - true on success - */ - virtual bool exportKeyImages(const std::string &filename, bool all = false) = 0; -- -+ virtual std::string exportKeyImagesUR(size_t max_fragment_length, bool all = false) = 0; - /*! - * \brief importKeyImages - imports key images from file - * \param filename - * \return - true on success - */ - virtual bool importKeyImages(const std::string &filename) = 0; -+ virtual bool importKeyImagesUR(const std::string &input) = 0; - - /*! -- * \brief importOutputs - exports outputs to file -+ * \brief exportOutputs - exports outputs to file - * \param filename - * \return - true on success - */ - virtual bool exportOutputs(const std::string &filename, bool all = false) = 0; -+ virtual std::string exportOutputsUR(size_t max_fragment_length, bool all = false) = 0; - - /*! - * \brief importOutputs - imports outputs from file -@@ -990,6 +996,7 @@ struct Wallet - * \return - true on success - */ - virtual bool importOutputs(const std::string &filename) = 0; -+ virtual bool importOutputsUR(const std::string &filename) = 0; - - /*! - * \brief scanTransactions - scan a list of transaction ids, this operation may reveal the txids to the remote node and affect your privacy -diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index 4de226a4a..7d97e683b 100644 ---- a/src/wallet/wallet2.cpp -+++ b/src/wallet/wallet2.cpp -@@ -14056,33 +14056,40 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle - - bool wallet2::export_key_images(const std::string &filename, bool all) const - { -- PERF_TIMER(export_key_images); -- std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all); -- std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC)); -- const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; -- const uint32_t offset = ski.first; -+ std::string data = export_key_images_str(all); -+ return save_to_file(filename, data); -+} - -- std::string data; -- data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key)); -- data.resize(4); -- data[0] = offset & 0xff; -- data[1] = (offset >> 8) & 0xff; -- data[2] = (offset >> 16) & 0xff; -- data[3] = (offset >> 24) & 0xff; -- data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); -- data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key)); -- for (const auto &i: ski.second) -- { -- data += std::string((const char *)&i.first, sizeof(crypto::key_image)); -- data += std::string((const char *)&i.second, sizeof(crypto::signature)); -- } -+std::string wallet2::export_key_images_str(bool all) const -+{ -+ PERF_TIMER(export_key_images); -+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all); -+ std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC)); -+ const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; -+ const uint32_t offset = ski.first; -+ -+ std::string data; -+ data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key)); -+ data.resize(4); -+ data[0] = offset & 0xff; -+ data[1] = (offset >> 8) & 0xff; -+ data[2] = (offset >> 16) & 0xff; -+ data[3] = (offset >> 24) & 0xff; -+ data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key)); -+ data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key)); -+ for (const auto &i: ski.second) -+ { -+ data += std::string((const char *)&i.first, sizeof(crypto::key_image)); -+ data += std::string((const char *)&i.second, sizeof(crypto::signature)); -+ } - -- // encrypt data, keep magic plaintext -- PERF_TIMER(export_key_images_encrypt); -- std::string ciphertext = encrypt_with_view_secret_key(data); -- return save_to_file(filename, magic + ciphertext); -+ // encrypt data, keep magic plaintext -+ PERF_TIMER(export_key_images_encrypt); -+ std::string ciphertext = encrypt_with_view_secret_key(data); -+ return magic + ciphertext; - } - -+ - //---------------------------------------------------------------------------------------------------- - std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const - { -@@ -14137,53 +14144,60 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>> - return std::make_pair(offset, ski); - } - --uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent) -+uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent) { -+ std::string data; -+ -+ bool r = load_from_file(filename, data); -+ -+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename); -+ -+ return import_key_images_str(data, spent, unspent); -+} -+ -+uint64_t wallet2::import_key_images_str(const std::string &data, uint64_t &spent, uint64_t &unspent) - { - PERF_TIMER(import_key_images_fsu); -- std::string data; -- bool r = load_from_file(filename, data); -- -- THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename); -+ std::string data_local = data; - - const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC); - if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen)) - { -- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename); -+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic")); - } - - try - { - PERF_TIMER(import_key_images_decrypt); -- data = decrypt_with_view_secret_key(std::string(data, magiclen)); -+ data_local = decrypt_with_view_secret_key(std::string(data, magiclen)); - } - catch (const std::exception &e) - { -- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what()); -+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + ": " + e.what()); - } - - const size_t headerlen = 4 + 2 * sizeof(crypto::public_key); -- THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename); -- const uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24); -- const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4]; -- const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)]; -+ THROW_WALLET_EXCEPTION_IF(data_local.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ")); -+ const uint32_t offset = (uint8_t)data_local[0] | (((uint8_t)data_local[1]) << 8) | (((uint8_t)data_local[2]) << 16) | (((uint8_t)data_local[3]) << 24); -+ const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data_local[4]; -+ const crypto::public_key &public_view_key = *(const crypto::public_key*)&data_local[4 + sizeof(crypto::public_key)]; - const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address; - if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key) - { -- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account"); -+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + " are for a different account"); - } - THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs"); - - const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature); -- THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size, -- error::wallet_internal_error, std::string("Bad data size from file ") + filename); -- size_t nki = (data.size() - headerlen) / record_size; -+ THROW_WALLET_EXCEPTION_IF((data_local.size() - headerlen) % record_size, -+ error::wallet_internal_error, std::string("Bad data size from file ")); -+ size_t nki = (data_local.size() - headerlen) / record_size; - - std::vector<std::pair<crypto::key_image, crypto::signature>> ski; - ski.reserve(nki); - for (size_t n = 0; n < nki; ++n) - { -- crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data[headerlen + n * record_size]); -- crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data[headerlen + n * record_size + sizeof(crypto::key_image)]); -+ crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data_local[headerlen + n * record_size]); -+ crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data_local[headerlen + n * record_size + sizeof(crypto::key_image)]); - - ski.push_back(std::make_pair(key_image, signature)); - } -diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index 3ce710433..9ff169a40 100644 ---- a/src/wallet/wallet2.h -+++ b/src/wallet/wallet2.h -@@ -1650,9 +1650,11 @@ private: - std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const; - void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc); - bool export_key_images(const std::string &filename, bool all = false) const; -+ std::string export_key_images_str(bool all) const; - std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const; - uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true); - uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent); -+ uint64_t import_key_images_str(const std::string &data, uint64_t &spent, uint64_t &unspent); - bool import_key_images(std::vector<crypto::key_image> key_images, size_t offset=0, boost::optional<std::unordered_set<size_t>> selected_transfers=boost::none); - bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false); - crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const; --- -2.39.2 - |
