1
0
Fork 0
forked from lthn/blockchain

Merge branch 'develop' into secp256k1

This commit is contained in:
sowle 2024-07-15 21:41:12 +02:00
commit 3cb471c46c
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
31 changed files with 910 additions and 215 deletions

View file

@ -6,15 +6,18 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
endif()
message("DB ENGINE: lmdb")
add_subdirectory(liblmdb)
if(MSVC)
target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172)
else()
# Warnings as used by LMDB itself (LMDB_0.9.23)
target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized)
endif()
if(NOT DISABLE_MDBX)
message("DB ENGINE: mdbx")
add_subdirectory(libmdbx)
endif()
message("DB ENGINE: lmdb")
add_subdirectory(liblmdb)
if(MSVC)
target_compile_options(lmdb PRIVATE /wd4996 /wd4503 /wd4345 /wd4267 /wd4244 /wd4146 /wd4333 /wd4172)
else()
# Warnings as used by LMDB itself (LMDB_0.9.23)
target_compile_options(lmdb PRIVATE -Wall -Wno-unused-parameter -Wbad-function-cast -Wuninitialized)
endif()
if(NOT DISABLE_MDBX)
message("DB ENGINE: mdbx")
add_subdirectory(libmdbx)
# remove mdbx tools from the default MSVC build
set_target_properties(mdbx_chk mdbx_copy mdbx_dump mdbx_load mdbx_stat PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()

View file

@ -1,3 +1,4 @@
// Copyright (c) 2024, Zano Project
// Copyright (c) 2006-2017, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
@ -35,11 +36,14 @@ namespace epee
inline std::string print_fixed_decimal_point(t_number amount, size_t decimal_point)
{
std::string s = boost::lexical_cast<std::string>(amount);
if (decimal_point > 32)
return std::string("!!") + s; // avoiding overflow issues
if (s.size() < decimal_point + 1)
{
s.insert(0, decimal_point + 1 - s.size(), '0');
}
s.insert(s.size() - decimal_point, ".");
if (decimal_point > 0)
s.insert(s.size() - decimal_point, ".");
return s;
}
}

View file

@ -105,7 +105,7 @@ namespace epee
std::string res;
for (const auto& item : a)
{
res += epee::string_tools::pod_to_hex(a) + ", ";
res += epee::string_tools::pod_to_hex(item) + ", ";
}
if (a.size())
{

View file

@ -19,6 +19,7 @@
#define API_RETURN_CODE_BAD_ARG_WRONG_FEE "BAD_ARG_WRONG_FEE"
#define API_RETURN_CODE_BAD_ARG_INVALID_ADDRESS "BAD_ARG_INVALID_ADDRESS"
#define API_RETURN_CODE_BAD_ARG_WRONG_AMOUNT "BAD_ARG_WRONG_AMOUNT"
#define API_RETURN_CODE_BAD_ARG_UNKNOWN_DECIMAL_POINT "BAD_ARG_UNKNOWN_DECIMAL_POINT"
#define API_RETURN_CODE_BAD_ARG_WRONG_PAYMENT_ID "BAD_ARG_WRONG_PAYMENT_ID"
#define API_RETURN_CODE_WRONG_PASSWORD "WRONG_PASSWORD"
#define API_RETURN_CODE_WALLET_WRONG_ID "WALLET_WRONG_ID"

View file

@ -700,7 +700,7 @@ namespace currency
{
uint64_t total_max_supply = 0;
uint64_t current_supply = 0;
uint8_t decimal_point = 12;
uint8_t decimal_point = 0;
std::string ticker;
std::string full_name;
std::string meta_info;
@ -733,12 +733,12 @@ namespace currency
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(total_max_supply) DOC_DSCR("Maximum possible supply for given asset, can't be changed after deployment") DOC_EXMP(1000000000000000000) DOC_END
KV_SERIALIZE(current_supply) DOC_DSCR("Currently emitted supply for given asset") DOC_EXMP(500000000000000000) DOC_END
KV_SERIALIZE(current_supply) DOC_DSCR("Currently emitted supply for given asset (ignored for REGISTER operation)") DOC_EXMP(500000000000000000) DOC_END
KV_SERIALIZE(decimal_point) DOC_DSCR("Decimal point") DOC_EXMP(12) DOC_END
KV_SERIALIZE(ticker) DOC_DSCR("Ticker associated with asset") DOC_EXMP("ZUSD") DOC_END
KV_SERIALIZE(full_name) DOC_DSCR("Full name of the asset") DOC_EXMP("Zano wrapped USD") DOC_END
KV_SERIALIZE(meta_info) DOC_DSCR("Any other information assetiaded with asset in a free form") DOC_EXMP("Stable and private") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Owner's key, used to validate any operations on the asset altering, could be changed in case of transfer ownership") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
KV_SERIALIZE_POD_AS_HEX_STRING(owner) DOC_DSCR("Owner's key, used only for EMIT and UPDATE validation, could be changed by transferring asset ownership") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
KV_SERIALIZE(hidden_supply) DOC_DSCR("This one reserved for future use, will be documented later") DOC_END
END_KV_SERIALIZE_MAP()
};

View file

@ -793,8 +793,7 @@ namespace currency
}
}
//---------------------------------------------------------------
// TODO: reverse order of arguments
bool parse_amount(uint64_t& amount, const std::string& str_amount_)
bool parse_amount(const std::string& str_amount_, uint64_t& amount, const size_t decimal_point /* = CURRENCY_DISPLAY_DECIMAL_POINT */)
{
std::string str_amount = str_amount_;
boost::algorithm::trim(str_amount);
@ -804,12 +803,12 @@ namespace currency
if (std::string::npos != point_index)
{
fraction_size = str_amount.size() - point_index - 1;
while (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back())
while (decimal_point < fraction_size && '0' == str_amount.back())
{
str_amount.erase(str_amount.size() - 1, 1);
--fraction_size;
}
if (CURRENCY_DISPLAY_DECIMAL_POINT < fraction_size)
if (decimal_point < fraction_size)
return false;
str_amount.erase(point_index, 1);
}
@ -821,9 +820,9 @@ namespace currency
if (str_amount.empty())
return false;
if (fraction_size < CURRENCY_DISPLAY_DECIMAL_POINT)
if (fraction_size < decimal_point)
{
str_amount.append(CURRENCY_DISPLAY_DECIMAL_POINT - fraction_size, '0');
str_amount.append(decimal_point - fraction_size, '0');
}
return string_tools::get_xtype_from_string(amount, str_amount);
@ -3464,11 +3463,32 @@ namespace currency
//---------------------------------------------------------------
std::string print_money_brief(uint64_t amount, size_t decimal_point /* = CURRENCY_DISPLAY_DECIMAL_POINT */)
{
// TODO: temporary fix for insanely big decimal points
// TODO: remove it after setting the limit to 18 -- sowle
if (decimal_point > 32)
return std::string("!!") + std::to_string(amount);
if (decimal_point >= 20)
{
std::string r = std::to_string(amount);
if (decimal_point + 1 > r.size())
r.insert(0, decimal_point - r.size() + 1, '0');
r.insert(r.begin() + 1, '.');
size_t p = r.find_last_not_of('0');
if (p != r.npos)
{
if (r[p] != '.' && p + 1 < r.size())
r.erase(p + 1);
else if (p + 2 < r.size())
r.erase(p + 2);
}
return r;
}
uint64_t coin = decimal_point == CURRENCY_DISPLAY_DECIMAL_POINT ? COIN : crypto::constexpr_pow(decimal_point, 10);
uint64_t remainder = amount % coin;
amount /= coin;
if (remainder == 0)
return std::to_string(amount) + ".0";
return std::to_string(amount) + (decimal_point > 0 ? ".0" : "");
std::string r = std::to_string(remainder);
if (r.size() < decimal_point)
r.insert(0, decimal_point - r.size(), '0');

View file

@ -402,7 +402,7 @@ namespace currency
uint64_t get_outs_money_amount(const transaction& tx, const currency::account_keys& acc_keys_for_hidden_amounts = currency::null_acc_keys);
bool check_inputs_types_supported(const transaction& tx);
bool check_outs_valid(const transaction& tx);
bool parse_amount(uint64_t& amount, const std::string& str_amount);
bool parse_amount(const std::string& str_amount, uint64_t& amount, const size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT);
bool parse_tracking_seed(const std::string& tracking_seed, account_public_address& address, crypto::secret_key& view_sec_key, uint64_t& creation_timestamp);
@ -610,20 +610,25 @@ namespace currency
return true;
}
//---------------------------------------------------------------
// outputs "1391306.970000000000"
// outputs "1391306.970000000000" (decimal_point = 12)
// outputs "1391306970000000000" (decimal_point = 0)
template<typename t_number>
std::string print_fixed_decimal_point(t_number amount, size_t decimal_point)
{
return epee::string_tools::print_fixed_decimal_point(amount, decimal_point);
}
//---------------------------------------------------------------
// outputs "1391306.97 "
// outputs "1391306.97 " (decimal_point = 12)
// outputs "139130697 " (decimal_point = 0)
template<typename t_number>
std::string print_fixed_decimal_point_with_trailing_spaces(t_number amount, size_t decimal_point)
{
std::string s = epee::string_tools::print_fixed_decimal_point(amount, decimal_point);
for(size_t n = s.size() - 1; n != 0 && s[n] == '0' && s[n-1] != '.'; --n)
s[n] = ' ';
if (s.find('.') != std::string::npos)
{
for(size_t n = s.size() - 1; n != 0 && s[n] == '0' && s[n-1] != '.'; --n)
s[n] = ' ';
}
return s;
}
//---------------------------------------------------------------
@ -1084,17 +1089,24 @@ namespace currency
bool operator()(const extra_user_data& ee)
{
tv.type = "user_data";
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.buff);
if (ee.buff.size() <= 8)
tv.short_view = tv.details_view;
else
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
return true;
}
bool operator()(const extra_padding& ee)
{
tv.type = "extra_padding";
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
if (!ee.buff.empty())
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(std::string(reinterpret_cast<const char*>(&ee.buff[0]), ee.buff.size()));
if (ee.buff.size() <= 8)
tv.short_view = tv.details_view;
else
tv.short_view = std::to_string(ee.buff.size()) + " bytes";
return true;
}
@ -1139,17 +1151,25 @@ namespace currency
bool operator()(const tx_derivation_hint& ee)
{
tv.type = "derivation_hint";
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee.msg);
if (ee.msg.size() <= 8)
tv.short_view = tv.details_view;
else
tv.short_view = std::to_string(ee.msg.size()) + " bytes";
return true;
}
bool operator()(const std::string& ee)
{
tv.type = "string";
tv.short_view = std::to_string(ee.size()) + " bytes";
tv.details_view = epee::string_tools::buff_to_hex_nodelimer(ee);
if (ee.size() <= 8)
tv.short_view = tv.details_view;
else
tv.short_view = std::to_string(ee.size()) + " bytes";
return true;
}
bool operator()(const etc_tx_flags16_t& dh)
@ -1179,6 +1199,15 @@ namespace currency
tv.type = "zc_balance_proof";
return true;
}
bool operator()(const asset_descriptor_operation& ado)
{
tv.type = "asset operation";
tv.short_view = std::string("op:") + get_asset_operation_type_string(ado.operation_type, true);
if (ado.opt_asset_id.has_value())
tv.short_view += std::string(" , id:") + crypto::pod_to_hex(ado.opt_asset_id);
tv.details_view = tv.short_view + std::string(" , ticker:") + ado.descriptor.ticker + std::string(" , cur.supply:") + print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point);
return true;
}
template<typename t_type>
bool operator()(const t_type& t_t)
{

View file

@ -7,6 +7,7 @@
#include <boost/interprocess/detail/atomic.hpp>
#include "currency_core/currency_format_utils.h"
#include "profile_tools.h"
#include <version.h>
namespace currency
{

View file

@ -817,6 +817,7 @@ private:
" amount cmt * 1/8: " << aop.amount_commitment << ENDL <<
" hidden supply: " << (aop.descriptor.hidden_supply ? "yes" : "no") << ENDL <<
"";
++idx;
}
LOG_PRINT_L0(ss.str());

View file

@ -1767,6 +1767,14 @@ QString MainWindow::validate_address(const QString& param)
LOG_API_TIMING();
view::address_validation_response ar = AUTO_VAL_INIT(ar);
ar.error_code = m_backend.validate_address(param.toStdString(), ar.payment_id);
//@#@
//#ifdef _DEBUG
// std::string json_body;
// bool r = epee::file_io_utils::load_file_to_string("C:\\Users\\roky\\home\\temp\\deploy_test.json", json_body);
// async_call_2a("call_wallet_rpc", "0", json_body.c_str());
//#endif
return MAKE_RESPONSE(ar);
CATCH_ENTRY_FAIL_API_RESPONCE();
}

@ -1 +1 @@
Subproject commit 0710887ae3231d329092691f326d91d90662149e
Subproject commit 2fb143cc67280f0e0cfcd3165e1c087ba8279edf

View file

@ -575,7 +575,7 @@ namespace currency
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_pos_mining_details(const COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, COMMAND_RPC_GET_POS_MINING_DETAILS::response& res, connection_context& cntx)
{
if (!m_p2p.get_connections_count())
if (!m_ignore_status && !m_p2p.get_connections_count())
{
res.status = API_RETURN_CODE_DISCONNECTED;
return true;
@ -793,7 +793,7 @@ namespace currency
return true;
}
if (!m_p2p.get_payload_object().get_synchronized_connections_count())
if (!m_ignore_status && !m_p2p.get_payload_object().get_synchronized_connections_count())
{
LOG_PRINT_L0("[on_send_raw_tx]: Failed to send, daemon not connected to net");
res.status = API_RETURN_CODE_DISCONNECTED;

View file

@ -1577,7 +1577,10 @@ bool preprocess_asset_id(std::string& address_arg, crypto::public_key& asset_id)
{
auto p = address_arg.find(':');
if (p == std::string::npos)
{
asset_id = currency::native_coin_asset_id;
return true;
}
std::string asset_id_str = address_arg.substr(0, p);
std::string address_itself = address_arg.substr(p+1, address_arg.size());
if (!epee::string_tools::parse_tpod_from_hex_string(asset_id_str, asset_id))
@ -1636,19 +1639,28 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
currency::tx_destination_entry de = AUTO_VAL_INIT(de);
de.addr.resize(1);
bool ok = currency::parse_amount(de.amount, local_args[i + 1]);
if (!ok || 0 == de.amount)
{
fail_msg_writer() << "amount is wrong: " << local_args[i] << ' ' << local_args[i + 1] <<
", expected number from 0 to " << print_money(std::numeric_limits<uint64_t>::max());
return true;
}
if (!preprocess_asset_id(local_args[i], de.asset_id))
{
fail_msg_writer() << "address is wrong: " << local_args[i];
return true;
}
uint32_t asset_flags = 0;
asset_descriptor_base asset_info{};
if (!m_wallet->get_asset_info(de.asset_id, asset_info, asset_flags))
{
fail_msg_writer() << "unknown asset id: " << de.asset_id;
return true;
}
bool ok = currency::parse_amount(local_args[i + 1], de.amount, asset_info.decimal_point);
if (!ok || 0 == de.amount)
{
fail_msg_writer() << "amount is wrong: " << local_args[i] << ' ' << local_args[i + 1] <<
", expected number from 0 to " << print_money_brief(std::numeric_limits<uint64_t>::max(), asset_info.decimal_point) << " with maximum " << (int)asset_info.decimal_point << " digits after decimal point";
return true;
}
//check if address looks like wrapped address
if (is_address_like_wrapped(local_args[i]))
@ -2150,24 +2162,29 @@ bool simple_wallet::emit_asset(const std::vector<std::string> &args)
bool r = epee::string_tools::parse_tpod_from_hex_string(args[0], asset_id);
if (!r)
{
fail_msg_writer() << "Failed to load asset_id from: " << args[0];
fail_msg_writer() << "Failed to load asset id: " << args[0];
return true;
}
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
uint32_t asset_flags = 0;
r = m_wallet->get_asset_info(asset_id, adb, asset_flags);
if (!r)
{
fail_msg_writer() << "Unknown asset id: " << args[0];
return true;
}
if (!(asset_flags & tools::wallet2::aif_own))
{
fail_msg_writer() << "The wallet appears to have no control over asset " << args[0];
return true;
}
uint64_t amount = 0;
r = epee::string_tools::get_xtype_from_string(amount, args[1]);
r = parse_amount(args[1], amount, adb.decimal_point);
if (!r)
{
fail_msg_writer() << "Failed to load amount from: " << args[1];
return true;
}
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
r = m_wallet->daemon_get_asset_info(asset_id, adb);
if (!r)
{
fail_msg_writer() << "Wallet seems to don't have control over asset: " << args[0];
fail_msg_writer() << "Failed to read amount: " << args[1] << " (assuming decimal point is " << (int)adb.decimal_point << ")";
return true;
}
@ -2180,12 +2197,14 @@ bool simple_wallet::emit_asset(const std::vector<std::string> &args)
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
m_wallet->emit_asset(asset_id, destinations, result_tx);
success_msg_writer(true) << "Emitted " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL
<< "Title: " << adb.full_name << ENDL
<< "Ticker: " << adb.ticker << ENDL
<< "Emitted: " << print_fixed_decimal_point(amount, adb.decimal_point) << ENDL
<< "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL
success_msg_writer(true) << "Emitted " << print_money_brief(amount, adb.decimal_point) << " in tx " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL
<< "Title: " << adb.full_name << ENDL
<< "Ticker: " << adb.ticker << ENDL
<< "Emitted now: " << print_money_brief(amount, adb.decimal_point) << ENDL
<< "Emitted before: " << print_money_brief(adb.current_supply, adb.decimal_point) << ENDL
<< "Emitted total: " << print_money_brief(adb.current_supply + amount, adb.decimal_point) << ENDL
<< "Max emission: " << print_money_brief(adb.total_max_supply, adb.decimal_point) << ENDL
;
SIMPLE_WALLET_CATCH_TRY_ENTRY();
@ -2205,36 +2224,40 @@ bool simple_wallet::burn_asset(const std::vector<std::string> &args)
bool r = epee::string_tools::parse_tpod_from_hex_string(args[0], asset_id);
if (!r)
{
fail_msg_writer() << "Failed to load asset_id from: " << args[0];
fail_msg_writer() << "Failed to load asset id: " << args[0];
return true;
}
uint64_t amount = 0;
r = epee::string_tools::get_xtype_from_string(amount, args[1]);
if (!r)
{
fail_msg_writer() << "Failed to load amount from: " << args[1];
return true;
}
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
r = m_wallet->daemon_get_asset_info(asset_id, adb);
uint32_t asset_flags = 0;
r = m_wallet->get_asset_info(asset_id, adb, asset_flags);
if (!r)
{
fail_msg_writer() << "Wallet seems to don't have control over asset: " << args[0];
fail_msg_writer() << "Unknown asset id: " << args[0];
return true;
}
// as this is asset burning, its not necessary for the wallet to own this asset, so we don't check tools::wallet2::aif_own here
uint64_t amount = 0;
r = parse_amount(args[1], amount, adb.decimal_point);
if (!r)
{
fail_msg_writer() << "Failed to read amount: " << args[1] << " (assuming decimal point is " << (int)adb.decimal_point << ")";
return true;
}
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
m_wallet->burn_asset(asset_id, amount, result_tx);
success_msg_writer(true) << "Burned " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL
<< "Title: " << adb.full_name << ENDL
<< "Ticker: " << adb.ticker << ENDL
<< "Burned: " << print_fixed_decimal_point(amount, adb.decimal_point) << ENDL
<< "Max emission: " << print_fixed_decimal_point(adb.total_max_supply, adb.decimal_point) << ENDL
success_msg_writer(true) << "Burned " << print_money_brief(amount, adb.decimal_point) << " in tx " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL
<< "Title: " << adb.full_name << ENDL
<< "Ticker: " << adb.ticker << ENDL
<< "Burned now: " << print_money_brief(amount, adb.decimal_point) << ENDL
<< "Emitted before: " << print_money_brief(adb.current_supply, adb.decimal_point) << ENDL
<< "Current supply: " << print_money_brief(adb.current_supply - amount, adb.decimal_point) << ENDL
<< "Max emission: " << print_money_brief(adb.total_max_supply, adb.decimal_point) << ENDL
;
SIMPLE_WALLET_CATCH_TRY_ENTRY();
@ -2268,10 +2291,16 @@ bool simple_wallet::update_asset(const std::vector<std::string> &args)
}
currency::asset_descriptor_base adb = AUTO_VAL_INIT(adb);
r = m_wallet->daemon_get_asset_info(asset_id, adb);
uint32_t asset_flags = 0;
r = m_wallet->get_asset_info(asset_id, adb, asset_flags);
if (!r)
{
fail_msg_writer() << "Wallet seems to don't have control over asset: " << args[0];
fail_msg_writer() << "Unknown asset id: " << args[0];
return true;
}
if (!(asset_flags & tools::wallet2::aif_own))
{
fail_msg_writer() << "The wallet appears to have no control over asset " << args[0];
return true;
}
@ -2279,7 +2308,7 @@ bool simple_wallet::update_asset(const std::vector<std::string> &args)
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
m_wallet->update_asset(asset_id, adb, result_tx);
success_msg_writer(true) << "Asset metainfo update tx sent: " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
success_msg_writer(true) << "Asset metainfo successfully updated in tx " << get_transaction_hash(result_tx) << " (unconfirmed) : " << ENDL
<< "Asset ID: " << asset_id << ENDL
<< "Title: " << adb.full_name << ENDL
<< "Ticker: " << adb.ticker << ENDL
@ -2592,7 +2621,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args)
}
uint64_t amount = 0;
r = currency::parse_amount(amount, args[2]);
r = currency::parse_amount(args[2], amount);
if (!r || amount == 0)
{
fail_msg_writer() << "incorrect amount: " << args[2];
@ -3127,7 +3156,7 @@ int main(int argc, char* argv[])
uint64_t max_amount = 0;
CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[0], outs_min) && outs_min > 0 && outs_min < 256, EXIT_FAILURE, "incorrect param: " << params[0]);
CHECK_AND_ASSERT_MES(epee::string_tools::string_to_num_fast(params[1], outs_max) && outs_max > 0 && outs_max < 256, EXIT_FAILURE, "incorrect param: " << params[1]);
CHECK_AND_ASSERT_MES(currency::parse_amount(max_amount, params[2]), EXIT_FAILURE, "incorrect param: " << params[2]);
CHECK_AND_ASSERT_MES(currency::parse_amount(params[2], max_amount), EXIT_FAILURE, "incorrect param: " << params[2]);
wal.set_defragmentation_tx_settings(true, outs_min, outs_max, max_amount);
}
}

View file

@ -8,6 +8,6 @@
#define PROJECT_REVISION "0"
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
#define PROJECT_VERSION_BUILD_NO 321
#define PROJECT_VERSION_BUILD_NO 333
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"

View file

@ -3823,6 +3823,15 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
return true;
}
// own asset?
auto it_own = m_own_asset_descriptors.find(asset_id);
if (it_own != m_own_asset_descriptors.end())
{
asset_info = it_own->second;
asset_flags |= aif_own;
return true;
}
// whitelisted?
auto it_white = m_whitelisted_assets.find(asset_id);
if (it_white != m_whitelisted_assets.end())
@ -3840,18 +3849,41 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
return true;
}
auto it_own = m_own_asset_descriptors.find(asset_id);
if (it_own != m_own_asset_descriptors.end())
{
asset_info = it_own->second;
asset_flags |= aif_own;
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id, size_t result_if_not_found /* = 0 */) const
{
if (asset_id == currency::native_coin_asset_id)
return currency::get_native_coin_asset_descriptor().decimal_point;
// whitelisted?
auto it_white = m_whitelisted_assets.find(asset_id);
if (it_white != m_whitelisted_assets.end())
return it_white->second.decimal_point;
// custom asset?
auto it_cust = m_custom_assets.find(asset_id);
if (it_cust != m_custom_assets.end())
return it_cust->second.decimal_point;
auto it_own = m_own_asset_descriptors.find(asset_id);
if (it_own != m_own_asset_descriptors.end())
return it_own->second.decimal_point;
return result_if_not_found; // if not overriden, use the 0 decimal point (raw numbers) as the default
}
//----------------------------------------------------------------------------------------------------
bool wallet2::get_asset_decimal_point(const crypto::public_key& asset_id, size_t* p_decimal_point_result) const
{
size_t decimal_point = get_asset_decimal_point(asset_id, SIZE_MAX);
if (decimal_point == SIZE_MAX)
return false;
if (p_decimal_point_result != nullptr)
*p_decimal_point_result = decimal_point;
return true;
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::balance() const
{
uint64_t stub = 0;
@ -3956,7 +3988,7 @@ bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::tran
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/, bool show_only_unknown /*= false*/, const std::string& filter_asset_ticker /*= std::string{}*/) const
{
static const char* header = "index amount ticker g_index flags block tx out# asset id";
static const char* header = " index amount ticker g_index flags block tx out# asset id";
std::stringstream ss;
ss << header << ENDL;
size_t count = 0;
@ -3968,6 +4000,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
if ((td.is_spent() && !include_spent) || (!td.is_spent() && !include_unspent))
continue;
bool is_locked = !is_transfer_unlocked(td);
bool native_coin = td.is_native_coin();
asset_descriptor_base adb{};
uint32_t asset_info_flags{};
@ -3981,7 +4014,7 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
if (!filter_asset_ticker.empty() && adb.ticker != filter_asset_ticker)
continue;
ss << std::right <<
ss << std::right << (is_locked ? "*" : " ") <<
std::setw(5) << i << " " <<
std::setw(21) << print_asset_money(td.m_amount, adb.decimal_point) << " " <<
std::setw(6) << std::left << (native_coin ? std::string(" ") : adb.ticker) << " " << std::right <<
@ -4012,11 +4045,12 @@ std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool inclu
std::string wallet2::get_balance_str() const
{
// balance unlocked / [balance total] ticker asset id
// 1391306.970000000000 / 1391306.970000000000 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 1391306.97 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 106.971 / 206.4 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 0.21 / 98.51 DP2 a6974d5874e97e5f4ed5ad0a62f0975edbccb1bb55502fc75c7fe808f12f44d3
// 190.123456789012 / 199.123456789012 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 98.0 BGTVUW af2b12f3033337f9aea1845a6bc3fc966ed4d13227a3ace7706fca7dbcdaa7e2
// 1000.034 DP3 d4aba1020f26927571771e04b585b4ffb211f52708d5e4c465bbdfa4a12e6271
static const char* header = " balance unlocked / [balance total] ticker asset id";
static const char* header = " balance unlocked / [balance total] ticker asset id";
std::stringstream ss;
ss << header << ENDL;
@ -4025,11 +4059,11 @@ std::string wallet2::get_balance_str() const
balance(balances, mined);
for (const tools::wallet_public::asset_balance_entry& b : balances)
{
ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point);
ss << " " << std::left << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(b.unlocked, b.asset_info.decimal_point);
if (b.total == b.unlocked)
ss << " ";
ss << std::string(21 + 3, ' ');
else
ss << " / " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(b.total, b.asset_info.decimal_point);
ss << " / " << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(b.total, b.asset_info.decimal_point);
ss << " " << std::setw(8) << std::left << b.asset_info.ticker << " " << b.asset_info.asset_id << ENDL;
}
@ -4038,12 +4072,16 @@ std::string wallet2::get_balance_str() const
//----------------------------------------------------------------------------------------------------
std::string wallet2::get_balance_str_raw() const
{
// balance unlocked / [balance total] ticker asset id
// 1391306.970000000000 / 1391306.970000000000 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 1391306.97 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 106.971 / 206.4 ZANO d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// balance unlocked / [balance total] DP asset id
// 0.21 / 98.51 2 a6974d5874e97e5f4ed5ad0a62f0975edbccb1bb55502fc75c7fe808f12f44d3
// 190.123456789012 / 199.123456789012 12 d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a
// 98.0 12 af2b12f3033337f9aea1845a6bc3fc966ed4d13227a3ace7706fca7dbcdaa7e2
// 1000.034 3 d4aba1020f26927571771e04b585b4ffb211f52708d5e4c465bbdfa4a12e6271
//WHITELIST:
// 7d3f348fbebfffc4e61a3686189cf870ea393e1c88b8f636acbfdacf9e4b2db2 CT
// ...
static const char* header = " balance unlocked / [balance total] asset id";
static const char* header = " balance unlocked / [balance total] DP asset id";
std::stringstream ss;
ss << header << ENDL;
@ -4053,32 +4091,41 @@ std::string wallet2::get_balance_str_raw() const
for(const auto& entry : balances_map)
{
ss << " " << std::left << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, 12);
size_t decimal_point = 0;
bool has_known_decimal_point = get_asset_decimal_point(entry.first, &decimal_point);
ss << " " << std::left << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(entry.second.unlocked, decimal_point);
if(entry.second.total == entry.second.unlocked)
ss << " ";
ss << std::string(21 + 3, ' ');
else
ss << " / " << std::setw(20) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, 12);
ss << " " << std::setw(8) << std::left << entry.first << ENDL;
ss << " / " << std::setw(21) << print_fixed_decimal_point_with_trailing_spaces(entry.second.total, decimal_point);
ss << " ";
if (has_known_decimal_point)
ss << std::setw(2) << std::right << decimal_point;
else
ss << "??";
ss << " " << entry.first << ENDL;
}
//print whitelist
ss << "WHITELIST: " << ENDL;
for(const auto& entry : m_whitelisted_assets)
{
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
}
// print whitelist
// print custom list
ss << "CUSTOM LIST: " << ENDL;
for(const auto& entry : m_custom_assets)
{
ss << " " << std::left << entry.first << " " << entry.second.ticker << ENDL;
}
// print own list
ss << "OWN DESCRIPTORS LIST: " << ENDL;
for(const auto& entry : m_own_asset_descriptors)
@ -5005,7 +5052,7 @@ bool wallet2::build_minted_block(const mining_context& cxt, const currency::acco
WLT_LOG_GREEN("Note: " << udtx.vin.size() << " inputs were aggregated into UTXO defragmentation tx " << get_transaction_hash(udtx), LOG_LEVEL_0);
}
m_core_proxy->call_COMMAND_RPC_GETBLOCKTEMPLATE(tmpl_req, tmpl_rsp);
WLT_CHECK_AND_ASSERT_MES(tmpl_rsp.status == API_RETURN_CODE_OK, false, "Failed to create block template after kernel hash found!");
WLT_CHECK_AND_ASSERT_MES(tmpl_rsp.status == API_RETURN_CODE_OK, false, "Failed to create block template after kernel hash found! Status: " << tmpl_rsp.status);
currency::block b = AUTO_VAL_INIT(b);
currency::blobdata block_blob;
@ -5258,6 +5305,8 @@ void wallet2::request_alias_registration(currency::extra_alias_entry& ai, curren
//----------------------------------------------------------------------------------------------------
void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info, const std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx, crypto::public_key& new_asset_id)
{
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(asset_info.decimal_point <= 18, "too big decimal point: " << asset_info.decimal_point);
asset_descriptor_operation asset_reg_info = AUTO_VAL_INIT(asset_reg_info);
asset_reg_info.descriptor = asset_info;
asset_reg_info.operation_type = ASSET_DESCRIPTOR_OPERATION_REGISTER;
@ -5371,7 +5420,7 @@ void wallet2::burn_asset(const crypto::public_key asset_id, uint64_t amount_to_b
asset_descriptor_operation asset_burn_info = AUTO_VAL_INIT(asset_burn_info);
asset_burn_info.descriptor = rsp.asset_descriptor;
CHECK_AND_ASSERT_THROW_MES(asset_burn_info.descriptor.current_supply > amount_to_burn, "Wrong amount to burn (current_supply" << asset_burn_info.descriptor.current_supply << " is less then " << amount_to_burn << ")");
CHECK_AND_ASSERT_THROW_MES(asset_burn_info.descriptor.current_supply >= amount_to_burn, "Wrong amount to burn (current_supply" << asset_burn_info.descriptor.current_supply << " is less then " << amount_to_burn << ")");
currency::tx_destination_entry dst_to_burn = AUTO_VAL_INIT(dst_to_burn);
dst_to_burn.amount = amount_to_burn;
@ -6204,7 +6253,7 @@ bool wallet2::accept_ionic_swap_proposal(const wallet_public::ionic_swap_proposa
{
if (balances[item.asset_id].unlocked < item.amount)
{
WLT_THROW_IF_FALSE_WALLET_EX_MES(false, error::not_enough_money, "", balances[item.asset_id].unlocked, item.amount, 0 /*fee*/, item.asset_id);
WLT_THROW_IF_FALSE_WALLET_EX_MES(false, error::not_enough_money, "", balances[item.asset_id].unlocked, item.amount, 0 /*fee*/, item.asset_id, get_asset_decimal_point(item.asset_id));
}
if (item.asset_id == currency::native_coin_asset_id)
{
@ -6557,10 +6606,13 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, bool use_all_decoys
src.real_output = interted_it - src.outputs.begin();
src.real_output_in_tx_index = td.m_internal_output_index;
std::stringstream ss;
ss << "source entry [" << i << "], td_idx: " << J << ", ";
print_source_entry(ss, src);
WLT_LOG_L1(ss.str());
if (epee::log_space::get_set_log_detalisation_level() >= LOG_LEVEL_1)
{
std::stringstream ss;
ss << "source entry [" << i << "], td_idx: " << J << ", ";
print_source_entry(ss, src);
WLT_LOG_L1(ss.str());
}
++i;
}
@ -7056,10 +7108,17 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
{
if(item.second.needed_amount == 0)
continue;
auto asset_cashe_it = m_found_free_amounts.find(item.first);
WLT_THROW_IF_FALSE_WALLET_EX_MES(asset_cashe_it != m_found_free_amounts.end(), error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, item.first);
item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cashe_it->second, item.second.needed_amount, fake_outputs_count);
WLT_THROW_IF_FALSE_WALLET_EX_MES(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, item.first);
const crypto::public_key asset_id = item.first;
asset_descriptor_base asset_info{};
uint32_t asset_flags = 0;
if (!get_asset_info(asset_id, asset_info, asset_flags))
WLT_LOG_L1("select_indices_for_transfer: unknown asset id: " << asset_id);
auto asset_cache_it = m_found_free_amounts.find(asset_id);
WLT_THROW_IF_FALSE_WALLET_EX_MES(asset_cache_it != m_found_free_amounts.end(), error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, asset_id, asset_info.decimal_point);
item.second.found_amount = select_indices_for_transfer(selected_indexes, asset_cache_it->second, item.second.needed_amount, fake_outputs_count, asset_id, asset_info.decimal_point);
WLT_THROW_IF_FALSE_WALLET_EX_MES(item.second.found_amount >= item.second.needed_amount, error::not_enough_money, "", item.second.found_amount, item.second.needed_amount, 0, asset_id, asset_info.decimal_point);
}
if (m_current_context.pconstruct_tx_param && m_current_context.pconstruct_tx_param->need_at_least_1_zc)
{
@ -7081,11 +7140,13 @@ bool wallet2::select_indices_for_transfer(assets_selection_context& needed_money
return true;
}
//----------------------------------------------------------------------------------------------------
uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_)
uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_indexes, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count_,
const crypto::public_key& asset_id, size_t decimal_point)
{
WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() << "...", LOG_LEVEL_0);
WLT_LOG_GREEN("Selecting indices for transfer of " << print_money_brief(needed_money, decimal_point) << " with " << fake_outputs_count_ << " fake outs, found_free_amounts.size()=" << found_free_amounts.size() <<
(asset_id == native_coin_asset_id ? std::string() : std::string(", asset_id: ") + crypto::pod_to_hex(asset_id)) << "...", LOG_LEVEL_0);
uint64_t found_money = 0;
//uint64_t found_zc_input = false;
size_t outputs_found = 0;
std::string selected_amounts_str;
while (found_money < needed_money && found_free_amounts.size())
{
@ -7105,7 +7166,8 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
found_money += it->first;
selected_indexes.push_back(*it->second.begin());
WLT_LOG_L2("Selected index: " << *it->second.begin() << ", transfer_details: " << ENDL << epee::serialization::store_t_to_json(m_transfers[*it->second.begin()]));
selected_amounts_str += (selected_amounts_str.empty() ? "" : "+") + print_money_brief(it->first);
selected_amounts_str += (selected_amounts_str.empty() ? "" : "+") + print_money_brief(it->first, decimal_point);
++outputs_found;
}
it->second.erase(it->second.begin());
if (!it->second.size())
@ -7113,7 +7175,8 @@ uint64_t wallet2::select_indices_for_transfer(std::vector<uint64_t>& selected_in
}
WLT_LOG_GREEN("Found " << print_money_brief(found_money) << " as " << selected_indexes.size() << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size(), LOG_LEVEL_0);
WLT_LOG_GREEN("Found " << print_money_brief(found_money, decimal_point) << " as " << outputs_found << " out(s): " << selected_amounts_str << ", found_free_amounts.size()=" << found_free_amounts.size() <<
(asset_id == native_coin_asset_id ? std::string() : std::string(", asset_id: ") + crypto::pod_to_hex(asset_id)), LOG_LEVEL_0);
return found_money;
}
//----------------------------------------------------------------------------------------------------
@ -7337,13 +7400,15 @@ void wallet2::print_source_entry(std::stringstream& output, const currency::tx_s
for(auto& el : src.outputs)
ss << el.out_reference << " ";
output << "amount: " << print_money_brief(src.amount) << (src.is_zc() ? " (hidden)" : "")
<< ", real_output: " << src.real_output
output << "amount: " << print_money_brief(src.amount, get_asset_decimal_point(src.asset_id)) << (src.is_zc() ? "" : " (bare)");
if (src.asset_id != currency::native_coin_asset_id)
output << " (" << print16(src.asset_id) << ")";
output << ", real_output: " << src.real_output
<< ", real_output_in_tx_index: " << src.real_output_in_tx_index
<< ", indexes: " << ss.str();
if (src.asset_id != currency::native_coin_asset_id)
output << ", asset_id: " << print16(src.asset_id);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key) const
@ -7588,8 +7653,8 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f
ftp, result);
//TIME_MEASURE_FINISH_MS(construct_tx_time);
THROW_IF_FALSE_WALLET_EX(r, error::tx_not_constructed, ftp.sources, ftp.prepared_destinations, ftp.unlock_time);
uint64_t effective_fee = get_tx_fee(result.tx);
THROW_IF_FALSE_WALLET_CMN_ERR_EX(effective_fee <= WALLET_TX_MAX_ALLOWED_FEE, "tx fee is WAY too big: " << print_money_brief(effective_fee) << ", max allowed is " << print_money_brief(WALLET_TX_MAX_ALLOWED_FEE));
uint64_t effective_fee = 0;
THROW_IF_FALSE_WALLET_CMN_ERR_EX(!get_tx_fee(result.tx, effective_fee) || effective_fee <= WALLET_TX_MAX_ALLOWED_FEE, "tx fee is WAY too big: " << print_money_brief(effective_fee) << ", max allowed is " << print_money_brief(WALLET_TX_MAX_ALLOWED_FEE));
//TIME_MEASURE_START_MS(sign_ms_input_time);
if (ftp.multisig_id != currency::null_hash)
@ -7605,7 +7670,8 @@ void wallet2::finalize_transaction(currency::finalize_tx_param& ftp, currency::f
}
//TIME_MEASURE_FINISH_MS(sign_ms_input_time);
THROW_IF_FALSE_WALLET_EX(get_object_blobsize(result.tx) < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, result.tx, m_upper_transaction_size_limit);
size_t tx_blob_size = tx_to_blob(result.tx).size();
THROW_IF_FALSE_WALLET_EX(tx_blob_size < CURRENCY_MAX_TRANSACTION_BLOB_SIZE, error::tx_too_big, result.tx, m_upper_transaction_size_limit);
if (store_tx_secret_key)
m_tx_keys.insert(std::make_pair(get_transaction_hash(result.tx), result.one_time_key));
@ -7823,7 +7889,7 @@ void wallet2::transfer(construct_tx_param& ctp,
void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public_address& destination_addr, uint64_t threshold_amount, const currency::payment_id_t& payment_id,
uint64_t fee, size_t& outs_total, uint64_t& amount_total, size_t& outs_swept, uint64_t& amount_swept, currency::transaction* p_result_tx /* = nullptr */, std::string* p_filename_or_unsigned_tx_blob_str /* = nullptr */)
{
static const size_t estimated_bytes_per_input = 78;
static const size_t estimated_bytes_per_input = 85;
const size_t estimated_max_inputs = static_cast<size_t>(CURRENCY_MAX_TRANSACTION_BLOB_SIZE / (estimated_bytes_per_input * (fake_outs_count + 1.5))); // estimated number of maximum tx inputs under the tx size limit
const size_t tx_sources_for_querying_random_outs_max = estimated_max_inputs * 2;
@ -7838,9 +7904,10 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
for (uint64_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details& td = m_transfers[i];
size_t fake_outs_count_for_td = is_auditable() ? 0 : (td.is_zc() ? m_core_runtime_config.hf4_minimum_mixins : fake_outs_count);
uint64_t amount = td.amount();
if (amount < threshold_amount &&
is_transfer_ready_to_go(td, fake_outs_count))
if (amount < threshold_amount && td.is_native_coin() &&
is_transfer_ready_to_go(td, fake_outs_count_for_td))
{
selected_transfers.push_back(i);
outs_total += 1;
@ -7916,9 +7983,12 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
auto try_construct_tx = [this, &selected_transfers, &rpc_get_random_outs_resp, &fake_outs_count, &fee, &destination_addr]
(size_t st_index_upper_boundary, currency::finalize_tx_param& ftp, uint64_t& amount_swept) -> try_construct_result_t
{
// prepare inputs
amount_swept = 0;
ftp.gen_context = tx_generation_context{};
ftp.sources.clear();
ftp.prepared_destinations.clear();
// prepare inputs
ftp.sources.resize(st_index_upper_boundary);
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(st_index_upper_boundary <= selected_transfers.size(), "index_upper_boundary = " << st_index_upper_boundary << ", selected_transfers.size() = " << selected_transfers.size());
for (size_t st_index = 0; st_index < st_index_upper_boundary; ++st_index)
@ -8013,7 +8083,7 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
size_t st_index_upper_boundary = std::min(selected_transfers.size(), estimated_max_inputs);
try_construct_result_t res = try_construct_tx(st_index_upper_boundary, ftp, amount_swept);
WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(res != rc_too_few_outputs, st_index_upper_boundary << " biggest unspent outputs have total amount of " << print_money_brief(amount_swept)
<< " which is less than required fee: " << print_money_brief(fee) << ", transaction cannot be constructed");
@ -8087,10 +8157,10 @@ void wallet2::sweep_below(size_t fake_outs_count, const currency::account_public
transaction local_tx;
transaction* p_tx = p_result_tx != nullptr ? p_result_tx : &local_tx;
*p_tx = AUTO_VAL_INIT_T(transaction);
*p_tx = transaction{};
try
{
crypto::secret_key sk = AUTO_VAL_INIT(sk);
crypto::secret_key sk{};
finalize_transaction(ftp, *p_tx, sk, true);
}
catch (...)

View file

@ -444,7 +444,9 @@ namespace tools
enum asset_info_flags_t : uint32_t { aif_none = 0, aif_whitelisted = 1 << 0, aif_own = 1 << 1 };
bool get_asset_info(const crypto::public_key& asset_id, currency::asset_descriptor_base& asset_info, uint32_t& asset_flags) const;
size_t get_asset_decimal_point(const crypto::public_key& asset_id, size_t result_if_not_found = 0) const;
bool get_asset_decimal_point(const crypto::public_key& asset_id, size_t* p_decimal_point_result) const;
void transfer(uint64_t amount, const currency::account_public_address& acc, const crypto::public_key& asset_id = currency::native_coin_asset_id);
void transfer(uint64_t amount, size_t fake_outs_count, const currency::account_public_address& acc, uint64_t fee = TX_DEFAULT_FEE, const crypto::public_key& asset_id = currency::native_coin_asset_id);
void transfer(uint64_t amount, const currency::account_public_address& acc, currency::transaction& result_tx, const crypto::public_key& asset_id = currency::native_coin_asset_id);
@ -607,7 +609,7 @@ namespace tools
bool is_transfer_ready_to_go(const transfer_details& td, uint64_t fake_outputs_count) const;
bool is_transfer_able_to_go(const transfer_details& td, uint64_t fake_outputs_count) const;
uint64_t select_indices_for_transfer(std::vector<uint64_t>& ind, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count);
uint64_t select_indices_for_transfer(std::vector<uint64_t>& ind, free_amounts_cache_type& found_free_amounts, uint64_t needed_money, uint64_t fake_outputs_count, const crypto::public_key& asset_id, size_t decimal_point);
bool select_indices_for_transfer(assets_selection_context& needed_money_map, uint64_t fake_outputs_count, std::vector<uint64_t>& selected_indexes);
//PoS

View file

@ -350,12 +350,13 @@ namespace tools
//----------------------------------------------------------------------------------------------------
struct not_enough_money : public transfer_error
{
not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::public_key& asset_id)
not_enough_money(std::string&& loc, uint64_t availbable, uint64_t tx_amount, uint64_t fee, const crypto::public_key& asset_id, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT)
: transfer_error(std::move(loc), "")
, m_available(availbable)
, m_tx_amount(tx_amount)
, m_fee(fee)
, m_asset_id(asset_id)
, m_decimal_point(decimal_point)
{
}
@ -367,9 +368,9 @@ namespace tools
{
std::ostringstream ss;
ss << transfer_error::to_string() <<
"available: " << currency::print_money_brief(m_available) <<
", required: " << currency::print_money_brief(m_tx_amount + m_fee) <<
" = " << currency::print_money_brief(m_tx_amount) << " + " << currency::print_money_brief(m_fee) << " (fee)";
"available: " << currency::print_money_brief(m_available, m_decimal_point) <<
", required: " << currency::print_money_brief(m_tx_amount + m_fee, m_decimal_point) <<
" = " << currency::print_money_brief(m_tx_amount, m_decimal_point) << " + " << currency::print_money_brief(m_fee) << " (fee)";
if (m_asset_id != currency::native_coin_asset_id)
ss << ", asset_id: " << m_asset_id;
return ss.str();
@ -380,6 +381,7 @@ namespace tools
uint64_t m_tx_amount;
uint64_t m_fee;
crypto::public_key m_asset_id;
size_t m_decimal_point;
};
struct no_zc_inputs : public transfer_error

View file

@ -1989,7 +1989,7 @@ namespace wallet_public
currency::asset_descriptor_base asset_descriptor;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(destinations) DOC_DSCR("Addresses where to receive emitted coins. Asset id in destinations should be set to 0000000000000000000000000000000000000000000000000000000000000000") DOC_EXMP_AUTO(1) DOC_END
KV_SERIALIZE(destinations) DOC_DSCR("Addresses where to receive emitted coins. Asset id in the destinations is irreleant and can be omitted.") DOC_EXMP_AUTO(1) DOC_END
KV_SERIALIZE(asset_descriptor) DOC_DSCR("Descriptor that holds all information about asset - ticker, emission, description etc") DOC_END
END_KV_SERIALIZE_MAP()
};
@ -2018,7 +2018,7 @@ namespace wallet_public
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Id of the asset to emit more coins") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
KV_SERIALIZE(destinations) DOC_DSCR("Addresses where to receive emitted coins. Asset id in destinations should be set to 0000000000000000000000000000000000000000000000000000000000000000") DOC_EXMP_AUTO(1) DOC_END
KV_SERIALIZE(destinations) DOC_DSCR("Addresses where to receive emitted coins. Asset id in the destinations is irreleant and can be omitted.") DOC_EXMP_AUTO(1) DOC_END
END_KV_SERIALIZE_MAP()
};
@ -2058,6 +2058,30 @@ namespace wallet_public
};
};
struct COMMAND_ASSETS_BURN
{
DOC_COMMAND("Burn some owned amount of the coins for the given asset.");
struct request
{
crypto::public_key asset_id;
uint64_t burn_amount;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(asset_id) DOC_DSCR("Id of the asset to burn") DOC_EXMP("40fa6db923728b38962718c61b4dc3af1acaa1967479c73703e260dc3609c58d") DOC_END
KV_SERIALIZE(burn_amount) DOC_DSCR("Amount to burn") DOC_EXMP(10000000) DOC_END
END_KV_SERIALIZE_MAP()
};
struct response
{
crypto::hash result_tx;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_POD_AS_HEX_STRING(result_tx) DOC_DSCR("Id of transaction that carries asset burn operation") DOC_EXMP("f74bb56a5b4fa562e679ccaadd697463498a66de4f1760b2cd40f11c3a00a7a8") DOC_END
END_KV_SERIALIZE_MAP()
};
};
} // namespace wallet_rpc
} // namespace tools

