Compare commits

...

11 Commits

Author SHA1 Message Date
auruya 5297072257 fix outgoing transfer destination addresses 2025-10-17 15:16:07 +03:00
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
23 changed files with 42177 additions and 39276 deletions
+5 -5
View File
@@ -1,4 +1,4 @@
# Salvium One v1.0.3 # Salvium One v1.0.6
Copyright (c) 2023-2025, Salvium Copyright (c) 2023-2025, Salvium
Portions Copyright (c) 2014-2023, The Monero Project Portions Copyright (c) 2014-2023, The Monero Project
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
```bash ```bash
cd salvium cd salvium
git checkout v1.0.3 git checkout v1.0.6
make make
``` ```
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash ```bash
git clone https://github.com/salvium/salvium git clone https://github.com/salvium/salvium
cd salvium cd salvium
git checkout v1.0.3 git checkout v1.0.6
``` ```
* Build: * Build:
@@ -370,10 +370,10 @@ application.
cd salvium 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.3'. 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 ```bash
git checkout v1.0.3 git checkout v1.0.6
``` ```
* If you are on a 64-bit system, run: * If you are on a 64-bit system, run:
+11 -6
View File
@@ -282,13 +282,13 @@ crypto::key_image carrot_and_legacy_account::derive_key_image(const crypto::publ
return L; 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}; 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) 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; this->default_derive_type = AddressDeriveType::Carrot;
generate_subaddress_map();
} }
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_derive_type) 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; m_keys.m_carrot_main_address.m_is_carrot = true;
this->default_derive_type = default_derive_type; 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) 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) 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}}); 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) 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::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const; 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( crypto::secret_key generate(
const crypto::secret_key& recovery_key = crypto::secret_key(), const crypto::secret_key& recovery_key = crypto::secret_key(),
+3 -3
View File
@@ -41,9 +41,9 @@
namespace carrot 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(bad_address_type, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(component_out_of_order, 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(too_many_outputs, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(invalid_tx_type, 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(crypto_function_failed, carrot_runtime_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_money, carrot_runtime_error) CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_money, carrot_runtime_error)
+2 -2
View File
@@ -519,7 +519,7 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
crypto::secret_key sum_g; crypto::secret_key sum_g;
sc_add(to_bytes(sum_g), to_bytes(sender_extension_g_out), to_bytes(k_return)); 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( 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, sum_g,
sender_extension_t_out, sender_extension_t_out,
K_r K_r
@@ -527,7 +527,7 @@ bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
crypto::secret_key x, y; crypto::secret_key x, y;
account.try_searching_for_opening_for_onetime_address( 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, sum_g,
sender_extension_t_out, sender_extension_t_out,
x, x,
+5 -1
View File
@@ -129,10 +129,12 @@ namespace cryptonote
std::string asset_type; std::string asset_type;
bool is_subaddress; bool is_subaddress;
bool is_integrated; bool is_integrated;
bool is_carrot;
bool is_change; bool is_change;
bool is_return; bool is_return;
tx_destination_entry() : amount(0), slippage_limit(0), addr(AUTO_VAL_INIT(addr)), is_subaddress(false), is_integrated(false), is_change(false), is_return(false) { } tx_destination_entry() : amount(0), slippage_limit(0), addr(AUTO_VAL_INIT(addr)), is_subaddress(false), is_integrated(false), is_change(false), is_return(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress, bool is_return, bool is_carrot) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false), is_carrot(is_carrot) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { } tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress, bool is_return) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(is_return) { } tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress, bool is_return) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(is_return) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { } tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { }
@@ -144,7 +146,7 @@ namespace cryptonote
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { } tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress, bool is_return) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(is_return) { } tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress, bool is_return) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false), is_return(is_return) { }
*/ */
std::string address(network_type nettype, const crypto::hash &payment_id) const std::string address(network_type nettype, const crypto::hash &payment_id)
{ {
if (!original.empty()) if (!original.empty())
{ {
@@ -156,6 +158,7 @@ namespace cryptonote
return get_account_integrated_address_as_str(nettype, addr, reinterpret_cast<const crypto::hash8 &>(payment_id)); return get_account_integrated_address_as_str(nettype, addr, reinterpret_cast<const crypto::hash8 &>(payment_id));
} }
addr.m_is_carrot = is_carrot;
return get_account_address_as_str(nettype, is_subaddress, addr); return get_account_address_as_str(nettype, is_subaddress, addr);
} }
@@ -168,6 +171,7 @@ namespace cryptonote
FIELD(is_integrated) FIELD(is_integrated)
FIELD(is_change) FIELD(is_change)
FIELD(is_return) FIELD(is_return)
FIELD(is_carrot)
END_SERIALIZE() END_SERIALIZE()
}; };
+10 -9
View File
@@ -7248,6 +7248,7 @@ bool simple_wallet::transfer_main(
de.asset_type = dest_asset; de.asset_type = dest_asset;
de.is_subaddress = info.is_subaddress; de.is_subaddress = info.is_subaddress;
de.is_integrated = info.has_payment_id; de.is_integrated = info.has_payment_id;
de.is_carrot = info.is_carrot;
if (info.has_payment_id || !payment_id_uri.empty()) if (info.has_payment_id || !payment_id_uri.empty())
{ {
@@ -9958,14 +9959,14 @@ bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vec
if (out || burnt || staked) { if (out || burnt || staked) {
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments; std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments;
m_wallet->get_payments_out(payments, min_height, max_height, m_current_subaddress_account, subaddr_indices); m_wallet->get_payments_out(payments, min_height, max_height, m_current_subaddress_account, subaddr_indices);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::iterator i = payments.begin(); i != payments.end(); ++i) {
const tools::wallet2::confirmed_transfer_details &pd = i->second; tools::wallet2::confirmed_transfer_details &pd = i->second;
if (!out && !staked && pd.m_tx.type != cryptonote::transaction_type::BURN) continue; if (!out && !staked && pd.m_tx.type != cryptonote::transaction_type::BURN) continue;
if (!out && !burnt && pd.m_tx.type != cryptonote::transaction_type::STAKE) continue; if (!out && !burnt && pd.m_tx.type != cryptonote::transaction_type::STAKE) continue;
uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
uint64_t fee = pd.m_amount_in - pd.m_amount_out; uint64_t fee = pd.m_amount_in - pd.m_amount_out;
std::vector<std::pair<std::string, uint64_t>> destinations; std::vector<std::pair<std::string, uint64_t>> destinations;
for (const auto &d: pd.m_dests) { for (auto &d: pd.m_dests) {
destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount}); destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount});
} }
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
@@ -10046,12 +10047,12 @@ bool simple_wallet::get_transfers(std::vector<std::string>& local_args, std::vec
if (pending || failed) { if (pending || failed) {
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments; std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
m_wallet->get_unconfirmed_payments_out(upayments, m_current_subaddress_account, subaddr_indices); m_wallet->get_unconfirmed_payments_out(upayments, m_current_subaddress_account, subaddr_indices);
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::iterator i = upayments.begin(); i != upayments.end(); ++i) {
const tools::wallet2::unconfirmed_transfer_details &pd = i->second; tools::wallet2::unconfirmed_transfer_details &pd = i->second;
uint64_t amount = pd.m_amount_in; uint64_t amount = pd.m_amount_in;
uint64_t fee = amount - pd.m_amount_out; uint64_t fee = amount - pd.m_amount_out;
std::vector<std::pair<std::string, uint64_t>> destinations; std::vector<std::pair<std::string, uint64_t>> destinations;
for (const auto &d: pd.m_dests) { for (auto &d: pd.m_dests) {
destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount}); destinations.push_back({d.address(m_wallet->nettype(), pd.m_payment_id), d.amount});
} }
std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id); std::string payment_id = string_tools::pod_to_hex(i->second.m_payment_id);
@@ -11806,14 +11807,14 @@ bool simple_wallet::show_transfer(const std::vector<std::string> &args)
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out; std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out;
m_wallet->get_payments_out(payments_out, 0, (uint64_t)-1, m_current_subaddress_account); m_wallet->get_payments_out(payments_out, 0, (uint64_t)-1, m_current_subaddress_account);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::iterator i = payments_out.begin(); i != payments_out.end(); ++i) {
if (i->first == txid) if (i->first == txid)
{ {
const tools::wallet2::confirmed_transfer_details &pd = i->second; tools::wallet2::confirmed_transfer_details &pd = i->second;
uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known uint64_t change = pd.m_change == (uint64_t)-1 ? 0 : pd.m_change; // change may not be known
uint64_t fee = pd.m_amount_in - pd.m_amount_out; uint64_t fee = pd.m_amount_in - pd.m_amount_out;
std::string dests; std::string dests;
for (const auto &d: pd.m_dests) { for (auto &d: pd.m_dests) {
if (!dests.empty()) if (!dests.empty())
dests += ", "; dests += ", ";
dests += d.address(m_wallet->nettype(), pd.m_payment_id) + ": " + print_money(d.amount); dests += d.address(m_wallet->nettype(), pd.m_payment_id) + ": " + print_money(d.amount);
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@" #define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "1.0.3" #define DEF_SALVIUM_VERSION "1.0.6"
#define DEF_MONERO_VERSION_TAG "release" #define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.4" #define DEF_MONERO_VERSION "0.18.3.4"
#define DEF_MONERO_RELEASE_NAME "One" #define DEF_MONERO_RELEASE_NAME "One"
+2 -2
View File
@@ -149,7 +149,7 @@ static cryptonote::tx_destination_entry make_tx_destination_entry(
{ {
cryptonote::tx_destination_entry dest = cryptonote::tx_destination_entry(payment_proposal.amount, cryptonote::tx_destination_entry dest = cryptonote::tx_destination_entry(payment_proposal.amount,
{payment_proposal.destination.address_spend_pubkey, payment_proposal.destination.address_view_pubkey, /*m_is_carrot*/true}, {payment_proposal.destination.address_spend_pubkey, payment_proposal.destination.address_view_pubkey, /*m_is_carrot*/true},
payment_proposal.destination.is_subaddress); payment_proposal.destination.is_subaddress, false, true);
dest.is_integrated = payment_proposal.destination.payment_id != carrot::null_payment_id; dest.is_integrated = payment_proposal.destination.payment_id != carrot::null_payment_id;
return dest; return dest;
} }
@@ -167,7 +167,7 @@ static cryptonote::tx_destination_entry make_tx_destination_entry(
return cryptonote::tx_destination_entry(payment_proposal.proposal.amount, return cryptonote::tx_destination_entry(payment_proposal.proposal.amount,
{payment_proposal.proposal.destination_address_spend_pubkey, address_view_pubkey, /*m_is_carrot*/true}, {payment_proposal.proposal.destination_address_spend_pubkey, address_view_pubkey, /*m_is_carrot*/true},
payment_proposal.subaddr_index.index.is_subaddress()); payment_proposal.subaddr_index.index.is_subaddress(), false, true);
} }
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------------------------
+25 -7
View File
@@ -1572,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 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); const auto subaddress_map = m_account.get_subaddress_map_ref();
if (index == m_subaddresses.end()) auto carrot_index = subaddress_map.find(address.m_spend_public_key);
if (carrot_index == subaddress_map.end())
return boost::none; 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 crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const
@@ -1651,6 +1653,7 @@ bool wallet2::should_expand(const cryptonote::subaddress_index &index) const
void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index) void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{ {
hw::device &hwdev = m_account.get_device(); 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) if (m_subaddress_labels.size() <= index.major)
{ {
// add new accounts // add new accounts
@@ -1664,6 +1667,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{ {
const crypto::public_key &D = pkeys[index2.minor]; const crypto::public_key &D = pkeys[index2.minor];
m_subaddresses[D] = index2; 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"}); m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
@@ -1681,9 +1685,12 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
{ {
const crypto::public_key &D = pkeys[index2.minor - begin]; const crypto::public_key &D = pkeys[index2.minor - begin];
m_subaddresses[D] = index2; 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); 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) void wallet2::create_one_off_subaddress(const cryptonote::subaddress_index& index)
@@ -5623,7 +5630,8 @@ void wallet2::create_keys_file(const std::string &wallet_, bool watch_only, cons
if (create_address_file) 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"); if(!r) MERROR("String with address text not saved");
} }
} }
@@ -6606,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); 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(); lock_keys_file();
} }
else if (!load_keys_buf(keys_buf, password)) else if (!load_keys_buf(keys_buf, password))
@@ -6653,6 +6663,8 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
if (get_num_subaddress_accounts() == 0) if (get_num_subaddress_accounts() == 0)
add_subaddress_account(tr("Primary account")); add_subaddress_account(tr("Primary account"));
m_account.generate_subaddress_map(get_subaddress_lookahead());
// populate account subaddress list // populate account subaddress list
if (!m_subaddresses.empty()) if (!m_subaddresses.empty())
{ {
@@ -11843,7 +11855,12 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
} else { } else {
THROW_WALLET_EXCEPTION_IF(true, error::wallet_internal_error, "Unsupported input type for return_payment"); 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 // 4. compute m_return
crypto::public_key output_key; crypto::public_key output_key;
@@ -11874,7 +11891,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
// 6. compute the change index // 6. compute the change index
crypto::secret_key z_i; 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 { struct {
char domain_separator[8]; char domain_separator[8];
crypto::secret_key output_index_key; crypto::secret_key output_index_key;
@@ -11898,6 +11915,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_return(std::vector
cryptonote::account_public_address address; cryptonote::account_public_address address;
address.m_spend_public_key = change_key; address.m_spend_public_key = change_key;
address.m_view_public_key = return_pub; 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); 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);
} }
+10 -9
View File
@@ -444,7 +444,7 @@ namespace tools
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time); set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time);
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd) void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, tools::wallet2::confirmed_transfer_details &pd)
{ {
entry.txid = string_tools::pod_to_hex(txid); entry.txid = string_tools::pod_to_hex(txid);
entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id); entry.payment_id = string_tools::pod_to_hex(pd.m_payment_id);
@@ -459,7 +459,7 @@ namespace tools
entry.amount = pd.m_amount_in - change - entry.fee; entry.amount = pd.m_amount_in - change - entry.fee;
entry.note = m_wallet->get_tx_note(txid); entry.note = m_wallet->get_tx_note(txid);
for (const auto &d: pd.m_dests) { for (auto &d: pd.m_dests) {
entry.destinations.push_back(wallet_rpc::transfer_destination()); entry.destinations.push_back(wallet_rpc::transfer_destination());
wallet_rpc::transfer_destination &td = entry.destinations.back(); wallet_rpc::transfer_destination &td = entry.destinations.back();
td.amount = d.amount; td.amount = d.amount;
@@ -478,7 +478,7 @@ namespace tools
set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time); set_confirmations(entry, m_wallet->get_blockchain_current_height(), m_wallet->get_last_block_reward(), pd.m_unlock_time);
} }
//------------------------------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------
void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd) void wallet_rpc_server::fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, tools::wallet2::unconfirmed_transfer_details &pd)
{ {
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
entry.txid = string_tools::pod_to_hex(txid); entry.txid = string_tools::pod_to_hex(txid);
@@ -494,7 +494,7 @@ namespace tools
entry.locked = true; entry.locked = true;
entry.note = m_wallet->get_tx_note(txid); entry.note = m_wallet->get_tx_note(txid);
for (const auto &d: pd.m_dests) { for (auto &d: pd.m_dests) {
entry.destinations.push_back(wallet_rpc::transfer_destination()); entry.destinations.push_back(wallet_rpc::transfer_destination());
wallet_rpc::transfer_destination &td = entry.destinations.back(); wallet_rpc::transfer_destination &td = entry.destinations.back();
td.amount = d.amount; td.amount = d.amount;
@@ -1033,6 +1033,7 @@ namespace tools
de.original = it->address; de.original = it->address;
de.addr = info.address; de.addr = info.address;
de.is_subaddress = info.is_subaddress; de.is_subaddress = info.is_subaddress;
de.is_carrot = info.is_carrot;
de.amount = it->amount; de.amount = it->amount;
de.is_integrated = info.has_payment_id; de.is_integrated = info.has_payment_id;
de.asset_type = it->asset_type; de.asset_type = it->asset_type;
@@ -2969,7 +2970,7 @@ namespace tools
{ {
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments; std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments;
m_wallet->get_payments_out(payments, min_height, max_height, account_index, subaddr_indices); m_wallet->get_payments_out(payments, min_height, max_height, account_index, subaddr_indices);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::iterator i = payments.begin(); i != payments.end(); ++i) {
res.out.push_back(wallet_rpc::transfer_entry()); res.out.push_back(wallet_rpc::transfer_entry());
fill_transfer_entry(res.out.back(), i->first, i->second); fill_transfer_entry(res.out.back(), i->first, i->second);
} }
@@ -2978,8 +2979,8 @@ namespace tools
if (req.pending || req.failed) { if (req.pending || req.failed) {
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments; std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
m_wallet->get_unconfirmed_payments_out(upayments, account_index, subaddr_indices); m_wallet->get_unconfirmed_payments_out(upayments, account_index, subaddr_indices);
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::iterator i = upayments.begin(); i != upayments.end(); ++i) {
const tools::wallet2::unconfirmed_transfer_details &pd = i->second; tools::wallet2::unconfirmed_transfer_details &pd = i->second;
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
if (!((req.failed && is_failed) || (!is_failed && req.pending))) if (!((req.failed && is_failed) || (!is_failed && req.pending)))
continue; continue;
@@ -3056,7 +3057,7 @@ namespace tools
std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out; std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>> payments_out;
m_wallet->get_payments_out(payments_out, 0, (uint64_t)-1, req.account_index); m_wallet->get_payments_out(payments_out, 0, (uint64_t)-1, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::iterator i = payments_out.begin(); i != payments_out.end(); ++i) {
if (i->first == txid) if (i->first == txid)
{ {
res.transfers.resize(res.transfers.size() + 1); res.transfers.resize(res.transfers.size() + 1);
@@ -3066,7 +3067,7 @@ namespace tools
std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments; std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>> upayments;
m_wallet->get_unconfirmed_payments_out(upayments, req.account_index); m_wallet->get_unconfirmed_payments_out(upayments, req.account_index);
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) { for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::iterator i = upayments.begin(); i != upayments.end(); ++i) {
if (i->first == txid) if (i->first == txid)
{ {
res.transfers.resize(res.transfers.size() + 1); res.transfers.resize(res.transfers.size() + 1);
+2 -2
View File
@@ -269,8 +269,8 @@ namespace tools
// helpers // helpers
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd); void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd);
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::confirmed_transfer_details &pd); void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, tools::wallet2::confirmed_transfer_details &pd);
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, const tools::wallet2::unconfirmed_transfer_details &pd); void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &txid, tools::wallet2::unconfirmed_transfer_details &pd);
void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &pd); void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::pool_payment_details &pd);
bool not_open(epee::json_rpc::error& er); bool not_open(epee::json_rpc::error& er);
void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code); void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code);
+3637 -3375
View File
File diff suppressed because it is too large Load Diff
+3714 -3453
View File
File diff suppressed because one or more lines are too long
+3713 -3452
View File
File diff suppressed because it is too large Load Diff
+3865 -3604
View File
File diff suppressed because one or more lines are too long
+3713 -3452
View File
File diff suppressed because it is too large Load Diff
+3713 -3452
View File
File diff suppressed because one or more lines are too long
+3713 -3452
View File
File diff suppressed because it is too large Load Diff
+3713 -3452
View File
File diff suppressed because it is too large Load Diff
+3713 -3452
View File
File diff suppressed because one or more lines are too long
+3713 -3452
View File
File diff suppressed because it is too large Load Diff
+3713 -3452
View File
File diff suppressed because it is too large Load Diff