Compare commits

..

5 Commits

Author SHA1 Message Date
Some Random Crypto Guy 19be3a6146 fixed gitignore issue with CMake and audit tool 2025-01-31 17:20:52 +00:00
Some Random Crypto Guy 64a69268fe set hard fork 6 height; bumped version number 2025-01-31 15:10:13 +00:00
Some Random Crypto Guy 7312652540 Merge branch 'develop' 2025-01-31 15:07:59 +00:00
Some Random Crypto Guy 8cd587ec54 added building of (private) audit tool; improved help text for AUDIT command in CLI 2025-01-30 13:56:17 +00:00
Some Random Crypto Guy 62c43a4ed2 added audit index=all command; added audit RPC command; bumped version 2025-01-30 12:59:33 +00:00
9 changed files with 188 additions and 24 deletions
+3
View File
@@ -30,6 +30,9 @@ contrib/gitian/builder/
contrib/gitian/docker/
contrib/gitian/sigs/
# Audit tool
src/blockchain_utilities/blockchain_audit.cpp
# Created by https://www.gitignore.io
### C++ ###
+1 -1
View File
@@ -1,4 +1,4 @@
# Salvium Zero v0.9.0-rc9
# Salvium Zero v0.9.0
Copyright (c) 2023-2024, Salvium
Portions Copyright (c) 2014-2023, The Monero Project
+38
View File
@@ -142,6 +142,18 @@ set(blockchain_scanner_private_headers)
monero_private_headers(blockchain_scanner
${blockchain_scanner_private_headers})
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
set(blockchain_audit_sources
blockchain_audit.cpp
)
set(blockchain_audit_private_headers)
monero_private_headers(blockchain_audit
${blockchain_audit_private_headers})
else()
message(STATUS "blockchain_audit.cpp not found - not building the audit tool")
endif()
monero_add_executable(blockchain_import
${blockchain_import_sources}
@@ -312,6 +324,32 @@ set_property(TARGET blockchain_scanner
OUTPUT_NAME "salvium-blockchain-scanner")
install(TARGETS blockchain_scanner DESTINATION bin)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
monero_add_executable(blockchain_audit
${blockchain_audit_sources}
${blockchain_audit_private_headers})
target_link_libraries(blockchain_audit
PRIVATE
wallet
crypto
cncrypto
cryptonote_core
blockchain_db
version
epee
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBRARIES})
set_property(TARGET blockchain_audit
PROPERTY
OUTPUT_NAME "salvium-blockchain-audit")
install(TARGETS blockchain_audit DESTINATION bin)
endif()
monero_add_executable(blockchain_stats
${blockchain_stats_sources}
${blockchain_stats_private_headers})
+3
View File
@@ -46,6 +46,9 @@ const hardfork_t mainnet_hard_forks[] = {
// version 5 starts from block 136100, which is on or around the 9th of January, 2025. Fork time finalised on 2025-01-08. No fork voting occurs for the v5 fork.
{ 5, 136100, 0, 1736265945 },
// version 6 starts from block 154750, which is on or around the 4th of February, 2025. Fork time finalised on 2025-01-31. No fork voting occurs for the v6 fork.
{ 6, 154750, 0, 1738336000 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
+33 -22
View File
@@ -214,7 +214,7 @@ namespace
const char* USAGE_BURN("burn <amount> <asset_type>");
const char* USAGE_CONVERT("convert <source_amount> <source_asset> <dest_asset> [<slippage_limit>]");
const char* USAGE_STAKE("stake <amount>");
const char* USAGE_AUDIT("audit [index=N]");
const char* USAGE_AUDIT("audit [index=<N1>[,<N2>,...] | index=all]");
const char* USAGE_PRICE_INFO("price_info");
const char* USAGE_SUPPLY_INFO("supply_info");
const char* USAGE_YIELD_INFO("yield_info");
@@ -3221,7 +3221,7 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
message_writer() << tr("\"burn <amount> <asset_type>\" - destroy coins forever.");
message_writer() << tr("\"convert <amount> <source_asset> <dest_asset> [<slippage_limit>]\" - convert between coin types.");
message_writer() << tr("\"stake <amount>\" - stake SAL for 30 days to earn yield.");
message_writer() << tr("\"audit\" - audit your wallet main address (or subaddress if specified).");
message_writer() << tr("\"audit\" - audit your wallet main address (or subaddress(es) if specified).");
message_writer() << tr("\"price_info\" - Display current pricing information for supported assets.");
message_writer() << tr("\"supply_info\" - Display circulating supply information.");
message_writer() << tr("\"yield_info\" - Display current stats on Salvium staking / yield.");
@@ -3418,7 +3418,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("audit",
boost::bind(&simple_wallet::audit, this, _1),
tr(USAGE_AUDIT),
tr("Sends your wallet balance for a single address (or subaddress) to audit (only available during AUDIT hard forks)"));
tr("Sends your wallet balance (or a single address or subaddress(es)) to audit (only available during AUDIT hard forks)"));
m_cmd_binder.set_handler("price_info",
boost::bind(&simple_wallet::price_info, this, _1),
tr(USAGE_PRICE_INFO),
@@ -6741,25 +6741,22 @@ bool simple_wallet::transfer_main(
// "transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]"
if (!try_connect_to_daemon())
return false;
/*
bool audit = false;
if (m_wallet->get_current_hard_fork() >= HF_VERSION_SALVIUM_ONE_PROOFS) {
if (transfer_type == Audit) {
audit = true;
}
}
*/
std::vector<std::string> local_args = args_;
std::set<uint32_t> subaddr_indices;
if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=")
{
if (!parse_subaddress_indices(local_args[0], subaddr_indices))
return false;
if (local_args[0] == "index=all")
{
for (uint32_t i = 0; i < m_wallet->get_num_subaddresses(m_current_subaddress_account); ++i)
subaddr_indices.insert(i);
}
else if (!parse_subaddress_indices(local_args[0], subaddr_indices))
{
return true;
}
local_args.erase(local_args.begin());
if (transfer_type == Audit)
while (subaddr_indices.size() > 1)
subaddr_indices.erase(std::prev(subaddr_indices.end())); }
}
uint32_t priority = m_wallet->get_default_priority();
if (local_args.size() > 0 && parse_priority(local_args[0], priority))
@@ -6975,8 +6972,25 @@ bool simple_wallet::transfer_main(
std::vector<tools::wallet2::pending_tx> ptx_vector;
uint64_t unlock_block = 0;
std::string err;
switch (transfer_type)
{
if (transfer_type == Audit) {
// Get the subaddress unlocked balances
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, source_asset, true);
unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
for (const auto subaddr_index : subaddr_indices) {
// Skip this wallet if there is no balance unlocked to audit
if (unlocked_balance_per_subaddr.count(subaddr_index) == 0) continue;
std::set<uint32_t> subaddr_indices_single;
subaddr_indices_single.insert(subaddr_index);
uint64_t unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
std::vector<tools::wallet2::pending_tx> ptx_vector_audit = m_wallet->create_transactions_all(0, cryptonote::transaction_type::AUDIT, source_asset, m_wallet->get_subaddress({m_current_subaddress_account, subaddr_index}), (subaddr_index>0), 1, fake_outs_count, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices_single);
ptx_vector.insert(ptx_vector.end(), ptx_vector_audit.begin(), ptx_vector_audit.end());
}
} else {
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);
@@ -6985,10 +6999,6 @@ bool simple_wallet::transfer_main(
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);
break;
case Audit:
unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
ptx_vector = m_wallet->create_transactions_all(0, cryptonote::transaction_type::AUDIT, source_asset, m_wallet->get_subaddress({m_current_subaddress_account, 0}), false, 1, fake_outs_count, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices);
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);
@@ -7003,6 +7013,7 @@ bool simple_wallet::transfer_main(
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);
break;
}
}
if (ptx_vector.empty())
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
#define DEF_SALVIUM_VERSION "0.9.0-rc9"
#define DEF_SALVIUM_VERSION "0.9.0"
#define DEF_MONERO_VERSION_TAG "release"
#define DEF_MONERO_VERSION "0.18.3.3"
#define DEF_MONERO_RELEASE_NAME "Zero"
+71
View File
@@ -1093,6 +1093,77 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_audit(const wallet_rpc::COMMAND_RPC_AUDIT::request& req, wallet_rpc::COMMAND_RPC_AUDIT::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
std::vector<cryptonote::tx_destination_entry> dsts;
std::vector<uint8_t> extra;
if (!m_wallet) return not_open(er);
if (m_restricted)
{
er.code = WALLET_RPC_ERROR_CODE_DENIED;
er.message = "Command unavailable in restricted mode.";
return false;
}
CHECK_MULTISIG_ENABLED();
std::string asset_type = req.asset_type.empty() ? "SAL" : req.asset_type;
// validate the transfer requested and populate dsts & extra
std::list<wallet_rpc::transfer_destination> destinations;
destinations.push_back(wallet_rpc::transfer_destination());
destinations.back().amount = 0;
destinations.back().address = req.address;
destinations.back().asset_type = asset_type;
// validate the transfer requested and populate dsts & extra
if (!validate_transfer(destinations, asset_type, asset_type, cryptonote::transaction_type::AUDIT, req.payment_id, dsts, extra, true, er))
{
return false;
}
std::set<uint32_t> subaddr_indices;
if (req.subaddr_indices_all)
{
for (uint32_t i = 0; i < m_wallet->get_num_subaddresses(req.account_index); ++i)
subaddr_indices.insert(i);
}
else
{
subaddr_indices= req.subaddr_indices;
}
try
{
std::vector<wallet2::pending_tx> ptx_vector_all;
// Get the subaddress unlocked balances
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(req.account_index, asset_type, true);
for (const auto subaddr_index : subaddr_indices) {
// Skip this wallet if there is no balance unlocked to audit
if (unlocked_balance_per_subaddr.count(subaddr_index) == 0) continue;
std::set<uint32_t> subaddr_indices_single;
subaddr_indices_single.insert(subaddr_index);
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
uint32_t priority = m_wallet->adjust_priority(0);
uint64_t unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(0, cryptonote::transaction_type::AUDIT, asset_type, m_wallet->get_subaddress({req.account_index, subaddr_index}), (subaddr_index > 0), 1, mixin, unlock_block, priority, extra, req.account_index, subaddr_indices_single);
ptx_vector_all.insert(ptx_vector_all.end(), ptx_vector.begin(), ptx_vector.end());
}
return fill_response(ptx_vector_all, req.get_tx_keys, res.tx_key_list, res.amount_list, res.amounts_by_dest_list, res.fee_list, res.weight_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, res.spent_key_images_list, er);
}
catch (const std::exception& e)
{
handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR);
return false;
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
+2
View File
@@ -87,6 +87,7 @@ namespace tools
MAP_JON_RPC_WE("freeze", on_freeze, wallet_rpc::COMMAND_RPC_FREEZE)
MAP_JON_RPC_WE("thaw", on_thaw, wallet_rpc::COMMAND_RPC_THAW)
MAP_JON_RPC_WE("frozen", on_frozen, wallet_rpc::COMMAND_RPC_FROZEN)
MAP_JON_RPC_WE("audit", on_audit, wallet_rpc::COMMAND_RPC_AUDIT)
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
MAP_JON_RPC_WE("transfer_split", on_transfer_split, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT)
MAP_JON_RPC_WE("sign_transfer", on_sign_transfer, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER)
@@ -180,6 +181,7 @@ namespace tools
bool on_freeze(const wallet_rpc::COMMAND_RPC_FREEZE::request& req, wallet_rpc::COMMAND_RPC_FREEZE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_thaw(const wallet_rpc::COMMAND_RPC_THAW::request& req, wallet_rpc::COMMAND_RPC_THAW::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_frozen(const wallet_rpc::COMMAND_RPC_FROZEN::request& req, wallet_rpc::COMMAND_RPC_FROZEN::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_audit(const wallet_rpc::COMMAND_RPC_AUDIT::request& req, wallet_rpc::COMMAND_RPC_AUDIT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_sign_transfer(const wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_SIGN_TRANSFER::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
@@ -864,6 +864,42 @@ namespace wallet_rpc
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_AUDIT
{
struct request_t
{
std::string address;
uint32_t account_index;
std::set<uint32_t> subaddr_indices;
bool subaddr_indices_all;
uint64_t ring_size;
std::string payment_id;
bool get_tx_keys;
bool do_not_relay;
bool get_tx_hex;
bool get_tx_metadata;
std::string asset_type;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
KV_SERIALIZE(account_index)
KV_SERIALIZE(subaddr_indices)
KV_SERIALIZE_OPT(subaddr_indices_all, false)
KV_SERIALIZE_OPT(ring_size, (uint64_t)0)
KV_SERIALIZE(payment_id)
KV_SERIALIZE(get_tx_keys)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
KV_SERIALIZE_OPT(get_tx_metadata, false)
KV_SERIALIZE(asset_type)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
typedef split_transfer_response response_t;
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_SWEEP_ALL
{
struct request_t