8 Commits

Author SHA1 Message Date
Some Random Crypto Guy d837147a0d removed extraneous files 2025-03-18 11:09:10 +00:00
Some Random Crypto Guy c4e09d99d6 fixed calls to wallet2_api functions 2025-03-18 10:45:48 +00:00
Some Random Crypto Guy 235107fe5d updated build to include correct source files upstream; renamed codebase to use SALVIUM_ 2025-03-18 10:31:55 +00:00
Some Random Crypto Guy e79f77f0a6 patches working 2025-03-18 09:58:46 +00:00
Some Random Crypto Guy dd7d17fb23 added background sync patch 2025-03-17 21:30:14 +00:00
Some Random Crypto Guy 5d5019d58f updated patches to apply against rebase-v0.18 2025-03-17 21:26:55 +00:00
Some Random Crypto Guy fab66493eb updated a couple of patches to work against the rebased v0.18.4.0 Zero code 2025-03-17 13:21:40 +00:00
Some Random Crypto Guy a4c301a9a9 initial import of salvium submodule and associated changes (not functional) 2025-03-14 15:38:13 +00:00
26 changed files with 9282 additions and 9 deletions
+4
View File
@@ -16,3 +16,7 @@
url = https://github.com/MrCyjaneK/wownero-seed
branch = cyjan-namespace2
shallow = true
[submodule "salvium"]
path = salvium
url = https://github.com/salvium/salvium
branch = rebase-v0.18
+4 -4
View File
@@ -6,14 +6,14 @@ repo="$1"
if [[ "x$repo" == "x" ]];
then
echo "Usage: $0 monero/wownero"
echo "Usage: $0 monero/wownero/zano/salvium"
exit 1
fi
if [[ "x$repo" != "xwownero" && "x$repo" != "xmonero" ]];
if [[ "x$repo" != "xwownero" && "x$repo" != "xmonero" && "x$repo" != "xzano" && "x$repo" != "xsalvium" ]];
then
echo "Usage: $0 monero/wownero"
echo "Invalid target given, only monero and wownero are supported targets"
echo "Usage: $0 monero/wownero/zano/salvium"
echo "Invalid target given, only monero, wownero,zano, and salvium are supported targets"
fi
if [[ ! -d "$repo" ]]
+5 -5
View File
@@ -20,13 +20,13 @@ set -e
repo=$1
if [[ "x$repo" == "x" ]];
then
echo "Usage: $0 monero/wownero/zano $(gcc -dumpmachine) -j$proccount"
echo "Usage: $0 monero/wownero/zano/salvium $(gcc -dumpmachine) -j$proccount"
exit 1
fi
if [[ "x$repo" != "xwownero" && "x$repo" != "xmonero" && "x$repo" != "xzano" ]];
if [[ "x$repo" != "xwownero" && "x$repo" != "xmonero" && "x$repo" != "xzano" && "x$repo" != "xsalvium" ]];
then
echo "Usage: $0 monero/wownero/zano $(gcc -dumpmachine) -j$proccount"
echo "Usage: $0 monero/wownero/zano/salvium $(gcc -dumpmachine) -j$proccount"
echo "Invalid target given"
exit 1
fi
@@ -41,7 +41,7 @@ fi
HOST_ABI="$2"
if [[ "x$HOST_ABI" == "x" ]];
then
echo "Usage: $0 monero/wownero $(gcc -dumpmachine) -j$proccount"
echo "Usage: $0 monero/wownero/zano/salvium $(gcc -dumpmachine) -j$proccount"
exit 1
fi
@@ -49,7 +49,7 @@ NPROC="$3"
if [[ "x$NPROC" == "x" ]];
then
echo "Usage: $0 monero/wownero $(gcc -dumpmachine) -j$proccount"
echo "Usage: $0 monero/wownero/zano/salvium $(gcc -dumpmachine) -j$proccount"
exit 1
fi
cd $(dirname $0)
@@ -0,0 +1,34 @@
From 6e284a2ef552f1f47e8ca9edcf8651312c9e37dd Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Tue, 2 Apr 2024 16:51:56 +0200
Subject: [PATCH 01/14] fix missing ___clear_cache when targetting iOS
---
.gitmodules | 3 ++-
external/randomx | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/.gitmodules b/.gitmodules
index 721cce3b4..ffb73fe9a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,7 +9,8 @@
url = https://github.com/trezor/trezor-common.git
[submodule "external/randomx"]
path = external/randomx
- url = https://github.com/tevador/RandomX
+ url = https://github.com/MrCyjaneK/RandomX
+ branch = cyjan-fix-ios
[submodule "external/supercop"]
path = external/supercop
url = https://github.com/monero-project/supercop
diff --git a/external/randomx b/external/randomx
index 102f8acf9..ce72c9bb9 160000
--- a/external/randomx
+++ b/external/randomx
@@ -1 +1 @@
-Subproject commit 102f8acf90a7649ada410de5499a7ec62e49e1da
+Subproject commit ce72c9bb9cb799e0d9171094b9abb009e04c5bfc
--
2.48.1
+208
View File
@@ -0,0 +1,208 @@
From b4f4b38af1ab974872862fc20735e41941b955e9 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Sat, 11 May 2024 16:25:10 +0200
Subject: [PATCH 02/14] store crash fix
Monero wallet crashes (sometimes) when it is syncing,
while the proper solution (that can be seen in feather)
is to not store wallet while it is being synced, this is not
acceptable for mobile wallets where OS can just come
and kill the wallet because it felt like it.
This patch depends on the background-sync patch, but
to use it as a standalone fix grabbing the definition for the
LOCK_REFRESH macro should be enough.
tobtoht suggested:
_say you want to store every 15 minutes during background sync. you stop the refresh every 15 minutes. then do something like this in the callback:_
```
// Make sure this doesn't run in the refresh thread
onRefreshed() {
if (hasItBeen15MinutesSinceWeStored()) {
store();
}
if (shouldWeContinueRefreshing()) {
startRefresh();
}
}
```
which works for crashes after the wallet is initially synced
but doesn't solve the issue for wallet that are syncing (it
would just wait for it to finish before actually storing).
Also imo store() functin should store the wallet, no matter
the current state.
---
src/wallet/api/wallet.cpp | 25 ++++++++++++-------------
src/wallet/api/wallet.h | 1 -
src/wallet/wallet2.cpp | 11 ++++++++++-
src/wallet/wallet2.h | 3 +++
4 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 8fda0bab7..67b170e3d 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -55,8 +55,8 @@ using namespace cryptonote;
#define MONERO_DEFAULT_LOG_CATEGORY "WalletAPI"
#define LOCK_REFRESH() \
- bool refresh_enabled = m_refreshEnabled; \
- m_refreshEnabled = false; \
+ bool refresh_enabled = m_wallet->get_refresh_enabled(); \
+ m_wallet->set_refresh_enabled(false); \
m_wallet->stop(); \
m_refreshCV.notify_one(); \
boost::mutex::scoped_lock lock(m_refreshMutex); \
@@ -466,7 +466,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
m_wallet2Callback.reset(new Wallet2CallbackImpl(this));
m_wallet->callback(m_wallet2Callback.get());
m_refreshThreadDone = false;
- m_refreshEnabled = false;
+ m_wallet->set_refresh_enabled(false);
m_addressBook.reset(new AddressBookImpl(this));
m_subaddress.reset(new SubaddressImpl(this));
m_subaddressAccount.reset(new SubaddressAccountImpl(this));
@@ -962,6 +962,7 @@ void WalletImpl::stop()
bool WalletImpl::store(const std::string &path)
{
clearStatus();
+ LOCK_REFRESH();
try {
if (path.empty()) {
m_wallet->store();
@@ -2448,10 +2449,10 @@ void WalletImpl::refreshThreadFunc()
}
LOG_PRINT_L3(__FUNCTION__ << ": refresh lock acquired...");
- LOG_PRINT_L3(__FUNCTION__ << ": m_refreshEnabled: " << m_refreshEnabled);
+ LOG_PRINT_L3(__FUNCTION__ << ": m_refreshEnabled: " << m_wallet->get_refresh_enabled());
LOG_PRINT_L3(__FUNCTION__ << ": m_status: " << status());
LOG_PRINT_L3(__FUNCTION__ << ": m_refreshShouldRescan: " << m_refreshShouldRescan);
- if (m_refreshEnabled) {
+ if (m_wallet->get_refresh_enabled()) {
LOG_PRINT_L3(__FUNCTION__ << ": refreshing...");
doRefresh();
}
@@ -2481,12 +2482,12 @@ void WalletImpl::doRefresh()
}
m_wallet->find_and_save_rings(false);
} else {
- LOG_PRINT_L3(__FUNCTION__ << ": skipping refresh - daemon is not synced");
+ LOG_PRINT_L3(__FUNCTION__ << ": skipping refresh - daemon is not synced");
}
} catch (const std::exception &e) {
setStatusError(e.what());
break;
- }while(!rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested
+ }while(m_wallet->get_refresh_enabled() && !rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested
if (m_wallet2Callback->getListener()) {
m_wallet2Callback->getListener()->refreshed();
@@ -2496,9 +2497,9 @@ void WalletImpl::doRefresh()
void WalletImpl::startRefresh()
{
- if (!m_refreshEnabled) {
+ if (!m_wallet->get_refresh_enabled()) {
LOG_PRINT_L2(__FUNCTION__ << ": refresh started/resumed...");
- m_refreshEnabled = true;
+ m_wallet->set_refresh_enabled(true);
m_refreshCV.notify_one();
}
}
@@ -2508,7 +2509,7 @@ void WalletImpl::startRefresh()
void WalletImpl::stopRefresh()
{
if (!m_refreshThreadDone) {
- m_refreshEnabled = false;
+ m_wallet->set_refresh_enabled(false);
m_refreshThreadDone = true;
m_refreshCV.notify_one();
m_refreshThread.join();
@@ -2519,9 +2520,7 @@ void WalletImpl::pauseRefresh()
{
LOG_PRINT_L2(__FUNCTION__ << ": refresh paused...");
// TODO synchronize access
- if (!m_refreshThreadDone) {
- m_refreshEnabled = false;
- }
+ m_wallet->set_refresh_enabled(false);
}
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 1f199a72c..ac7ce2f6a 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -273,7 +273,6 @@ private:
std::unique_ptr<SubaddressAccountImpl> m_subaddressAccount;
// multi-threaded refresh stuff
- std::atomic<bool> m_refreshEnabled;
std::atomic<bool> m_refreshThreadDone;
std::atomic<int> m_refreshIntervalMillis;
std::atomic<bool> m_refreshShouldRescan;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index dfb8b23cb..c9c2dbc82 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1192,6 +1192,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_upper_transaction_weight_limit(0),
m_run(true),
m_callback(0),
+ m_refreshEnabled(false),
m_trusted_daemon(false),
m_nettype(nettype),
m_multisig_rounds_passed(0),
@@ -1412,6 +1413,14 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
return ret;
}
//----------------------------------------------------------------------------------------------------
+bool wallet2::get_refresh_enabled() {
+ return m_refreshEnabled;
+}
+//----------------------------------------------------------------------------------------------------
+void wallet2::set_refresh_enabled(bool val) {
+ m_refreshEnabled = val;
+}
+//----------------------------------------------------------------------------------------------------
bool wallet2::set_proxy(const std::string &address)
{
return m_http_client->set_proxy(address);
@@ -4107,7 +4116,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
// infer when we get an incoming output
bool first = true, last = false;
- while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks)
+ while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks && m_refreshEnabled)
{
uint64_t next_blocks_start_height;
std::vector<cryptonote::block_complete_entry> next_blocks;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 2f4ad52f1..daad1e940 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1078,6 +1078,8 @@ private:
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect,
const std::string &proxy = "");
bool set_proxy(const std::string &address);
+ bool get_refresh_enabled();
+ void set_refresh_enabled(bool val);
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
@@ -1989,6 +1991,7 @@ private:
boost::recursive_mutex m_daemon_rpc_mutex;
+ bool m_refreshEnabled;
bool m_trusted_daemon;
i_wallet2_callback* m_callback;
hw::device::device_type m_key_device_type;
--
2.48.1
@@ -0,0 +1,25 @@
From a74f616e3c1671a883182b0db1c6fc11a1242c01 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 2 Sep 2024 16:40:31 +0200
Subject: [PATCH 03/14] uint64_t missing definition fix
---
contrib/epee/include/net/http_base.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
index 4af4da790..ae4c0d05e 100644
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -28,7 +28,7 @@
#pragma once
#include "memwipe.h"
-
+#include <stdint.h>
#include <boost/utility/string_ref.hpp>
#include <string>
--
2.48.1
@@ -0,0 +1,71 @@
From f9b222f1611d7cfbaf0ac52cd6194724c7554def Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 24 Jun 2024 10:49:12 +0200
Subject: [PATCH 04/14] use proper error handling in get_seed
---
src/wallet/api/wallet.cpp | 17 ++++++++++++-----
src/wallet/wallet2.cpp | 5 ++++-
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 67b170e3d..89df5c517 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -763,12 +763,19 @@ bool WalletImpl::close(bool store)
std::string WalletImpl::seed(const std::string& seed_offset) const
{
- if (checkBackgroundSync("cannot get seed"))
+ if (checkBackgroundSync("cannot get seed")) {
+ setStatusError("cannot get seed");
return std::string();
- epee::wipeable_string seed;
- if (m_wallet)
- m_wallet->get_seed(seed, seed_offset);
- return std::string(seed.data(), seed.size()); // TODO
+ }
+ try {
+ epee::wipeable_string seed;
+ if (m_wallet)
+ m_wallet->get_seed(seed, seed_offset);
+ return std::string(seed.data(), seed.size()); // TODO
+ } catch (const std::exception &e) {
+ setStatusError(e.what());
+ return std::string();
+ }
}
std::string WalletImpl::getSeedLanguage() const
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index c9c2dbc82..b827b826f 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1428,11 +1428,13 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
bool keys_deterministic = is_deterministic();
if (!keys_deterministic)
{
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "This is not a deterministic wallet");
std::cout << "This is not a deterministic wallet" << std::endl;
return false;
}
if (seed_language.empty())
{
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "seed_language not set");
std::cout << "seed_language not set" << std::endl;
return false;
}
@@ -1444,8 +1446,9 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
key = cryptonote::encrypt_key(key, passphrase);
if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language))
{
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Failed to create seed from key for language: "+seed_language+", falling back to English.");
std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
- return false;
+ crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
}
return true;
--
2.48.1
+986
View File
@@ -0,0 +1,986 @@
From ff70c74c8b331758ace1f14df0ca107731dda49d Mon Sep 17 00:00:00 2001
From: tobtoht <tob@featherwallet.org>
Date: Tue, 12 Mar 2024 10:09:50 +0100
Subject: [PATCH 05/14] 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 | 4 +
CMakeLists.txt | 4 +-
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 | 309 +++++++++++++++++++++++-
src/wallet/api/wallet.h | 8 +
src/wallet/api/wallet2_api.h | 22 +-
src/wallet/wallet2.cpp | 141 +++++++----
src/wallet/wallet2.h | 3 +
15 files changed, 519 insertions(+), 57 deletions(-)
create mode 160000 external/bc-ur
diff --git a/.gitmodules b/.gitmodules
index ffb73fe9a..72af74d55 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -11,6 +11,10 @@
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
+ branch = misc
[submodule "external/miniupnp"]
path = external/miniupnp
url = https://github.com/miniupnp/miniupnp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index db69b1b04..c73b813d8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -100,6 +100,7 @@ enable_language(C ASM)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
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)
@@ -367,6 +368,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/external/CMakeLists.txt b/external/CMakeLists.txt
index 538e4d215..074e23f16 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
@@ -69,4 +69,5 @@ endif()
add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
add_subdirectory(qrcodegen)
+add_subdirectory(bc-ur)
add_subdirectory(randomx EXCLUDE_FROM_ALL)
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,1 @@
+Subproject commit d82e7c753e710b8000706dc3383b498438795208
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 70a702796..9c3c26ee5 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 {
@@ -162,6 +164,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 0a9779c07..403bfe281 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 89df5c517..3fcd6f332 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;
@@ -961,6 +962,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
return m_wallet->unlocked_balance(accountIndex, asset, false);
}
+uint64_t WalletImpl::viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images, const std::string& asset) const
+{
+ clearStatus();
+
+ std::vector<crypto::key_image> kis;
+ for (const auto &key_image : key_images) {
+ crypto::key_image ki;
+ if (!epee::string_tools::hex_to_pod(key_image, ki))
+ {
+ setStatusError(tr("failed to parse key image"));
+ return 0;
+ }
+ kis.push_back(ki);
+ }
+
+ return m_wallet->view_only_balance(accountIndex, kis, asset);
+}
+
uint64_t WalletImpl::blockChainHeight() const
{
return m_wallet->get_blockchain_current_height();
@@ -1139,6 +1158,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"))
@@ -1159,6 +1233,61 @@ 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();
+}
+
bool WalletImpl::exportKeyImages(const string &filename, bool all)
{
if (m_wallet->watch_only())
@@ -1186,6 +1318,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"))
@@ -1211,6 +1373,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"))
@@ -1243,6 +1461,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"))
@@ -1277,6 +1529,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 ac7ce2f6a..edf8bb8ce 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -113,6 +113,7 @@ public:
bool setProxy(const std::string &address) override;
uint64_t balance(const std::string& asset, uint32_t accountIndex = 0) const override;
uint64_t unlockedBalance(const std::string& asset, uint32_t accountIndex = 0) const override;
+ uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images, const std::string& asset = "SAL1") const override;
uint64_t blockChainHeight() const override;
uint64_t approximateBlockChainHeight() const override;
uint64_t estimateBlockChainHeight() const override;
@@ -177,11 +178,18 @@ public:
std::set<uint32_t> subaddr_indices = {}) 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 e349df176..764adbfbf 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -92,6 +92,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;
@@ -195,7 +196,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;
};
/**
@@ -668,6 +670,7 @@ struct Wallet
result += unlockedBalance(asset, i);
return result;
}
+ virtual uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images = {}, const std::string& asset = "SAL1") const = 0;
/**
* @brief watchOnly - checks if wallet is watch only
@@ -965,13 +968,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
@@ -987,6 +992,8 @@ struct Wallet
virtual uint64_t estimateTransactionFee(const std::vector<std::pair<std::string, uint64_t>> &destinations,
PendingTransaction::Priority priority) const = 0;
+ virtual bool hasUnknownKeyImages() const = 0;
+
/*!
* \brief exportKeyImages - exports key images to file
* \param filename
@@ -994,20 +1001,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
@@ -1015,6 +1024,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 b827b826f..765cefb32 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -945,6 +945,16 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra)
return idx + extra;
}
+bool is_preferred_input(const std::vector<crypto::key_image>& preferred_input_list, const crypto::key_image& input) {
+ if (!preferred_input_list.empty()) {
+ auto it = std::find(preferred_input_list.begin(), preferred_input_list.end(), input);
+ if (it == preferred_input_list.end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet)
{
shim->get_tx_pub_key_from_received_outs = std::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, std::placeholders::_1);
@@ -7088,6 +7098,29 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, const std::string& asse
return amount;
}
//----------------------------------------------------------------------------------------------------
+uint64_t wallet2::view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs, const std::string& asset_type)
+{
+ uint64_t amount = 0;
+ if (m_transfers_indices.count(asset_type) > 0) {
+ for (const auto& idx: m_transfers_indices.at(asset_type))
+ {
+ const transfer_details& td = m_transfers[idx];
+ if (is_preferred_input(selected_inputs, td.m_key_image) &&
+ !is_spent(td, false) &&
+ !td.m_frozen &&
+ !td.m_key_image_partial &&
+ td.m_key_image_known &&
+ td.is_rct() &&
+ is_transfer_unlocked(td) &&
+ td.m_subaddr_index.major == index_major)
+ {
+ amount += td.m_amount;
+ }
+ }
+ }
+ return amount;
+}
+//----------------------------------------------------------------------------------------------------
std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, const std::string& asset_type, bool strict) const
{
std::map<uint32_t, uint64_t> amount_per_subaddr;
@@ -7963,9 +7992,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
crypto::key_derivation derivation;
std::vector<crypto::key_derivation> additional_derivations;
- // compute public keys from out secret keys
- crypto::public_key tx_pub_key;
- crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
+ crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
std::vector<crypto::public_key> additional_tx_pub_keys;
for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
{
@@ -10880,7 +10907,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below fractional threshold " << print_money(fractional_threshold));
continue;
}
- if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
+ if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.m_key_image_known && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
{
if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
{
@@ -10930,9 +10957,15 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Starting with " << num_nondust_outputs << " non-dust outputs and " << num_dust_outputs << " dust outputs");
- if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
- return std::vector<wallet2::pending_tx>();
+ // use tobotoht's code path on view-only wallet, otherwise default to upstream
+ bool throwOnNoEnotes = m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig || m_is_background_wallet;
+ if (throwOnNoEnotes) {
+ THROW_WALLET_EXCEPTION_IF(unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty(), error::wallet_internal_error, "No enotes available to spend")
+ } else {
+ if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
+ return std::vector<wallet2::pending_tx>();
+ }
// if empty, put dummy entry so that the front can be referenced later in the loop
if (unused_dust_indices_per_subaddr.empty())
unused_dust_indices_per_subaddr.push_back({});
@@ -13742,33 +13775,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;
- // 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);
+ 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 magic + ciphertext;
}
+
//----------------------------------------------------------------------------------------------------
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
{
@@ -13828,53 +13868,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 daad1e940..a752f15b9 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1112,6 +1112,7 @@ private:
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major, const std::string& asset_type, bool strict) const;
uint64_t unlocked_balance(uint32_t subaddr_index_major, const std::string& asset_type, bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL);
+ uint64_t view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs = {}, const std::string& asset_type = "SAL1");
// locked & unlocked balance per subaddress of given or current subaddress account
std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major, const std::string& asset_type, bool strict) const;
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, const std::string& asset_type, bool strict);
@@ -1596,9 +1597,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.48.1
@@ -0,0 +1,606 @@
From 904fe95204ba02d1a8c81fc46c1423ba1685c94f Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Wed, 26 Jun 2024 15:04:38 +0200
Subject: [PATCH 06/14] add dummy device for ledger
---
CMakeLists.txt | 6 +-
src/device/CMakeLists.txt | 6 +-
src/device/device.cpp | 10 ++-
src/device/device.hpp | 12 +--
src/device/device_io_dummy.cpp | 133 ++++++++++++++++++++++++++++++
src/device/device_io_dummy.hpp | 74 +++++++++++++++++
src/device/device_ledger.cpp | 6 +-
src/device/device_ledger.hpp | 7 +-
src/wallet/api/wallet.cpp | 94 +++++++++++++++++++++
src/wallet/api/wallet.h | 18 ++++
src/wallet/api/wallet2_api.h | 12 +++
src/wallet/api/wallet_manager.cpp | 12 ++-
12 files changed, 365 insertions(+), 25 deletions(-)
create mode 100644 src/device/device_io_dummy.cpp
create mode 100644 src/device/device_io_dummy.hpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c73b813d8..5c0f31cb8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -692,8 +692,12 @@ include_directories(${LMDB_INCLUDE})
include_directories(${LIBUNWIND_INCLUDE})
link_directories(${LIBUNWIND_LIBRARY_DIRS})
+if (HIDAPI_DUMMY)
+ add_definitions(-DHIDAPI_DUMMY)
+endif()
+
# Final setup for hid
-if (HIDAPI_FOUND)
+if (HIDAPI_FOUND)
message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
add_definitions(-DHAVE_HIDAPI)
include_directories(${HIDAPI_INCLUDE_DIR})
diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt
index e4f1159b5..14d398f87 100644
--- a/src/device/CMakeLists.txt
+++ b/src/device/CMakeLists.txt
@@ -29,10 +29,11 @@
set(device_sources
device.cpp
device_default.cpp
+ device_io_dummy.cpp
log.cpp
)
-if(HIDAPI_FOUND)
+if(HIDAPI_FOUND OR HIDAPI_DUMMY)
set(device_sources
${device_sources}
device_ledger.cpp
@@ -45,10 +46,11 @@ set(device_headers
device_io.hpp
device_default.hpp
device_cold.hpp
+ device_io_dummy.hpp
log.hpp
)
-if(HIDAPI_FOUND)
+if(HIDAPI_FOUND OR HIDAPI_DUMMY)
set(device_headers
${device_headers}
device_ledger.hpp
diff --git a/src/device/device.cpp b/src/device/device.cpp
index e6cd358b6..dd0701e0c 100644
--- a/src/device/device.cpp
+++ b/src/device/device.cpp
@@ -29,7 +29,7 @@
#include "device.hpp"
#include "device_default.hpp"
-#ifdef WITH_DEVICE_LEDGER
+#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
#include "device_ledger.hpp"
#endif
#include "misc_log_ex.h"
@@ -57,7 +57,7 @@ namespace hw {
device_registry::device_registry(){
hw::core::register_all(registry);
- #ifdef WITH_DEVICE_LEDGER
+ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
hw::ledger::register_all(registry);
#endif
atexit(clear_device_registry);
@@ -83,11 +83,13 @@ namespace hw {
auto device = registry.find(device_descriptor_lookup);
if (device == registry.end()) {
- MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: ");
+ std::stringstream ss("Device not found in registry: '" + device_descriptor + "'. Known devices: ");
+ MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: \n");
for( const auto& sm_pair : registry ) {
+ ss << "\n- " + sm_pair.first;
MERROR(" - " << sm_pair.first);
}
- throw std::runtime_error("device not found: " + device_descriptor);
+ throw std::runtime_error("device not found: " + device_descriptor + "\n" + ss.str());
}
return *device->second;
}
diff --git a/src/device/device.hpp b/src/device/device.hpp
index 392703a24..ffd419779 100644
--- a/src/device/device.hpp
+++ b/src/device/device.hpp
@@ -34,17 +34,7 @@
#include "ringct/rctTypes.h"
#include "cryptonote_config.h"
-
-#ifndef USE_DEVICE_LEDGER
-#define USE_DEVICE_LEDGER 1
-#endif
-
-#if !defined(HAVE_HIDAPI)
-#undef USE_DEVICE_LEDGER
-#define USE_DEVICE_LEDGER 0
-#endif
-
-#if USE_DEVICE_LEDGER
+#if defined(HAVE_HIDAPI) || defined(HIDAPI_DUMMY)
#define WITH_DEVICE_LEDGER
#endif
diff --git a/src/device/device_io_dummy.cpp b/src/device/device_io_dummy.cpp
new file mode 100644
index 000000000..edb4beea3
--- /dev/null
+++ b/src/device/device_io_dummy.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2017-2022, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+// device_io_dummy
+// Main goal of device_io_dummy is to emulate a hw::io::device_io without the need to actually
+// connect a device.
+// Many operating systems do not support giving raw USB access to a process (android), or don't
+// support that at all (hi iOS), therefore other means of connection can be used, either USB
+// abstraction provided by the OS (monerujo), or BLE (also monerujo).
+// Monerujo implementation is written in Java, which makes it a nice fit for iOS, but makes the
+// code extremely unportable, so for this reason the code in here is written in CPP.
+// Data transport is made available in wallet2_api.h, so wallet developers can easily plug their
+// own USB/BLE/other transport layer.
+
+#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+#include <boost/scope_exit.hpp>
+#include "log.hpp"
+#include "device_io_dummy.hpp"
+#include "device_ledger.hpp"
+
+
+bool hw::io::device_io_dummy::stateIsConnected = false;
+unsigned char* hw::io::device_io_dummy::sendToDevice = {};
+size_t hw::io::device_io_dummy::sendToDeviceLength = 0;
+unsigned char* hw::io::device_io_dummy::receivedFromDevice = {};
+size_t hw::io::device_io_dummy::receivedFromDeviceLength = 0;
+bool hw::io::device_io_dummy::waitsForDeviceSend = false;
+bool hw::io::device_io_dummy::waitsForDeviceReceive = false;
+
+namespace hw {
+ namespace io {
+
+#undef MONERO_DEFAULT_LOG_CATEGORY
+#define MONERO_DEFAULT_LOG_CATEGORY "device.io_dummy"
+ device_io_dummy::device_io_dummy(int a, int b, int c, int d) {
+ MDEBUG("device_io_dummy(a: " << a << ", b: " << b << ", c: " << c << ", d: " << d <<")");
+ }
+
+ void device_io_dummy::init() {
+ MDEBUG("init()");
+ }
+
+ void device_io_dummy::connect(void *params) {
+ MDEBUG("connect(" << params << ")");
+ stateIsConnected = true;
+ }
+
+ void device_io_dummy::connect(const std::vector<hw::io::hid_conn_params>& known_devices) {
+ MDEBUG("connect([");
+ for (const auto &item: known_devices) {
+ MDEBUG("{ interface_number: " << item.interface_number);
+ MDEBUG(" pid : " << item.pid);
+ MDEBUG(" usage_page : " << item.usage_page);
+ MDEBUG(" vid : " << item.vid << " },");
+ }
+ MDEBUG("])");
+ stateIsConnected = true;
+ }
+
+ bool device_io_dummy::connected() const {
+ MDEBUG("connected()");
+ return stateIsConnected;
+ }
+
+ int device_io_dummy::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) {
+ MDEBUG("exchange(): locking mutex");
+ boost::unique_lock<boost::mutex> lock(mutex);
+ sendToDevice = command;
+ sendToDeviceLength = cmd_len;
+ waitsForDeviceSend = true;
+ waitsForDeviceReceive = true;
+ MDEBUG("exchange(): waitsForDeviceSend");
+ // NOTE: waitsForDeviceSend should be changed by external code
+ while (waitsForDeviceSend) {
+ usleep(1000);
+ MDEBUG("exchange(): waitsForDeviceSend (still)");
+ }
+
+ MDEBUG("exchange(): waitsForDeviceReceive");
+ while (waitsForDeviceReceive) {
+ usleep(1000);
+ MDEBUG("exchange(): waitsForDeviceReceive (still)");
+ }
+
+ if (receivedFromDeviceLength > max_resp_len) {
+ MDEBUG("exchange(): receivedFromDeviceLength ("<<receivedFromDeviceLength<<") is larger than max_resp_len ("<<max_resp_len<<")");
+ return 1;
+ }
+
+ memset(response,0,max_resp_len);
+ memcpy(response, receivedFromDevice, receivedFromDeviceLength);
+ return receivedFromDeviceLength;
+ }
+
+ void device_io_dummy::disconnect() {
+ MDEBUG("disconnect()");
+ }
+
+ void device_io_dummy::release() {
+ MDEBUG("release()");
+ }
+
+
+
+ }
+}
+#endif // HAVE_HIDAPI
\ No newline at end of file
diff --git a/src/device/device_io_dummy.hpp b/src/device/device_io_dummy.hpp
new file mode 100644
index 000000000..a1733616d
--- /dev/null
+++ b/src/device/device_io_dummy.hpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2017-2022, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+#ifdef HIDAPI_DUMMY
+
+#pragma once
+
+#include "device_io.hpp"
+#include "device_io_hid.hpp"
+
+namespace hw {
+ namespace io {
+ struct hid_conn_params {
+ unsigned int vid;
+ unsigned int pid;
+ int interface_number;
+ unsigned short usage_page;
+ };
+ class device_io_dummy : device_io {
+ private:
+ boost::mutex mutex;
+
+ public:
+ static bool stateIsConnected;
+ static unsigned char* sendToDevice;
+ static size_t sendToDeviceLength;
+ static unsigned char* receivedFromDevice;
+ static size_t receivedFromDeviceLength;
+ static bool waitsForDeviceSend;
+ static bool waitsForDeviceReceive;
+
+ device_io_dummy() = default;
+ device_io_dummy(int a, int b, int c, int d);
+ ~device_io_dummy() = default;
+
+ void init();
+ void release();
+
+ void connect(void *parms);
+ void connect(const std::vector<hw::io::hid_conn_params>& known_devices);
+ void disconnect();
+ bool connected() const;
+
+ int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input);
+ };
+ };
+};
+
+#endif // HAVE_HIDAPI
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index bb5b6f497..046201a1e 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -41,7 +41,7 @@ namespace hw {
namespace ledger {
- #ifdef WITH_DEVICE_LEDGER
+ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
namespace {
bool apdu_verbose =true;
@@ -300,7 +300,7 @@ namespace hw {
device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 2000) {
this->id = device_id++;
- this->reset_buffer();
+ this->reset_buffer();
this->mode = NONE;
this->has_view_key = false;
this->tx_in_progress = false;
@@ -533,7 +533,9 @@ namespace hw {
bool device_ledger::connect(void) {
this->disconnect();
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
hw_device.connect(known_devices);
+ #endif
this->reset();
#ifdef DEBUG_HWDEVICE
cryptonote::account_public_address pubkey;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 03058c4f1..39454ca6d 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -35,6 +35,7 @@
#include "device.hpp"
#include "log.hpp"
#include "device_io_hid.hpp"
+#include "device_io_dummy.hpp"
#include <mutex>
namespace hw {
@@ -56,7 +57,7 @@ namespace hw {
void register_all(std::map<std::string, std::unique_ptr<device>> &registry);
- #ifdef WITH_DEVICE_LEDGER
+ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
// Origin: https://github.com/LedgerHQ/ledger-app-monero/blob/master/src/monero_types.h
#define SW_OK 0x9000
@@ -143,7 +144,11 @@ namespace hw {
mutable std::mutex command_locker;
//IO
+#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+ hw::io::device_io_dummy hw_device;
+#else
hw::io::device_io_hid hw_device;
+#endif
unsigned int length_send;
unsigned char buffer_send[BUFFER_SEND_SIZE];
unsigned int length_recv;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 3fcd6f332..25ade04a7 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -48,6 +48,9 @@
#include <boost/locale.hpp>
#include <boost/filesystem.hpp>
#include "bc-ur/src/bc-ur.hpp"
+#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+#include "device/device_io_dummy.hpp"
+#endif
using namespace std;
using namespace cryptonote;
@@ -3186,6 +3189,97 @@ uint64_t WalletImpl::getBytesSent()
return m_wallet->get_bytes_sent();
}
+
+// HIDAPI_DUMMY
+bool WalletImpl::getStateIsConnected() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::stateIsConnected;
+ #endif
+}
+
+unsigned char* WalletImpl::getSendToDevice() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return {};
+ #else
+ return hw::io::device_io_dummy::sendToDevice;
+ #endif
+}
+
+size_t WalletImpl::getSendToDeviceLength() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return -1;
+ #else
+ return hw::io::device_io_dummy::sendToDeviceLength;
+ #endif
+}
+
+unsigned char* WalletImpl::getReceivedFromDevice() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return {};
+ #else
+ return hw::io::device_io_dummy::receivedFromDevice;
+ #endif
+}
+
+size_t WalletImpl::getReceivedFromDeviceLength() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return -1;
+ #else
+ return hw::io::device_io_dummy::receivedFromDeviceLength;
+ #endif
+}
+
+bool WalletImpl::getWaitsForDeviceSend() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::receivedFromDeviceLength;
+ #endif
+}
+
+bool WalletImpl::getWaitsForDeviceReceive() {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::waitsForDeviceReceive;
+ #endif
+}
+
+void WalletImpl::setDeviceReceivedData(unsigned char* data, size_t len) {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return;
+ #else
+ hw::io::device_io_dummy::receivedFromDevice = static_cast<unsigned char *>(malloc(len));
+ hw::io::device_io_dummy::receivedFromDeviceLength = len;
+ memset(hw::io::device_io_dummy::receivedFromDevice, 0, len);
+ memcpy(hw::io::device_io_dummy::receivedFromDevice, data, len);
+ hw::io::device_io_dummy::waitsForDeviceReceive = false;
+ #endif
+}
+
+void WalletImpl::setDeviceSendData(unsigned char* data, size_t len) {
+ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return;
+ #else
+ hw::io::device_io_dummy::sendToDevice = static_cast<unsigned char *>(malloc(len));
+ hw::io::device_io_dummy::sendToDeviceLength = len;
+ memset(hw::io::device_io_dummy::sendToDevice, 0, len);
+ memcpy(hw::io::device_io_dummy::sendToDevice, data, len);
+ hw::io::device_io_dummy::waitsForDeviceSend = false;
+ #endif
+}
+
YieldInfo * WalletImpl::getYieldInfo()
{
auto yi = new YieldInfoImpl(*this);
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index edf8bb8ce..4e9c21ecb 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -301,6 +301,24 @@ private:
// cache connection status to avoid unnecessary RPC calls
mutable std::atomic<bool> m_is_connected;
boost::optional<epee::net_utils::http::login> m_daemon_login{};
+
+ bool getStateIsConnected();
+
+ unsigned char *getSendToDevice();
+
+ size_t getSendToDeviceLength();
+
+ unsigned char *getReceivedFromDevice();
+
+ size_t getReceivedFromDeviceLength();
+
+ bool getWaitsForDeviceSend();
+
+ bool getWaitsForDeviceReceive();
+
+ void setDeviceReceivedData(unsigned char *data, size_t len);
+
+ void setDeviceSendData(unsigned char *data, size_t len);
};
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 764adbfbf..53ec4abfc 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -1150,6 +1150,18 @@ struct Wallet
//! get bytes sent
virtual uint64_t getBytesSent() = 0;
+
+ // HIDAPI_DUMMY
+ virtual bool getStateIsConnected() = 0;
+ virtual unsigned char* getSendToDevice() = 0;
+ virtual size_t getSendToDeviceLength() = 0;
+ virtual unsigned char* getReceivedFromDevice() = 0;
+ virtual size_t getReceivedFromDeviceLength() = 0;
+ virtual bool getWaitsForDeviceSend() = 0;
+ virtual bool getWaitsForDeviceReceive() = 0;
+
+ virtual void setDeviceReceivedData(unsigned char* data, size_t len) = 0;
+ virtual void setDeviceSendData(unsigned char* data, size_t len) = 0;
//! get yield information
virtual YieldInfo * getYieldInfo() = 0;
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index e81b8f83a..277be6ac9 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -188,10 +188,14 @@ bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name,
bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
{
- hw::device::device_type type;
- bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
- device_type = static_cast<Wallet::Device>(type);
- return r;
+ try {
+ hw::device::device_type type;
+ bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
+ device_type = static_cast<Wallet::Device>(type);
+ return r;
+ } catch (...) {
+ return false;
+ }
}
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
--
2.48.1
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,68 @@
From 0ba0339b11d8f7f66f2d5cd27075d438a76351b4 Mon Sep 17 00:00:00 2001
From: M <m@cakewallet.com>
Date: Fri, 21 Apr 2023 15:43:47 -0400
Subject: [PATCH 09/14] Add hex encoding and tx key getter for
PendingTransction in wallet api.
---
src/wallet/api/pending_transaction.cpp | 16 ++++++++++++++++
src/wallet/api/pending_transaction.h | 2 ++
src/wallet/api/wallet2_api.h | 2 ++
3 files changed, 20 insertions(+)
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index 9c3c26ee5..1f714d229 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -80,6 +80,22 @@ std::vector<std::string> PendingTransactionImpl::txid() const
return txid;
}
+std::vector<std::string> PendingTransactionImpl::hex() const
+{
+ std::vector<std::string> hexs;
+ for (const auto &pt: m_pending_tx)
+ hexs.push_back(epee::string_tools::buff_to_hex_nodelimer(cryptonote::tx_to_blob(pt.tx)));
+ return hexs;
+}
+
+std::vector<std::string> PendingTransactionImpl::txKey() const
+{
+ std::vector<std::string> keys;
+ for (const auto& pt: m_pending_tx)
+ keys.push_back(epee::string_tools::pod_to_hex(pt.tx_key));
+ return keys;
+}
+
bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
{
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
index 403bfe281..0cc6c58e9 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
@@ -59,6 +59,8 @@ public:
std::string multisigSignData() override;
void signMultisigTx() override;
std::vector<std::string> signersKeys() const override;
+ std::vector<std::string> hex() const override;
+ std::vector<std::string> txKey() const override;
private:
friend class WalletImpl;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 013b5bcba..f421fdc05 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -127,6 +127,8 @@ struct PendingTransaction
* @return vector of base58-encoded signers' public keys
*/
virtual std::vector<std::string> signersKeys() const = 0;
+ virtual std::vector<std::string> hex() const = 0;
+ virtual std::vector<std::string> txKey() const = 0;
};
/**
--
2.48.1
@@ -0,0 +1,153 @@
From cb02355313d504e6a44f8f70b8eb2be64167ffd4 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Wed, 11 Oct 2023 16:47:59 +0200
Subject: [PATCH 10/14] Add recoverDeterministicWalletFromSpendKey
This function is used by Cake Wallet to enable polyseed (dart implementation)
support.
Sourced from the following commit:
https://github.com/cake-tech/monero/commit/cb6fb5ab218878702ed151c0e3d5d68eb2732788
Co-authored-by: Godwin Asuquo <godilite@gmail.com>
---
src/wallet/api/wallet.cpp | 29 +++++++++++++++++++++++++++++
src/wallet/api/wallet.h | 4 ++++
src/wallet/api/wallet2_api.h | 19 +++++++++++++++++++
src/wallet/api/wallet_manager.cpp | 16 ++++++++++++++++
src/wallet/api/wallet_manager.h | 7 +++++++
5 files changed, 75 insertions(+)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 933cc2531..d8fe108b4 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -824,6 +824,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
return status() == Status_Ok;
}
+bool WalletImpl::recoverDeterministicWalletFromSpendKey(const std::string &path, const std::string &password, const std::string &language, const std::string &spendkey_string)
+{
+ clearStatus();
+ m_errorString.clear();
+
+ m_recoveringFromSeed = true;
+ m_recoveringFromDevice = false;
+
+ // parse spend key
+ crypto::secret_key spendkey;
+ if (!spendkey_string.empty()) {
+ cryptonote::blobdata spendkey_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
+ {
+ setStatusError(tr("failed to parse secret spend key"));
+ return false;
+ }
+ spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
+ }
+
+ try {
+ m_wallet->generate(path, password, spendkey, true, false);
+ setSeedLanguage(language);
+ } catch (const std::exception &e) {
+ setStatusCritical(e.what());
+ }
+ return status() == Status_Ok;
+}
+
bool WalletImpl::close(bool store)
{
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index a82f270e4..9e1fbb40b 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -77,6 +77,10 @@ public:
const std::string &address_string,
const std::string &viewkey_string,
const std::string &spendkey_string = "");
+ bool recoverDeterministicWalletFromSpendKey(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ const std::string &spendkey_string);
bool recoverFromDevice(const std::string &path,
const std::string &password,
const std::string &device_name);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index f421fdc05..c8d6bb179 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -1323,6 +1323,25 @@ struct WalletManager
return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
}
+ /*!
+ * \brief recover deterministic wallet from spend key.
+ * \param path Name of wallet file to be created
+ * \param password Password of wallet file
+ * \param language language
+ * \param nettype Network type
+ * \param restoreHeight restore from start height
+ * \param spendKeyString spend key
+ * \param kdf_rounds Number of rounds for key derivation function
+ * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
+ */
+ virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ NetworkType nettype,
+ uint64_t restoreHeight,
+ const std::string &spendKeyString,
+ uint64_t kdf_rounds = 1) = 0;
+
/*!
* \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index da2056d8a..c200f52ae 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -127,6 +127,22 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
return wallet;
}
+Wallet *WalletManagerImpl::createDeterministicWalletFromSpendKey(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ NetworkType nettype,
+ uint64_t restoreHeight,
+ const std::string &spendkey_string,
+ uint64_t kdf_rounds)
+{
+ WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
+ if(restoreHeight > 0){
+ wallet->setRefreshFromBlockHeight(restoreHeight);
+ }
+ wallet->recoverDeterministicWalletFromSpendKey(path, password, language, spendkey_string);
+ return wallet;
+}
+
Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
const std::string &password,
NetworkType nettype,
diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
index 28fcd36c9..be3ff8184 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -67,6 +67,13 @@ public:
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "") override;
+ virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
+ const std::string &password,
+ const std::string &language,
+ NetworkType nettype,
+ uint64_t restoreHeight,
+ const std::string &spendkey_string,
+ uint64_t kdf_rounds) override;
virtual Wallet * createWalletFromDevice(const std::string &path,
const std::string &password,
NetworkType nettype,
--
2.48.1
@@ -0,0 +1,65 @@
From 846d3f60093add6653d9102d841288066fc08311 Mon Sep 17 00:00:00 2001
From: cyan <cyjan@mrcyjanek.net>
Date: Thu, 7 Nov 2024 16:46:24 +0000
Subject: [PATCH 11/14] add monero submodule support
---
CMakeLists.txt | 6 +++---
cmake/CheckLinkerFlag.cmake | 2 +-
src/wallet/wallet_rpc_server.cpp | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f0630ef9b..9406e57b4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -226,9 +226,9 @@ function(forbid_undefined_symbols)
cmake_minimum_required(VERSION 3.5)
project(test)
option(EXPECT_SUCCESS "" ON)
-file(WRITE "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
+file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
if (EXPECT_SUCCESS)
- file(APPEND "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
+ file(APPEND "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
endif()
add_library(l0 SHARED incorrect_source.cpp)
add_library(l1 MODULE incorrect_source.cpp)
@@ -390,7 +390,7 @@ else()
endif()
list(INSERT CMAKE_MODULE_PATH 0
- "${CMAKE_SOURCE_DIR}/cmake")
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
if (NOT DEFINED ENV{DEVELOPER_LOCAL_TOOLS})
message(STATUS "Could not find DEVELOPER_LOCAL_TOOLS in env (not required)")
diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake
index 7ecf5f610..89fb9d167 100644
--- a/cmake/CheckLinkerFlag.cmake
+++ b/cmake/CheckLinkerFlag.cmake
@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
message(STATUS "Looking for ${flag} linker flag")
endif()
- set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
+ set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "${flag}")
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 3188c88db..9fbdb3c05 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -1286,7 +1286,7 @@ namespace tools
{
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(req.priority);
- std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, type, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, req.subtract_fee_from_outputs);
+ std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, req.source_asset, req.dest_asset, type, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices, {}, req.subtract_fee_from_outputs);
if (ptx_vector.empty())
{
--
2.48.1
@@ -0,0 +1,104 @@
From 53cc0482e55a39b5dbf2261fea11fcb160778800 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Thu, 21 Nov 2024 06:05:03 -0500
Subject: [PATCH 12/14] fix iOS depends build
---
CMakeLists.txt | 4 ----
src/checkpoints/CMakeLists.txt | 6 +++++-
src/cryptonote_basic/CMakeLists.txt | 6 +++++-
src/cryptonote_basic/miner.cpp | 8 ++++----
4 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9406e57b4..1eac121db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,10 +39,6 @@ include(CheckLibraryExists)
endif()
include(FindPythonInterp)
-if (IOS)
- INCLUDE(CmakeLists_IOS.txt)
-endif()
-
project(salvium)
option (USE_CCACHE "Use ccache if a usable instance is found" ON)
diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt
index 665441f62..841df3256 100644
--- a/src/checkpoints/CMakeLists.txt
+++ b/src/checkpoints/CMakeLists.txt
@@ -28,7 +28,11 @@
if(APPLE)
if(DEPENDS)
- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
+ else()
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ endif()
else()
find_library(IOKIT_LIBRARY IOKit)
mark_as_advanced(IOKIT_LIBRARY)
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
index 414936a05..81c81767f 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -28,7 +28,11 @@
if(APPLE)
if(DEPENDS)
- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
+ else()
+ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
+ endif()
else()
find_library(IOKIT_LIBRARY IOKit)
mark_as_advanced(IOKIT_LIBRARY)
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 71b8f78cc..0f53f024e 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -45,7 +45,7 @@
#include "boost/logic/tribool.hpp"
#include <boost/filesystem.hpp>
-#ifdef __APPLE__
+#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
#include <sys/times.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/ps/IOPSKeys.h>
@@ -883,7 +883,7 @@ namespace cryptonote
return true;
- #elif defined(__APPLE__)
+ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
mach_msg_type_number_t count;
kern_return_t status;
@@ -949,7 +949,7 @@ namespace cryptonote
return true;
}
- #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__)
+ #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || (defined(__APPLE__) && !defined(TARGET_OS_IPHONE)) || defined(__FreeBSD__)
struct tms tms;
if ( times(&tms) != (clock_t)-1 )
@@ -978,7 +978,7 @@ namespace cryptonote
return boost::logic::tribool(power_status.ACLineStatus != 1);
}
- #elif defined(__APPLE__)
+ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
#if TARGET_OS_MAC && (!defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7)
return boost::logic::tribool(IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited);
--
2.48.1
@@ -0,0 +1,27 @@
From 1eacd30724559749be5adeb31d763f44c3f221f9 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 18 Nov 2024 10:57:37 -0500
Subject: [PATCH 13/14] include locale only when targeting WIN32
---
src/wallet/api/wallet.cpp | 2 ++
1 files changed, 2 insertions(+), 0 deletion(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index d8fe108b4..e3e838b13 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -46,7 +46,9 @@
#include <sstream>
#include <unordered_map>
+#ifdef WIN32
#include <boost/locale.hpp>
+#endif
#include <boost/filesystem.hpp>
#include "bc-ur/src/bc-ur.hpp"
#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
--
2.48.1
@@ -0,0 +1,25 @@
From 2d31234e859bff817d30d91b21d9412375668aae Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Wed, 29 Jan 2025 16:13:28 +0100
Subject: [PATCH 14/14] change earliest fork height message
---
src/wallet/wallet2.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 8720e18b1..69da11d9c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -12365,7 +12365,7 @@ bool wallet2::use_fork_rules(uint8_t version, int64_t early_blocks)
boost::optional<std::string> result = m_node_rpc_proxy.get_height(height);
THROW_WALLET_EXCEPTION_IF(result, error::wallet_internal_error, "Failed to get height");
result = m_node_rpc_proxy.get_earliest_height(version, earliest_height);
- THROW_WALLET_EXCEPTION_IF(result, error::wallet_internal_error, "Failed to get earliest fork height");
+ THROW_WALLET_EXCEPTION_IF(result, error::wallet_internal_error, "Failed to get earliest fork height. Please check your connection and/or switch node you are connected to currently.");
bool close_enough = (int64_t)height >= (int64_t)earliest_height - early_blocks && earliest_height != std::numeric_limits<uint64_t>::max(); // start using the rules that many blocks beforehand
if (close_enough)
--
2.48.1
@@ -0,0 +1,24 @@
From 71cf45cfbd571ec58e8b2a1d408ff74804bf7e1d Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Thu, 20 Feb 2025 08:36:28 +0100
Subject: [PATCH] remove trivially_copyable assert
---
contrib/epee/include/span.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h
index 01dc387d6..2ad733a2f 100644
--- a/contrib/epee/include/span.h
+++ b/contrib/epee/include/span.h
@@ -162,7 +162,6 @@ namespace epee
{
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
- static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
static_assert(alignof(T) == 1, "type may have padding");
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
}
--
2.48.1
Submodule
+1
Submodule salvium added at 1f49c178ee
+179
View File
@@ -0,0 +1,179 @@
cmake_minimum_required(VERSION 3.5)
project(wallet2_api_c)
message(STATUS ABI_INFO = ${HOST_ABI})
set(MD_LIBRARY "")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-lto")
if(${HOST_ABI} STREQUAL "x86_64-w64-mingw32")
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_LINKER "x86_64-w64-mingw32-ld")
set(TARGET "x86_64-w64-mingw32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lssp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lssp")
elseif(${HOST_ABI} STREQUAL "i686-w64-mingw32")
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_LINKER "i686-w64-mingw32-ld")
set(TARGET "i686-w64-mingw32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -lssp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lssp")
elseif(${HOST_ABI} STREQUAL "host-apple-ios" OR
${HOST_ABI} STREQUAL "aarch64-apple-ios")
set(CMAKE_SYSTEM_NAME iOS)
elseif(${HOST_ABI} STREQUAL "host-apple-darwin" OR
${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" OR
${HOST_ABI} STREQUAL "aarch64-host-apple-darwin")
set(CMAKE_SYSTEM_NAME Darwin)
endif()
if (${HOST_ABI} STREQUAL "host-apple-darwin" OR
${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" OR
${HOST_ABI} STREQUAL "aarch64-host-apple-darwin")
EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE ARCHITECTURE )
if (NOT ${ARCHITECTURE} STREQUAL arm64)
set(CMAKE_OSX_ARCHITECTURES x86_64)
endif()
endif()
if(${HOST_ABI} STREQUAL "x86_64-linux-android" OR
${HOST_ABI} STREQUAL "i686-linux-android" OR
${HOST_ABI} STREQUAL "aarch64-linux-android" OR
${HOST_ABI} STREQUAL "armv7a-linux-androideabi")
add_link_options(-stdlib=libc++ -static-libstdc++)
set(EXTRA_LIBS_ANDROID log)
endif()
add_library( wallet2_api_c
SHARED
src/main/cpp/helpers.cpp
src/main/cpp/wallet2_api_c.cpp )
if(${HOST_ABI} STREQUAL "x86_64-linux-android" OR
${HOST_ABI} STREQUAL "i686-linux-android" OR
${HOST_ABI} STREQUAL "aarch64-linux-android" OR
${HOST_ABI} STREQUAL "armv7a-linux-androideabi")
set_target_properties(wallet2_api_c PROPERTIES LINK_FLAGS "-Wl,-z,noexecstack")
endif()
if(${HOST_ABI} STREQUAL "x86_64-linux-gnu" OR
${HOST_ABI} STREQUAL "i686-linux-gnu" OR
${HOST_ABI} STREQUAL "aarch64-linux-gnu" OR
${HOST_ABI} STREQUAL "armv7a-linux-gnu")
set_target_properties(wallet2_api_c PROPERTIES LINK_FLAGS "-Wl,-z,noexecstack")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set(MONERO_DIR ${CMAKE_SOURCE_DIR}/../${MONERO_FLAVOR})
set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../contrib/depends/${HOST_ABI})
if (${HOST_ABI} STREQUAL "x86_64-apple-darwin11" OR ${HOST_ABI} STREQUAL "aarch64-apple-darwin11")
set(EXTRA_LIBS_APPLE "-framework IOKit" "-framework CoreFoundation" "-framework Cocoa" hidapi)
# set_target_properties(wallet2_api_c PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks")
elseif(${HOST_ABI} STREQUAL "host-apple-darwin" OR
${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" OR
${HOST_ABI} STREQUAL "aarch64-host-apple-darwin")
set(EXTRA_LIBS_APPLE "-framework IOKit" "-framework CoreFoundation" "-framework Cocoa" apple_nghttp2)
elseif(${HOST_ABI} STREQUAL "host-apple-ios" OR ${HOST_ABI} STREQUAL "aarch64-apple-ios" OR ${HOST_ABI} STREQUAL "arm64-apple-ios" OR ${HOST_ABI} STREQUAL "arm64-apple-iossimulator" OR ${HOST_ABI} STREQUAL "x86_64-apple-iossimulator")
set(EXTRA_LIBS_APPLE "-framework IOKit" "-framework CoreFoundation" iconv )
endif()
if(${HOST_ABI} STREQUAL "x86_64-w64-mingw32" OR ${HOST_ABI} STREQUAL "i686-w64-mingw32")
target_link_options(wallet2_api_c PRIVATE -static-libgcc -static-libstdc++)
endif()
if(${HOST_ABI} STREQUAL "x86_64-apple-darwin11" OR ${HOST_ABI} STREQUAL "aarch64-apple-darwin11" OR ${HOST_ABI} STREQUAL "host-apple-darwin" OR ${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" OR ${HOST_ABI} STREQUAL "aarch64-host-apple-darwin" OR ${HOST_ABI} STREQUAL "host-apple-ios" OR ${HOST_ABI} STREQUAL "aarch64-apple-ios" OR ${HOST_ABI} STREQUAL "arm64-apple-iossimulator" OR ${HOST_ABI} STREQUAL "x86_64-apple-iossimulator")
set_target_properties(wallet2_api_c PROPERTIES SUFFIX ".dylib")
set_target_properties(wallet2_api_c PROPERTIES NO_SONAME 1)
endif()
if (${MONERO_FLAVOR} STREQUAL "monero")
target_compile_definitions(wallet2_api_c PRIVATE FLAVOR_MONERO)
set(BCUR_ENABLED bc-ur)
elseif(${MONERO_FLAVOR} STREQUAL "wownero")
target_compile_definitions(wallet2_api_c PRIVATE FLAVOR_WOWNERO)
elseif(${MONERO_FLAVOR} STREQUAL "zano")
target_compile_definitions(wallet2_api_c PRIVATE FLAVOR_ZANO)
elseif(${MONERO_FLAVOR} STREQUAL "salvium")
target_compile_definitions(wallet2_api_c PRIVATE FLAVOR_SALVIUM)
set(BCUR_ENABLED bc-ur)
endif()
if(NOT ${HOST_ABI} STREQUAL "x86_64-apple-darwin11" AND NOT ${HOST_ABI} STREQUAL "aarch64-apple-darwin11" AND NOT ${HOST_ABI} STREQUAL "aarch64-apple-darwin" AND NOT ${HOST_ABI} STREQUAL "x86_64-apple-darwin" AND NOT ${HOST_ABI} STREQUAL "host-apple-darwin" AND NOT ${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" AND NOT ${HOST_ABI} STREQUAL "aarch64-host-apple-darwin" AND NOT ${HOST_ABI} STREQUAL "host-apple-ios" AND NOT ${HOST_ABI} STREQUAL "aarch64-apple-ios" AND NOT ${HOST_ABI} STREQUAL "aarch64-apple-iossimulator" AND NOT ${HOST_ABI} STREQUAL "x86_64-apple-iossimulator")
set_target_properties(wallet2_api_c PROPERTIES LINK_FLAGS "-Wl,--exclude-libs,ALL")
endif()
if (${MONERO_FLAVOR} STREQUAL "zano")
include_directories(
${CMAKE_SOURCE_DIR}/build/${HOST_ABI}/zano_build/contrib/zlib
)
endif()
add_subdirectory("${CMAKE_SOURCE_DIR}/../${MONERO_FLAVOR}" ${CMAKE_BINARY_DIR}/${MONERO_FLAVOR}_build EXCLUDE_FROM_ALL)
if(${HOST_ABI} STREQUAL "x86_64-apple-darwin11" OR ${HOST_ABI} STREQUAL "aarch64-apple-darwin11" OR ${HOST_ABI} STREQUAL "x86_64-apple-darwin" OR ${HOST_ABI} STREQUAL "aarch64-apple-darwin" OR ${HOST_ABI} STREQUAL "host-apple-darwin" OR ${HOST_ABI} STREQUAL "x86_64-host-apple-darwin" OR ${HOST_ABI} STREQUAL "aarch64-host-apple-darwin" OR ${HOST_ABI} STREQUAL "host-apple-ios" OR ${HOST_ABI} STREQUAL "aarch64-apple-ios" OR ${HOST_ABI} STREQUAL "aarch64-apple-iossimulator" OR ${HOST_ABI} STREQUAL "x86_64-apple-iossimulator")
if (${MONERO_FLAVOR} STREQUAL "monero")
set(EXPORTED_SYMBOLS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/monero_libwallet2_api_c.exp)
elseif(${MONERO_FLAVOR} STREQUAL "wownero")
set(EXPORTED_SYMBOLS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/wownero_libwallet2_api_c.exp)
elseif(${MONERO_FLAVOR} STREQUAL "zano")
set(EXPORTED_SYMBOLS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/zano_libwallet2_api_c.exp)
elseif(${MONERO_FLAVOR} STREQUAL "salvium")
set(EXPORTED_SYMBOLS_FILE ${CMAKE_CURRENT_SOURCE_DIR}/salvium_libwallet2_api_c.exp)
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${EXPORTED_SYMBOLS_FILE}")
set_target_properties(${TARGET} PROPERTIES LINK_DEPENDS ${EXPORTED_SYMBOLS_FILE})
endif()
if (${MONERO_FLAVOR} STREQUAL "monero")
set(WALLET_TARGETS wallet_api ${wallet_api_LIB_DEPENDS}) # wallet_api_LIB_DEPENDS
elseif(${MONERO_FLAVOR} STREQUAL "wownero")
set(WALLET_TARGETS wallet_api ${wallet_api_LIB_DEPENDS}) # wallet_api_LIB_DEPENDS
elseif(${MONERO_FLAVOR} STREQUAL "zano")
find_package(Boost 1.71 REQUIRED COMPONENTS system filesystem thread timer date_time chrono regex serialization atomic program_options)
find_package(OpenSSL REQUIRED)
set(WALLET_TARGETS
wallet
general
tor-connect
crypto
currency_core
common
zlibstatic
${Boost_LIBRARIES}
${OpenSSL_LIBRARIES})
elseif(${MONERO_FLAVOR} STREQUAL "salvium")
set(WALLET_TARGETS wallet_api ${wallet_api_LIB_DEPENDS}) # wallet_api_LIB_DEPENDS
endif()
if(${MONERO_FLAVOR} STREQUAL "wownero")
add_subdirectory(wownero-seed EXCLUDE_FROM_ALL)
set(EXTRA_LIBS_WOWNEROSEED wownero-seed)
endif()
#get_cmake_property(_variableNames VARIABLES)
#list (SORT _variableNames)
#foreach (_variableName ${_variableNames})
# message(STATUS "${_variableName}=${${_variableName}}")
#endforeach()
#message(SEND_ERROR "${Boost_LIBRARIES}")
#message(SEND_ERROR "${WALLET_TARGETS}
# ${EXTRA_LIBS_WOWNEROSEED}
# ${EXTRA_LIBS_ANDROID}")
target_link_libraries( wallet2_api_c
${WALLET_TARGETS}
${EXTRA_LIBS_WOWNEROSEED}
${EXTRA_LIBS_ANDROID}
)
@@ -0,0 +1,308 @@
_SALVIUM_PendingTransaction_status
_SALVIUM_PendingTransaction_errorString
_SALVIUM_PendingTransaction_commit
_SALVIUM_PendingTransaction_commitUR
_SALVIUM_PendingTransaction_amount
_SALVIUM_PendingTransaction_dust
_SALVIUM_PendingTransaction_fee
_SALVIUM_PendingTransaction_txid
_SALVIUM_PendingTransaction_txCount
_SALVIUM_PendingTransaction_subaddrAccount
_SALVIUM_PendingTransaction_subaddrIndices
_SALVIUM_PendingTransaction_multisigSignData
_SALVIUM_PendingTransaction_signMultisigTx
_SALVIUM_PendingTransaction_signersKeys
_SALVIUM_PendingTransaction_hex
_SALVIUM_UnsignedTransaction_status
_SALVIUM_UnsignedTransaction_errorString
_SALVIUM_UnsignedTransaction_amount
_SALVIUM_UnsignedTransaction_fee
_SALVIUM_UnsignedTransaction_mixin
_SALVIUM_UnsignedTransaction_confirmationMessage
_SALVIUM_UnsignedTransaction_paymentId
_SALVIUM_UnsignedTransaction_recipientAddress
_SALVIUM_UnsignedTransaction_minMixinCount
_SALVIUM_UnsignedTransaction_txCount
_SALVIUM_UnsignedTransaction_sign
_SALVIUM_UnsignedTransaction_signUR
_SALVIUM_TransactionInfo_direction
_SALVIUM_TransactionInfo_isPending
_SALVIUM_TransactionInfo_isFailed
_SALVIUM_TransactionInfo_isCoinbase
_SALVIUM_TransactionInfo_amount
_SALVIUM_TransactionInfo_fee
_SALVIUM_TransactionInfo_blockHeight
_SALVIUM_TransactionInfo_description
_SALVIUM_TransactionInfo_subaddrIndex
_SALVIUM_TransactionInfo_subaddrAccount
_SALVIUM_TransactionInfo_label
_SALVIUM_TransactionInfo_confirmations
_SALVIUM_TransactionInfo_unlockTime
_SALVIUM_TransactionInfo_hash
_SALVIUM_TransactionInfo_timestamp
_SALVIUM_TransactionInfo_paymentId
_SALVIUM_TransactionInfo_transfers_count
_SALVIUM_TransactionInfo_transfers_amount
_SALVIUM_TransactionInfo_transfers_address
_SALVIUM_TransactionHistory_count
_SALVIUM_TransactionHistory_transaction
_SALVIUM_TransactionHistory_transactionById
_SALVIUM_TransactionHistory_refresh
_SALVIUM_TransactionHistory_setTxNote
_SALVIUM_AddressBookRow_extra
_SALVIUM_AddressBookRow_getAddress
_SALVIUM_AddressBookRow_getDescription
_SALVIUM_AddressBookRow_getPaymentId
_SALVIUM_AddressBookRow_getRowId
_SALVIUM_AddressBook_getAll_size
_SALVIUM_AddressBook_getAll_byIndex
_SALVIUM_AddressBook_addRow
_SALVIUM_AddressBook_deleteRow
_SALVIUM_AddressBook_setDescription
_SALVIUM_AddressBook_refresh
_SALVIUM_AddressBook_errorString
_SALVIUM_AddressBook_errorCode
_SALVIUM_AddressBook_lookupPaymentID
_SALVIUM_CoinsInfo_blockHeight
_SALVIUM_CoinsInfo_hash
_SALVIUM_CoinsInfo_internalOutputIndex
_SALVIUM_CoinsInfo_globalOutputIndex
_SALVIUM_CoinsInfo_spent
_SALVIUM_CoinsInfo_frozen
_SALVIUM_CoinsInfo_spentHeight
_SALVIUM_CoinsInfo_amount
_SALVIUM_CoinsInfo_rct
_SALVIUM_CoinsInfo_keyImageKnown
_SALVIUM_CoinsInfo_pkIndex
_SALVIUM_CoinsInfo_subaddrIndex
_SALVIUM_CoinsInfo_subaddrAccount
_SALVIUM_CoinsInfo_address
_SALVIUM_CoinsInfo_addressLabel
_SALVIUM_CoinsInfo_keyImage
_SALVIUM_CoinsInfo_unlockTime
_SALVIUM_CoinsInfo_unlocked
_SALVIUM_CoinsInfo_pubKey
_SALVIUM_CoinsInfo_coinbase
_SALVIUM_CoinsInfo_description
_SALVIUM_Coins_count
_SALVIUM_Coins_coin
_SALVIUM_Coins_getAll_size
_SALVIUM_Coins_getAll_byIndex
_SALVIUM_Coins_refresh
_SALVIUM_Coins_setFrozenByPublicKey
_SALVIUM_Coins_setFrozen
_SALVIUM_Coins_thaw
_SALVIUM_Coins_thawByPublicKey
_SALVIUM_Coins_isTransferUnlocked
_SALVIUM_Coins_setDescription
_SALVIUM_SubaddressRow_extra
_SALVIUM_SubaddressRow_getAddress
_SALVIUM_SubaddressRow_getLabel
_SALVIUM_SubaddressRow_getRowId
_SALVIUM_Subaddress_getAll_size
_SALVIUM_Subaddress_getAll_byIndex
_SALVIUM_Subaddress_addRow
_SALVIUM_Subaddress_setLabel
_SALVIUM_Subaddress_refresh
_SALVIUM_SubaddressAccountRow_extra
_SALVIUM_SubaddressAccountRow_getAddress
_SALVIUM_SubaddressAccountRow_getLabel
_SALVIUM_SubaddressAccountRow_getBalance
_SALVIUM_SubaddressAccountRow_getUnlockedBalance
_SALVIUM_SubaddressAccountRow_getRowId
_SALVIUM_SubaddressAccount_getAll_size
_SALVIUM_SubaddressAccount_getAll_byIndex
_SALVIUM_SubaddressAccount_addRow
_SALVIUM_SubaddressAccount_setLabel
_SALVIUM_SubaddressAccount_refresh
_SALVIUM_MultisigState_isMultisig
_SALVIUM_MultisigState_isReady
_SALVIUM_MultisigState_threshold
_SALVIUM_MultisigState_total
_SALVIUM_DeviceProgress_progress
_SALVIUM_DeviceProgress_indeterminate
_SALVIUM_Wallet_seed
_SALVIUM_Wallet_getSeedLanguage
_SALVIUM_Wallet_setSeedLanguage
_SALVIUM_Wallet_status
_SALVIUM_Wallet_errorString
_SALVIUM_Wallet_setPassword
_SALVIUM_Wallet_getPassword
_SALVIUM_Wallet_setDevicePin
_SALVIUM_Wallet_setDevicePassphrase
_SALVIUM_Wallet_address
_SALVIUM_Wallet_path
_SALVIUM_Wallet_nettype
_SALVIUM_Wallet_useForkRules
_SALVIUM_Wallet_integratedAddress
_SALVIUM_Wallet_secretViewKey
_SALVIUM_Wallet_publicViewKey
_SALVIUM_Wallet_secretSpendKey
_SALVIUM_Wallet_publicSpendKey
_SALVIUM_Wallet_publicMultisigSignerKey
_SALVIUM_Wallet_stop
_SALVIUM_Wallet_store
_SALVIUM_Wallet_filename
_SALVIUM_Wallet_keysFilename
_SALVIUM_Wallet_init
_SALVIUM_Wallet_createWatchOnly
_SALVIUM_Wallet_setRefreshFromBlockHeight
_SALVIUM_Wallet_getRefreshFromBlockHeight
_SALVIUM_Wallet_setRecoveringFromSeed
_SALVIUM_Wallet_setRecoveringFromDevice
_SALVIUM_Wallet_setSubaddressLookahead
_SALVIUM_Wallet_connectToDaemon
_SALVIUM_Wallet_connected
_SALVIUM_Wallet_setTrustedDaemon
_SALVIUM_Wallet_trustedDaemon
_SALVIUM_Wallet_setProxy
_SALVIUM_Wallet_balance
_SALVIUM_Wallet_unlockedBalance
_SALVIUM_Wallet_viewOnlyBalance
_SALVIUM_Wallet_watchOnly
_SALVIUM_Wallet_isDeterministic
_SALVIUM_Wallet_blockChainHeight
_SALVIUM_Wallet_approximateBlockChainHeight
_SALVIUM_Wallet_estimateBlockChainHeight
_SALVIUM_Wallet_daemonBlockChainHeight
_SALVIUM_Wallet_daemonBlockChainTargetHeight
_SALVIUM_Wallet_synchronized
_SALVIUM_Wallet_displayAmount
_SALVIUM_Wallet_amountFromString
_SALVIUM_Wallet_amountFromDouble
_SALVIUM_Wallet_genPaymentId
_SALVIUM_Wallet_paymentIdValid
_SALVIUM_Wallet_addressValid
_SALVIUM_Wallet_keyValid
_SALVIUM_Wallet_keyValid_error
_SALVIUM_Wallet_paymentIdFromAddress
_SALVIUM_Wallet_maximumAllowedAmount
_SALVIUM_Wallet_init3
_SALVIUM_Wallet_getPolyseed
_SALVIUM_Wallet_createPolyseed
_SALVIUM_Wallet_startRefresh
_SALVIUM_Wallet_pauseRefresh
_SALVIUM_Wallet_refresh
_SALVIUM_Wallet_refreshAsync
_SALVIUM_Wallet_rescanBlockchain
_SALVIUM_Wallet_rescanBlockchainAsync
_SALVIUM_Wallet_setAutoRefreshInterval
_SALVIUM_Wallet_autoRefreshInterval
_SALVIUM_Wallet_addSubaddressAccount
_SALVIUM_Wallet_numSubaddressAccounts
_SALVIUM_Wallet_numSubaddresses
_SALVIUM_Wallet_addSubaddress
_SALVIUM_Wallet_getSubaddressLabel
_SALVIUM_Wallet_setSubaddressLabel
_SALVIUM_Wallet_multisig
_SALVIUM_Wallet_getMultisigInfo
_SALVIUM_Wallet_makeMultisig
_SALVIUM_Wallet_exchangeMultisigKeys
_SALVIUM_Wallet_exportMultisigImages
_SALVIUM_Wallet_importMultisigImages
_SALVIUM_Wallet_hasMultisigPartialKeyImages
_SALVIUM_Wallet_restoreMultisigTransaction
_SALVIUM_Wallet_createTransactionMultDest
_SALVIUM_Wallet_createTransaction
_SALVIUM_Wallet_loadUnsignedTx
_SALVIUM_Wallet_loadUnsignedTxUR
_SALVIUM_Wallet_submitTransaction
_SALVIUM_Wallet_submitTransactionUR
_SALVIUM_Wallet_hasUnknownKeyImages
_SALVIUM_Wallet_exportKeyImages
_SALVIUM_Wallet_exportKeyImagesUR
_SALVIUM_Wallet_importKeyImages
_SALVIUM_Wallet_importKeyImagesUR
_SALVIUM_Wallet_exportOutputs
_SALVIUM_Wallet_exportOutputsUR
_SALVIUM_Wallet_importOutputs
_SALVIUM_Wallet_importOutputsUR
_SALVIUM_Wallet_setupBackgroundSync
_SALVIUM_Wallet_getBackgroundSyncType
_SALVIUM_Wallet_startBackgroundSync
_SALVIUM_Wallet_stopBackgroundSync
_SALVIUM_Wallet_isBackgroundSyncing
_SALVIUM_Wallet_isBackgroundWallet
_SALVIUM_Wallet_history
_SALVIUM_Wallet_addressBook
_SALVIUM_Wallet_coins
_SALVIUM_Wallet_subaddress
_SALVIUM_Wallet_subaddressAccount
_SALVIUM_Wallet_defaultMixin
_SALVIUM_Wallet_setDefaultMixin
_SALVIUM_Wallet_setCacheAttribute
_SALVIUM_Wallet_getCacheAttribute
_SALVIUM_Wallet_setUserNote
_SALVIUM_Wallet_getUserNote
_SALVIUM_Wallet_getTxKey
_SALVIUM_Wallet_signMessage
_SALVIUM_Wallet_verifySignedMessage
_SALVIUM_Wallet_rescanSpent
_SALVIUM_Wallet_setOffline
_SALVIUM_Wallet_isOffline
_SALVIUM_Wallet_segregatePreForkOutputs
_SALVIUM_Wallet_segregationHeight
_SALVIUM_Wallet_keyReuseMitigation2
_SALVIUM_Wallet_lockKeysFile
_SALVIUM_Wallet_unlockKeysFile
_SALVIUM_Wallet_isKeysFileLocked
_SALVIUM_Wallet_getDeviceType
_SALVIUM_Wallet_coldKeyImageSync
_SALVIUM_Wallet_deviceShowAddress
_SALVIUM_Wallet_reconnectDevice
_SALVIUM_Wallet_getBytesReceived
_SALVIUM_Wallet_getBytesSent
_SALVIUM_Wallet_getStateIsConnected
_SALVIUM_Wallet_getSendToDevice
_SALVIUM_Wallet_getSendToDeviceLength
_SALVIUM_Wallet_getReceivedFromDevice
_SALVIUM_Wallet_getReceivedFromDeviceLength
_SALVIUM_Wallet_getWaitsForDeviceSend
_SALVIUM_Wallet_getWaitsForDeviceReceive
_SALVIUM_Wallet_setDeviceReceivedData
_SALVIUM_Wallet_setDeviceSendData
_SALVIUM_WalletManager_createWallet
_SALVIUM_WalletManager_openWallet
_SALVIUM_WalletManager_recoveryWallet
_SALVIUM_WalletManager_createWalletFromKeys
_SALVIUM_WalletManager_createDeterministicWalletFromSpendKey
_SALVIUM_WalletManager_createWalletFromDevice
_SALVIUM_WalletManager_createWalletFromPolyseed
_SALVIUM_WalletManager_closeWallet
_SALVIUM_WalletManager_walletExists
_SALVIUM_WalletManager_verifyWalletPassword
_SALVIUM_WalletManager_queryWalletDevice
_SALVIUM_WalletManager_findWallets
_SALVIUM_WalletManager_errorString
_SALVIUM_WalletManager_setDaemonAddress
_SALVIUM_WalletManager_blockchainHeight
_SALVIUM_WalletManager_blockchainTargetHeight
_SALVIUM_WalletManager_networkDifficulty
_SALVIUM_WalletManager_miningHashRate
_SALVIUM_WalletManager_blockTarget
_SALVIUM_WalletManager_isMining
_SALVIUM_WalletManager_startMining
_SALVIUM_WalletManager_stopMining
_SALVIUM_WalletManager_resolveOpenAlias
_SALVIUM_WalletManager_setProxy
_SALVIUM_WalletManagerFactory_getWalletManager
_SALVIUM_WalletManagerFactory_setLogLevel
_SALVIUM_WalletManagerFactory_setLogCategories
_SALVIUM_DEBUG_test0
_SALVIUM_DEBUG_test1
_SALVIUM_DEBUG_test2
_SALVIUM_DEBUG_test3
_SALVIUM_DEBUG_test4
_SALVIUM_DEBUG_test5
_SALVIUM_DEBUG_test5_std
_SALVIUM_DEBUG_isPointerNull
_SALVIUM_cw_getWalletListener
_SALVIUM_cw_WalletListener_resetNeedToRefresh
_SALVIUM_cw_WalletListener_isNeedToRefresh
_SALVIUM_cw_WalletListener_isNewTransactionExist
_SALVIUM_cw_WalletListener_resetIsNewTransactionExist
_SALVIUM_cw_WalletListener_height
_SALVIUM_free
_SALVIUM_checksum_wallet2_api_c_h
_SALVIUM_checksum_wallet2_api_c_cpp
_SALVIUM_checksum_wallet2_api_c_exp
@@ -0,0 +1,265 @@
#include <inttypes.h>
#include <unistd.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <vector>
#include <string>
#include "helpers.hpp"
#include <set>
#include <sstream>
#include <cstring>
#include <thread>
#include <iostream>
#include <stdexcept>
#ifdef __ANDROID__
#include <android/log.h>
#define LOG_TAG "moneroc"
#define BUFFER_SIZE 1024*32
static int stdoutToLogcat(const char *buf, int size) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, buf);
return size;
}
static int stderrToLogcat(const char *buf, int size) {
__android_log_write(ANDROID_LOG_ERROR, LOG_TAG, buf);
return size;
}
void redirectStdoutThread(int pipe_stdout[2]) {
char bufferStdout[BUFFER_SIZE];
while (true) {
int read_size = read(pipe_stdout[0], bufferStdout, sizeof(bufferStdout) - 1);
if (read_size > 0) {
bufferStdout[read_size] = '\0';
stdoutToLogcat(bufferStdout, read_size);
}
}
}
void redirectStderrThread(int pipe_stderr[2]) {
char bufferStderr[BUFFER_SIZE];
while (true) {
int read_size = read(pipe_stderr[0], bufferStderr, sizeof(bufferStderr) - 1);
if (read_size > 0) {
bufferStderr[read_size] = '\0';
stderrToLogcat(bufferStderr, read_size);
}
}
}
void setupAndroidLogging() {
static int pfdStdout[2];
static int pfdStderr[2];
pipe(pfdStdout);
pipe(pfdStderr);
dup2(pfdStdout[1], STDOUT_FILENO);
dup2(pfdStderr[1], STDERR_FILENO);
std::thread stdoutThread(redirectStdoutThread, pfdStdout);
std::thread stderrThread(redirectStderrThread, pfdStderr);
stdoutThread.detach();
stderrThread.detach();
}
#endif // __ANDROID__
__attribute__((constructor))
void library_init() {
#ifdef __ANDROID__
setupAndroidLogging(); // This will now run automatically when the library is loaded
#endif
}
const char* vectorToString(const std::vector<std::string>& vec, const std::string separator) {
// Check if the vector is empty
if (vec.empty()) {
return "";
}
// Concatenate all strings in the vector
std::string result;
for (size_t i = 0; i < vec.size() - 1; ++i) {
result += vec[i];
result += separator;
}
result += vec.back(); // Append the last string without the separator
std::string str = result;
const std::string::size_type size = str.size();
char *buffer = new char[size + 1]; //we need extra char for NUL
memcpy(buffer, str.c_str(), size + 1);
return buffer;
}
const char* vectorToString(const std::vector<uint32_t>& vec, const std::string separator) {
// Calculate the size needed for the result string
size_t size = 0;
for (size_t i = 0; i < vec.size(); ++i) {
// Calculate the number of digits in each element
size += snprintf(nullptr, 0, "%u", vec[i]);
// Add comma and space for all elements except the last one
if (i < vec.size() - 1) {
size += separator.size(); // comma and space
}
}
// Allocate memory for the result string
char* result = static_cast<char*>(malloc(size + 1));
if (result == nullptr) {
// Handle memory allocation failure
return nullptr;
}
// Fill in the result string
char* current = result;
for (size_t i = 0; i < vec.size(); ++i) {
// Convert each element to string and copy to the result string
int written = snprintf(current, size + 1, "%u", vec[i]);
current += written;
// Add comma and space for all elements except the last one
if (i < vec.size() - 1) {
strcpy(current, separator.c_str());
current += separator.size();
}
}
return result;
}
const char* vectorToString(const std::vector<uint64_t>& vec, const std::string separator) {
// Calculate the size needed for the result string
size_t size = 0;
for (size_t i = 0; i < vec.size(); ++i) {
// Calculate the number of digits in each element
size += snprintf(nullptr, 0, "%llu", vec[i]);
// Add comma and space for all elements except the last one
if (i < vec.size() - 1) {
size += separator.size(); // comma and space
}
}
// Allocate memory for the result string
char* result = static_cast<char*>(malloc(size + 1));
if (result == nullptr) {
// Handle memory allocation failure
return nullptr;
}
// Fill in the result string
char* current = result;
for (size_t i = 0; i < vec.size(); ++i) {
// Convert each element to string and copy to the result string
int written = snprintf(current, size + 1, "%llu", vec[i]);
current += written;
// Add comma and space for all elements except the last one
if (i < vec.size() - 1) {
strcpy(current, separator.c_str());
current += separator.size();
}
}
return result;
}
const char* vectorToString(const std::vector<std::set<uint32_t>>& vec, const std::string separator) {
// Check if the vector is empty
if (vec.empty()) {
return "";
}
// Use a stringstream to concatenate sets with commas and individual elements with spaces
std::ostringstream oss;
oss << "{";
for (auto it = vec.begin(); it != vec.end(); ++it) {
if (it != vec.begin()) {
oss << separator;
}
oss << "{";
for (auto setIt = it->begin(); setIt != it->end(); ++setIt) {
if (setIt != it->begin()) {
oss << separator;
}
oss << *setIt;
}
oss << "}";
}
oss << "}";
std::string str = oss.str();
const std::string::size_type size = str.size();
char *buffer = new char[size + 1]; //we need extra char for NUL
memcpy(buffer, str.c_str(), size + 1);
return buffer;
}
// Function to convert std::set<uint32_t> to a string
const char* vectorToString(const std::set<uint32_t>& intSet, const std::string separator) {
// Check if the set is empty
if (intSet.empty()) {
return "";
}
// Use a stringstream to concatenate elements with commas
std::ostringstream oss;
auto it = intSet.begin();
oss << *it;
for (++it; it != intSet.end(); ++it) {
oss << ", " << *it;
}
std::string str = oss.str();
const std::string::size_type size = str.size();
char *buffer = new char[size + 1]; //we need extra char for NUL
memcpy(buffer, str.c_str(), size + 1);
return buffer;
}
std::set<std::string> splitString(const std::string& str, const std::string& delim) {
std::set<std::string> tokens;
if (str.empty()) return tokens;
size_t pos = 0;
std::string token;
std::string content = str; // Copy of str so we can safely erase content
while ((pos = content.find(delim)) != std::string::npos) {
token = content.substr(0, pos);
tokens.insert(token);
content.erase(0, pos + delim.length());
}
tokens.insert(content); // Inserting the last token
return tokens;
}
std::vector<std::string> splitStringVector(const std::string& str, const std::string& delim) {
std::vector<std::string> tokens;
if (str.empty()) return tokens;
size_t pos = 0;
std::string content = str; // Copy of str so we can safely erase content
while ((pos = content.find(delim)) != std::string::npos) {
tokens.push_back(content.substr(0, pos));
content.erase(0, pos + delim.length());
}
tokens.push_back(content); // Inserting the last token
return tokens;
}
std::vector<uint64_t> splitStringUint(const std::string& str, const std::string& delim) {
std::vector<uint64_t> tokens;
if (str.empty()) return tokens;
size_t pos = 0;
std::string token;
std::string content = str; // Copy of str so we can safely erase content
while ((pos = content.find(delim)) != std::string::npos) {
token = content.substr(0, pos);
tokens.push_back(std::stoull(token)); // Convert string to uint64_t and push to vector
content.erase(0, pos + delim.length());
}
tokens.push_back(std::stoull(content)); // Inserting the last token
return tokens;
}
@@ -0,0 +1,32 @@
#include <vector>
#include <string>
#include <set>
#include <sstream>
#include <cstdlib>
#include <iostream>
// Debug macros
#define DEBUG_START() \
try {
#define DEBUG_END() \
} catch (const std::exception &e) { \
std::cerr << "Exception caught in function: " << __FUNCTION__ \
<< " at " << __FILE__ << ":" << __LINE__ << std::endl \
<< "Message: " << e.what() << std::endl; \
std::abort(); \
} catch (...) { \
std::cerr << "Unknown exception caught in function: " << __FUNCTION__ \
<< " at " << __FILE__ << ":" << __LINE__ << std::endl; \
std::abort(); \
}
const char* vectorToString(const std::vector<std::string>& vec, const std::string separator);
const char* vectorToString(const std::vector<uint32_t>& vec, const std::string separator);
const char* vectorToString(const std::vector<uint64_t>& vec, const std::string separator);
const char* vectorToString(const std::vector<std::set<uint32_t>>& vec, const std::string separator);
const char* vectorToString(const std::set<uint32_t>& intSet, const std::string separator);
std::set<std::string> splitString(const std::string& str, const std::string& delim);
std::vector<uint64_t> splitStringUint(const std::string& str, const std::string& delim);
std::vector<std::string> splitStringVector(const std::string& str, const std::string& delim);
@@ -0,0 +1,6 @@
#ifndef SALVIUMC_CHECKSUMS
#define SALVIUMC_CHECKSUMS
const char * SALVIUM_wallet2_api_c_h_sha256 = "9e80c4b59a0509aa02fbf01e8df2881b89f82225d1765bfa7856cbdbaf7af116";
const char * SALVIUM_wallet2_api_c_cpp_sha256 = "d229507db508e574bd2badf4819a38dbead8c16a84311ad32c22c887a6003439-0232839913b13cf0ab0bb7ad25fff0c05f37d2fe";
const char * SALVIUM_wallet2_api_c_exp_sha256 = "d0f95f1f3bc49f1f59fe4eb0b61826128d7d3bb75405d5a01a252d02db03097d";
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff