fixed Carrot mining; added support for dedicated Carrot wallet addresses with SC1 prefix

This commit is contained in:
Some Random Crypto Guy
2025-07-03 23:08:24 +01:00
parent 520d4b4eab
commit b7cc8e8100
9 changed files with 89 additions and 18 deletions

View File

@@ -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);

View File

@@ -53,7 +53,7 @@ namespace carrot
std::unordered_map<crypto::public_key, subaddress_index_extended> 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<crypto::public_key, cryptonote::subaddress_index> 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,

View File

@@ -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
{

View File

@@ -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<crypto::secret_key> &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();}

View File

@@ -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;

View File

@@ -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(

View File

@@ -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,

View File

@@ -5477,15 +5477,9 @@ boost::optional<epee::wipeable_string> 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<std::string>& 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();

View File

@@ -238,8 +238,11 @@ static std::optional<enote_view_incoming_scan_info_t> 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<const crypto::public_key>
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)