From b7cc8e8100cbd8378221f0c10e1c505c5d8059bc Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Thu, 3 Jul 2025 23:08:24 +0100 Subject: [PATCH] fixed Carrot mining; added support for dedicated Carrot wallet addresses with SC1 prefix --- src/carrot_impl/account.cpp | 1 + src/carrot_impl/account.h | 4 +- src/cryptonote_basic/account.cpp | 8 ++++ src/cryptonote_basic/account.h | 3 +- .../cryptonote_basic_impl.cpp | 38 +++++++++++++++++-- src/cryptonote_basic/cryptonote_basic_impl.h | 3 ++ src/cryptonote_config.h | 21 ++++++++++ src/simplewallet/simplewallet.cpp | 20 +++++----- src/wallet/scanning_tools.cpp | 9 +++-- 9 files changed, 89 insertions(+), 18 deletions(-) diff --git a/src/carrot_impl/account.cpp b/src/carrot_impl/account.cpp index a6dc59c..bbbe80e 100644 --- a/src/carrot_impl/account.cpp +++ b/src/carrot_impl/account.cpp @@ -315,6 +315,7 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_ make_carrot_viewbalance_secret(m_keys.s_master, m_keys.s_view_balance); // view balance keys + make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming); make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image); make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address); diff --git a/src/carrot_impl/account.h b/src/carrot_impl/account.h index 1f4cc72..e839860 100644 --- a/src/carrot_impl/account.h +++ b/src/carrot_impl/account.h @@ -53,7 +53,7 @@ namespace carrot std::unordered_map subaddress_map; AddressDeriveType default_derive_type; - carrot_and_legacy_account(): k_view_incoming_dev(get_keys().m_view_secret_key), + carrot_and_legacy_account(): k_view_incoming_dev(get_keys().k_view_incoming), s_view_balance_dev(get_keys().s_view_balance), s_generate_address_dev(get_keys().s_generate_address) {} @@ -70,7 +70,7 @@ namespace carrot CarrotDestinationV1 subaddress(const subaddress_index_extended &subaddress_index) const; std::unordered_map subaddress_map_cn() const; - + // brief: opening_for_subaddress - return (k^g_a, k^t_a) for j s.t. K^j_s = (k^g_a * G + k^t_a * T) void opening_for_subaddress(const subaddress_index_extended &subaddress_index, crypto::secret_key &address_privkey_g_out, diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 6ca7173..eb03456 100644 --- a/src/cryptonote_basic/account.cpp +++ b/src/cryptonote_basic/account.cpp @@ -276,6 +276,14 @@ DISABLE_VS_WARNINGS(4244 4345) //TODO: change this code into base 58 return get_account_address_as_str(nettype, false, m_keys.m_account_address); } + //---------------------------------------------------------------------------------------------------------------------- + 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_account_address.m_spend_public_key, m_keys.m_account_address.m_view_public_key}; + // change this code into base 58 + return get_account_address_as_str(nettype, false, addr, true); + } //----------------------------------------------------------------- std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const { diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h index 44fd507..b28ef78 100644 --- a/src/cryptonote_basic/account.h +++ b/src/cryptonote_basic/account.h @@ -61,7 +61,7 @@ namespace cryptonote crypto::secret_key k_generate_image; crypto::secret_key s_generate_address; - // carrot public keys (minus K^0_v, which is shared with legacy K^0_v) + // carrot public keys (minus K_v, which is shared with legacy K_v) account_public_address m_carrot_account_address; @@ -101,6 +101,7 @@ namespace cryptonote 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 &multisig_keys); const account_keys& get_keys() const; std::string get_public_address_str(network_type nettype) const; + std::string get_carrot_public_address_str(network_type nettype) const; std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const; hw::device& get_device() const {return m_keys.get_device();} diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index 8ac8816..b7ebcf0 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -155,9 +155,12 @@ namespace cryptonote { network_type nettype , bool subaddress , account_public_address const & adr + , bool is_carrot ) { - uint64_t address_prefix = subaddress ? get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; + uint64_t address_prefix = 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); return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); } @@ -166,9 +169,10 @@ namespace cryptonote { network_type nettype , account_public_address const & adr , crypto::hash8 const & payment_id + , bool is_carrot ) { - uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + 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; integrated_address iadr = { adr, payment_id @@ -196,6 +200,9 @@ namespace cryptonote { uint64_t address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; uint64_t integrated_address_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; uint64_t subaddress_prefix = get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; + uint64_t carrot_address_prefix = get_config(nettype).CARROT_PUBLIC_ADDRESS_BASE58_PREFIX; + uint64_t carrot_integrated_address_prefix = get_config(nettype).CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + uint64_t carrot_subaddress_prefix = get_config(nettype).CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX; if (2 * sizeof(public_address_outer_blob) != str.size()) { @@ -211,21 +218,45 @@ namespace cryptonote { { info.is_subaddress = false; info.has_payment_id = true; + info.is_carrot = false; } else if (address_prefix == prefix) { info.is_subaddress = false; info.has_payment_id = false; + info.is_carrot = false; } else if (subaddress_prefix == prefix) { info.is_subaddress = true; info.has_payment_id = false; + info.is_carrot = false; + } + else if (carrot_integrated_address_prefix == prefix) + { + info.is_subaddress = false; + info.has_payment_id = true; + info.is_carrot = true; + } + else if (carrot_address_prefix == prefix) + { + info.is_subaddress = false; + info.has_payment_id = false; + info.is_carrot = true; + } + else if (carrot_subaddress_prefix == prefix) + { + info.is_subaddress = true; + info.has_payment_id = false; + info.is_carrot = true; } else { LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix << " or " << integrated_address_prefix - << " or " << subaddress_prefix); + << " or " << subaddress_prefix + << " or " << carrot_address_prefix + << " or " << carrot_integrated_address_prefix + << " or " << carrot_subaddress_prefix); return false; } @@ -287,6 +318,7 @@ namespace cryptonote { info.address = blob.m_address; info.is_subaddress = false; info.has_payment_id = false; + info.is_carrot = false; } return true; diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index 3ba4200..ea20aae 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -71,6 +71,7 @@ namespace cryptonote { account_public_address address; bool is_subaddress; bool has_payment_id; + bool is_carrot; crypto::hash8 payment_id; }; @@ -87,12 +88,14 @@ 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( diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 361dd4c..6173444 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -292,6 +292,9 @@ namespace config uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x3ef318; // SaLv uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x55ef318; // SaLvi uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0xf5ef318; // SaLvs + uint64_t const CARROT_PUBLIC_ADDRESS_BASE58_PREFIX = 0x180c96; // SC1 + uint64_t const CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x2ccc96; // SC1i + uint64_t const CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x314c96; // SC1s uint16_t const P2P_DEFAULT_PORT = 19080; uint16_t const RPC_DEFAULT_PORT = 19081; uint16_t const ZMQ_RPC_DEFAULT_PORT = 19082; @@ -396,6 +399,9 @@ namespace config uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x15beb318; // SaLvT uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0xd055eb318; // SaLvTi uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0xa59eb318; // SaLvTs + uint64_t const CARROT_PUBLIC_ADDRESS_BASE58_PREFIX = 0x254c96; // SC1T + uint64_t const CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x1ac50c96; // SC1Ti + uint64_t const CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x3c54c96; // SC1Ts uint16_t const P2P_DEFAULT_PORT = 29080; uint16_t const RPC_DEFAULT_PORT = 29081; uint16_t const ZMQ_RPC_DEFAULT_PORT = 29082; @@ -448,6 +454,9 @@ namespace config uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0x149eb318; // SaLvS uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0xf343eb318; // SaLvSi uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x2d47eb318; // SaLvSs + uint64_t const CARROT_PUBLIC_ADDRESS_BASE58_PREFIX = 0x24cc96; // SC1S + uint64_t const CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 0x1a848c96; // SC1Si + uint64_t const CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX = 0x384cc96; // SC1Ss uint16_t const P2P_DEFAULT_PORT = 39080; uint16_t const RPC_DEFAULT_PORT = 39081; uint16_t const ZMQ_RPC_DEFAULT_PORT = 39082; @@ -508,6 +517,9 @@ namespace cryptonote uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX; + uint64_t const CARROT_PUBLIC_ADDRESS_BASE58_PREFIX; + uint64_t const CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; + uint64_t const CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX; uint16_t const P2P_DEFAULT_PORT; uint16_t const RPC_DEFAULT_PORT; uint16_t const ZMQ_RPC_DEFAULT_PORT; @@ -528,6 +540,9 @@ namespace cryptonote ::config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, ::config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, ::config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX, + ::config::CARROT_PUBLIC_ADDRESS_BASE58_PREFIX, + ::config::CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, + ::config::CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX, ::config::P2P_DEFAULT_PORT, ::config::RPC_DEFAULT_PORT, ::config::ZMQ_RPC_DEFAULT_PORT, @@ -546,6 +561,9 @@ namespace cryptonote ::config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, ::config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, ::config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX, + ::config::testnet::CARROT_PUBLIC_ADDRESS_BASE58_PREFIX, + ::config::testnet::CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, + ::config::testnet::CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX, ::config::testnet::P2P_DEFAULT_PORT, ::config::testnet::RPC_DEFAULT_PORT, ::config::testnet::ZMQ_RPC_DEFAULT_PORT, @@ -564,6 +582,9 @@ namespace cryptonote ::config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, ::config::stagenet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, ::config::stagenet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX, + ::config::stagenet::CARROT_PUBLIC_ADDRESS_BASE58_PREFIX, + ::config::stagenet::CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX, + ::config::stagenet::CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX, ::config::stagenet::P2P_DEFAULT_PORT, ::config::stagenet::RPC_DEFAULT_PORT, ::config::stagenet::ZMQ_RPC_DEFAULT_PORT, diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index da79f1d..5d44971 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -5477,15 +5477,9 @@ boost::optional simple_wallet::open_wallet(const boost::p message_writer(console_color_white, true) << prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); - - const auto addr = m_wallet->get_account().cryptonote_address(carrot::null_payment_id, carrot::AddressDeriveType::Carrot); - cryptonote::account_public_address carrot_address { - .m_spend_public_key = addr.address_spend_pubkey, - .m_view_public_key = addr.address_view_pubkey - }; prefix = tr("Opened carrot wallet"); message_writer(console_color_white, true) << - prefix << ": " << cryptonote::get_account_address_as_str(m_wallet->nettype(), false, carrot_address); + prefix << ": " << m_wallet->get_account().get_carrot_public_address_str(m_wallet->nettype()); if (m_wallet->get_account().get_device()) { message_writer(console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name(); } @@ -5645,7 +5639,11 @@ void simple_wallet::start_background_mining() { COMMAND_RPC_START_MINING::request req; COMMAND_RPC_START_MINING::response res; - req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + uint8_t hf_version = m_wallet->get_current_hard_fork(); + if (hf_version >= HF_VERSION_CARROT) + req.miner_address = m_wallet->get_account().get_carrot_public_address_str(m_wallet->nettype()); + else + req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); req.threads_count = 1; req.do_background_mining = true; req.ignore_battery = false; @@ -5769,7 +5767,11 @@ bool simple_wallet::start_mining(const std::vector& args) return true; } COMMAND_RPC_START_MINING::request req = AUTO_VAL_INIT(req); - req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + uint8_t hf_version = m_wallet->get_current_hard_fork(); + if (hf_version >= HF_VERSION_CARROT) + req.miner_address = m_wallet->get_account().get_carrot_public_address_str(m_wallet->nettype()); + else + req.miner_address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); bool ok = true; size_t arg_size = args.size(); diff --git a/src/wallet/scanning_tools.cpp b/src/wallet/scanning_tools.cpp index edac442..ee77c25 100644 --- a/src/wallet/scanning_tools.cpp +++ b/src/wallet/scanning_tools.cpp @@ -238,8 +238,11 @@ static std::optional view_incoming_scan_pre_car .derive_type = carrot::AddressDeriveType::PreCarrot }; - // add the entry to our temporary subaddress map via the keystore + // HERE BE DRAGONS!!! + // SRCG: whilst the following code will work, it'd be better being moved to the TX_BUILDER code + // add the entry to our subaddress map in case it's a change payment (false positives won't hurt us) account.subaddress_map.insert({enote.onetime_address, subaddr_index}); + // LAND AHOY!!! return enote_view_incoming_scan_info_t{ .sender_extension_g = sender_extension_g, @@ -390,7 +393,7 @@ static void perform_ecdh_derivations(const epee::span main_derivations_out.clear(); additional_derivations_out.clear(); main_derivations_out.reserve(main_tx_ephemeral_pubkeys.size()); - additional_derivations_out.reserve(additional_derivations_out.size()); + additional_derivations_out.reserve(additional_tx_ephemeral_pubkeys.size()); if (is_carrot) { @@ -719,7 +722,7 @@ void view_incoming_scan_transaction( //! @TODO: HW device const bool is_carrot = carrot::is_carrot_transaction_v1(tx); - carrot::view_incoming_key_ram_borrowed_device k_view_dev(account.get_keys().m_view_secret_key); + carrot::view_incoming_key_ram_borrowed_device k_view_dev(is_carrot ? account.get_keys().k_view_incoming : account.get_keys().m_view_secret_key); // do view-incoming scan for each output enotes for (size_t local_output_index = 0; local_output_index < n_outputs; ++local_output_index)