Compare commits

...

10 Commits

Author SHA1 Message Date
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
13 changed files with 69 additions and 39 deletions

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:

View File

@@ -1,4 +1,4 @@
# Salvium One v1.0.0
# Salvium One v1.0.3
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.3
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.3
```
* 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.3'. 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.3
```
* If you are on a 64-bit system, run:

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
{

View File

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

View File

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

View File

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

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;

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;

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

View File

@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "1.0.1"
#define DEF_SALVIUM_VERSION "1.0.3"
#define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.4"
#define DEF_MONERO_RELEASE_NAME "One"

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 = {};

View File

@@ -1606,7 +1606,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
@@ -1618,7 +1618,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)
@@ -7824,7 +7824,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;
@@ -11645,6 +11645,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
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());
@@ -11653,6 +11656,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;
@@ -11735,6 +11741,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());
@@ -11744,6 +11753,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);
@@ -12570,8 +12582,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;

View File

@@ -3305,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});
}
}