summaryrefslogtreecommitdiff
path: root/patches/monero/0012-WIP-UR-functions.patch
diff options
context:
space:
mode:
authorcyan <cyjan@mrcyjanek.net>2024-12-04 10:22:48 -0500
committerGitHub <noreply@github.com>2024-12-04 10:22:48 -0500
commit2a38bf29618a8ce163f9d6f83b7ae86924752e32 (patch)
tree585af02d98d0d042d7b873c5af96b80ddf776b08 /patches/monero/0012-WIP-UR-functions.patch
parent40c1a1bda4b6f125c702f5a37ecc48a6ebec24b8 (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.patch893
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
-