View file

@ -1282,9 +1282,16 @@ namespace tools
bool wallet_rpc_server::on_assets_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
WALLET_RPC_BEGIN_TRY_ENTRY();
currency::transaction result_tx;
std::vector<currency::tx_destination_entry> currency_destinations;
rpc_destinations_to_currency_destination(req.destinations, currency_destinations);
//fix for default asset_id
for (auto& d : currency_destinations)
{
d.asset_id = currency::null_pkey;
}
w.get_wallet()->deploy_new_asset(req.asset_descriptor, currency_destinations, result_tx, res.new_asset_id);
res.result_tx = currency::get_transaction_hash(result_tx);
return true;
@ -1297,6 +1304,11 @@ namespace tools
currency::transaction result_tx;
std::vector<currency::tx_destination_entry> currency_destinations;
rpc_destinations_to_currency_destination(req.destinations, currency_destinations);
//fix for default asset_id
for (auto& d : currency_destinations)
{
d.asset_id = currency::null_pkey;
}
w.get_wallet()->emit_asset(req.asset_id, currency_destinations, result_tx);
res.result_tx = currency::get_transaction_hash(result_tx);
@ -1316,6 +1328,16 @@ namespace tools
WALLET_RPC_CATCH_TRY_ENTRY();
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_assets_burn(const wallet_public::COMMAND_ASSETS_BURN::request& req, wallet_public::COMMAND_ASSETS_BURN::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
WALLET_RPC_BEGIN_TRY_ENTRY();
currency::transaction result_tx;
w.get_wallet()->burn_asset(req.asset_id, req.burn_amount, result_tx);
res.result_tx = currency::get_transaction_hash(result_tx);
return true;
WALLET_RPC_CATCH_TRY_ENTRY();
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx)
{
WALLET_RPC_BEGIN_TRY_ENTRY();

View file

@ -149,6 +149,8 @@ namespace tools
MAP_JON_RPC_WE("deploy_asset", on_assets_deploy, wallet_public::COMMAND_ASSETS_DEPLOY)
MAP_JON_RPC_WE("emit_asset", on_assets_emit, wallet_public::COMMAND_ASSETS_EMIT)
MAP_JON_RPC_WE("update_asset", on_assets_update, wallet_public::COMMAND_ASSETS_UPDATE)
MAP_JON_RPC_WE("burn_asset", on_assets_burn, wallet_public::COMMAND_ASSETS_BURN)
//MULTIWALLET APIs
MAP_JON_RPC_WE("mw_get_wallets", on_mw_get_wallets, wallet_public::COMMAND_MW_GET_WALLETS)
@ -219,7 +221,7 @@ namespace tools
bool on_assets_deploy(const wallet_public::COMMAND_ASSETS_DEPLOY::request& req, wallet_public::COMMAND_ASSETS_DEPLOY::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_assets_emit(const wallet_public::COMMAND_ASSETS_EMIT::request& req, wallet_public::COMMAND_ASSETS_EMIT::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_assets_update(const wallet_public::COMMAND_ASSETS_UPDATE::request& req, wallet_public::COMMAND_ASSETS_UPDATE::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_assets_burn(const wallet_public::COMMAND_ASSETS_BURN::request& req, wallet_public::COMMAND_ASSETS_BURN::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_mw_get_wallets(const wallet_public::COMMAND_MW_GET_WALLETS::request& req, wallet_public::COMMAND_MW_GET_WALLETS::response& res, epee::json_rpc::error& er, connection_context& cntx);
bool on_mw_select_wallet(const wallet_public::COMMAND_MW_SELECT_WALLET::request& req, wallet_public::COMMAND_MW_SELECT_WALLET::response& res, epee::json_rpc::error& er, connection_context& cntx);

View file

@ -1495,11 +1495,12 @@ std::string wallets_manager::request_alias_update(const currency::alias_rpc_deta
std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_params& tp, currency::transaction& res_tx)
{
std::vector<currency::tx_destination_entry> dsts;
if(!tp.destinations.size())
return API_RETURN_CODE_BAD_ARG_EMPTY_DESTINATIONS;
GET_WALLET_BY_ID(wallet_id, w);
uint64_t fee = tp.fee;
//payment_id
std::vector<currency::attachment_v> attachments;
@ -1538,8 +1539,13 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p
return API_RETURN_CODE_BAD_ARG_INVALID_ADDRESS;
}
if(!currency::parse_amount(dsts.back().amount, d.amount))
size_t decimal_point = 0;
if (!w->get()->get_asset_decimal_point(d.asset_id, &decimal_point))
{
return API_RETURN_CODE_BAD_ARG_UNKNOWN_DECIMAL_POINT;
}
if(!currency::parse_amount(d.amount, dsts.back().amount, decimal_point))
{
return API_RETURN_CODE_BAD_ARG_WRONG_AMOUNT;
}
@ -1552,8 +1558,6 @@ std::string wallets_manager::transfer(uint64_t wallet_id, const view::transfer_p
dsts.back().asset_id = d.asset_id;
}
GET_WALLET_BY_ID(wallet_id, w);
if (payment_id.size())
{
if (!currency::is_payment_id_size_ok(payment_id))

View file

@ -1070,7 +1070,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_wallet_refreshing_on_chain_switch_2);
GENERATE_AND_PLAY(gen_wallet_unconfirmed_tx_from_tx_pool);
GENERATE_AND_PLAY_HF(gen_wallet_save_load_and_balance, "*");
GENERATE_AND_PLAY_HF(gen_wallet_mine_pos_block, "3");
GENERATE_AND_PLAY_HF(gen_wallet_mine_pos_block, "3-*");
GENERATE_AND_PLAY(gen_wallet_unconfirmed_outdated_tx);
GENERATE_AND_PLAY(gen_wallet_unlock_by_block_and_by_time);
GENERATE_AND_PLAY(gen_wallet_payment_id);
@ -1102,6 +1102,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(wallet_rpc_transfer);
GENERATE_AND_PLAY(wallet_rpc_alias_tests);
GENERATE_AND_PLAY_HF(wallet_rpc_exchange_suite, "3,4");
GENERATE_AND_PLAY_HF(wallet_true_rpc_pos_mining, "4-*");
GENERATE_AND_PLAY(wallet_chain_switch_with_spending_the_same_ki);
GENERATE_AND_PLAY(wallet_sending_to_integrated_address);
GENERATE_AND_PLAY_HF(block_template_blacklist_test, "4-*");
@ -1288,6 +1289,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(zarcanum_block_with_txs);
GENERATE_AND_PLAY(asset_depoyment_and_few_zc_utxos);
GENERATE_AND_PLAY_HF(assets_and_pos_mining, "4-*");
// GENERATE_AND_PLAY_HF(asset_emission_and_unconfirmed_balance, "4-*");
GENERATE_AND_PLAY_HF(pos_fuse_test, "4-*");

View file

@ -823,3 +823,67 @@ bool assets_and_pos_mining::c1(currency::core& c, size_t ev_index, const std::ve
return true;
}
//------------------------------------------------------------------------------
asset_emission_and_unconfirmed_balance::asset_emission_and_unconfirmed_balance()
{
REGISTER_CALLBACK_METHOD(asset_emission_and_unconfirmed_balance, c1);
}
bool asset_emission_and_unconfirmed_balance::generate(std::vector<test_event_entry>& events) const
{
uint64_t ts = test_core_time::get_time();
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
//account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
miner_acc.generate();
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
DO_CALLBACK(events, "c1");
return true;
}
bool asset_emission_and_unconfirmed_balance::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
miner_wlt->refresh();
asset_descriptor_base adb{};
adb.total_max_supply = UINT64_MAX;
adb.full_name = "2**64";
adb.ticker = "2POWER64";
std::vector<currency::tx_destination_entry> destinations;
destinations.emplace_back(adb.total_max_supply, m_accounts[MINER_ACC_IDX].get_public_address(), null_pkey);
currency::transaction tx{};
crypto::public_key asset_id = currency::null_pkey;
miner_wlt->deploy_new_asset(adb, destinations, tx, asset_id);
LOG_PRINT_L0("Deployed new asset: " << asset_id << ", tx_id: " << currency::get_transaction_hash(tx));
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
bool stub_bool = 0;
miner_wlt->refresh();
miner_wlt->scan_tx_pool(stub_bool);
uint64_t total, unlocked, awaiting_in, awaiting_out, mined;
balance_via_wallet(*miner_wlt, asset_id, &total, &unlocked, &awaiting_in, &awaiting_out, &mined);
CHECK_AND_ASSERT_EQ(total, UINT64_MAX);
CHECK_AND_ASSERT_EQ(unlocked, 0);
CHECK_AND_ASSERT_EQ(awaiting_in, UINT64_MAX);
CHECK_AND_ASSERT_EQ(awaiting_out, 0);
//CHECK_AND_ASSERT_EQ(mined, 0);
r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_block_in_playtime failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
return true;
}

View file

@ -41,3 +41,9 @@ struct assets_and_pos_mining : public wallet_test
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};
struct asset_emission_and_unconfirmed_balance : public wallet_test
{
asset_emission_and_unconfirmed_balance();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};

View file

@ -801,3 +801,126 @@ bool wallet_rpc_exchange_suite::c1(currency::core& c, size_t ev_index, const std
return true;
}
//------------------------------------------------------------------------------
wallet_true_rpc_pos_mining::wallet_true_rpc_pos_mining()
{
REGISTER_CALLBACK_METHOD(wallet_true_rpc_pos_mining, c1);
}
bool wallet_true_rpc_pos_mining::generate(std::vector<test_event_entry>& events) const
{
uint64_t ts = test_core_time::get_time();
m_accounts.resize(TOTAL_ACCS_COUNT);
account_base& miner_acc = m_accounts[MINER_ACC_IDX]; miner_acc.generate(); miner_acc.set_createtime(ts);
account_base& alice_acc = m_accounts[ALICE_ACC_IDX]; alice_acc.generate(); alice_acc.set_createtime(ts);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
DO_CALLBACK(events, "c1");
return true;
}
#include <boost/program_options/detail/parsers.hpp>
bool wallet_true_rpc_pos_mining::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
{
bool r = false;
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet_with_true_http_rpc(events, c, MINER_ACC_IDX);
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet_with_true_http_rpc(events, c, ALICE_ACC_IDX);
/*currency::t_currency_protocol_handler<currency::core> m_cprotocol(c, nullptr);
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > p2p(m_cprotocol);
bc_services::bc_offers_service bos(nullptr);
bos.set_disabled(true);
currency::core_rpc_server core_rpc_wrapper(c, p2p, bos);
core_rpc_wrapper.set_ignore_connectivity_status(true);
boost::program_options::options_description desc_options;
currency::core_rpc_server::init_options(desc_options);
boost::program_options::variables_map vm{};
char* argv[] = {"--rpc-bind-ip=127.0.0.1", "--rpc-bind-port=33777"};
boost::program_options::store(boost::program_options::parse_command_line(sizeof argv / sizeof argv[0], argv, desc_options), vm);
r = core_rpc_wrapper.init(vm);
CHECK_AND_ASSERT_MES(r, false, "rpc server init failed");
r = core_rpc_wrapper.run(1, false);
CHECK_AND_ASSERT_MES(r, 1, "rpc server run failed");
auto slh = epee::misc_utils::create_scope_leave_handler([&](){
core_rpc_wrapper.deinit();
});
auto http_core_proxy = std::shared_ptr<tools::i_core_proxy>(new tools::default_http_core_proxy());
http_core_proxy->set_connectivity(5000, 1);
CHECK_AND_ASSERT_MES(http_core_proxy->set_connection_addr("127.0.0.1:33777"), false, "");
CHECK_AND_ASSERT_MES(http_core_proxy->check_connection(), false, "no connection");
miner_wlt->set_core_proxy(http_core_proxy);*/
uint64_t top_height = c.get_top_block_height();
size_t blocks_fetched = 0;
miner_wlt->refresh(blocks_fetched);
CHECK_AND_ASSERT_EQ(blocks_fetched, top_height);
alice_wlt->refresh(blocks_fetched);
CHECK_AND_ASSERT_EQ(blocks_fetched, top_height);
//uint64_t balance_unlocked = 1, balance_awaiting_in = 1, balance_awaiting_out = 1, balance_mined = 1;
//uint64_t miner_initial_balance = miner_wlt->balance(balance_unlocked, balance_awaiting_in, balance_awaiting_out, balance_mined);
//CHECK_AND_ASSERT_EQ(miner_initial_balance, PREMINE_AMOUNT + CURRENCY_BLOCK_REWARD * top_height);
uint64_t miner_amount = PREMINE_AMOUNT + CURRENCY_BLOCK_REWARD * top_height;
uint64_t expected_unlocked = miner_amount - (CURRENCY_MINED_MONEY_UNLOCK_WINDOW - 1) * COIN;
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt, "miner", miner_amount, INVALID_BALANCE_VAL, expected_unlocked, 0, 0), false, "");
CHECK_AND_ASSERT_MES(miner_wlt->try_mint_pos(), false, "try_mint_pos failed");
CHECK_AND_ASSERT_EQ(c.get_top_block_height(), top_height + 1);
miner_wlt->refresh(blocks_fetched);
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt, "miner", miner_amount + COIN), false, "");
uint64_t amount_to_alice = MK_TEST_COINS(500);
miner_wlt->transfer(amount_to_alice, m_accounts[ALICE_ACC_IDX].get_public_address());
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
CHECK_AND_ASSERT_MES(miner_wlt->try_mint_pos(), false, "try_mint_pos failed");
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "enexpected pool txs count: " << c.get_pool_transactions_count());
miner_wlt->refresh(blocks_fetched);
CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*miner_wlt, "miner", miner_amount + 2 * COIN - amount_to_alice - TESTS_DEFAULT_FEE), false, "");
// Alice
//alice_wlt->refresh(blocks_fetched);
//CHECK_AND_ASSERT_EQ(blocks_fetched, 2);
//CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", amount_to_alice, 0, 0, 0, 0), false, "");
//r = mine_next_pow_blocks_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
//CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
//alice_wlt->refresh(blocks_fetched);
//CHECK_AND_ASSERT_EQ(blocks_fetched, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
//
//CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", amount_to_alice, 0, amount_to_alice, 0, 0), false, "");
//std::this_thread::yield();
//std::this_thread::sleep_for( std::chrono::milliseconds(1) );
//CHECK_AND_ASSERT_MES(alice_wlt->try_mint_pos(), false, "try_mint_pos failed");
//alice_wlt->refresh(blocks_fetched);
//CHECK_AND_ASSERT_EQ(blocks_fetched, 1);
//CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt, "Alice", amount_to_alice + CURRENCY_BLOCK_REWARD, 0, 0, 0, 0), false, "");
return true;
}

