Compare commits

..

23 Commits

Author SHA1 Message Date
Some Random Crypto Guy 48fb95bdc1 bumped version to v1.0.6 2025-10-16 14:58:02 +01:00
Some Random Crypto Guy bb4d3768b2 Merge branch 'wallet-ui-improvements' 2025-10-16 14:52:47 +01:00
Some Random Crypto Guy cea3f0f341 fixed Carrot wallet exceptions reporting 'unknown error'; fixed wallet.address.txt file to contain Carrot keys as well; fixed sending to subaddress from same wallet 2025-10-16 14:51:49 +01:00
Some Random Crypto Guy 35fc88c0ec bumped version 2025-10-15 13:45:16 +01:00
Some Random Crypto Guy 312413aeb0 Merge branch 'hotfix-subaddress-limit-removal-optimisation' 2025-10-15 13:31:28 +01:00
Some Random Crypto Guy 6ba060e116 fixed subaddress lookahead generation for Carrot; optimised to reduce scanning times 2025-10-15 13:29:04 +01:00
Some Random Crypto Guy 88d5e1f50e updated translation bundles; bumped version 2025-10-14 13:55:35 +01:00
Some Random Crypto Guy 644a8d3b4d Merge branch 'hotfix-carrot-address-display-in-cli' 2025-10-14 13:52:50 +01:00
Some Random Crypto Guy e80d135c15 Merge branch 'hotfix-return-from-multiple-dest-transaction' 2025-10-14 13:51:46 +01:00
Some Random Crypto Guy a40026f941 fixed return_payment when receiving Carrot output from a multiple-destination transaction 2025-10-14 13:51:04 +01:00
Some Random Crypto Guy fb25a36bf2 fixes for Carrot address display in CLI wallet 2025-10-14 10:44:26 +01:00
Some Random Crypto Guy 6f3f7c8e9a Merge branch 'hotfix-Carrot-get-tx-key' 2025-10-14 06:20:16 +01:00
Some Random Crypto Guy c6c35d5639 fixed get_tx_key implementation for Carrot (kludgy) 2025-10-14 06:19:45 +01:00
Some Random Crypto Guy 63433cc58f bumped version to v1.0.3 2025-10-14 05:05:55 +01:00
Some Random Crypto Guy 940c0e03f7 Merge branch 'hotfix-sweepall-to-self' 2025-10-14 05:04:03 +01:00
Some Random Crypto Guy 445e498fbf Merge branch 'hotfix-additional-cn-address-checks' 2025-10-14 05:03:51 +01:00
Some Random Crypto Guy 09ad75f0cc additional CN/Carrot address checks implemented in wallet 2025-10-14 05:02:28 +01:00
Some Random Crypto Guy f8d9f9335e fixed issue with post-Carrot-HF sweep_all to self 2025-10-13 21:17:45 +01:00
Some Random Crypto Guy cd31dafa97 updated ubuntu version for GH action runner 2025-10-13 19:17:52 +01:00
Some Random Crypto Guy 6aa32701b8 fixed get_block_template RPC call to handle payouts for treasury and miner 2025-10-13 16:20:39 +01:00
Some Random Crypto Guy 4bfb5f51bf Merge branch 'develop' 2025-10-04 13:38:50 +01:00
Some Random Crypto Guy 260bc3721b bumped version 2025-10-03 21:18:52 +01:00
Some Random Crypto Guy 3e0457de09 Merge branch 'develop' 2025-10-03 21:17:54 +01:00
80 changed files with 42418 additions and 42502 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ env:
jobs:
build-cross:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
strategy:
+1 -12
View File
@@ -6,22 +6,11 @@
url = https://github.com/trezor/trezor-common.git
[submodule "external/randomx"]
path = external/randomx
url = https://github.com/MrCyjaneK/RandomX
branch = cyjan-fix-ios
[submodule "external/utf8proc"]
path = external/utf8proc
url = https://github.com/JuliaStrings/utf8proc.git
[submodule "external/polyseed"]
path = external/polyseed
url = https://github.com/tevador/polyseed.git
url = https://github.com/tevador/RandomX
[submodule "external/supercop"]
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
View File
+15 -20
View File
@@ -45,6 +45,10 @@ if (POLICY CMP0148)
endif()
include(FindPythonInterp)
if (IOS)
INCLUDE(CmakeLists_IOS.txt)
endif()
project(salvium)
option (USE_CCACHE "Use ccache if a usable instance is found" ON)
@@ -96,7 +100,6 @@ set(CMAKE_C_STANDARD 11)
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)
@@ -222,9 +225,9 @@ function(forbid_undefined_symbols)
cmake_minimum_required(VERSION 3.5)
project(test)
option(EXPECT_SUCCESS "" ON)
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
file(WRITE "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
if (EXPECT_SUCCESS)
file(APPEND "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
file(APPEND "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
endif()
add_library(l0 SHARED incorrect_source.cpp)
add_library(l1 MODULE incorrect_source.cpp)
@@ -364,15 +367,12 @@ 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)
check_submodule(external/randomx)
check_submodule(external/supercop)
check_submodule(external/mx25519)
check_submodule(external/polyseed)
check_submodule(external/utf8proc)
endif()
endif()
@@ -390,7 +390,7 @@ else()
endif()
list(INSERT CMAKE_MODULE_PATH 0
"${CMAKE_CURRENT_SOURCE_DIR}/cmake")
"${CMAKE_SOURCE_DIR}/cmake")
if (NOT DEFINED ENV{DEVELOPER_LOCAL_TOOLS})
message(STATUS "Could not find DEVELOPER_LOCAL_TOOLS in env (not required)")
@@ -459,7 +459,7 @@ elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
set(BSDI TRUE)
endif()
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include external/mx25519/include external/polyseed/include external/utf8proc)
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include external/mx25519/include)
if(APPLE)
cmake_policy(SET CMP0042 NEW)
@@ -692,21 +692,16 @@ include_directories(${LMDB_INCLUDE})
include_directories(${LIBUNWIND_INCLUDE})
link_directories(${LIBUNWIND_LIBRARY_DIRS})
if (HIDAPI_DUMMY)
add_definitions(-DHIDAPI_DUMMY)
# Final setup for hid
if (HIDAPI_FOUND)
message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
add_definitions(-DHAVE_HIDAPI)
include_directories(${HIDAPI_INCLUDE_DIR})
link_directories(${LIBHIDAPI_LIBRARY_DIRS})
else()
# Final setup for hid
if (HIDAPI_FOUND)
message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
add_definitions(-DHAVE_HIDAPI)
include_directories(${HIDAPI_INCLUDE_DIR})
link_directories(${LIBHIDAPI_LIBRARY_DIRS})
else()
message(STATUS "Could not find HIDAPI")
endif()
message(STATUS "Could not find HIDAPI")
endif()
# Trezor support check
include(CheckTrezor)
+5 -5
View File
@@ -1,4 +1,4 @@
# Salvium One v1.0.0
# Salvium One v1.0.6
Copyright (c) 2023-2025, Salvium
Portions Copyright (c) 2014-2023, The Monero Project
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
```bash
cd salvium
git checkout v1.0.0
git checkout v1.0.6
make
```
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/salvium/salvium
cd salvium
git checkout v1.0.0
git checkout v1.0.6
```
* Build:
@@ -370,10 +370,10 @@ application.
cd salvium
```
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v1.0.0'. If you don't care about the version and just want binaries from master, skip this step:
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v1.0.6'. If you don't care about the version and just want binaries from master, skip this step:
```bash
git checkout v1.0.0
git checkout v1.0.6
```
* If you are on a 64-bit system, run:
+1 -1
View File
@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
message(STATUS "Looking for ${flag} linker flag")
endif()
set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "${flag}")
+1 -1
View File
@@ -28,7 +28,7 @@
#pragma once
#include "memwipe.h"
#include <stdint.h>
#include <boost/utility/string_ref.hpp>
#include <string>
+1
View File
@@ -162,6 +162,7 @@ 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)};
}
-7
View File
@@ -34,7 +34,6 @@
#include <string>
#include "memwipe.h"
#include "fnv1.h"
#include "serialization/keyvalue_serialization.h"
namespace epee
{
@@ -76,12 +75,6 @@ namespace epee
bool operator!=(const wipeable_string &other) const noexcept { return buffer != other.buffer; }
wipeable_string &operator=(wipeable_string &&other);
wipeable_string &operator=(const wipeable_string &other);
char& operator[](size_t idx);
const char& operator[](size_t idx) const;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(buffer)
END_KV_SERIALIZE_MAP()
private:
void grow(size_t sz, size_t reserved = 0);
-10
View File
@@ -261,14 +261,4 @@ wipeable_string &wipeable_string::operator=(const wipeable_string &other)
return *this;
}
char& wipeable_string::operator[](size_t idx) {
CHECK_AND_ASSERT_THROW_MES(idx < buffer.size(), "Index out of bounds");
return buffer[idx];
}
const char& wipeable_string::operator[](size_t idx) const {
CHECK_AND_ASSERT_THROW_MES(idx < buffer.size(), "Index out of bounds");
return buffer[idx];
}
}
-3
View File
@@ -69,8 +69,5 @@ endif()
add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
add_subdirectory(qrcodegen)
add_subdirectory(polyseed EXCLUDE_FROM_ALL)
add_subdirectory(utf8proc EXCLUDE_FROM_ALL)
add_subdirectory(bc-ur)
add_subdirectory(randomx EXCLUDE_FROM_ALL)
add_subdirectory(mx25519)
-1
Submodule external/bc-ur deleted from d82e7c753e
Submodule external/polyseed deleted from bd79f5014c
Submodule external/utf8proc deleted from 3de4596fbe
-1
View File
@@ -98,7 +98,6 @@ add_subdirectory(net)
add_subdirectory(hardforks)
add_subdirectory(blockchain_db)
add_subdirectory(mnemonics)
add_subdirectory(polyseed)
add_subdirectory(rpc)
add_subdirectory(seraphis_crypto)
if(NOT IOS)
+12 -7
View File
@@ -282,13 +282,13 @@ crypto::key_image carrot_and_legacy_account::derive_key_image(const crypto::publ
return L;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::generate_subaddress_map()
void carrot_and_legacy_account::generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size)
{
const std::vector<AddressDeriveType> derive_types{AddressDeriveType::Carrot, AddressDeriveType::PreCarrot};
for (uint32_t major_index = 0; major_index <= MAX_SUBADDRESS_MAJOR_INDEX; ++major_index)
for (uint32_t major_index = 0; major_index <= lookahead_size.first; ++major_index)
{
for (uint32_t minor_index = 0; minor_index <= MAX_SUBADDRESS_MINOR_INDEX; ++minor_index)
for (uint32_t minor_index = 0; minor_index <= lookahead_size.first; ++minor_index)
{
for (const AddressDeriveType derive_type : derive_types)
{
@@ -361,7 +361,6 @@ void carrot_and_legacy_account::create_from_svb_key(const cryptonote::account_pu
);
this->default_derive_type = AddressDeriveType::Carrot;
generate_subaddress_map();
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_derive_type)
@@ -393,13 +392,19 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_
m_keys.m_carrot_main_address.m_is_carrot = true;
this->default_derive_type = default_derive_type;
generate_subaddress_map();
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map_cn)
{
for (const auto &p : subaddress_map_cn)
subaddress_map.insert({p.first, {{p.second.index.major, p.second.index.minor}, p.second.derive_type, p.second.is_return_spend_key}});
for (const auto &p : subaddress_map_cn) {
subaddress_map.insert({p.first, {{p.second.index.major, p.second.index.minor}, p.second.derive_type, p.second.is_return_spend_key}});
if (p.second.derive_type == AddressDeriveType::PreCarrot) {
// Create a matching Carrot address
const subaddress_index_extended subaddr_index{{p.second.index.major, p.second.index.minor}, AddressDeriveType::Carrot, p.second.is_return_spend_key};
const CarrotDestinationV1 addr = subaddress(subaddr_index);
subaddress_map.insert({addr.address_spend_pubkey, subaddr_index});
}
}
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::insert_return_output_info(const std::unordered_map<crypto::public_key, return_output_info_t>& roi_map)
+1 -1
View File
@@ -144,7 +144,7 @@ namespace carrot
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
void generate_subaddress_map();
void generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size);
crypto::secret_key generate(
const crypto::secret_key& recovery_key = crypto::secret_key(),
+3 -3
View File
@@ -41,9 +41,9 @@
namespace carrot
{
#define CARROT_DEFINE_SIMPLE_ERROR_TYPE(e, b) class e: b { using b::b; };
#define CARROT_DEFINE_SIMPLE_ERROR_TYPE(e, b) class e: public b { using b::b; };
class carrot_logic_error: std::logic_error { using std::logic_error::logic_error; };
class carrot_logic_error: public std::logic_error { using std::logic_error::logic_error; };
CARROT_DEFINE_SIMPLE_ERROR_TYPE(bad_address_type, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(component_out_of_order, carrot_logic_error)
@@ -55,7 +55,7 @@ CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_few_outputs, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_many_outputs, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(invalid_tx_type, carrot_logic_error)
class carrot_runtime_error: std::runtime_error { using std::runtime_error::runtime_error; };
class carrot_runtime_error: public std::runtime_error { using std::runtime_error::runtime_error; };
CARROT_DEFINE_SIMPLE_ERROR_TYPE(crypto_function_failed, carrot_runtime_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_money, carrot_runtime_error)
+1 -1
View File
@@ -77,7 +77,7 @@ std::optional<AdditionalOutputType> get_additional_output_type(const size_t num_
}
else if (!need_change_output)
{
return AdditionalOutputType::DUMMY;
return AdditionalOutputType::CHANGE_UNIQUE;
}
else // num_selfsend == 1 && need_change_output
{
+2 -2
View File
@@ -519,7 +519,7 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
crypto::secret_key sum_g;
sc_add(to_bytes(sum_g), to_bytes(sender_extension_g_out), to_bytes(k_return));
crypto::key_image key_image = account.derive_key_image(
account.get_keys().m_carrot_account_address.m_spend_public_key,
address_spend_pubkey_out, // THIS WAS WRONG!!! -> account.get_keys().m_carrot_account_address.m_spend_public_key,
sum_g,
sender_extension_t_out,
K_r
@@ -527,7 +527,7 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
crypto::secret_key x, y;
account.try_searching_for_opening_for_onetime_address(
account.get_keys().m_carrot_account_address.m_spend_public_key,
address_spend_pubkey_out, // THIS WAS WRONG!!! -> account.get_keys().m_carrot_account_address.m_spend_public_key,
sum_g,
sender_extension_t_out,
x,
+1 -5
View File
@@ -28,11 +28,7 @@
if(APPLE)
if(DEPENDS)
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()
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
else()
find_library(IOKIT_LIBRARY IOKit)
mark_as_advanced(IOKIT_LIBRARY)
+1 -6
View File
@@ -28,11 +28,7 @@
if(APPLE)
if(DEPENDS)
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()
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
else()
find_library(IOKIT_LIBRARY IOKit)
mark_as_advanced(IOKIT_LIBRARY)
@@ -75,7 +71,6 @@ target_link_libraries(cryptonote_basic
checkpoints
cryptonote_format_utils_basic
device
polyseed_wrapper
oracle
${Boost_DATE_TIME_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
+3 -24
View File
@@ -89,16 +89,12 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_keys::xor_with_key_stream(const crypto::chacha_key &key)
{
// encrypt a large enough byte stream with chacha20
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (3 + m_multisig_keys.size()) + m_passphrase.size());
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (2 + m_multisig_keys.size()));
const char *ptr = key_stream.data();
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_spend_secret_key.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_view_secret_key.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_polyseed.data[i] ^= *ptr++;
for (size_t i = 0; i < m_passphrase.size(); ++i)
m_passphrase.data()[i] ^= *ptr++;
for (crypto::secret_key &k: m_multisig_keys)
{
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
@@ -158,8 +154,6 @@ DISABLE_VS_WARNINGS(4244 4345)
m_keys.s_master = m_keys.m_spend_secret_key;
m_keys.k_prove_spend = m_keys.m_spend_secret_key;
m_keys.m_multisig_keys.clear();
m_keys.m_polyseed = crypto::secret_key();
m_keys.m_passphrase.wipe();
}
//-----------------------------------------------------------------
void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
@@ -266,21 +260,6 @@ DISABLE_VS_WARNINGS(4244 4345)
create_from_keys(address, fake, viewkey);
}
//-----------------------------------------------------------------
void account_base::create_from_polyseed(const polyseed::data& seed, const epee::wipeable_string &passphrase)
{
crypto::secret_key secret_key;
seed.keygen(&secret_key, sizeof(secret_key));
if (!passphrase.empty()) {
secret_key = cryptonote::decrypt_key(secret_key, passphrase);
}
generate(secret_key, true, false);
seed.save(m_keys.m_polyseed.data);
m_keys.m_passphrase = passphrase;
}
//-----------------------------------------------------------------
bool account_base::make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys)
{
m_keys.m_account_address.m_spend_public_key = spend_public_key;
@@ -304,9 +283,9 @@ DISABLE_VS_WARNINGS(4244 4345)
std::string account_base::get_carrot_public_address_str(network_type nettype) const
{
// Build the cryptonote::account_public_address
account_public_address addr{m_keys.m_carrot_main_address.m_spend_public_key, m_keys.m_carrot_main_address.m_view_public_key};
account_public_address addr{m_keys.m_carrot_main_address.m_spend_public_key, m_keys.m_carrot_main_address.m_view_public_key, true};
// change this code into base 58
return get_account_address_as_str(nettype, false, addr, true);
return get_account_address_as_str(nettype, false, addr);
}
//-----------------------------------------------------------------
std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const
-6
View File
@@ -33,7 +33,6 @@
#include "cryptonote_basic.h"
#include "crypto/crypto.h"
#include "serialization/keyvalue_serialization.h"
#include "polyseed/polyseed.hpp"
#include "carrot_core/account_secrets.h"
#include "carrot_core/address_utils.h"
@@ -53,8 +52,6 @@ namespace cryptonote
std::vector<crypto::secret_key> m_multisig_keys;
hw::device *m_device = &hw::get_device("default");
crypto::chacha_iv m_encryption_iv;
crypto::secret_key m_polyseed;
epee::wipeable_string m_passphrase; // Only used with polyseed
// carrot secret keys (minus k_v, which is shared with legacy k_v)
crypto::secret_key s_master;
@@ -78,8 +75,6 @@ namespace cryptonote
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_multisig_keys)
const crypto::chacha_iv default_iv{{0, 0, 0, 0, 0, 0, 0, 0}};
KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(m_encryption_iv, default_iv)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_polyseed)
KV_SERIALIZE(m_passphrase)
END_KV_SERIALIZE_MAP()
void encrypt(const crypto::chacha_key &key);
@@ -106,7 +101,6 @@ namespace cryptonote
void create_from_device(hw::device &hwdev);
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
void create_from_polyseed(const polyseed::data &polyseed, const epee::wipeable_string &passphrase);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
const account_keys& get_keys() const;
std::string get_public_address_str(network_type nettype) const;
@@ -155,10 +155,9 @@ namespace cryptonote {
network_type nettype
, bool subaddress
, account_public_address const & adr
, bool is_carrot
)
{
uint64_t address_prefix = is_carrot
uint64_t address_prefix = adr.m_is_carrot
? (subaddress ? get_config(nettype).CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CARROT_PUBLIC_ADDRESS_BASE58_PREFIX)
: (subaddress ? get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX);
@@ -169,10 +168,9 @@ namespace cryptonote {
network_type nettype
, account_public_address const & adr
, crypto::hash8 const & payment_id
, bool is_carrot
)
{
uint64_t integrated_address_prefix = is_carrot ? get_config(nettype).CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
uint64_t integrated_address_prefix = adr.m_is_carrot ? get_config(nettype).CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
integrated_address iadr = {
adr, payment_id
@@ -88,14 +88,12 @@ namespace cryptonote {
network_type nettype
, bool subaddress
, const account_public_address& adr
, bool is_carrot = false
);
std::string get_account_integrated_address_as_str(
network_type nettype
, const account_public_address& adr
, const crypto::hash8& payment_id
, bool is_carrot = false
);
bool get_account_address_from_str(
+4 -4
View File
@@ -46,7 +46,7 @@
#include "boost/logic/tribool.hpp"
#include <boost/filesystem.hpp>
#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
#ifdef __APPLE__
#include <sys/times.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/ps/IOPSKeys.h>
@@ -902,7 +902,7 @@ namespace cryptonote
return true;
#elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
#elif defined(__APPLE__)
mach_msg_type_number_t count;
kern_return_t status;
@@ -968,7 +968,7 @@ namespace cryptonote
return true;
}
#elif (defined(__linux__) && defined(_SC_CLK_TCK)) || (defined(__APPLE__) && !defined(TARGET_OS_IPHONE)) || defined(__FreeBSD__)
#elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__)
struct tms tms;
if ( times(&tms) != (clock_t)-1 )
@@ -997,7 +997,7 @@ namespace cryptonote
return boost::logic::tribool(power_status.ACLineStatus != 1);
}
#elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
#elif defined(__APPLE__)
#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
View File
@@ -274,8 +274,6 @@
#define DNS_BLOCKLIST_LIFETIME (86400 * 8)
#define POLYSEED_COIN POLYSEED_MONERO
#define PRICING_RECORD_VALID_BLOCKS 10
#define PRICING_RECORD_VALID_TIME_DIFF_FROM_BLOCK 120 // seconds
+3 -11
View File
@@ -1440,24 +1440,16 @@ namespace cryptonote
bool get_block_longhash(const Blockchain *pbc, const blobdata& bd, crypto::hash& res, const uint64_t height, const int major_version, const crypto::hash *seed_hash, const int miners)
{
crypto::hash hash;
if (pbc != NULL)
{
crypto::hash hash;
const uint64_t seed_height = rx_seedheight(height);
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
} else
{
// only happens when generating genesis block
// Hardcoded genesis for ios compat
const char* hex = "4ade63d5ccb8cfae075e8b882514c471f35da95f85dd1b20fdcd6f3a95caabc5";
char bytes[32];
for (int i = 0; i < 32; i++) {
char byte_str[3] = { hex[i * 2], hex[i * 2 + 1], '\0' };
bytes[i] = (char)strtol(byte_str, NULL, 16);
}
memcpy(res.data, bytes, sizeof(bytes));
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
}
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
return true;
}
+1 -1
View File
@@ -1355,7 +1355,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery, bool is_carrot) {
cryptonote::COMMAND_RPC_START_MINING::request req;
cryptonote::COMMAND_RPC_START_MINING::response res;
req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address, is_carrot);
req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address);
req.threads_count = num_threads;
req.do_background_mining = do_background_mining;
req.ignore_battery = ignore_battery;
+2 -4
View File
@@ -29,11 +29,10 @@
set(device_sources
device.cpp
device_default.cpp
device_io_dummy.cpp
log.cpp
)
if(HIDAPI_FOUND OR HIDAPI_DUMMY)
if(HIDAPI_FOUND)
set(device_sources
${device_sources}
device_ledger.cpp
@@ -46,11 +45,10 @@ set(device_headers
device_io.hpp
device_default.hpp
device_cold.hpp
device_io_dummy.hpp
log.hpp
)
if(HIDAPI_FOUND OR HIDAPI_DUMMY)
if(HIDAPI_FOUND)
set(device_headers
${device_headers}
device_ledger.hpp
+4 -6
View File
@@ -29,7 +29,7 @@
#include "device.hpp"
#include "device_default.hpp"
#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
#ifdef WITH_DEVICE_LEDGER
#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);
#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
#ifdef WITH_DEVICE_LEDGER
hw::ledger::register_all(registry);
#endif
atexit(clear_device_registry);
@@ -83,13 +83,11 @@ namespace hw {
auto device = registry.find(device_descriptor_lookup);
if (device == registry.end()) {
std::stringstream ss("Device not found in registry: '" + device_descriptor + "'. Known devices: ");
MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: \n");
MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: ");
for( const auto& sm_pair : registry ) {
ss << "\n- " + sm_pair.first;
MERROR(" - " << sm_pair.first);
}
throw std::runtime_error("device not found: " + device_descriptor + "\n" + ss.str());
throw std::runtime_error("device not found: " + device_descriptor);
}
return *device->second;
}
+11 -1
View File
@@ -34,7 +34,17 @@
#include "ringct/rctTypes.h"
#include "cryptonote_config.h"
#if defined(HAVE_HIDAPI) || defined(HIDAPI_DUMMY)
#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
#define WITH_DEVICE_LEDGER
#endif
-161
View File
@@ -1,161 +0,0 @@
// 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;
void (*hw::io::device_io_dummy::sendToLedgerDeviceCallback)(unsigned char *command, unsigned int cmd_len) = nullptr;
std::mutex hw::io::device_io_dummy::mutex;
std::condition_variable hw::io::device_io_dummy::cv_send;
std::condition_variable hw::io::device_io_dummy::cv_receive;
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");
std::unique_lock<std::mutex> lock(mutex);
sendToDevice = command;
sendToDeviceLength = cmd_len;
waitsForDeviceSend = true;
waitsForDeviceReceive = true;
// Call the callback if it's set
if (sendToLedgerDeviceCallback != nullptr) {
MDEBUG("exchange(): calling sendToLedgerDeviceCallback");
sendToLedgerDeviceCallback(command, cmd_len);
}
MDEBUG("exchange(): waitsForDeviceSend");
// Wait for the send flag to be cleared by external code
while (waitsForDeviceSend) {
cv_send.wait(lock);
MDEBUG("exchange(): waitsForDeviceSend notified");
}
MDEBUG("exchange(): waitsForDeviceReceive");
// Wait for the receive flag to be cleared by external code
while (waitsForDeviceReceive) {
cv_receive.wait(lock);
MDEBUG("exchange(): waitsForDeviceReceive notified");
}
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()");
}
void device_io_dummy::setLedgerCallback(void (*sendToLedgerDevice)(unsigned char *command, unsigned int cmd_len)) {
MDEBUG("setLedgerCallback()");
sendToLedgerDeviceCallback = sendToLedgerDevice;
}
void device_io_dummy::setDeviceReceivedData(unsigned char* data, size_t len) {
MDEBUG("setDeviceReceivedData(len: " << len << ")");
std::unique_lock<std::mutex> lock(mutex);
receivedFromDevice = static_cast<unsigned char *>(malloc(len));
receivedFromDeviceLength = len;
memset(receivedFromDevice, 0, len);
memcpy(receivedFromDevice, data, len);
waitsForDeviceReceive = false;
waitsForDeviceSend = false;
cv_send.notify_all();
cv_receive.notify_all();
}
}
}
#endif // HAVE_HIDAPI
-82
View File
@@ -1,82 +0,0 @@
// 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"
#include <mutex>
#include <condition_variable>
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:
static std::mutex mutex;
public:
static std::condition_variable cv_send;
static std::condition_variable cv_receive;
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;
static void (*sendToLedgerDeviceCallback)(unsigned char *command, unsigned int cmd_len);
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);
static void setLedgerCallback(void (*sendToLedgerDevice)(unsigned char *command, unsigned int cmd_len));
static void setDeviceReceivedData(unsigned char* data, size_t len);
};
};
};
#endif // HAVE_HIDAPI
+2 -4
View File
@@ -38,7 +38,7 @@ namespace hw {
namespace ledger {
#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
#ifdef WITH_DEVICE_LEDGER
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,9 +533,7 @@ 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;
+1 -6
View File
@@ -35,7 +35,6 @@
#include "device.hpp"
#include "log.hpp"
#include "device_io_hid.hpp"
#include "device_io_dummy.hpp"
#include <mutex>
namespace hw {
@@ -56,7 +55,7 @@ namespace hw {
void register_all(std::map<std::string, std::unique_ptr<device>> &registry);
#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
#ifdef WITH_DEVICE_LEDGER
// Origin: https://github.com/LedgerHQ/ledger-app-monero/blob/master/src/monero_types.h
#define SW_OK 0x9000
@@ -144,11 +143,7 @@ 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;
-25
View File
@@ -1,25 +0,0 @@
set(polyseed_sources
pbkdf2.c
polyseed.cpp
)
monero_find_all_headers(polyseed_private_headers "${CMAKE_CURRENT_SOURCE_DIR}")
monero_private_headers(polyseed_wrapper
${polyseed_private_headers}
)
monero_add_library(polyseed_wrapper
${polyseed_sources}
${polyseed_headers}
${polyseed_private_headers}
)
target_link_libraries(polyseed_wrapper
PUBLIC
polyseed
utf8proc
${SODIUM_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES}
)
-85
View File
@@ -1,85 +0,0 @@
// Copyright (c) 2023, The Monero Project
// Copyright (c) 2021, tevador <tevador@gmail.com>
// Copyright (c) 2005,2007,2009 Colin Percival
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
#include <string.h>
#include <sodium/crypto_auth_hmacsha256.h>
#include <sodium/utils.h>
static inline void
store32_be(uint8_t dst[4], uint32_t w)
{
dst[3] = (uint8_t) w; w >>= 8;
dst[2] = (uint8_t) w; w >>= 8;
dst[1] = (uint8_t) w; w >>= 8;
dst[0] = (uint8_t) w;
}
void
crypto_pbkdf2_sha256(const uint8_t* passwd, size_t passwdlen,
const uint8_t* salt, size_t saltlen, uint64_t c,
uint8_t* buf, size_t dkLen)
{
crypto_auth_hmacsha256_state Phctx, PShctx, hctx;
size_t i;
uint8_t ivec[4];
uint8_t U[32];
uint8_t T[32];
uint64_t j;
int k;
size_t clen;
crypto_auth_hmacsha256_init(&Phctx, passwd, passwdlen);
PShctx = Phctx;
crypto_auth_hmacsha256_update(&PShctx, salt, saltlen);
for (i = 0; i * 32 < dkLen; i++) {
store32_be(ivec, (uint32_t)(i + 1));
hctx = PShctx;
crypto_auth_hmacsha256_update(&hctx, ivec, 4);
crypto_auth_hmacsha256_final(&hctx, U);
memcpy(T, U, 32);
for (j = 2; j <= c; j++) {
hctx = Phctx;
crypto_auth_hmacsha256_update(&hctx, U, 32);
crypto_auth_hmacsha256_final(&hctx, U);
for (k = 0; k < 32; k++) {
T[k] ^= U[k];
}
}
clen = dkLen - i * 32;
if (clen > 32) {
clen = 32;
}
memcpy(&buf[i * 32], T, clen);
}
sodium_memzero((void*)&Phctx, sizeof Phctx);
sodium_memzero((void*)&PShctx, sizeof PShctx);
}
-46
View File
@@ -1,46 +0,0 @@
// Copyright (c) 2023, The Monero Project
// Copyright (c) 2021, tevador <tevador@gmail.com>
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
#ifndef PBKDF2_H
#define PBKDF2_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
void
crypto_pbkdf2_sha256(const uint8_t* passwd, size_t passwdlen,
const uint8_t* salt, size_t saltlen, uint64_t c,
uint8_t* buf, size_t dkLen);
#ifdef __cplusplus
}
#endif
#endif
-182
View File
@@ -1,182 +0,0 @@
// Copyright (c) 2023, The Monero Project
// Copyright (c) 2021, tevador <tevador@gmail.com>
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
#include "polyseed.hpp"
#include "pbkdf2.h"
#include <sodium/core.h>
#include <sodium/utils.h>
#include <sodium/randombytes.h>
#include <utf8proc.h>
#include <cstring>
#include <algorithm>
#include <array>
namespace polyseed {
inline size_t utf8_norm(const char* str, polyseed_str norm, utf8proc_option_t options) {
utf8proc_int32_t buffer[POLYSEED_STR_SIZE];
utf8proc_ssize_t result;
result = utf8proc_decompose(reinterpret_cast<const uint8_t*>(str), 0, buffer, POLYSEED_STR_SIZE, options);
if (result < 0 || result > (POLYSEED_STR_SIZE - 1)) {
throw std::runtime_error("Unicode normalization failed");
}
result = utf8proc_reencode(buffer, result, options);
if (result < 0 || result > POLYSEED_STR_SIZE) {
throw std::runtime_error("Unicode normalization failed");
}
strcpy(norm, reinterpret_cast<const char*>(buffer));
sodium_memzero(buffer, POLYSEED_STR_SIZE);
return result;
}
static size_t utf8_nfc(const char* str, polyseed_str norm) {
// Note: UTF8PROC_LUMP is used here to replace the ideographic space with a regular space for Japanese phrases
// to allow wallets to split on ' '.
return utf8_norm(str, norm, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_COMPOSE | UTF8PROC_STRIPNA));
}
static size_t utf8_nfkd(const char* str, polyseed_str norm) {
return utf8_norm(str, norm, (utf8proc_option_t)(UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT | UTF8PROC_STRIPNA));
}
struct dependency {
dependency();
std::vector<language> languages;
};
static dependency deps;
dependency::dependency() {
if (sodium_init() == -1) {
throw std::runtime_error("sodium_init failed");
}
polyseed_dependency pd;
pd.randbytes = &randombytes_buf;
pd.pbkdf2_sha256 = &crypto_pbkdf2_sha256;
pd.memzero = &sodium_memzero;
pd.u8_nfc = &utf8_nfc;
pd.u8_nfkd = &utf8_nfkd;
pd.time = nullptr;
pd.alloc = nullptr;
pd.free = nullptr;
polyseed_inject(&pd);
for (int i = 0; i < polyseed_get_num_langs(); ++i) {
languages.push_back(language(polyseed_get_lang(i)));
}
}
static language invalid_lang;
const std::vector<language>& get_langs() {
return deps.languages;
}
const language& get_lang_by_name(const std::string& name) {
for (auto& lang : deps.languages) {
if (name == lang.name_en()) {
return lang;
}
if (name == lang.name()) {
return lang;
}
}
return invalid_lang;
}
inline void data::check_init() const {
if (valid()) {
throw std::runtime_error("already initialized");
}
}
static std::array<const char*, 8> error_desc = {
"Success",
"Wrong number of words in the phrase",
"Unknown language or unsupported words",
"Checksum mismatch",
"Unsupported seed features",
"Invalid seed format",
"Memory allocation failure",
"Unicode normalization failed"
};
static error get_error(polyseed_status status) {
if (status > 0 && status < sizeof(error_desc) / sizeof(const char*)) {
return error(error_desc[(int)status], status);
}
return error("Unknown error", status);
}
void data::create(feature_type features) {
check_init();
auto status = polyseed_create(features, &m_data);
if (status != POLYSEED_OK) {
throw get_error(status);
}
}
void data::split(const language& lang, polyseed_phrase& words) {
check_init();
if (!lang.valid()) {
throw std::runtime_error("invalid language");
}
}
void data::load(polyseed_storage storage) {
check_init();
auto status = polyseed_load(storage, &m_data);
if (status != POLYSEED_OK) {
throw get_error(status);
}
}
void data::load(const crypto::secret_key &key) {
polyseed_storage d;
memcpy(&d, &key.data, 32);
auto status = polyseed_load(d, &m_data);
if (status != POLYSEED_OK) {
throw get_error(status);
}
}
language data::decode(const char* phrase) {
check_init();
const polyseed_lang* lang;
auto status = polyseed_decode(phrase, m_coin, &lang, &m_data);
if (status != POLYSEED_OK) {
throw get_error(status);
}
return language(lang);
}
}
-167
View File
@@ -1,167 +0,0 @@
// Copyright (c) 2023, The Monero Project
// Copyright (c) 2021, tevador <tevador@gmail.com>
//
// 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
#ifndef POLYSEED_HPP
#define POLYSEED_HPP
#include <polyseed/include/polyseed.h>
#include <polyseed/src/lang.h>
#include <vector>
#include <stdexcept>
#include <string>
#include "crypto/crypto.h"
namespace polyseed {
class data;
class language {
public:
language() : m_lang(nullptr) {}
language(const language&) = default;
language(const polyseed_lang* lang) : m_lang(lang) {}
const char* name() const {
return polyseed_get_lang_name(m_lang);
}
const char* name_en() const {
return polyseed_get_lang_name_en(m_lang);
}
const char* separator() const {
return m_lang->separator;
}
bool valid() const {
return m_lang != nullptr;
}
const polyseed_lang* m_lang;
private:
friend class data;
};
const std::vector<language>& get_langs();
const language& get_lang_by_name(const std::string& name);
class error : public std::runtime_error {
public:
error(const char* msg, polyseed_status status)
: std::runtime_error(msg), m_status(status)
{
}
polyseed_status status() const {
return m_status;
}
private:
polyseed_status m_status;
};
using feature_type = unsigned int;
inline int enable_features(feature_type features) {
return polyseed_enable_features(features);
}
class data {
public:
data(const data&) = delete;
data(polyseed_coin coin) : m_data(nullptr), m_coin(coin) {}
~data() {
polyseed_free(m_data);
}
void create(feature_type features);
void load(polyseed_storage storage);
void load(const crypto::secret_key &key);
language decode(const char* phrase);
template<class str_type>
void encode(const language& lang, str_type& str) const {
check_valid();
if (!lang.valid()) {
throw std::runtime_error("invalid language");
}
str.resize(POLYSEED_STR_SIZE);
auto size = polyseed_encode(m_data, lang.m_lang, m_coin, &str[0]);
str.resize(size);
}
void split(const language& lang, polyseed_phrase& words);
void save(polyseed_storage storage) const {
check_valid();
polyseed_store(m_data, storage);
}
void save(void *storage) const {
check_valid();
polyseed_store(m_data, (uint8_t*)storage);
}
void crypt(const char* password) {
check_valid();
polyseed_crypt(m_data, password);
}
void keygen(void* ptr, size_t key_size) const {
check_valid();
polyseed_keygen(m_data, m_coin, key_size, (uint8_t*)ptr);
}
bool valid() const {
return m_data != nullptr;
}
bool encrypted() const {
check_valid();
return polyseed_is_encrypted(m_data);
}
uint64_t birthday() const {
check_valid();
return polyseed_get_birthday(m_data);
}
bool has_feature(feature_type feature) const {
check_valid();
return polyseed_get_feature(m_data, feature) != 0;
}
private:
void check_valid() const {
if (m_data == nullptr) {
throw std::runtime_error("invalid object");
}
}
void check_init() const;
polyseed_data* m_data;
polyseed_coin m_coin;
};
}
#endif //POLYSEED_HPP
+21 -4
View File
@@ -1879,12 +1879,29 @@ namespace cryptonote
}
blobdata block_blob = t_serializable_object_to_blob(b);
crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx);
const std::vector<crypto::public_key> additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(b.miner_tx);
if(tx_pub_key == crypto::null_pkey)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";
LOG_ERROR("Failed to get tx pub key in coinbase extra");
return false;
// Check for Carrot treasury payout
const uint8_t hf_version = m_core.get_blockchain_storage().get_current_hard_fork_version();
if (hf_version >= HF_VERSION_CARROT && b.miner_tx.vout.size() == 2) {
const auto treasury_payout_data = get_config(nettype()).TREASURY_SAL1_MINT_OUTPUT_DATA;
const bool treasury_payout_exists = (treasury_payout_data.count(height) == 1);
if (!treasury_payout_exists) {
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template (missing treasury payout)";
LOG_ERROR("Failed to get tx pub key in coinbase extra (missing treasury payout)");
return false;
}
tx_pub_key = additional_tx_pub_keys.back();
} else {
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";
LOG_ERROR("Failed to get tx pub key in coinbase extra");
return false;
}
}
uint64_t next_height;
+8 -8
View File
@@ -5335,7 +5335,7 @@ boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::pr
.m_is_carrot = true
};
message_writer(console_color_white, true) << tr("Generated new Carrot wallet: ")
<< cryptonote::get_account_address_as_str(m_wallet->nettype(), false, carrot_address, true);
<< cryptonote::get_account_address_as_str(m_wallet->nettype(), false, carrot_address);
PAUSE_READLINE();
std::cout << tr("View key: ");
print_secret_key(m_wallet->get_account().get_keys().m_view_secret_key);
@@ -7337,25 +7337,25 @@ bool simple_wallet::transfer_main(
switch (transfer_type) {
case Burn:
unlock_block = 0;
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::BURN, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::BURN, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
break;
case Convert:
unlock_block = CONVERT_LOCK_PERIOD;
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::CONVERT, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::CONVERT, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
break;
case Stake:
unlock_block = get_config(m_wallet->nettype()).STAKE_LOCK_PERIOD;
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::STAKE, fake_outs_count, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::STAKE, fake_outs_count, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
break;
case TransferLocked:
unlock_block = locked_blocks;
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::TRANSFER, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::TRANSFER, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
break;
default:
LOG_ERROR("Unknown transfer method, using default");
/* FALLTHRU */
case Transfer:
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::TRANSFER, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
ptx_vector = m_wallet->create_transactions_2(dsts, source_asset, dest_asset, cryptonote::transaction_type::TRANSFER, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
break;
}
}
@@ -11231,9 +11231,9 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
success_msg_writer() << tr("Index: ") << i;
std::string address;
if (row.m_has_payment_id)
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), row.m_address, row.m_payment_id, row.m_is_carrot);
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), row.m_address, row.m_payment_id);
else
address = get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address, row.m_is_carrot);
address = get_account_address_as_str(m_wallet->nettype(), row.m_is_subaddress, row.m_address);
success_msg_writer() << tr("Address: ") << address;
success_msg_writer() << tr("Description: ") << row.m_description << "\n";
}
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "1.0.0"
#define DEF_SALVIUM_VERSION "1.0.6"
#define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.4"
#define DEF_MONERO_RELEASE_NAME "One"
-2
View File
@@ -38,7 +38,6 @@ set(wallet_sources
message_store.cpp
message_transporter.cpp
wallet_rpc_payments.cpp
wallet_cache_to_json.cpp
tx_builder.cpp
)
@@ -52,7 +51,6 @@ monero_add_library(wallet
target_link_libraries(wallet
PUBLIC
rpc_base
bc-ur
multisig
carrot_impl
common
+2 -6
View File
@@ -41,9 +41,7 @@ set(wallet_api_sources
address_book.cpp
subaddress.cpp
subaddress_account.cpp
unsigned_transaction.cpp
coins.cpp
coins_info.cpp)
unsigned_transaction.cpp)
set(wallet_api_headers
wallet2_api.h)
@@ -59,9 +57,7 @@ set(wallet_api_private_headers
address_book.h
subaddress.h
subaddress_account.h
unsigned_transaction.h
coins.h
coins_info.h)
unsigned_transaction.h)
monero_private_headers(wallet_api
${wallet_api_private_headers})
-194
View File
@@ -1,194 +0,0 @@
#include "coins.h"
#include "coins_info.h"
#include "wallet.h"
#include "crypto/hash.h"
#include "wallet/wallet2.h"
#include "common_defines.h"
#include <string>
#include <vector>
using namespace epee;
namespace Monero {
Coins::~Coins() = default;
CoinsImpl::CoinsImpl(WalletImpl *wallet)
: m_wallet(wallet) {}
CoinsImpl::~CoinsImpl()
{
for (auto t : m_rows)
delete t;
}
int CoinsImpl::count() const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
int result = m_rows.size();
return result;
}
CoinsInfo *CoinsImpl::coin(int index) const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
// sanity check
if (index < 0)
return nullptr;
auto index_ = static_cast<unsigned>(index);
return index_ < m_rows.size() ? m_rows[index_] : nullptr;
}
std::vector<CoinsInfo *> CoinsImpl::getAll() const
{
boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
return m_rows;
}
void CoinsImpl::refresh()
{
LOG_PRINT_L2("Refreshing coins");
boost::unique_lock<boost::shared_mutex> lock(m_rowsMutex);
boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_wallet->m_transfers_mutex);
// delete old outputs;
for (auto t : m_rows)
delete t;
m_rows.clear();
for (size_t i = 0; i < m_wallet->m_wallet->get_num_transfer_details(); ++i)
{
const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(i);
// Make a subaddress_index_extended from td.m_subaddr_index
carrot::subaddress_index_extended csub{
{td.m_subaddr_index.major, td.m_subaddr_index.minor},
td.is_carrot() ? carrot::AddressDeriveType::Carrot : carrot::AddressDeriveType::PreCarrot,
false};
auto ci = new CoinsInfoImpl();
ci->m_blockHeight = td.m_block_height;
ci->m_hash = string_tools::pod_to_hex(td.m_txid);
ci->m_internalOutputIndex = td.m_internal_output_index;
ci->m_globalOutputIndex = td.m_global_output_index;
ci->m_spent = td.m_spent;
ci->m_frozen = td.m_frozen;
ci->m_spentHeight = td.m_spent_height;
ci->m_amount = td.m_amount;
ci->m_rct = td.m_rct;
ci->m_keyImageKnown = td.m_key_image_known;
ci->m_pkIndex = td.m_pk_index;
ci->m_subaddrIndex = td.m_subaddr_index.minor;
ci->m_subaddrAccount = td.m_subaddr_index.major;
ci->m_address = m_wallet->m_wallet->get_subaddress_as_str(csub); // todo: this is expensive, cache maybe?
ci->m_addressLabel = m_wallet->m_wallet->get_subaddress_label(td.m_subaddr_index);
ci->m_keyImage = string_tools::pod_to_hex(td.m_key_image);
ci->m_unlockTime = td.m_tx.unlock_time;
ci->m_unlocked = m_wallet->m_wallet->is_transfer_unlocked(td);
ci->m_pubKey = string_tools::pod_to_hex(td.get_public_key());
ci->m_coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen);
ci->m_description = m_wallet->m_wallet->get_tx_note(td.m_txid);
ci->m_asset = td.asset_type;
ci->m_type = td.m_tx.type;
m_rows.push_back(ci);
}
}
void CoinsImpl::setFrozen(std::string public_key)
{
crypto::public_key pk;
if (!epee::string_tools::hex_to_pod(public_key, pk))
{
LOG_ERROR("Invalid public key: " << public_key);
return;
}
try
{
m_wallet->m_wallet->freeze(pk);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("setFrozen: " << e.what());
}
}
void CoinsImpl::setFrozen(int index)
{
try
{
LOG_ERROR("Freezing coin: " << index);
m_wallet->m_wallet->freeze(index);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("setLabel: " << e.what());
}
}
void CoinsImpl::thaw(std::string public_key)
{
crypto::public_key pk;
if (!epee::string_tools::hex_to_pod(public_key, pk))
{
LOG_ERROR("Invalid public key: " << public_key);
return;
}
try
{
m_wallet->m_wallet->thaw(pk);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("thaw: " << e.what());
}
}
void CoinsImpl::thaw(int index)
{
try
{
m_wallet->m_wallet->thaw(index);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("thaw: " << e.what());
}
}
bool CoinsImpl::isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) {
return m_wallet->m_wallet->is_transfer_unlocked(unlockTime, blockHeight);
}
void CoinsImpl::setDescription(const std::string &public_key, const std::string &description)
{
crypto::public_key pk;
if (!epee::string_tools::hex_to_pod(public_key, pk))
{
LOG_ERROR("Invalid public key: " << public_key);
return;
}
try
{
const size_t index = m_wallet->m_wallet->get_transfer_details(pk);
const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(index);
m_wallet->m_wallet->set_tx_note(td.m_txid, description);
refresh();
}
catch (const std::exception& e)
{
LOG_ERROR("setDescription: " << e.what());
}
}
} // namespace
-40
View File
@@ -1,40 +0,0 @@
#ifndef FEATHER_COINS_H
#define FEATHER_COINS_H
#include "wallet/api/wallet2_api.h"
#include "wallet/wallet2.h"
namespace Monero {
class WalletImpl;
class CoinsImpl : public Coins
{
public:
explicit CoinsImpl(WalletImpl * wallet);
~CoinsImpl() override;
int count() const override;
CoinsInfo * coin(int index) const override;
std::vector<CoinsInfo*> getAll() const override;
void refresh() override;
void setFrozen(std::string public_key) override;
void setFrozen(int index) override;
void thaw(std::string public_key) override;
void thaw(int index) override;
bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) override;
void setDescription(const std::string &public_key, const std::string &description) override;
private:
WalletImpl *m_wallet;
std::vector<CoinsInfo*> m_rows;
mutable boost::shared_mutex m_rowsMutex;
};
}
namespace Bitmonero = Monero;
#endif //FEATHER_COINS_H
-132
View File
@@ -1,132 +0,0 @@
#include "coins_info.h"
using namespace std;
namespace Monero {
CoinsInfo::~CoinsInfo() = default;
CoinsInfoImpl::CoinsInfoImpl()
: m_blockHeight(0)
, m_internalOutputIndex(0)
, m_globalOutputIndex(0)
, m_spent(false)
, m_frozen(false)
, m_spentHeight(0)
, m_amount(0)
, m_rct(false)
, m_keyImageKnown(false)
, m_pkIndex(0)
, m_subaddrAccount(0)
, m_subaddrIndex(0)
, m_unlockTime(0)
, m_unlocked(false)
, m_type(0)
{
}
CoinsInfoImpl::~CoinsInfoImpl() = default;
uint64_t CoinsInfoImpl::blockHeight() const
{
return m_blockHeight;
}
string CoinsInfoImpl::hash() const
{
return m_hash;
}
size_t CoinsInfoImpl::internalOutputIndex() const {
return m_internalOutputIndex;
}
uint64_t CoinsInfoImpl::globalOutputIndex() const
{
return m_globalOutputIndex;
}
bool CoinsInfoImpl::spent() const
{
return m_spent;
}
bool CoinsInfoImpl::frozen() const
{
return m_frozen;
}
uint64_t CoinsInfoImpl::spentHeight() const
{
return m_spentHeight;
}
uint64_t CoinsInfoImpl::amount() const
{
return m_amount;
}
bool CoinsInfoImpl::rct() const {
return m_rct;
}
bool CoinsInfoImpl::keyImageKnown() const {
return m_keyImageKnown;
}
size_t CoinsInfoImpl::pkIndex() const {
return m_pkIndex;
}
uint32_t CoinsInfoImpl::subaddrIndex() const {
return m_subaddrIndex;
}
uint32_t CoinsInfoImpl::subaddrAccount() const {
return m_subaddrAccount;
}
string CoinsInfoImpl::address() const {
return m_address;
}
string CoinsInfoImpl::addressLabel() const {
return m_addressLabel;
}
string CoinsInfoImpl::keyImage() const {
return m_keyImage;
}
uint64_t CoinsInfoImpl::unlockTime() const {
return m_unlockTime;
}
bool CoinsInfoImpl::unlocked() const {
return m_unlocked;
}
string CoinsInfoImpl::pubKey() const {
return m_pubKey;
}
bool CoinsInfoImpl::coinbase() const {
return m_coinbase;
}
string CoinsInfoImpl::description() const {
return m_description;
}
string CoinsInfoImpl::asset() const {
return m_asset;
}
uint8_t CoinsInfoImpl::type() const {
return m_type;
}
} // namespace
namespace Bitmonero = Monero;
-75
View File
@@ -1,75 +0,0 @@
#ifndef FEATHER_COINS_INFO_H
#define FEATHER_COINS_INFO_H
#include "wallet/api/wallet2_api.h"
#include <string>
#include <ctime>
namespace Monero {
class CoinsImpl;
class CoinsInfoImpl : public CoinsInfo
{
public:
CoinsInfoImpl();
~CoinsInfoImpl();
virtual uint64_t blockHeight() const override;
virtual std::string hash() const override;
virtual size_t internalOutputIndex() const override;
virtual uint64_t globalOutputIndex() const override;
virtual bool spent() const override;
virtual bool frozen() const override;
virtual uint64_t spentHeight() const override;
virtual uint64_t amount() const override;
virtual bool rct() const override;
virtual bool keyImageKnown() const override;
virtual size_t pkIndex() const override;
virtual uint32_t subaddrIndex() const override;
virtual uint32_t subaddrAccount() const override;
virtual std::string address() const override;
virtual std::string addressLabel() const override;
virtual std::string keyImage() const override;
virtual uint64_t unlockTime() const override;
virtual bool unlocked() const override;
virtual std::string pubKey() const override;
virtual bool coinbase() const override;
virtual std::string description() const override;
virtual std::string asset() const override;
virtual uint8_t type() const override;
private:
uint64_t m_blockHeight;
std::string m_hash;
size_t m_internalOutputIndex;
uint64_t m_globalOutputIndex;
bool m_spent;
bool m_frozen;
uint64_t m_spentHeight;
uint64_t m_amount;
bool m_rct;
bool m_keyImageKnown;
size_t m_pkIndex;
uint32_t m_subaddrIndex;
uint32_t m_subaddrAccount;
std::string m_address;
std::string m_addressLabel;
std::string m_keyImage;
uint64_t m_unlockTime;
bool m_unlocked;
std::string m_pubKey;
bool m_coinbase;
std::string m_description;
std::string m_asset;
uint8_t m_type;
friend class CoinsImpl;
};
} // namespace
namespace Bitmonero = Monero;
#endif //FEATHER_COINS_INFO_H
-55
View File
@@ -42,8 +42,6 @@
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include "bc-ur/src/bc-ur.hpp"
using namespace std;
namespace Monero {
@@ -80,22 +78,6 @@ 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)
{
@@ -180,50 +162,13 @@ 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;
for (const auto &ptx : m_pending_tx) {
if (ptx.tx.type == cryptonote::transaction_type::AUDIT ||
ptx.tx.type == cryptonote::transaction_type::BURN ||
ptx.tx.type == cryptonote::transaction_type::STAKE) {
result += ptx.tx.amount_burnt;
} else {
for (const auto &dest : ptx.dests) {
result += dest.amount;
}
}
}
return result;
}
-3
View File
@@ -46,7 +46,6 @@ 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;
@@ -59,8 +58,6 @@ 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;
+1 -62
View File
@@ -34,60 +34,16 @@
#include "wallet.h"
#include "crypto/hash.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "wallet/wallet2.h"
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
using namespace epee;
namespace Monero {
namespace {
std::string to_hex_or_empty(const crypto::public_key &key)
{
if (key == crypto::null_pkey)
return {};
return string_tools::pod_to_hex(key);
}
std::vector<std::string> extract_return_addresses(const cryptonote::transaction_prefix &tx)
{
std::vector<std::string> addresses;
if (tx.type == cryptonote::transaction_type::STAKE)
{
auto hex = to_hex_or_empty(tx.protocol_tx_data.return_address);
if (hex.empty())
hex = to_hex_or_empty(tx.return_address);
if (!hex.empty())
addresses.push_back(hex);
return addresses;
}
if (tx.type != cryptonote::transaction_type::PROTOCOL)
return addresses;
std::unordered_set<std::string> seen;
for (const auto &out : tx.vout)
{
crypto::public_key output_key = crypto::null_pkey;
if (!cryptonote::get_output_public_key(out, output_key))
continue;
auto hex = to_hex_or_empty(output_key);
if (hex.empty())
continue;
if (seen.emplace(hex).second)
addresses.push_back(hex);
}
return addresses;
}
} // namespace
TransactionHistory::~TransactionHistory() {}
@@ -174,7 +130,6 @@ void TransactionHistoryImpl::refresh()
std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> in_payments;
m_wallet->m_wallet->get_payments(in_payments, min_height, max_height);
std::unordered_map<crypto::hash, TransactionInfoImpl*> protocol_by_hash;
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = in_payments.begin(); i != in_payments.end(); ++i) {
const tools::wallet2::payment_details &pd = i->second;
std::string payment_id = string_tools::pod_to_hex(i->first);
@@ -197,8 +152,6 @@ void TransactionHistoryImpl::refresh()
ti->m_unlock_time = pd.m_unlock_time;
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx_type));
ti->m_asset = pd.m_asset_type;
if (pd.m_tx_type == cryptonote::transaction_type::PROTOCOL)
protocol_by_hash.emplace(pd.m_tx_hash, ti);
m_history.push_back(ti);
}
@@ -244,7 +197,6 @@ void TransactionHistoryImpl::refresh()
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx.type));
ti->m_asset = pd.m_tx.source_asset_type;
ti->m_return_addresses = extract_return_addresses(pd.m_tx);
// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
@@ -283,7 +235,6 @@ void TransactionHistoryImpl::refresh()
ti->m_confirmations = 0;
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx.type));
ti->m_asset = pd.m_tx.source_asset_type;
ti->m_return_addresses = extract_return_addresses(pd.m_tx);
for (const auto &d : pd.m_dests)
{
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id), d.asset_type});
@@ -315,23 +266,11 @@ void TransactionHistoryImpl::refresh()
ti->m_confirmations = 0;
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx_type));
ti->m_asset = pd.m_asset_type;
if (pd.m_tx_type == cryptonote::transaction_type::PROTOCOL)
protocol_by_hash.emplace(pd.m_tx_hash, ti);
m_history.push_back(ti);
LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
}
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> confirmed_protocol_payments;
m_wallet->m_wallet->get_payments_out(confirmed_protocol_payments, min_height, max_height);
for (const auto &entry : confirmed_protocol_payments)
{
const auto it = protocol_by_hash.find(entry.first);
if (it == protocol_by_hash.end())
continue;
it->second->m_return_addresses = extract_return_addresses(entry.second.m_tx);
}
}
} // namespace
-5
View File
@@ -134,11 +134,6 @@ string TransactionInfoImpl::paymentId() const
return m_paymentid;
}
const std::vector<std::string> &TransactionInfoImpl::returnAddresses() const
{
return m_return_addresses;
}
const std::vector<TransactionInfo::Transfer> &TransactionInfoImpl::transfers() const
{
return m_transfers;
-2
View File
@@ -60,7 +60,6 @@ public:
virtual std::string hash() const override;
virtual std::time_t timestamp() const override;
virtual std::string paymentId() const override;
virtual const std::vector<std::string> &returnAddresses() const override;
virtual const std::vector<Transfer> &transfers() const override;
virtual uint64_t confirmations() const override;
virtual uint64_t unlockTime() const override;
@@ -82,7 +81,6 @@ private:
std::string m_hash;
std::time_t m_timestamp;
std::string m_paymentid;
std::vector<std::string> m_return_addresses;
std::vector<Transfer> m_transfers;
uint64_t m_confirmations;
uint64_t m_unlock_time;
-42
View File
@@ -40,8 +40,6 @@
#include <sstream>
#include <boost/format.hpp>
#include "bc-ur/src/bc-ur.hpp"
using namespace std;
namespace Monero {
@@ -98,46 +96,6 @@ 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)
{
-1
View File
@@ -53,7 +53,6 @@ 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;
+59 -729
View File
File diff suppressed because it is too large Load Diff
+3 -53
View File
@@ -47,7 +47,6 @@ class PendingTransactionImpl;
class UnsignedTransactionImpl;
class AddressBookImpl;
class SubaddressImpl;
class CoinsImpl;
class SubaddressAccountImpl;
struct Wallet2CallbackImpl;
@@ -78,28 +77,12 @@ 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);
bool createFromPolyseed(const std::string &path,
const std::string &password,
const std::string &seed,
const std::string &passphrase = "",
bool newWallet = true,
uint64_t restoreHeight = 0);
Device getDeviceType() const override;
bool close(bool store = true);
std::string seed(const std::string& seed_offset = "") const override;
bool getPolyseed(std::string &seed_words, std::string &passphrase) const override;
void setStoreTxInfo(bool store) override;
bool storeTxInfo() const override;
std::string getSeedLanguage() const override;
void setSeedLanguage(const std::string &arg) override;
// void setListener(Listener *) {}
@@ -116,12 +99,7 @@ public:
std::string publicViewKey() const override;
std::string secretSpendKey() const override;
std::string publicSpendKey() const override;
std::vector<std::string> carrotKeys() const override;
std::string publicMultisigSignerKey() const override;
std::string secretViewBalance() const override;
std::string secretProveSpend() const override;
std::string secretGenerateAddress() const override;
std::string secretGenerateImage() const override;
std::string path() const override;
void stop() override;
bool store(const std::string &path) override;
@@ -135,7 +113,6 @@ 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;
@@ -191,29 +168,20 @@ public:
const std::string &asset_type, const bool is_return,
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) override;
std::set<uint32_t> subaddr_indices = {}) override;
PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
optional<uint64_t> amount, uint32_t mixin_count,
const std::string &asset_type, const bool is_return,
PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) override;
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;
@@ -228,7 +196,6 @@ public:
PendingTransaction::Priority priority) const override;
virtual TransactionHistory * history() override;
virtual AddressBook * addressBook() override;
virtual Coins * coins() override;
virtual Subaddress * subaddress() override;
virtual SubaddressAccount * subaddressAccount() override;
virtual void setListener(WalletListener * l) override;
@@ -301,7 +268,6 @@ private:
friend class TransactionHistoryImpl;
friend struct Wallet2CallbackImpl;
friend class AddressBookImpl;
friend class CoinsImpl;
friend class SubaddressImpl;
friend class SubaddressAccountImpl;
@@ -318,10 +284,10 @@ private:
std::unique_ptr<Wallet2CallbackImpl> m_wallet2Callback;
std::unique_ptr<AddressBookImpl> m_addressBook;
std::unique_ptr<SubaddressImpl> m_subaddress;
std::unique_ptr<CoinsImpl> m_coins;
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;
@@ -342,22 +308,6 @@ 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();
virtual std::string serializeCacheToJson() const override;
};
+8 -169
View File
@@ -126,7 +126,6 @@ struct PendingTransaction
virtual std::string errorString() const = 0;
// commit transaction or save to file if filename is provided.
virtual bool commit(const std::string &filename = "", bool overwrite = false) = 0;
virtual std::string commitUR(int max_fragment_length = 130) = 0;
virtual uint64_t amount() const = 0;
virtual uint64_t dust() const = 0;
virtual uint64_t fee() const = 0;
@@ -162,8 +161,6 @@ 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;
};
/**
@@ -198,8 +195,7 @@ struct UnsignedTransaction
* @param signedFileName
* return - true on success
*/
virtual bool sign(const std::string &signedFileName) = 0;
virtual std::string signUR(int max_fragment_length = 130) = 0;
virtual bool sign(const std::string &signedFileName) = 0;
};
/**
@@ -238,7 +234,6 @@ struct TransactionInfo
virtual std::string hash() const = 0;
virtual std::time_t timestamp() const = 0;
virtual std::string paymentId() const = 0;
virtual const std::vector<std::string> & returnAddresses() const = 0;
//! only applicable for output transactions
virtual const std::vector<Transfer> & transfers() const = 0;
virtual Monero::transaction_type type() const = 0;
@@ -304,53 +299,6 @@ struct AddressBook
virtual int lookupPaymentID(const std::string &payment_id) const = 0;
};
/**
* @brief The CoinsInfo - interface for displaying coins information
*/
struct CoinsInfo
{
virtual ~CoinsInfo() = 0;
virtual uint64_t blockHeight() const = 0;
virtual std::string hash() const = 0;
virtual size_t internalOutputIndex() const = 0;
virtual uint64_t globalOutputIndex() const = 0;
virtual bool spent() const = 0;
virtual bool frozen() const = 0;
virtual uint64_t spentHeight() const = 0;
virtual uint64_t amount() const = 0;
virtual bool rct() const = 0;
virtual bool keyImageKnown() const = 0;
virtual size_t pkIndex() const = 0;
virtual uint32_t subaddrIndex() const = 0;
virtual uint32_t subaddrAccount() const = 0;
virtual std::string address() const = 0;
virtual std::string addressLabel() const = 0;
virtual std::string keyImage() const = 0;
virtual uint64_t unlockTime() const = 0;
virtual bool unlocked() const = 0;
virtual std::string pubKey() const = 0;
virtual bool coinbase() const = 0;
virtual std::string description() const = 0;
virtual std::string asset() const = 0;
virtual uint8_t type() const = 0;
};
struct Coins
{
virtual ~Coins() = 0;
virtual int count() const = 0;
virtual CoinsInfo * coin(int index) const = 0;
virtual std::vector<CoinsInfo*> getAll() const = 0;
virtual void refresh() = 0;
virtual void setFrozen(std::string public_key) = 0;
virtual void setFrozen(int index) = 0;
virtual void thaw(std::string public_key) = 0;
virtual void thaw(int index) = 0;
virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
virtual void setDescription(const std::string &public_key, const std::string &description) = 0;
};
struct SubaddressRow {
public:
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
@@ -553,8 +501,6 @@ struct Wallet
virtual ~Wallet() = 0;
virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual void setStoreTxInfo(bool store) = 0;
virtual bool storeTxInfo() const = 0;
virtual std::string getSeedLanguage() const = 0;
virtual void setSeedLanguage(const std::string &arg) = 0;
//! returns wallet status (Status_Ok | Status_Error)
@@ -613,48 +559,12 @@ struct Wallet
*/
virtual std::string publicSpendKey() const = 0;
/*!
* \brief allCarrotKeys - returns all Carrot keys
* [0] - s_master
* [1] - k_prove_spend
* [2] - s_view_balance
* [3] - k_view_incoming
* [4] - k_generate_image
* [5] - s_generate_address
* \return - vector of all Carrot keys
*/
virtual std::vector<std::string> carrotKeys() const = 0;
/*!
* \brief publicMultisigSignerKey - returns public signer key
* \return - public multisignature signer key or empty string if wallet is not multisig
*/
virtual std::string publicMultisigSignerKey() const = 0;
/*!
* \brief secretViewBalance - returns Carrot "view balance" secret
* \return - Carrot s_vb
*/
virtual std::string secretViewBalance() const = 0;
/*!
* \brief secretProveSpend - returns Carrot "prove spend" secret
* \return - Carrot secret k_ps
*/
virtual std::string secretProveSpend() const = 0;
/*!
* \brief secretGenerateAddress - returns Carrot "generate address" secret
* \return - Carrot secret s_ga
*/
virtual std::string secretGenerateAddress() const = 0;
/*!
* \brief secretGenerateImage - returns Carrot "generate key image" secret
* \return - Carrot secret k_gi
*/
virtual std::string secretGenerateImage() const = 0;
/*!
* \brief stop - interrupts wallet refresh() loop once (doesn't stop background refresh thread)
*/
@@ -764,7 +674,6 @@ 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
@@ -845,10 +754,6 @@ struct Wallet
static void warning(const std::string &category, const std::string &str);
static void error(const std::string &category, const std::string &str);
virtual bool getPolyseed(std::string &seed, std::string &passphrase) const = 0;
static bool createPolyseed(std::string &seed_words, std::string &err, const std::string &language = "English");
static std::vector<std::pair<std::string, std::string>> getPolyseedLanguages();
/**
* @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
*/
@@ -1028,8 +933,7 @@ struct Wallet
const std::string &asset_type, const bool is_return,
PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) = 0;
std::set<uint32_t> subaddr_indices = {}) = 0;
/*!
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
@@ -1051,8 +955,7 @@ struct Wallet
const std::string &asset_type, const bool is_return,
PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
std::set<uint32_t> subaddr_indices = {},
const std::set<std::string> &preferred_inputs = {}) = 0;
std::set<uint32_t> subaddr_indices = {}) = 0;
/*!
* \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
@@ -1068,15 +971,13 @@ 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
@@ -1092,8 +993,6 @@ 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
@@ -1101,22 +1000,20 @@ 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 exportOutputs - exports outputs to file
* \brief importOutputs - 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
@@ -1124,7 +1021,6 @@ 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
@@ -1171,7 +1067,6 @@ struct Wallet
virtual TransactionHistory * history() = 0;
virtual AddressBook * addressBook() = 0;
virtual Coins * coins() = 0;
virtual Subaddress * subaddress() = 0;
virtual SubaddressAccount * subaddressAccount() = 0;
virtual void setListener(WalletListener *) = 0;
@@ -1327,22 +1222,6 @@ struct Wallet
//! get bytes sent
virtual uint64_t getBytesSent() = 0;
// HIDAPI_DUMMY
static bool getStateIsConnected();
static unsigned char* getSendToDevice();
static size_t getSendToDeviceLength();
static unsigned char* getReceivedFromDevice();
static size_t getReceivedFromDeviceLength();
static bool getWaitsForDeviceSend();
static bool getWaitsForDeviceReceive();
static void setDeviceReceivedData(unsigned char* data, size_t len);
static void setDeviceSendData(unsigned char* data, size_t len);
static void setLedgerCallback(void (*sendToLedgerDevice)(unsigned char *command, unsigned int cmd_len));
//! serialize wallet cache to JSON
virtual std::string serializeCacheToJson() const = 0;
//! get yield information
virtual YieldInfo * getYieldInfo() = 0;
};
@@ -1452,25 +1331,6 @@ 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
@@ -1522,27 +1382,6 @@ struct WalletManager
uint64_t kdf_rounds = 1,
WalletListener * listener = nullptr) = 0;
/*!
* \brief creates a wallet from a polyseed mnemonic phrase
* \param path Name of the wallet file to be created
* \param password Password of wallet file
* \param nettype Network type
* \param mnemonic Polyseed mnemonic
* \param passphrase Optional seed offset passphrase
* \param newWallet Whether it is a new wallet
* \param restoreHeight Override the embedded restore height
* \param kdf_rounds Number of rounds for key derivation function
* @return
*/
virtual Wallet * createWalletFromPolyseed(const std::string &path,
const std::string &password,
NetworkType nettype,
const std::string &mnemonic,
const std::string &passphrase = "",
bool newWallet = true,
uint64_t restore_height = 0,
uint64_t kdf_rounds = 1) = 0;
/*!
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
* \param wallet previously opened / created wallet instance
+4 -33
View File
@@ -127,22 +127,6 @@ 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,
@@ -172,15 +156,6 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
return wallet;
}
Wallet *WalletManagerImpl::createWalletFromPolyseed(const std::string &path, const std::string &password, NetworkType nettype,
const std::string &mnemonic, const std::string &passphrase,
bool newWallet, uint64_t restoreHeight, uint64_t kdf_rounds)
{
WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
wallet->createFromPolyseed(path, password, mnemonic, passphrase, newWallet, restoreHeight);
return wallet;
}
bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store)
{
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
@@ -213,14 +188,10 @@ 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
{
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;
}
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;
}
std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
-17
View File
@@ -67,13 +67,6 @@ 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,
@@ -82,16 +75,6 @@ public:
const std::string &subaddressLookahead = "",
uint64_t kdf_rounds = 1,
WalletListener * listener = nullptr) override;
virtual Wallet * createWalletFromPolyseed(const std::string &path,
const std::string &password,
NetworkType nettype,
const std::string &mnemonic,
const std::string &passphrase,
bool newWallet = true,
uint64_t restore_height = 0,
uint64_t kdf_rounds = 1) override;
virtual bool closeWallet(Wallet *wallet, bool store = true) override;
bool walletExists(const std::string &path) override;
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override;
+13 -8
View File
@@ -148,7 +148,7 @@ static cryptonote::tx_destination_entry make_tx_destination_entry(
const carrot::CarrotPaymentProposalV1 &payment_proposal)
{
cryptonote::tx_destination_entry dest = cryptonote::tx_destination_entry(payment_proposal.amount,
{payment_proposal.destination.address_spend_pubkey, payment_proposal.destination.address_view_pubkey},
{payment_proposal.destination.address_spend_pubkey, payment_proposal.destination.address_view_pubkey, /*m_is_carrot*/true},
payment_proposal.destination.is_subaddress);
dest.is_integrated = payment_proposal.destination.payment_id != carrot::null_payment_id;
return dest;
@@ -166,8 +166,8 @@ static cryptonote::tx_destination_entry make_tx_destination_entry(
"make_tx_destination_entry: view-key multiplication failed");
return cryptonote::tx_destination_entry(payment_proposal.proposal.amount,
{payment_proposal.proposal.destination_address_spend_pubkey, address_view_pubkey},
payment_proposal.subaddr_index.index.is_subaddress());
{payment_proposal.proposal.destination_address_spend_pubkey, address_view_pubkey, /*m_is_carrot*/true},
payment_proposal.subaddr_index.index.is_subaddress());
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
@@ -1360,11 +1360,16 @@ wallet2::pending_tx make_pending_carrot_tx(const carrot::CarrotTransactionPropos
ptx.change_dts = change_dts;
ptx.selected_transfers = std::move(selected_transfers);
ptx.key_images = key_images_string.str();
ptx.tx_key = shared_ephemeral_pubkey ? ephemeral_privkeys.at(0) : crypto::null_skey;
if (shared_ephemeral_pubkey)
ptx.additional_tx_keys = std::move(ephemeral_privkeys);
else
ptx.additional_tx_keys.clear();
if (ephemeral_privkeys.size() == 1) {
ptx.tx_key = ephemeral_privkeys.at(0);
ptx.additional_tx_keys.clear();
} else if (ephemeral_privkeys.size() == 2 && shared_ephemeral_pubkey) {
ptx.tx_key = (ephemeral_privkeys.at(0) == crypto::null_skey) ? ephemeral_privkeys.at(1) : ephemeral_privkeys.at(0);
ptx.additional_tx_keys.clear();
} else {
ptx.tx_key = crypto::null_skey;
ptx.additional_tx_keys = std::move(ephemeral_privkeys);
}
ptx.dests = std::move(dests);
ptx.multisig_sigs = {};
ptx.multisig_tx_key_entropy = {};
+111 -253
View File
@@ -95,7 +95,6 @@ using namespace epee;
#include "device/device_cold.hpp"
#include "device_trezor/device_trezor.hpp"
#include "net/socks_connect.h"
#include "polyseed/include/polyseed.h"
#include "carrot_impl/format_utils.h"
#include "tx_builder.h"
#include "scanning_tools.h"
@@ -969,16 +968,6 @@ 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);
@@ -1219,7 +1208,6 @@ 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),
@@ -1291,8 +1279,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_send_change_back_to_subaddress(false),
m_pool_info_query_time(0),
m_has_ever_refreshed_from_node(false),
m_allow_mismatched_daemon_version(false),
m_polyseed(false)
m_allow_mismatched_daemon_version(false)
{
set_rpc_client_secret_key(rct::rct2sk(rct::skGen()));
}
@@ -1437,14 +1424,6 @@ 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);
@@ -1473,13 +1452,11 @@ 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;
}
@@ -1489,25 +1466,10 @@ 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;
crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
}
return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::get_polyseed(epee::wipeable_string& polyseed, epee::wipeable_string& passphrase) const
{
if (!m_polyseed) {
return false;
}
polyseed::data data(POLYSEED_COIN);
data.load(get_account().get_keys().m_polyseed);
data.encode(polyseed::get_lang_by_name(seed_language), polyseed);
passphrase = get_account().get_keys().m_passphrase;
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -1610,10 +1572,12 @@ cryptonote::account_public_address wallet2::get_subaddress(const cryptonote::sub
//----------------------------------------------------------------------------------------------------
boost::optional<cryptonote::subaddress_index> wallet2::get_subaddress_index(const cryptonote::account_public_address& address) const
{
auto index = m_subaddresses.find(address.m_spend_public_key);
if (index == m_subaddresses.end())
const auto subaddress_map = m_account.get_subaddress_map_ref();
auto carrot_index = subaddress_map.find(address.m_spend_public_key);
if (carrot_index == subaddress_map.end())
return boost::none;
return index->second;
cryptonote::subaddress_index index{carrot_index->second.index.major, carrot_index->second.index.minor};
return index;
}
//----------------------------------------------------------------------------------------------------
crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const
@@ -1644,7 +1608,7 @@ std::string wallet2::get_subaddress_as_str(const carrot::subaddress_index_extend
addr.m_is_carrot = subaddr.derive_type == carrot::AddressDeriveType::Carrot;
// change this code into base 58
return cryptonote::get_account_address_as_str(m_nettype, address.is_subaddress, addr, addr.m_is_carrot);
return cryptonote::get_account_address_as_str(m_nettype, address.is_subaddress, addr);
}
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id, bool carrot) const
@@ -1656,7 +1620,7 @@ std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_
account_public_address addr{address.address_spend_pubkey, address.address_view_pubkey};
addr.m_is_carrot = carrot;
return cryptonote::get_account_integrated_address_as_str(m_nettype, addr, payment_id, carrot);
return cryptonote::get_account_integrated_address_as_str(m_nettype, addr, payment_id);
}
//----------------------------------------------------------------------------------------------------
void wallet2::add_subaddress_account(const std::string& label)
@@ -1689,6 +1653,7 @@ bool wallet2::should_expand(const cryptonote::subaddress_index &index) const
void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{
hw::device &hwdev = m_account.get_device();
std::unordered_map<crypto::public_key, carrot::subaddress_index_extended> new_addresses;
if (m_subaddress_labels.size() <= index.major)
{
// add new accounts
@@ -1702,6 +1667,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{
const crypto::public_key &D = pkeys[index2.minor];
m_subaddresses[D] = index2;
new_addresses.insert({D, {{index2.major, index2.minor}, carrot::AddressDeriveType::PreCarrot, false}});
}
}
m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
@@ -1719,9 +1685,12 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{
const crypto::public_key &D = pkeys[index2.minor - begin];
m_subaddresses[D] = index2;
new_addresses.insert({D, {{index2.major, index2.minor}, carrot::AddressDeriveType::PreCarrot, false}});
}
m_subaddress_labels[index.major].resize(index.minor + 1);
}
// Add to the Carrot account
m_account.insert_subaddresses(new_addresses);
}
//----------------------------------------------------------------------------------------------------
void wallet2::create_one_off_subaddress(const cryptonote::subaddress_index& index)
@@ -2156,21 +2125,12 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
return false;
}
void wallet2::freeze(const crypto::public_key &pk)
{
freeze(get_transfer_details(pk));
}
//----------------------------------------------------------------------------------------------------
void wallet2::freeze(const crypto::key_image &ki)
{
freeze(get_transfer_details(ki));
}
//----------------------------------------------------------------------------------------------------
void wallet2::thaw(const crypto::public_key &pk)
{
thaw(get_transfer_details(pk));
}
//----------------------------------------------------------------------------------------------------
void wallet2::thaw(const crypto::key_image &ki)
{
thaw(get_transfer_details(ki));
@@ -2181,18 +2141,6 @@ bool wallet2::frozen(const crypto::key_image &ki) const
return frozen(get_transfer_details(ki));
}
//----------------------------------------------------------------------------------------------------
size_t wallet2::get_transfer_details(const crypto::public_key &pk) const
{
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
{
const transfer_details &td = m_transfers[idx];
if (td.get_public_key() == pk) {
return idx;
}
}
CHECK_AND_ASSERT_THROW_MES(false, "Public key not found");
}
//----------------------------------------------------------------------------------------------------
size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
{
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
@@ -2701,7 +2649,6 @@ void wallet2::process_new_scanned_transaction(
continue;
// update m_transfers view-incoming scan info, and default values
boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
transfer_details& td = m_transfers.emplace_back();
td.m_block_height = height;
td.m_internal_output_index = local_output_index;
@@ -4258,7 +4205,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 && m_refreshEnabled)
while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks)
{
uint64_t next_blocks_start_height;
std::vector<cryptonote::block_complete_entry> next_blocks;
@@ -4935,9 +4882,6 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
value2.SetInt(m_enable_multisig ? 1 : 0);
json.AddMember("enable_multisig", value2, json.GetAllocator());
value2.SetInt(m_polyseed ? 1 : 0);
json.AddMember("polyseed", value2, json.GetAllocator());
value2.SetInt(m_freeze_incoming_payments ? 1 : 0);
json.AddMember("freeze_incoming_payments", value2, json.GetAllocator());
@@ -5185,7 +5129,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
m_send_change_back_to_subaddress = false;
m_allow_mismatched_daemon_version = false;
m_custom_background_key = boost::none;
m_polyseed = false;
}
else if(json.IsObject())
{
@@ -5430,9 +5373,6 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, background_sync_type, BackgroundSyncType, Int, false, BackgroundSyncOff);
m_background_sync_type = field_background_sync_type;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, polyseed, int, Int, false, false);
m_polyseed = field_polyseed;
// Load encryption key used to encrypt background cache
crypto::chacha_key custom_background_key;
m_custom_background_key = boost::none;
@@ -5690,7 +5630,8 @@ void wallet2::create_keys_file(const std::string &wallet_, bool watch_only, cons
if (create_address_file)
{
r = save_to_file(m_wallet_file + ".address.txt", m_account.get_public_address_str(m_nettype), true);
std::string addresses = m_account.get_public_address_str(m_nettype) + "\n" + m_account.get_carrot_public_address_str(m_nettype) + "\n";
r = save_to_file(m_wallet_file + ".address.txt", addresses, true);
if(!r) MERROR("String with address text not saved");
}
}
@@ -5762,48 +5703,6 @@ void wallet2::init_type(hw::device::device_type device_type)
m_key_device_type = device_type;
}
/*!
* \brief Generates a polyseed wallet or restores one.
* \param wallet_ Name of wallet file
* \param password Password of wallet file
* \param passphrase Seed offset passphrase
* \param recover Whether it is a restore
* \param seed_words If it is a restore, the polyseed
* \param create_address_file Whether to create an address file
* \return The secret key of the generated wallet
*/
void wallet2::generate(const std::string& wallet_, const epee::wipeable_string& password,
const polyseed::data &seed, const epee::wipeable_string& passphrase, bool recover, uint64_t restoreHeight, bool create_address_file)
{
clear();
prepare_file_names(wallet_);
if (!wallet_.empty()) {
boost::system::error_code ignored_ec;
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
}
m_account.create_from_polyseed(seed, passphrase);
init_type(hw::device::device_type::SOFTWARE);
m_polyseed = true;
setup_keys(password);
if (recover) {
m_refresh_from_block_height = estimate_blockchain_height(restoreHeight > 0 ? restoreHeight : seed.birthday());
} else {
m_refresh_from_block_height = estimate_blockchain_height();
}
create_keys_file(wallet_, false, password, m_nettype != MAINNET || create_address_file);
setup_new_blockchain();
if (!wallet_.empty())
store();
}
/*!
* \brief Generates a wallet or restores one. Assumes the multisig setup
* has already completed for the provided multisig info.
@@ -5931,7 +5830,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
return retval;
}
uint64_t wallet2::estimate_blockchain_height(uint64_t time)
uint64_t wallet2::estimate_blockchain_height()
{
// -1 month for fluctuations in block time and machine date/time setup.
// avg seconds per block
@@ -5955,7 +5854,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
// the daemon is currently syncing.
// If we use the approximate height we subtract one month as
// a safety margin.
height = get_approximate_blockchain_height(time);
height = get_approximate_blockchain_height();
uint64_t target_height = get_daemon_blockchain_target_height(err);
if (err.empty()) {
if (target_height < height)
@@ -6715,7 +6614,9 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, m_keys_file);
}
LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype));
LOG_PRINT_L0("Loaded wallet keys file, with public addresses: ");
LOG_PRINT_L0(" CN : " << m_account.get_public_address_str(m_nettype));
LOG_PRINT_L0(" Carrot : " << m_account.get_carrot_public_address_str(m_nettype));
lock_keys_file();
}
else if (!load_keys_buf(keys_buf, password))
@@ -6762,6 +6663,8 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
if (get_num_subaddress_accounts() == 0)
add_subaddress_account(tr("Primary account"));
m_account.generate_subaddress_map(get_subaddress_lookahead());
// populate account subaddress list
if (!m_subaddresses.empty())
{
@@ -7290,29 +7193,6 @@ 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;
@@ -7956,7 +7836,7 @@ void wallet2::commit_tx(pending_tx& ptx)
amount_in += m_transfers[idx].amount();
}
add_unconfirmed_tx(ptx.tx, amount_in, dests, payment_id, ptx.change_dts.amount, subaddr_account, subaddr_indices);
if (store_tx_info() && ptx.tx_key != crypto::null_skey)
if (store_tx_info() && (ptx.tx_key != crypto::null_skey || ptx.additional_tx_keys.size() != 0))
{
m_tx_keys[txid] = ptx.tx_key;
m_additional_tx_keys[txid] = ptx.additional_tx_keys;
@@ -8233,7 +8113,9 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
crypto::key_derivation derivation;
std::vector<crypto::key_derivation> additional_derivations;
crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
// 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);
std::vector<crypto::public_key> additional_tx_pub_keys;
for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
{
@@ -10769,7 +10651,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2("transfer_selected_rct done");
}
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type, const std::vector<crypto::key_image>& preferred_input_list)
std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type)
{
std::vector<size_t> picks;
float current_output_relatdness = 1.0f;
@@ -10786,9 +10668,6 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
for (size_t i: m_transfers_indices[asset_type])
{
const transfer_details& td = m_transfers[i];
if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
continue;
}
if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && 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)
@@ -10810,9 +10689,6 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
{
size_t idx = *i;
const transfer_details& td = m_transfers[idx];
if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
continue;
}
if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && 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)
@@ -10828,9 +10704,6 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
{
size_t idx2 = *j;
const transfer_details& td2 = m_transfers[idx2];
if (!is_preferred_input(preferred_input_list, td2.m_key_image)) {
continue;
}
if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below)
{
MDEBUG("Ignoring output " << idx2 << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
@@ -10933,7 +10806,7 @@ static uint32_t get_count_above(const std::vector<wallet2::transfer_details> &tr
// This system allows for sending (almost) the entire balance, since it does
// not generate spurious change in all txes, thus decreasing the instantaneous
// usable balance.
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list, const unique_index_container& subtract_fee_from_outputs)
std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs)
{
//ensure device is let in NONE mode in any case
hw::device &hwdev = m_account.get_device();
@@ -11200,15 +11073,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
for (size_t i: m_transfers_indices[source_asset])
{
const transfer_details& td = m_transfers[i];
if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
continue;
}
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
{
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 && 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 (!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 (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
{
@@ -11258,15 +11128,9 @@ 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");
// 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 (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
return std::vector<wallet2::pending_tx>();
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({});
@@ -11294,7 +11158,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// will get us a known fee.
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : estimated_fee);
preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices, source_asset, preferred_input_list);
preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices, source_asset);
if (!preferred_inputs.empty())
{
string s;
@@ -11788,11 +11652,14 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
return true;
}
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, cryptonote::transaction_type tx_type, const std::string &asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list)
std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, cryptonote::transaction_type tx_type, const std::string &asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
{
const bool do_carrot_tx_construction = use_fork_rules(HF_VERSION_CARROT);
if (do_carrot_tx_construction)
{
// Sanity checks
THROW_WALLET_EXCEPTION_IF(!address.m_is_carrot, error::wallet_internal_error, "CryptoNote address supplied, but Carrot is now active");
const auto tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep_all(*this, below, address, is_subaddress, outputs, priority, extra, tx_type, subaddr_account, subaddr_indices);
std::vector<pending_tx> ptx_vector;
ptx_vector.reserve(tx_proposals.size());
@@ -11801,6 +11668,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
return ptx_vector;
}
// Sanity checks
THROW_WALLET_EXCEPTION_IF(address.m_is_carrot, error::wallet_internal_error, "Carrot address supplied, but Carrot not yet active");
std::vector<size_t> unused_transfers_indices;
std::vector<size_t> unused_dust_indices;
const bool use_per_byte_fee = true;
@@ -11834,9 +11704,6 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
{
//size_t i = m_transfers_indices[asset_type][idx];
const transfer_details& td = m_transfers[i];
if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
continue;
}
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
{
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold));
@@ -11886,6 +11753,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
const bool do_carrot_tx_construction = use_fork_rules(HF_VERSION_CARROT);
if (do_carrot_tx_construction)
{
// Sanity checks
THROW_WALLET_EXCEPTION_IF(!address.m_is_carrot, error::wallet_internal_error, "CryptoNote address supplied, but Carrot is now active");
const auto tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(*this, {ki}, address, is_subaddress, outputs, priority, extra, tx_type);
std::vector<pending_tx> ptx_vector;
ptx_vector.reserve(tx_proposals.size());
@@ -11895,6 +11765,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt
return ptx_vector;
}
// Sanity checks
THROW_WALLET_EXCEPTION_IF(address.m_is_carrot, error::wallet_internal_error, "Carrot address supplied, but Carrot not yet active");
std::vector<size_t> unused_transfers_indices;
std::vector<size_t> unused_dust_indices;
const bool use_rct = use_fork_rules(4, 0);
@@ -11982,8 +11855,13 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
} else {
THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "Unsupported input type for return_payment");
}
const mx25519_pubkey origin_tx_shared_secret_unctx = carrot::raw_byte_convert<mx25519_pubkey>(main_derivations[0]);
THROW_WALLET_EXCEPTION_IF(!main_derivations.size() && !additional_derivations.size(), error::wallet_internal_error, "No derivations found");
THROW_WALLET_EXCEPTION_IF(!main_derivations.size() && additional_derivations.size() < td_origin.m_internal_output_index + 1, error::wallet_internal_error, "No derivations found");
const key_derivation derivation = (main_derivations.size() == 1) ? main_derivations[0] : additional_derivations[td_origin.m_internal_output_index];
const mx25519_pubkey origin_tx_shared_secret_unctx = carrot::raw_byte_convert<mx25519_pubkey>(derivation);
// 4. compute m_return
crypto::public_key output_key;
carrot::encrypted_return_pubkey_t m_return;
@@ -12013,7 +11891,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
// 6. compute the change index
crypto::secret_key z_i;
derivation_to_scalar(main_derivations[0], td_origin.m_internal_output_index, z_i);
derivation_to_scalar(derivation, td_origin.m_internal_output_index, z_i);
struct {
char domain_separator[8];
crypto::secret_key output_index_key;
@@ -12037,6 +11915,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
cryptonote::account_public_address address;
address.m_spend_public_key = change_key;
address.m_view_public_key = return_pub;
address.m_is_carrot = true;
return create_transactions_from(address, cryptonote::transaction_type::RETURN, asset_type, is_subaddress, outputs, transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra);
}
@@ -12531,7 +12410,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. Please check your connection and/or switch node you are connected to currently.");
THROW_WALLET_EXCEPTION_IF(result, error::wallet_internal_error, "Failed to get earliest fork height");
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)
@@ -12721,8 +12600,8 @@ bool wallet2::get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx
if (i == m_tx_keys.end())
return false;
tx_key = i->second;
if (tx_key == crypto::null_skey)
return false;
//if (tx_key == crypto::null_skey)
// return false;
const auto j = m_additional_tx_keys.find(txid);
if (j != m_additional_tx_keys.end())
additional_tx_keys = j->second;
@@ -13865,7 +13744,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
return target_height;
}
uint64_t wallet2::get_approximate_blockchain_height(uint64_t t) const
uint64_t wallet2::get_approximate_blockchain_height() const
{
if (m_nettype != MAINNET) return 0;
@@ -13876,7 +13755,7 @@ uint64_t wallet2::get_approximate_blockchain_height(uint64_t t) const
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
uint64_t approx_blockchain_height = fork_block + ((t > 0 ? t : time(NULL)) - fork_time)/seconds_per_block;
uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
return approx_blockchain_height;
}
@@ -14162,40 +14041,33 @@ 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
{
std::string data = export_key_images_str(all);
return save_to_file(filename, data);
PERF_TIMER(export_key_images);
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
const uint32_t offset = ski.first;
std::string data;
data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
data.resize(4);
data[0] = offset & 0xff;
data[1] = (offset >> 8) & 0xff;
data[2] = (offset >> 16) & 0xff;
data[3] = (offset >> 24) & 0xff;
data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
for (const auto &i: ski.second)
{
data += std::string((const char *)&i.first, sizeof(crypto::key_image));
data += std::string((const char *)&i.second, sizeof(crypto::signature));
}
// encrypt data, keep magic plaintext
PERF_TIMER(export_key_images_encrypt);
std::string ciphertext = encrypt_with_view_secret_key(data);
return save_to_file(filename, magic + ciphertext);
}
std::string wallet2::export_key_images_str(bool all) const
{
PERF_TIMER(export_key_images);
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
const uint32_t offset = ski.first;
std::string data;
data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
data.resize(4);
data[0] = offset & 0xff;
data[1] = (offset >> 8) & 0xff;
data[2] = (offset >> 16) & 0xff;
data[3] = (offset >> 24) & 0xff;
data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
for (const auto &i: ski.second)
{
data += std::string((const char *)&i.first, sizeof(crypto::key_image));
data += std::string((const char *)&i.second, sizeof(crypto::signature));
}
// encrypt data, keep magic plaintext
PERF_TIMER(export_key_images_encrypt);
std::string ciphertext = encrypt_with_view_secret_key(data);
return magic + ciphertext;
}
//----------------------------------------------------------------------------------------------------
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
{
@@ -14255,60 +14127,53 @@ 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) {
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)
uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent)
{
PERF_TIMER(import_key_images_fsu);
std::string data_local = data;
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);
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"));
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
}
try
{
PERF_TIMER(import_key_images_decrypt);
data_local = decrypt_with_view_secret_key(std::string(data, magiclen));
data = 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 ") + ": " + e.what());
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
}
const size_t headerlen = 4 + 2 * 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)];
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)];
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 ") + " are for a different account");
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " 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_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;
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;
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_local[headerlen + n * record_size]);
crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data_local[headerlen + n * record_size + sizeof(crypto::key_image)]);
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)]);
ski.push_back(std::make_pair(key_image, signature));
}
@@ -16000,21 +15865,6 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day)
{
std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 };
date.tm_year = year - 1900;
date.tm_mon = month - 1;
date.tm_mday = day;
if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday)
{
throw std::runtime_error("month or day out of range");
}
uint64_t timestamp_target = std::mktime(&date);
return get_blockchain_height_by_timestamp(timestamp_target);
}
uint64_t wallet2::get_blockchain_height_by_timestamp(uint64_t timestamp_target) {
uint32_t version;
if (!check_connection(&version))
{
@@ -16024,7 +15874,15 @@ uint64_t wallet2::get_blockchain_height_by_timestamp(uint64_t timestamp_target)
{
throw std::runtime_error("this function requires RPC version 1.6 or higher");
}
std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 };
date.tm_year = year - 1900;
date.tm_mon = month - 1;
date.tm_mday = day;
if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday)
{
throw std::runtime_error("month or day out of range");
}
uint64_t timestamp_target = std::mktime(&date);
std::string err;
uint64_t height_min = 0;
uint64_t height_max = get_daemon_blockchain_height(err) - 1;
+5 -48
View File
@@ -78,7 +78,6 @@
#include "message_store.h"
#include "wallet_light_rpc.h"
#include "wallet_rpc_helpers.h"
#include "polyseed/polyseed.hpp"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
@@ -994,20 +993,6 @@ private:
void generate(const std::string& wallet_, const epee::wipeable_string& password,
const epee::wipeable_string& multisig_data, bool create_address_file = false);
/*!
* \brief Generates a wallet from a polyseed.
* @param wallet_ Name of wallet file
* @param password Password of wallet file
* @param seed Polyseed data
* @param passphrase Optional seed offset passphrase
* @param recover Whether it is a restore
* @param restoreHeight Override the embedded restore height
* @param create_address_file Whether to create an address file
*/
void generate(const std::string& wallet_, const epee::wipeable_string& password,
const polyseed::data &seed, const epee::wipeable_string& passphrase = "",
bool recover = false, uint64_t restoreHeight = 0, bool create_address_file = false);
/*!
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
@@ -1186,8 +1171,6 @@ 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(); }
@@ -1203,15 +1186,6 @@ private:
bool is_deterministic() const;
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
/*!
* \brief get_polyseed Gets the polyseed (if available) and passphrase (if set) needed to recover the wallet.
* @param seed Polyseed mnemonic phrase
* @param passphrase Seed offset passphrase that was used to restore the wallet
* @return Returns true if the wallet has a polyseed.
* Note: both the mnemonic phrase and the passphrase are needed to recover the wallet
*/
bool get_polyseed(epee::wipeable_string& seed, epee::wipeable_string &passphrase) const;
/*!
* \brief Gets the seed language
*/
@@ -1272,7 +1246,6 @@ 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);
@@ -1321,8 +1294,8 @@ private:
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {}, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, cryptonote::transaction_type tx_type, const std::string& asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {});
std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const std::string& source_asset, const std::string& dest_asset, const cryptonote::transaction_type tx_type, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, cryptonote::transaction_type tx_type, const std::string& asset_type, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
std::vector<wallet2::pending_tx> create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, const cryptonote::transaction_type tx_type, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
std::vector<wallet2::pending_tx> create_transactions_return(std::vector<size_t> transfers_indices);
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, const cryptonote::transaction_type tx_type, const std::string& asset_type, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
@@ -1551,12 +1524,6 @@ private:
FIELD(m_return_output_info)
END_SERIALIZE()
/*!
* \brief Serialize wallet cache fields to JSON
* \return const char* pointing to JSON string containing all cache fields
*/
const char* serialize_cache_to_json() const;
/*!
* \brief Check if wallet keys and bin files exist
* \param file_path Wallet file path
@@ -1700,7 +1667,6 @@ private:
uint64_t get_num_rct_outputs();
size_t get_num_transfer_details() const { return m_transfers.size(); }
const transfer_details &get_transfer_details(size_t idx) const;
size_t get_transfer_details(const crypto::public_key &pk) const;
uint8_t estimate_current_hard_fork(const uint64_t height = 0) const;
uint8_t get_current_hard_fork();
@@ -1719,8 +1685,8 @@ private:
/*!
* \brief Calculates the approximate blockchain height from current date/time.
*/
uint64_t get_approximate_blockchain_height(uint64_t time = 0) const;
uint64_t estimate_blockchain_height(uint64_t time = 0);
uint64_t get_approximate_blockchain_height() const;
uint64_t estimate_blockchain_height();
std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct);
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
std::vector<size_t> select_available_unmixable_outputs();
@@ -1789,11 +1755,9 @@ 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;
@@ -1814,7 +1778,6 @@ private:
bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error);
uint64_t get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day); // 1<=month<=12, 1<=day<=31
uint64_t get_blockchain_height_by_timestamp(uint64_t timestamp);
bool is_synced();
@@ -1915,9 +1878,7 @@ private:
void freeze(size_t idx);
void thaw(size_t idx);
bool frozen(size_t idx) const;
void freeze(const crypto::public_key &pk);
void freeze(const crypto::key_image &ki);
void thaw(const crypto::public_key &pk);
void thaw(const crypto::key_image &ki);
bool frozen(const crypto::key_image &ki) const;
bool frozen(const transfer_details &td) const;
@@ -1958,8 +1919,6 @@ private:
static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; }
boost::shared_mutex m_transfers_mutex;
bool get_pricing_record(oracle::pricing_record& pr, const uint64_t height);
bool get_circulating_supply(std::vector<std::pair<std::string, std::string>> &amounts);
bool get_yield_info(std::vector<cryptonote::yield_block_info>& ybi_data);
@@ -2107,7 +2066,7 @@ private:
std::vector<uint64_t> get_unspent_amounts_vector(bool strict);
uint64_t get_dynamic_base_fee_estimate();
float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const;
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type, const std::vector<crypto::key_image>& preferred_input_list);
std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::string& asset_type);
void set_spent(size_t idx, uint64_t height);
void set_spent(const crypto::key_image &ki, const uint64_t height);
void set_unspent(size_t idx);
@@ -2220,7 +2179,6 @@ 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;
@@ -2229,7 +2187,6 @@ private:
std::string seed_language; /*!< Language of the mnemonics (seed). */
bool is_old_file_format; /*!< Whether the wallet file is of an old file format */
bool m_watch_only; /*!< no spend key */
bool m_polyseed;
bool m_multisig; /*!< if > 1 spend secret key will not match spend public key */
uint32_t m_multisig_threshold;
std::vector<crypto::public_key> m_multisig_signers;
-368
View File
@@ -1,368 +0,0 @@
#include "wallet2.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"
#include "serialization/serialization.h"
#include <sstream>
#include <iomanip>
namespace tools
{
static void write_escaped_json_string(std::ostream& os, const std::string& str)
{
for (char c : str) {
switch (c) {
case '"': os << "\\\""; break;
case '\\': os << "\\\\"; break;
case '\n': os << "\\n"; break;
case '\r': os << "\\r"; break;
case '\t': os << "\\t"; break;
case '\b': os << "\\b"; break;
case '\f': os << "\\f"; break;
default: os << c; break;
}
}
}
static void post_process_json(std::string& json)
{
// ": ," --> ": null,"
size_t pos = 0;
while ((pos = json.find(": ,", pos)) != std::string::npos) {
json.replace(pos, 3, ": null,");
pos += 7;
}
// ": }" --> ": null}"
pos = 0;
while ((pos = json.find(": }", pos)) != std::string::npos) {
json.replace(pos, 3, ": null}");
pos += 7;
}
// ": ]" --> ": null]"
pos = 0;
while ((pos = json.find(": ]", pos)) != std::string::npos) {
json.replace(pos, 3, ": null]");
pos += 7;
}
// "key": number"hexstring" --> "key": "numberhexstring"
pos = 0;
while (pos < json.length()) {
size_t colon_pos = json.find(": ", pos);
if (colon_pos == std::string::npos) break;
size_t value_start = colon_pos + 2;
if (value_start >= json.length()) break;
if (std::isdigit(json[value_start])) {
size_t quote_pos = json.find('"', value_start);
if (quote_pos != std::string::npos && quote_pos < json.find_first_of(",}]", value_start)) {
size_t closing_quote = json.find('"', quote_pos + 1);
if (closing_quote != std::string::npos && closing_quote < json.find_first_of(",}]", value_start)) {
std::string digits;
size_t digit_end = value_start;
while (digit_end < quote_pos && std::isdigit(json[digit_end])) {
digits += json[digit_end];
digit_end++;
}
if (digit_end == quote_pos && !digits.empty()) {
std::string hex_part = json.substr(quote_pos + 1, closing_quote - quote_pos - 1);
std::string replacement = "\"" + digits + hex_part + "\"";
json.replace(value_start, closing_quote - value_start + 1, replacement);
pos = value_start + replacement.length();
continue;
}
}
}
}
pos = colon_pos + 1;
}
}
const char* wallet2::serialize_cache_to_json() const
{
static std::string json_result;
try
{
std::stringstream oss;
json_archive<true> ar(oss, true); // true for pretty printing
ar.begin_object();
// MAGIC_FIELD("monero wallet cache")
std::string magic = "monero wallet cache";
ar.tag("magic");
ar.serialize_blob((void*)magic.data(), magic.size());
if (!ar.good()) {
json_result = "{\"error\":\"Failed to serialize magic field\"}";
return json_result.c_str();
}
// VERSION_FIELD(2)
uint32_t version = 2;
ar.tag("version");
ar.serialize_varint(version);
if (!ar.good()) {
json_result = "{\"error\":\"Failed to serialize version field\"}";
return json_result.c_str();
}
// FIELD(m_blockchain) - hashchain type, has serialization support
ar.tag("m_blockchain");
if (!::serialization::serialize(ar, const_cast<hashchain&>(m_blockchain))) {
json_result = "{\"error\":\"Failed to serialize m_blockchain\"}";
return json_result.c_str();
}
// FIELD(m_transfers) - transfer_container (std::vector<transfer_details>)
ar.tag("m_transfers");
if (!::serialization::serialize(ar, const_cast<transfer_container&>(m_transfers))) {
json_result = "{\"error\":\"Failed to serialize m_transfers\"}";
return json_result.c_str();
}
// FIELD(m_account_public_address) - cryptonote::account_public_address
ar.tag("m_account_public_address");
if (!::serialization::serialize(ar, const_cast<cryptonote::account_public_address&>(m_account_public_address))) {
json_result = "{\"error\":\"Failed to serialize m_account_public_address\"}";
return json_result.c_str();
}
// FIELD(m_key_images) - serializable_unordered_map<crypto::key_image, size_t>
ar.tag("m_key_images");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::key_image, size_t>&>(m_key_images))) {
json_result = "{\"error\":\"Failed to serialize m_key_images\"}";
return json_result.c_str();
}
// FIELD(m_unconfirmed_txs) - serializable_unordered_map<crypto::hash, unconfirmed_transfer_details>
ar.tag("m_unconfirmed_txs");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, unconfirmed_transfer_details>&>(m_unconfirmed_txs))) {
json_result = "{\"error\":\"Failed to serialize m_unconfirmed_txs\"}";
return json_result.c_str();
}
// FIELD(m_payments) - payment_container (serializable_unordered_multimap<crypto::hash, payment_details>)
ar.tag("m_payments");
if (!::serialization::serialize(ar, const_cast<payment_container&>(m_payments))) {
json_result = "{\"error\":\"Failed to serialize m_payments\"}";
return json_result.c_str();
}
// FIELD(m_tx_keys) - serializable_unordered_map<crypto::hash, crypto::secret_key>
ar.tag("m_tx_keys");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, crypto::secret_key>&>(m_tx_keys))) {
json_result = "{\"error\":\"Failed to serialize m_tx_keys\"}";
return json_result.c_str();
}
// FIELD(m_confirmed_txs) - serializable_unordered_map<crypto::hash, confirmed_transfer_details>
ar.tag("m_confirmed_txs");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, confirmed_transfer_details>&>(m_confirmed_txs))) {
json_result = "{\"error\":\"Failed to serialize m_confirmed_txs\"}";
return json_result.c_str();
}
// FIELD(m_tx_notes) - serializable_unordered_map<crypto::hash, std::string>
ar.tag("m_tx_notes");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::string>&>(m_tx_notes))) {
json_result = "{\"error\":\"Failed to serialize m_tx_notes\"}";
return json_result.c_str();
}
// FIELD(m_unconfirmed_payments) - serializable_unordered_multimap<crypto::hash, pool_payment_details>
ar.tag("m_unconfirmed_payments");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_multimap<crypto::hash, pool_payment_details>&>(m_unconfirmed_payments))) {
json_result = "{\"error\":\"Failed to serialize m_unconfirmed_payments\"}";
return json_result.c_str();
}
// FIELD(m_pub_keys) - serializable_unordered_map<crypto::public_key, size_t>
ar.tag("m_pub_keys");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, size_t>&>(m_pub_keys))) {
json_result = "{\"error\":\"Failed to serialize m_pub_keys\"}";
return json_result.c_str();
}
// FIELD(m_address_book) - std::vector<tools::wallet2::address_book_row>
ar.tag("m_address_book");
if (!::serialization::serialize(ar, const_cast<std::vector<tools::wallet2::address_book_row>&>(m_address_book))) {
json_result = "{\"error\":\"Failed to serialize m_address_book\"}";
return json_result.c_str();
}
// FIELD(m_scanned_pool_txs[0]) - std::unordered_set<crypto::hash>
ar.tag("m_scanned_pool_txs_0");
if (!::serialization::serialize(ar, const_cast<std::unordered_set<crypto::hash>&>(m_scanned_pool_txs[0]))) {
json_result = "{\"error\":\"Failed to serialize m_scanned_pool_txs[0]\"}";
return json_result.c_str();
}
// FIELD(m_scanned_pool_txs[1]) - std::unordered_set<crypto::hash>
ar.tag("m_scanned_pool_txs_1");
if (!::serialization::serialize(ar, const_cast<std::unordered_set<crypto::hash>&>(m_scanned_pool_txs[1]))) {
json_result = "{\"error\":\"Failed to serialize m_scanned_pool_txs[1]\"}";
return json_result.c_str();
}
// FIELD(m_subaddresses) - serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index>
ar.tag("m_subaddresses");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, cryptonote::subaddress_index>&>(m_subaddresses))) {
json_result = "{\"error\":\"Failed to serialize m_subaddresses\"}";
return json_result.c_str();
}
// FIELD(m_subaddress_labels) - std::vector<std::vector<std::string>> - manual JSON serialization
oss << ", \n \"m_subaddress_labels\": [";
for (size_t i = 0; i < m_subaddress_labels.size(); ++i) {
if (i > 0) oss << ", ";
oss << "\n [";
for (size_t j = 0; j < m_subaddress_labels[i].size(); ++j) {
if (j > 0) oss << ", ";
oss << "\"";
write_escaped_json_string(oss, m_subaddress_labels[i][j]);
oss << "\"";
}
oss << "]";
}
oss << "\n ]";
// FIELD(m_additional_tx_keys) - serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>>
ar.tag("m_additional_tx_keys");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::vector<crypto::secret_key>>&>(m_additional_tx_keys))) {
json_result = "{\"error\":\"Failed to serialize m_additional_tx_keys\"}";
return json_result.c_str();
}
// FIELD(m_attributes) - serializable_unordered_map<std::string, std::string> - manual JSON serialization
oss << ", \n \"m_attributes\": {";
bool first_attr = true;
for (const auto& attr : m_attributes) {
if (!first_attr) oss << ", ";
first_attr = false;
oss << "\n \"";
write_escaped_json_string(oss, attr.first);
oss << "\": \"";
write_escaped_json_string(oss, attr.second);
oss << "\"";
}
oss << "\n }";
// FIELD(m_account_tags) - std::pair<serializable_map<std::string, std::string>, std::vector<std::string>> - manual JSON serialization
oss << ", \n \"m_account_tags\": {";
oss << "\n \"tags_map\": {";
bool first_tag = true;
for (const auto& tag : m_account_tags.first) {
if (!first_tag) oss << ", ";
first_tag = false;
oss << "\n \"";
write_escaped_json_string(oss, tag.first);
oss << "\": \"";
write_escaped_json_string(oss, tag.second);
oss << "\"";
}
oss << "\n },";
oss << "\n \"account_list\": [";
for (size_t i = 0; i < m_account_tags.second.size(); ++i) {
if (i > 0) oss << ", ";
oss << "\n \"";
write_escaped_json_string(oss, m_account_tags.second[i]);
oss << "\"";
}
oss << "\n ]";
oss << "\n }";
// FIELD(m_ring_history_saved) - bool
// ar.tag("m_ring_history_saved");
// ar.serialize_blob(&m_ring_history_saved, sizeof(m_ring_history_saved));
// if (!ar.good()) {
// json_result = "{\"error\":\"Failed to serialize m_ring_history_saved\"}";
// return json_result.c_str();
// }
// FIELD(m_last_block_reward) - uint64_t
ar.tag("m_last_block_reward");
ar.serialize_int(m_last_block_reward);
if (!ar.good()) {
json_result = "{\"error\":\"Failed to serialize m_last_block_reward\"}";
return json_result.c_str();
}
// FIELD(m_tx_device) - serializable_unordered_map<crypto::hash, std::string>
ar.tag("m_tx_device");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::hash, std::string>&>(m_tx_device))) {
json_result = "{\"error\":\"Failed to serialize m_tx_device\"}";
return json_result.c_str();
}
// FIELD(m_device_last_key_image_sync) - uint64_t
ar.tag("m_device_last_key_image_sync");
ar.serialize_int(m_device_last_key_image_sync);
if (!ar.good()) {
json_result = "{\"error\":\"Failed to serialize m_device_last_key_image_sync\"}";
return json_result.c_str();
}
// FIELD(m_cold_key_images) - serializable_unordered_map<crypto::public_key, crypto::key_image>
ar.tag("m_cold_key_images");
if (!::serialization::serialize(ar, const_cast<serializable_unordered_map<crypto::public_key, crypto::key_image>&>(m_cold_key_images))) {
json_result = "{\"error\":\"Failed to serialize m_cold_key_images\"}";
return json_result.c_str();
}
// FIELD(m_rpc_client_secret_key) - crypto::secret_key
// ar.tag("m_rpc_client_secret_key");
// ar.serialize_blob(&m_rpc_client_secret_key, sizeof(m_rpc_client_secret_key));
// if (!ar.good()) {
// json_result = "{\"error\":\"Failed to serialize m_rpc_client_secret_key\"}";
// return json_result.c_str();
// }
// Version-dependent fields
if (version >= 1) {
// FIELD(m_has_ever_refreshed_from_node) - bool
// ar.tag("m_has_ever_refreshed_from_node");
// ar.serialize_blob(&m_has_ever_refreshed_from_node, sizeof(m_has_ever_refreshed_from_node));
// if (!ar.good()) {
// json_result = "{\"error\":\"Failed to serialize m_has_ever_refreshed_from_node\"}";
// return json_result.c_str();
// }
}
if (version >= 2) {
// FIELD(m_background_sync_data) - background_sync_data_t
ar.tag("m_background_sync_data");
if (!::serialization::serialize(ar, const_cast<background_sync_data_t&>(m_background_sync_data))) {
json_result = "{\"error\":\"Failed to serialize m_background_sync_data\"}";
return json_result.c_str();
}
}
ar.end_object();
if (!ar.good()) {
json_result = "{\"error\":\"Failed to finalize JSON serialization\"}";
return json_result.c_str();
}
json_result = oss.str();
// Post-process to fix malformed JSON
post_process_json(json_result);
return json_result.c_str();
}
catch (const std::exception& e)
{
json_result = "{\"error\":\"Failed to serialize wallet cache: " + std::string(e.what()) + "\"}";
return json_result.c_str();
}
}
} // namespace tools
+3 -52
View File
@@ -1302,7 +1302,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())
{
@@ -2355,55 +2355,6 @@ namespace tools
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().m_spend_secret_key);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("s_master") == 0)
{
if (m_wallet->watch_only())
{
er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY;
er.message = "The wallet is watch-only. Cannot retrieve s_master key.";
return false;
}
CHECK_IF_BACKGROUND_SYNCING();
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().s_master);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("k_prove_spend") == 0)
{
if (m_wallet->watch_only())
{
er.code = WALLET_RPC_ERROR_CODE_WATCH_ONLY;
er.message = "The wallet is watch-only. Cannot retrieve k_prove_spend key.";
return false;
}
CHECK_IF_BACKGROUND_SYNCING();
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().k_prove_spend);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("s_view_balance") == 0)
{
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().s_view_balance);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("s_view_balance") == 0)
{
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().s_view_balance);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("k_view_incoming") == 0)
{
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().k_view_incoming);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("k_generate_image") == 0)
{
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().k_generate_image);
res.key = std::string(key.data(), key.size());
}
else if(req.key_type.compare("s_generate_address") == 0)
{
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().s_generate_address);
res.key = std::string(key.data(), key.size());
}
else
{
er.message = "key_type " + req.key_type + " not found";
@@ -3354,9 +3305,9 @@ namespace tools
const auto &entry = ab[idx];
std::string address;
if (entry.m_has_payment_id)
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.m_address, entry.m_payment_id, entry.m_is_carrot);
address = cryptonote::get_account_integrated_address_as_str(m_wallet->nettype(), entry.m_address, entry.m_payment_id);
else
address = get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address, entry.m_is_carrot);
address = get_account_address_as_str(m_wallet->nettype(), entry.m_is_subaddress, entry.m_address);
res.entries.push_back(wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::entry{idx, address, entry.m_description});
}
}
+3637 -3375
View File
File diff suppressed because it is too large Load Diff
+3833 -3572
View File
File diff suppressed because one or more lines are too long
+3832 -3571
View File
File diff suppressed because it is too large Load Diff
+3973 -3712
View File
File diff suppressed because one or more lines are too long
+3832 -3571
View File
File diff suppressed because it is too large Load Diff
+3832 -3571
View File
File diff suppressed because one or more lines are too long
+3832 -3571
View File
File diff suppressed because it is too large Load Diff
+3832 -3571
View File
File diff suppressed because it is too large Load Diff
+3832 -3571
View File
File diff suppressed because one or more lines are too long
+3832 -3571
View File
File diff suppressed because it is too large Load Diff
+3832 -3571
View File
File diff suppressed because it is too large Load Diff