Compare commits
5 Commits
v0.9.0-rc9
..
v0.9.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 19be3a6146 | |||
| 64a69268fe | |||
| 7312652540 | |||
| 8cd587ec54 | |||
| 62c43a4ed2 |
@@ -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,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
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user