View file

@ -49,3 +49,9 @@ struct wallet_rpc_exchange_suite : public wallet_test
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};
struct wallet_true_rpc_pos_mining : public wallet_test
{
wallet_true_rpc_pos_mining();
bool generate(std::vector<test_event_entry>& events) const;
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
};

View file

@ -639,8 +639,19 @@ bool gen_wallet_mine_pos_block::c1(currency::core& c, size_t ev_index, const std
block top_block = AUTO_VAL_INIT(top_block);
bool r = c.get_blockchain_storage().get_top_block(top_block);
CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong");
uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx);
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", top_block_reward, top_block_reward - MK_TEST_COINS(2000), 0, 0, 0), false, "");
uint64_t top_block_reward = 0, expected_mined = 0;
if (c.get_blockchain_storage().is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
{
top_block_reward = MK_TEST_COINS(2000) + CURRENCY_BLOCK_REWARD;
expected_mined = INVALID_BALANCE_VAL; // Don't check mined balace for post-HF4 due to a lack of mined balance correctness TODO -- sowle
}
else
{
top_block_reward = get_outs_money_amount(top_block.miner_tx);
expected_mined = top_block_reward - MK_TEST_COINS(2000);
}
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice_wlt", top_block_reward, expected_mined, 0, 0, 0), false, "");
alice_wlt->reset_password(g_wallet_password);
alice_wlt->store(g_wallet_filename);

View file

@ -99,3 +99,8 @@ std::shared_ptr<tools::wallet2> wallet_test::init_playtime_test_wallet(const std
return init_playtime_test_wallet(events, c, m_accounts[account_index]);
}
std::shared_ptr<tools::wallet2> wallet_test::init_playtime_test_wallet_with_true_http_rpc(const std::vector<test_event_entry>& events, currency::core& c, size_t account_index) const
{
CHECK_AND_ASSERT_THROW_MES(account_index < m_accounts.size(), "Invalid account index");
return init_playtime_test_wallet_t<tools::wallet2>(events, c, m_accounts[account_index], true);
}

View file

@ -1,10 +1,15 @@
// Copyright (c) 2014-2018 Zano Project
// Copyright (c) 2014-2024 Zano Project
// Copyright (c) 2014-2018 The Louisdor Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "chaingen.h"
#include "currency_protocol/currency_protocol_handler.h"
#include "currency_core/currency_core.h"
#include "p2p/net_node.h"
#include "currency_core/bc_offers_service.h"
#include "rpc/core_rpc_server.h"
struct wallet_test : virtual public test_chain_unit_enchanced
{
@ -22,11 +27,30 @@ struct wallet_test : virtual public test_chain_unit_enchanced
static std::string get_test_account_name_by_id(size_t acc_id);
template<typename wallet_t>
std::shared_ptr<wallet_t> init_playtime_test_wallet_t(const std::vector<test_event_entry>& events, currency::core& c, const currency::account_base& acc) const
std::shared_ptr<wallet_t> init_playtime_test_wallet_t(const std::vector<test_event_entry>& events, currency::core& c, const currency::account_base& acc, bool true_http_rpc = false) const
{
CHECK_AND_ASSERT_THROW_MES(events.size() > 0 && events[0].type() == typeid(currency::block), "Invalid events queue, can't find genesis block at the beginning");
crypto::hash genesis_hash = get_block_hash(boost::get<currency::block>(events[0]));
if (true_http_rpc)
{
m_core_proxy = std::make_shared<tools::default_http_core_proxy>();
m_core_proxy->set_connectivity(100, 1);
CHECK_AND_ASSERT_THROW_MES(m_core_proxy->set_connection_addr("127.0.0.1:33777"), "set_connection_addr failed");
if (!m_core_proxy->check_connection())
{
// if there's not http rpc core server yet, create one
boost::program_options::options_description desc_options;
currency::core_rpc_server::init_options(desc_options);
boost::program_options::variables_map vm{};
char* argv[] = {"--rpc-bind-ip=127.0.0.1", "--rpc-bind-port=33777"};
boost::program_options::store(boost::program_options::parse_command_line(sizeof argv / sizeof argv[0], argv, desc_options), vm);
m_http_rpc_server = std::make_shared<core_http_rpc_server_details>(c, vm);
}
m_core_proxy->set_connectivity(30000, 1);
CHECK_AND_ASSERT_THROW_MES(m_core_proxy->check_connection(), "m_core_proxy: no connection");
}
std::shared_ptr<wallet_t> w(new wallet_t);
w->set_core_runtime_config(c.get_blockchain_storage().get_core_runtime_config());
w->assign_account(acc);
@ -64,12 +88,42 @@ protected:
size_t account_index;
};
struct core_http_rpc_server_details
{
currency::t_currency_protocol_handler<currency::core> cph;
nodetool::node_server<currency::t_currency_protocol_handler<currency::core> > p2p;
bc_services::bc_offers_service bos;
currency::core_rpc_server core_rpc_server;
core_http_rpc_server_details(currency::core& c, const boost::program_options::variables_map& vm)
: cph(c, nullptr)
, p2p(cph)
, bos(nullptr)
, core_rpc_server(c, p2p, bos)
{
bos.set_disabled(true);
core_rpc_server.set_ignore_connectivity_status(true);
bool r = core_rpc_server.init(vm);
CRYPTO_CHECK_AND_THROW_MES(r, "core_http_rpc_server_details: rpc server init failed");
r = core_rpc_server.run(2, false);
CRYPTO_CHECK_AND_THROW_MES(r, "core_http_rpc_server_details: rpc server run failed");
}
~core_http_rpc_server_details()
{
core_rpc_server.deinit();
}
};
std::shared_ptr<tools::wallet2> init_playtime_test_wallet(const std::vector<test_event_entry>& events, currency::core& c, size_t account_index) const;
std::shared_ptr<tools::wallet2> init_playtime_test_wallet(const std::vector<test_event_entry>& events, currency::core& c, const currency::account_base& acc) const;
std::shared_ptr<tools::wallet2> init_playtime_test_wallet_with_true_http_rpc(const std::vector<test_event_entry>& events, currency::core& c, size_t account_index) const;
mutable std::vector<currency::account_base> m_accounts;
mutable test_generator generator;
std::shared_ptr<tools::i_core_proxy> m_core_proxy;
mutable std::shared_ptr<tools::i_core_proxy> m_core_proxy;
mutable std::shared_ptr<core_http_rpc_server_details> m_http_rpc_server; // "True" RPC via http on localhost
};

View file

@ -1,4 +1,4 @@
// Copyright (c) 2022 Zano Project
// Copyright (c) 2022-2024 Zano Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -10,23 +10,23 @@ using namespace currency;
namespace
{
void do_pos_test(uint64_t expected, const std::string& str)
void do_pos_test(uint64_t expected, const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT)
{
uint64_t val;
std::string number_str = str;
std::replace(number_str.begin(), number_str.end(), '_', '.');
number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end());
ASSERT_TRUE(parse_amount(val, number_str));
ASSERT_TRUE(parse_amount(number_str, val, decimal_point));
ASSERT_EQ(expected, val);
}
void do_neg_test(const std::string& str)
void do_neg_test(const std::string& str, size_t decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT)
{
uint64_t val;
std::string number_str = str;
std::replace(number_str.begin(), number_str.end(), '_', '.');
number_str.erase(std::remove(number_str.begin(), number_str.end(), '~'), number_str.end());
ASSERT_FALSE(parse_amount(val, number_str));
ASSERT_FALSE(parse_amount(number_str, val, decimal_point));
}
}
@ -48,6 +48,23 @@ namespace
do_neg_test(#str); \
}
#define TEST_pos_dp(expected, str, decimal_point) \
TEST(parse_amount, handles_pos_ ## str ## _dp ## decimal_point) \
{ \
do_pos_test(UINT64_C(expected), #str, decimal_point); \
}
#define TEST_neg_dp(str, decimal_point) \
TEST(parse_amount, handles_neg_ ## str ## _dp ## decimal_point) \
{ \
do_neg_test(#str, decimal_point); \
}
#define TEST_neg_n_dp(str, name, decimal_point) \
TEST(parse_amount, handles_neg_ ## name ## _dp ## decimal_point) \
{ \
do_neg_test(#str, decimal_point); \
}
TEST_pos(0, 0);
TEST_pos(0, 00);
@ -96,6 +113,44 @@ TEST_pos(18446744073700000000, 18446744_0737000000000);
TEST_pos(18446744073700000000, 18446744_07370000000000000000000);
TEST_pos(18446744073709551615, 18446744_073709551615);
// non-standard decimal point
TEST_pos_dp(0, 0_0, 3);
TEST_pos_dp(0, 00_0, 3);
TEST_pos_dp(0, 00_00, 3);
TEST_pos_dp(0, 00000000_00, 3);
TEST_pos_dp(0, 00_000000000, 3);
TEST_pos_dp(0, 00_00000000000000000000000000000000, 3);
TEST_pos_dp( 65535, 65535, 0);
TEST_pos_dp( 6553500, 65535, 2);
TEST_pos_dp( 65535000000, 65535, 6);
TEST_pos_dp( 18000000000000000000, 18, 18);
TEST_pos_dp( 1, 0_1, 1);
TEST_pos_dp( 10, 0_1, 2);
TEST_pos_dp( 100, 0_1, 3);
TEST_pos_dp( 10000000000000000000, 0_1, 20);
TEST_pos_dp( 1, 0_001, 3);
TEST_pos_dp( 123, 0_123, 3);
TEST_pos_dp( 1230, 0_123, 4);
TEST_pos_dp( 12300, 0_123, 5);
TEST_pos_dp( 123000, 0_123, 6);
TEST_pos_dp(18446744073709551615, 18446744073709551615, 0);
TEST_pos_dp(18446744073709551615, 18446744073709551615_0, 0);
TEST_pos_dp(18446744073709551615, 1844674407370955161_5, 1);
TEST_pos_dp(18446744073709551615, 1844674407370955161_50, 1);
TEST_pos_dp(18446744073709551615, 18446744073709551_615, 3);
TEST_pos_dp(18446744073709551615, 18446744073709551_615000, 3);
TEST_pos_dp(18446744073709551615, 1_8446744073709551615, 19);
TEST_pos_dp(18446744073709551615, 1_844674407370955161500, 19);
TEST_pos_dp(18446744073709551615, 0_18446744073709551615, 20);
TEST_pos_dp(18446744073709551615, 0_1844674407370955161500, 20);
// Invalid numbers
TEST_neg_n(~, empty_string);
TEST_neg_n(-0, minus_0);
@ -109,10 +164,17 @@ TEST_neg(0_0000000000001);
TEST_neg(0_0000000000009);
TEST_neg(18446744_0737000000001);
TEST_neg_dp(00_184467440737095516150001, 20);
TEST_neg_dp(00_184467440737095516151, 20);
TEST_neg_dp(1_2, 0);
// Overflow
TEST_neg(184467440737_09551616);
TEST_neg(184467440738);
TEST_neg(18446744073709551616);
TEST_neg_dp(18446744073709551616, 0);
TEST_neg_dp(1844674407370955161_60, 1);
TEST_neg_dp(0_18446744073709551616, 20);
// Two or more points
TEST_neg(__);
@ -123,6 +185,51 @@ TEST_neg(0_0_);
TEST_neg(_0_0);
TEST_neg(0_0_0);
// moved from test_format_utils.cpp
TEST(validate_parse_amount_case, validate_parse_amount)
{
uint64_t res = 0;
bool r = currency::parse_amount("0.0001", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000000);
r = currency::parse_amount("100.0001", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000100000000);
r = currency::parse_amount("000.0000", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 0);
r = currency::parse_amount("0", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 0);
r = currency::parse_amount(" 100.0001 ", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000100000000);
r = currency::parse_amount(" 100.0000 ", res);
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000000000000);
r = currency::parse_amount(" 100. 0000 ", res);
ASSERT_FALSE(r);
r = currency::parse_amount("100. 0000", res);
ASSERT_FALSE(r);
r = currency::parse_amount("100 . 0000", res);
ASSERT_FALSE(r);
r = currency::parse_amount("100.00 00", res);
ASSERT_FALSE(r);
r = currency::parse_amount("1 00.00 00", res);
ASSERT_FALSE(r);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -201,3 +308,143 @@ TEST(decompose_amount_randomly, 1)
foo(1000000000000, 2, 3);
}
}
TEST(print_money_brief, 1)
{
// decimal point 12 (default)
ASSERT_EQ(print_money_brief( 0), "0.0");
ASSERT_EQ(print_money_brief( 1), "0.000000000001");
ASSERT_EQ(print_money_brief( 1000000000000), "1.0");
ASSERT_EQ(print_money_brief( 1900000000000), "1.9");
ASSERT_EQ(print_money_brief( 1000000100000), "1.0000001");
ASSERT_EQ(print_money_brief( 1000000000001), "1.000000000001");
ASSERT_EQ(print_money_brief( 9999999999999), "9.999999999999");
ASSERT_EQ(print_money_brief( 90009990009900), "90.0099900099");
ASSERT_EQ(print_money_brief(10109010000000000000), "10109010.0");
ASSERT_EQ(print_money_brief(10109010010000000000), "10109010.01");
ASSERT_EQ(print_money_brief(18446744073709551610), "18446744.07370955161");
ASSERT_EQ(print_money_brief(18446744073709551614), "18446744.073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615), "18446744.073709551615");
// decimal point 0
ASSERT_EQ(print_money_brief( 0, 0), "0");
ASSERT_EQ(print_money_brief( 1, 0), "1");
ASSERT_EQ(print_money_brief( 1000000000000, 0), "1000000000000");
ASSERT_EQ(print_money_brief( 1900000000000, 0), "1900000000000");
ASSERT_EQ(print_money_brief( 1000000100000, 0), "1000000100000");
ASSERT_EQ(print_money_brief( 1000000000001, 0), "1000000000001");
ASSERT_EQ(print_money_brief( 9999999999999, 0), "9999999999999");
ASSERT_EQ(print_money_brief( 90009990009900, 0), "90009990009900");
ASSERT_EQ(print_money_brief(10109010000000000000, 0), "10109010000000000000");
ASSERT_EQ(print_money_brief(10109010010000000000, 0), "10109010010000000000");
ASSERT_EQ(print_money_brief(18446744073709551610, 0), "18446744073709551610");
ASSERT_EQ(print_money_brief(18446744073709551614, 0), "18446744073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615, 0), "18446744073709551615");
// decimal point 1
ASSERT_EQ(print_money_brief( 0, 1), "0.0");
ASSERT_EQ(print_money_brief( 1, 1), "0.1");
ASSERT_EQ(print_money_brief( 1000000000000, 1), "100000000000.0");
ASSERT_EQ(print_money_brief( 1900000000000, 1), "190000000000.0");
ASSERT_EQ(print_money_brief( 1000000100000, 1), "100000010000.0");
ASSERT_EQ(print_money_brief( 1000000000001, 1), "100000000000.1");
ASSERT_EQ(print_money_brief( 9999999999999, 1), "999999999999.9");
ASSERT_EQ(print_money_brief( 90009990009900, 1), "9000999000990.0");
ASSERT_EQ(print_money_brief(10109010000000000000, 1), "1010901000000000000.0");
ASSERT_EQ(print_money_brief(10109010010000000000, 1), "1010901001000000000.0");
ASSERT_EQ(print_money_brief(18446744073709551610, 1), "1844674407370955161.0");
ASSERT_EQ(print_money_brief(18446744073709551614, 1), "1844674407370955161.4");
ASSERT_EQ(print_money_brief(18446744073709551615, 1), "1844674407370955161.5");
// decimal point 2
ASSERT_EQ(print_money_brief( 0, 2), "0.0");
ASSERT_EQ(print_money_brief( 1, 2), "0.01");
ASSERT_EQ(print_money_brief( 1000000000000, 2), "10000000000.0");
ASSERT_EQ(print_money_brief( 1900000000000, 2), "19000000000.0");
ASSERT_EQ(print_money_brief( 1000000100000, 2), "10000001000.0");
ASSERT_EQ(print_money_brief( 1000000000001, 2), "10000000000.01");
ASSERT_EQ(print_money_brief( 9999999999999, 2), "99999999999.99");
ASSERT_EQ(print_money_brief( 90009990009900, 2), "900099900099.0");
ASSERT_EQ(print_money_brief(10109010000000000000, 2), "101090100000000000.0");
ASSERT_EQ(print_money_brief(10109010010000000000, 2), "101090100100000000.0");
ASSERT_EQ(print_money_brief(18446744073709551610, 2), "184467440737095516.1");
ASSERT_EQ(print_money_brief(18446744073709551614, 2), "184467440737095516.14");
ASSERT_EQ(print_money_brief(18446744073709551615, 2), "184467440737095516.15");
// decimal point 3
ASSERT_EQ(print_money_brief( 0, 3), "0.0");
ASSERT_EQ(print_money_brief( 1, 3), "0.001");
ASSERT_EQ(print_money_brief( 1000000000000, 3), "1000000000.0");
ASSERT_EQ(print_money_brief( 1900000000000, 3), "1900000000.0");
ASSERT_EQ(print_money_brief( 1000000100000, 3), "1000000100.0");
ASSERT_EQ(print_money_brief( 1000000000001, 3), "1000000000.001");
ASSERT_EQ(print_money_brief( 9999999999999, 3), "9999999999.999");
ASSERT_EQ(print_money_brief( 90009990009900, 3), "90009990009.9");
ASSERT_EQ(print_money_brief(10109010000000000000, 3), "10109010000000000.0");
ASSERT_EQ(print_money_brief(10109010010000000000, 3), "10109010010000000.0");
ASSERT_EQ(print_money_brief(18446744073709551610, 3), "18446744073709551.61");
ASSERT_EQ(print_money_brief(18446744073709551614, 3), "18446744073709551.614");
ASSERT_EQ(print_money_brief(18446744073709551615, 3), "18446744073709551.615");
// decimal point 18
ASSERT_EQ(print_money_brief( 0, 18), "0.0");
ASSERT_EQ(print_money_brief( 1, 18), "0.000000000000000001");
ASSERT_EQ(print_money_brief( 1000000000000, 18), "0.000001");
ASSERT_EQ(print_money_brief( 1900000000000, 18), "0.0000019");
ASSERT_EQ(print_money_brief( 1000000100000, 18), "0.0000010000001");
ASSERT_EQ(print_money_brief( 1000000000001, 18), "0.000001000000000001");
ASSERT_EQ(print_money_brief( 9999999999999, 18), "0.000009999999999999");
ASSERT_EQ(print_money_brief( 90009990009900, 18), "0.0000900099900099");
ASSERT_EQ(print_money_brief(10109010000000000000, 18), "10.10901");
ASSERT_EQ(print_money_brief(10109010010000000000, 18), "10.10901001");
ASSERT_EQ(print_money_brief(18446744073709551610, 18), "18.44674407370955161");
ASSERT_EQ(print_money_brief(18446744073709551614, 18), "18.446744073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615, 18), "18.446744073709551615");
// decimal point 19
ASSERT_EQ(print_money_brief( 0, 19), "0.0");
ASSERT_EQ(print_money_brief( 1, 19), "0.0000000000000000001");
ASSERT_EQ(print_money_brief( 1000000000000, 19), "0.0000001");
ASSERT_EQ(print_money_brief( 1900000000000, 19), "0.00000019");
ASSERT_EQ(print_money_brief( 1000000100000, 19), "0.00000010000001");
ASSERT_EQ(print_money_brief( 1000000000001, 19), "0.0000001000000000001");
ASSERT_EQ(print_money_brief( 9999999999999, 19), "0.0000009999999999999");
ASSERT_EQ(print_money_brief( 90009990009900, 19), "0.00000900099900099");
ASSERT_EQ(print_money_brief(10109010000000000000, 19), "1.010901");
ASSERT_EQ(print_money_brief(10109010010000000000, 19), "1.010901001");
ASSERT_EQ(print_money_brief(18446744073709551610, 19), "1.844674407370955161");
ASSERT_EQ(print_money_brief(18446744073709551614, 19), "1.8446744073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615, 19), "1.8446744073709551615");
// TODO: remove it after setting reasonable limit of 18
// decimal point 20
ASSERT_EQ(print_money_brief( 0, 20), "0.0");
ASSERT_EQ(print_money_brief( 1, 20), "0.00000000000000000001");
ASSERT_EQ(print_money_brief( 1000000000000, 20), "0.00000001");
ASSERT_EQ(print_money_brief( 1900000000000, 20), "0.000000019");
ASSERT_EQ(print_money_brief( 1000000100000, 20), "0.000000010000001");
ASSERT_EQ(print_money_brief( 1000000000001, 20), "0.00000001000000000001");
ASSERT_EQ(print_money_brief( 9999999999999, 20), "0.00000009999999999999");
ASSERT_EQ(print_money_brief( 90009990009900, 20), "0.000000900099900099");
ASSERT_EQ(print_money_brief(10109010000000000000, 20), "0.1010901");
ASSERT_EQ(print_money_brief(10109010010000000000, 20), "0.1010901001");
ASSERT_EQ(print_money_brief(18446744073709551610, 20), "0.1844674407370955161");
ASSERT_EQ(print_money_brief(18446744073709551614, 20), "0.18446744073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615, 20), "0.18446744073709551615");
// TODO: remove it after setting reasonable limit of 18
// decimal point 21
ASSERT_EQ(print_money_brief( 0, 21), "0.0");
ASSERT_EQ(print_money_brief( 1, 21), "0.000000000000000000001");
ASSERT_EQ(print_money_brief( 1000000000000, 21), "0.000000001");
ASSERT_EQ(print_money_brief( 1900000000000, 21), "0.0000000019");
ASSERT_EQ(print_money_brief( 1000000100000, 21), "0.0000000010000001");
ASSERT_EQ(print_money_brief( 1000000000001, 21), "0.000000001000000000001");
ASSERT_EQ(print_money_brief( 9999999999999, 21), "0.000000009999999999999");
ASSERT_EQ(print_money_brief( 90009990009900, 21), "0.0000000900099900099");
ASSERT_EQ(print_money_brief(10109010000000000000, 21), "0.01010901");
ASSERT_EQ(print_money_brief(10109010010000000000, 21), "0.01010901001");
ASSERT_EQ(print_money_brief(18446744073709551610, 21), "0.01844674407370955161");
ASSERT_EQ(print_money_brief(18446744073709551614, 21), "0.018446744073709551614");
ASSERT_EQ(print_money_brief(18446744073709551615, 21), "0.018446744073709551615");
}

View file

@ -125,48 +125,3 @@ void force_random(forced_to_pod_t& o)
// }
//
// }
TEST(validate_parse_amount_case, validate_parse_amount)
{
uint64_t res = 0;
bool r = currency::parse_amount(res, "0.0001");
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000000);
r = currency::parse_amount(res, "100.0001");
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000100000000);
r = currency::parse_amount(res, "000.0000");
ASSERT_TRUE(r);
ASSERT_EQ(res, 0);
r = currency::parse_amount(res, "0");
ASSERT_TRUE(r);
ASSERT_EQ(res, 0);
r = currency::parse_amount(res, " 100.0001 ");
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000100000000);
r = currency::parse_amount(res, " 100.0000 ");
ASSERT_TRUE(r);
ASSERT_EQ(res, 100000000000000);
r = currency::parse_amount(res, " 100. 0000 ");
ASSERT_FALSE(r);
r = currency::parse_amount(res, "100. 0000");
ASSERT_FALSE(r);
r = currency::parse_amount(res, "100 . 0000");
ASSERT_FALSE(r);
r = currency::parse_amount(res, "100.00 00");
ASSERT_FALSE(r);
r = currency::parse_amount(res, "1 00.00 00");
ASSERT_FALSE(r);
}