Merge branch 'release' into develop
# Conflicts: # src/wallet/wallet2.cpp
This commit is contained in:
commit
ee883a690c
5 changed files with 197 additions and 92 deletions
|
|
@ -59,6 +59,7 @@ namespace epee
|
|||
storage_entry load_storage_entry();
|
||||
void read(section& sec);
|
||||
void read(std::string& str);
|
||||
void read(array_entry &ae);
|
||||
private:
|
||||
struct recursuion_limitation_guard
|
||||
{
|
||||
|
|
@ -114,6 +115,7 @@ namespace epee
|
|||
void throwable_buffer_reader::read(t_pod_type& pod_val)
|
||||
{
|
||||
RECURSION_LIMITATION();
|
||||
static_assert(std::is_pod<t_pod_type>::value, "POD type expected");
|
||||
read(&pod_val, sizeof(pod_val));
|
||||
}
|
||||
|
||||
|
|
@ -277,5 +279,11 @@ namespace epee
|
|||
m_ptr+=len;
|
||||
m_count -= len;
|
||||
}
|
||||
inline
|
||||
void throwable_buffer_reader::read(array_entry &ae)
|
||||
{
|
||||
RECURSION_LIMITATION();
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
#include "parserse_base_utils.h"
|
||||
#include "file_io_utils.h"
|
||||
|
||||
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
|
|
@ -54,9 +56,10 @@ namespace epee
|
|||
ASSERT_MES_AND_THROW("json parse error");
|
||||
}*/
|
||||
template<class t_storage>
|
||||
inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg)
|
||||
inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg, unsigned int recursion)
|
||||
{
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL,
|
||||
"Wrong JSON data: recursion limitation (" << EPEE_JSON_RECURSION_LIMIT_INTERNAL << ") exceeded");
|
||||
std::string::const_iterator sub_element_start;
|
||||
std::string name;
|
||||
typename t_storage::harray h_array = nullptr;
|
||||
|
|
@ -167,7 +170,7 @@ namespace epee
|
|||
//sub section here
|
||||
typename t_storage::hsection new_sec = stg.open_section(name, current_section, true);
|
||||
CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end));
|
||||
run_handler(new_sec, it, buf_end, stg);
|
||||
run_handler(new_sec, it, buf_end, stg, recursion + 1);
|
||||
state = match_state_wonder_after_value;
|
||||
}else if(*it == '[')
|
||||
{//array of something
|
||||
|
|
@ -196,7 +199,7 @@ namespace epee
|
|||
typename t_storage::hsection new_sec = nullptr;
|
||||
h_array = stg.insert_first_section(name, new_sec, current_section);
|
||||
CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section");
|
||||
run_handler(new_sec, it, buf_end, stg);
|
||||
run_handler(new_sec, it, buf_end, stg, recursion + 1);
|
||||
state = match_state_array_after_value;
|
||||
array_md = array_mode_sections;
|
||||
}else if(*it == '"')
|
||||
|
|
@ -270,7 +273,7 @@ namespace epee
|
|||
typename t_storage::hsection new_sec = NULL;
|
||||
bool res = stg.insert_next_section(h_array, new_sec);
|
||||
CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section");
|
||||
run_handler(new_sec, it, buf_end, stg);
|
||||
run_handler(new_sec, it, buf_end, stg, recursion + 1);
|
||||
state = match_state_array_after_value;
|
||||
}else CHECK_ISSPACE();
|
||||
break;
|
||||
|
|
@ -372,7 +375,7 @@ namespace epee
|
|||
std::string::const_iterator sec_buf_begin = buff_json.begin();
|
||||
try
|
||||
{
|
||||
run_handler(nullptr, sec_buf_begin, buff_json.end(), stg);
|
||||
run_handler(nullptr, sec_buf_begin, buff_json.end(), stg, 0);
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& ex)
|
||||
|
|
|
|||
|
|
@ -3832,6 +3832,9 @@ bool wallet2::balance(std::unordered_map<crypto::public_key, wallet_public::asse
|
|||
|
||||
}
|
||||
|
||||
if (balances.empty())
|
||||
balances[currency::native_coin_asset_id] = wallet_public::asset_balance_entry_base{};
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -3882,64 +3885,33 @@ bool wallet2::balance(std::list<wallet_public::asset_balance_entry>& balances, u
|
|||
balances.clear();
|
||||
std::unordered_map<crypto::public_key, wallet_public::asset_balance_entry_base> balances_map;
|
||||
this->balance(balances_map, mined);
|
||||
std::unordered_map<crypto::public_key, currency::asset_descriptor_base> custom_assets_local = m_custom_assets;
|
||||
|
||||
for (auto& own_asset : m_own_asset_descriptors)
|
||||
for (const auto& [asset_id, balance_entry] : balances_map)
|
||||
{
|
||||
if (m_whitelisted_assets.find(own_asset.first) == m_whitelisted_assets.end())
|
||||
{
|
||||
custom_assets_local[own_asset.first] = own_asset.second;
|
||||
}
|
||||
}
|
||||
asset_descriptor_base asset_info{};
|
||||
uint32_t asset_flags = 0;
|
||||
if (!get_asset_info(asset_id, asset_info, asset_flags))
|
||||
continue;
|
||||
|
||||
asset_descriptor_base native_asset_info = AUTO_VAL_INIT(native_asset_info);
|
||||
native_asset_info.full_name = CURRENCY_NAME_SHORT_BASE;
|
||||
native_asset_info.ticker = CURRENCY_NAME_ABR;
|
||||
native_asset_info.decimal_point = CURRENCY_DISPLAY_DECIMAL_POINT;
|
||||
custom_assets_local[currency::native_coin_asset_id] = native_asset_info;
|
||||
if (!m_use_assets_whitelisting)
|
||||
asset_flags &= ~aif_whitelisted;
|
||||
|
||||
for (const auto& item : balances_map)
|
||||
{
|
||||
asset_descriptor_base asset_info = AUTO_VAL_INIT(asset_info);
|
||||
//check if asset is whitelisted or customly added
|
||||
if ((asset_flags & (aif_native_coin | aif_custom | aif_whitelisted)) == 0)
|
||||
continue;
|
||||
|
||||
//check if it custom asset
|
||||
auto it_cust = custom_assets_local.find(item.first);
|
||||
if (it_cust == custom_assets_local.end())
|
||||
{
|
||||
if (!m_use_assets_whitelisting)
|
||||
continue;
|
||||
|
||||
auto it_local = m_whitelisted_assets.find(item.first);
|
||||
if (it_local == m_whitelisted_assets.end())
|
||||
{
|
||||
WLT_LOG_YELLOW("WARNING: unknown asset " << item.first << " found and skipped; it's NOT included in balance", LOG_LEVEL_1);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
asset_info = it_local->second;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asset_info = it_cust->second;
|
||||
custom_assets_local.erase(it_cust);
|
||||
}
|
||||
|
||||
balances.push_back(wallet_public::asset_balance_entry());
|
||||
wallet_public::asset_balance_entry& new_item = balances.back();
|
||||
static_cast<wallet_public::asset_balance_entry_base&>(new_item) = item.second;
|
||||
new_item.asset_info.asset_id = item.first;
|
||||
wallet_public::asset_balance_entry& new_item = balances.emplace_back();
|
||||
static_cast<wallet_public::asset_balance_entry_base&>(new_item) = balance_entry;
|
||||
new_item.asset_info.asset_id = asset_id;
|
||||
static_cast<currency::asset_descriptor_base&>(new_item.asset_info) = asset_info;
|
||||
}
|
||||
//manually added assets should be always present, at least as zero balanced items
|
||||
for (auto& asset : custom_assets_local)
|
||||
for (const auto& [asset_id, custom_asset_entry] : m_custom_assets)
|
||||
{
|
||||
balances.push_back(wallet_public::asset_balance_entry());
|
||||
wallet_public::asset_balance_entry& new_item = balances.back();
|
||||
new_item.asset_info.asset_id = asset.first;
|
||||
static_cast<currency::asset_descriptor_base&>(new_item.asset_info) = asset.second;
|
||||
if (std::find_if(balances.begin(), balances.end(), [&](wallet_public::asset_balance_entry& e){ return e.asset_info.asset_id == asset_id; }) != balances.end())
|
||||
continue;
|
||||
wallet_public::asset_balance_entry& new_item = balances.emplace_back();
|
||||
new_item.asset_info.asset_id = asset_id;
|
||||
static_cast<currency::asset_descriptor_base&>(new_item.asset_info) = custom_asset_entry;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -3961,7 +3933,6 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
|
|||
{
|
||||
asset_info = it_own->second;
|
||||
asset_flags |= aif_own;
|
||||
return true;
|
||||
}
|
||||
|
||||
// whitelisted?
|
||||
|
|
@ -3970,7 +3941,6 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
|
|||
{
|
||||
asset_info = it_white->second;
|
||||
asset_flags |= aif_whitelisted;
|
||||
return true;
|
||||
}
|
||||
|
||||
// custom asset?
|
||||
|
|
@ -3979,7 +3949,6 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
|
|||
{
|
||||
asset_info = it_cust->second;
|
||||
asset_flags |= aif_custom;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ask_daemon_for_unknown)
|
||||
|
|
@ -3987,11 +3956,10 @@ bool wallet2::get_asset_info(const crypto::public_key& asset_id, currency::asset
|
|||
if (daemon_get_asset_info(asset_id, asset_info))
|
||||
{
|
||||
asset_flags |= aif_unknown;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return asset_flags != aif_none;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
size_t wallet2::get_asset_decimal_point(const crypto::public_key& asset_id, size_t result_if_not_found /* = 0 */) const
|
||||
|
|
|
|||
|
|
@ -962,7 +962,7 @@ typedef boost::variant<crypto::public_key, crypto::eth_public_key> public_key_v;
|
|||
|
||||
|
||||
template<typename t_response>
|
||||
bool sign_signature_with_keys(const t_response& rsp_with_data, tools::wallet_rpc_server& attached_wallet_rpc, const secret_key_v& signer_v, const public_key_v& verifier)
|
||||
bool ext_sign_and_send_asset_tx(const t_response& rsp_with_data, tools::wallet_rpc_server& attached_wallet_rpc, const secret_key_v& signer_v, const public_key_v& verifier)
|
||||
{
|
||||
bool r = false;
|
||||
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::request send_signed_req = AUTO_VAL_INIT(send_signed_req);
|
||||
|
|
@ -993,15 +993,15 @@ bool sign_signature_with_keys(const t_response& rsp_with_data, tools::wallet_rpc
|
|||
return false;
|
||||
}
|
||||
|
||||
send_signed_req.unsigned_tx = rsp_with_data.data_for_external_signing->unsigned_tx;
|
||||
send_signed_req.expected_tx_id = rsp_with_data.tx_id;
|
||||
send_signed_req.finalized_tx = rsp_with_data.data_for_external_signing->finalized_tx;
|
||||
send_signed_req.unsigned_tx = rsp_with_data.data_for_external_signing->unsigned_tx;
|
||||
send_signed_req.expected_tx_id = rsp_with_data.tx_id;
|
||||
send_signed_req.finalized_tx = rsp_with_data.data_for_external_signing->finalized_tx;
|
||||
send_signed_req.unlock_transfers_on_fail = true;
|
||||
tools::wallet_public::COMMAND_ASSET_SEND_EXT_SIGNED_TX::response send_signed_resp{};
|
||||
|
||||
r = invoke_text_json_for_rpc(attached_wallet_rpc, "send_ext_signed_asset_tx", send_signed_req, send_signed_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
|
||||
CHECK_AND_ASSERT_MES(send_signed_resp.status == API_RETURN_CODE_OK, false, "RPC send_ext_signed_asset_tx failed: ");
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed");
|
||||
CHECK_AND_ASSERT_MES(send_signed_resp.status == API_RETURN_CODE_OK, false, "RPC send_ext_signed_asset_tx failed: " << send_signed_resp.status);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1025,7 +1025,6 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
|
||||
r = mine_next_pow_blocks_in_playtime(alice_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(bob_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(carol_wlt->get_account().get_public_address(), c, 3);
|
||||
//r = mine_next_pow_blocks_in_playtime(custody_wlt->get_account().get_public_address(), c, 3);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
|
|
@ -1054,7 +1053,10 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
return false;
|
||||
}
|
||||
|
||||
const crypto::public_key asset_id = resp.new_asset_id;
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
// core RPC server
|
||||
currency::t_currency_protocol_handler<currency::core> cprotocol(c, NULL);
|
||||
|
|
@ -1104,26 +1106,34 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
return false;
|
||||
}
|
||||
|
||||
r = sign_signature_with_keys(emm_resp, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
|
||||
r = ext_sign_and_send_asset_tx(emm_resp, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call ext_sign_and_send_asset_tx");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
|
||||
|
||||
//check bob wallet
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::request wtl_req = AUTO_VAL_INIT(wtl_req);
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::response wtl_resp = AUTO_VAL_INIT(wtl_resp);
|
||||
wtl_req.asset_id = resp.new_asset_id;
|
||||
tools::wallet_rpc_server bob_wlt_rpc(bob_wlt);
|
||||
r = invoke_text_json_for_rpc(bob_wlt_rpc, "assets_whitelist_add", wtl_req, wtl_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
|
||||
CHECK_AND_ASSERT_MES(wtl_resp.status == API_RETURN_CODE_OK, false, "RPC status failed");
|
||||
bob_wlt->refresh();
|
||||
|
||||
tools::wallet_public::COMMAND_RPC_GET_BALANCE::request balance_req = AUTO_VAL_INIT(balance_req);
|
||||
tools::wallet_public::COMMAND_RPC_GET_BALANCE::response balance_resp = AUTO_VAL_INIT(balance_resp);
|
||||
r = invoke_text_json_for_rpc(bob_wlt_rpc, "getbalance", balance_req, balance_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC send_ext_signed_asset_tx failed: ");
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC getbalance failed");
|
||||
r = std::find_if(balance_resp.balances.begin(), balance_resp.balances.end(), [&](tools::wallet_public::asset_balance_entry& e){ return e.asset_info.asset_id == asset_id; }) == balance_resp.balances.end();
|
||||
CHECK_AND_ASSERT_MES(r, false, "found asset " << resp.new_asset_id << " which is unexpected");
|
||||
|
||||
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::request wtl_req = AUTO_VAL_INIT(wtl_req);
|
||||
tools::wallet_public::COMMAND_ASSETS_WHITELIST_ADD::response wtl_resp = AUTO_VAL_INIT(wtl_resp);
|
||||
wtl_req.asset_id = resp.new_asset_id;
|
||||
r = invoke_text_json_for_rpc(bob_wlt_rpc, "assets_whitelist_add", wtl_req, wtl_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC assets_whitelist_add failed");
|
||||
CHECK_AND_ASSERT_MES(wtl_resp.status == API_RETURN_CODE_OK, false, "RPC status failed");
|
||||
bob_wlt->refresh();
|
||||
|
||||
balance_req = AUTO_VAL_INIT(balance_req);
|
||||
balance_resp = AUTO_VAL_INIT(balance_resp);
|
||||
r = invoke_text_json_for_rpc(bob_wlt_rpc, "getbalance", balance_req, balance_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC getbalance failed");
|
||||
|
||||
|
||||
bool found_asset = false;
|
||||
|
|
@ -1132,14 +1142,14 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
if (bal.asset_info.asset_id == resp.new_asset_id)
|
||||
{
|
||||
found_asset = true;
|
||||
CHECK_AND_ASSERT_MES(bal.total == COINS_TO_TRANSFER, false, "Amount is unexpected");
|
||||
CHECK_EQ(bal.total, COINS_TO_TRANSFER);
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(found_asset, false, "Asset not found ");
|
||||
CHECK_AND_ASSERT_MES(found_asset, false, "Asset with id " << resp.new_asset_id << " was not found");
|
||||
|
||||
|
||||
|
||||
//transfer ownership of the asset to new address
|
||||
//transfer ownership of the asset to an ETH key
|
||||
//let's change the owner to ecdsa
|
||||
crypto::eth_secret_key eth_sk_2{};
|
||||
crypto::eth_public_key eth_pk_2{};
|
||||
|
|
@ -1160,8 +1170,8 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
return false;
|
||||
}
|
||||
|
||||
r = sign_signature_with_keys(res_own, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
|
||||
r = ext_sign_and_send_asset_tx(res_own, alice_wlt_rpc, miner_wlt->get_account().get_keys().spend_secret_key, miner_wlt->get_account().get_keys().account_address.spend_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call ext_sign_and_send_asset_tx");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
|
||||
|
|
@ -1169,15 +1179,11 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
//now make another tx and see of ownership got changed
|
||||
emm_resp = AUTO_VAL_INIT(emm_resp);
|
||||
r = invoke_text_json_for_rpc(alice_wlt_rpc, "emit_asset", emm_req, emm_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call");
|
||||
if (!emm_resp.data_for_external_signing)
|
||||
{
|
||||
LOG_ERROR("Missing data_for_external_signing");
|
||||
return false;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "invoke_text_json_for_rpc failed");
|
||||
CHECK_AND_ASSERT_MES(res_own.data_for_external_signing, false, "data_for_external_signing is missing");
|
||||
|
||||
r = sign_signature_with_keys(emm_resp, alice_wlt_rpc, eth_sk_2, eth_pk_2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call sign_signature_with_keys");
|
||||
r = ext_sign_and_send_asset_tx(emm_resp, alice_wlt_rpc, eth_sk_2, eth_pk_2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to call ext_sign_and_send_asset_tx");
|
||||
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 3);
|
||||
|
||||
|
|
@ -1197,6 +1203,66 @@ bool wallet_rpc_thirdparty_custody::c1(currency::core& c, size_t ev_index, const
|
|||
CHECK_AND_ASSERT_MES(found_asset, false, "Asset not found ");
|
||||
|
||||
|
||||
// Transfer ownership to Carol (standard owner pub key)
|
||||
|
||||
tools::wallet_rpc_server carol_wlt_rpc(carol_wlt);
|
||||
req_own = AUTO_VAL_INIT(req_own);
|
||||
res_own = AUTO_VAL_INIT(res_own);
|
||||
req_own.asset_id = asset_id;
|
||||
req_own.new_owner = carol_acc.get_public_address().spend_public_key;
|
||||
alice_wlt->refresh();
|
||||
r = invoke_text_json_for_rpc(alice_wlt_rpc, "transfer_asset_ownership", req_own, res_own);
|
||||
CHECK_AND_ASSERT_MES(r, false, "invoke_text_json_for_rpc failed");
|
||||
CHECK_AND_ASSERT_MES(res_own.data_for_external_signing, false, "data_for_external_signing is missing");
|
||||
// externally sign and send transfer ownership tx
|
||||
r = ext_sign_and_send_asset_tx(res_own, alice_wlt_rpc, eth_sk_2, eth_pk_2);
|
||||
CHECK_AND_ASSERT_MES(r, false, "ext_sign_and_send_asset_tx failed");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "unexpected pool txs count: " << c.get_pool_transactions_count());
|
||||
|
||||
// Miner still has some asset coins, transfer them to Carol
|
||||
miner_wlt->refresh();
|
||||
tools::wallet_public::COMMAND_RPC_TRANSFER::request miner_tr_req = AUTO_VAL_INIT(miner_tr_req);
|
||||
tools::wallet_public::COMMAND_RPC_TRANSFER::request miner_tr_res = AUTO_VAL_INIT(miner_tr_res);
|
||||
miner_tr_req.fee = TESTS_DEFAULT_FEE;
|
||||
miner_tr_req.destinations.push_back({COINS_TO_TRANSFER * 7ull, carol_acc.get_public_address_str(), asset_id});
|
||||
r = invoke_text_json_for_rpc(miner_wlt_rpc, "transfer", miner_tr_req, miner_tr_res);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 2, false, "unexpected pool txs count: " << c.get_pool_transactions_count());
|
||||
// confirm it
|
||||
CHECK_AND_ASSERT_MES(mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW), false, "");
|
||||
// make sure the pool is now empty
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "unexpected pool txs count: " << c.get_pool_transactions_count());
|
||||
|
||||
// Carol shouldn't have this asset whitelisted and present in balance
|
||||
carol_wlt->refresh();
|
||||
balance_req = AUTO_VAL_INIT(balance_req);
|
||||
balance_resp = AUTO_VAL_INIT(balance_resp);
|
||||
r = invoke_text_json_for_rpc(carol_wlt_rpc, "getbalance", balance_req, balance_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC getbalance failed");
|
||||
CHECK_EQ(balance_resp.balance, 0);
|
||||
r = std::find_if(balance_resp.balances.begin(), balance_resp.balances.end(), [&](tools::wallet_public::asset_balance_entry& e){ return e.asset_info.asset_id == asset_id; }) == balance_resp.balances.end();
|
||||
CHECK_AND_ASSERT_MES(r, false, "asset was found, which in unexpected");
|
||||
// make sure she has asset_id among own assets in spite of that
|
||||
auto& carol_own_assets = carol_wlt->get_own_assets();
|
||||
CHECK_EQ(carol_own_assets.size(), 1);
|
||||
CHECK_EQ(carol_own_assets.count(asset_id), 1);
|
||||
|
||||
// whitelist and re-check
|
||||
wtl_req = AUTO_VAL_INIT(wtl_req);
|
||||
wtl_resp = AUTO_VAL_INIT(wtl_resp);
|
||||
wtl_req.asset_id = asset_id;
|
||||
CHECK_AND_ASSERT_MES(invoke_text_json_for_rpc(carol_wlt_rpc, "assets_whitelist_add", wtl_req, wtl_resp), false, "");
|
||||
CHECK_AND_ASSERT_MES(wtl_resp.status == API_RETURN_CODE_OK, false, "RPC failed");
|
||||
|
||||
// now the asset must show up in the balance
|
||||
balance_req = AUTO_VAL_INIT(balance_req);
|
||||
balance_resp = AUTO_VAL_INIT(balance_resp);
|
||||
r = invoke_text_json_for_rpc(carol_wlt_rpc, "getbalance", balance_req, balance_resp);
|
||||
CHECK_AND_ASSERT_MES(r, false, "RPC getbalance failed");
|
||||
CHECK_EQ(balance_resp.balance, 0); // the balance for native coin is still zero
|
||||
auto it = std::find_if(balance_resp.balances.begin(), balance_resp.balances.end(), [&](tools::wallet_public::asset_balance_entry& e){ return e.asset_info.asset_id == asset_id; });
|
||||
CHECK_AND_ASSERT_MES(it != balance_resp.balances.end(), false, "asset was not found, which in unexpected");
|
||||
CHECK_EQ(it->total, COINS_TO_TRANSFER * 7);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
#include "net/levin_protocol_handler_async.h"
|
||||
#include "net/net_utils_base.h"
|
||||
#include "unit_tests_utils.h"
|
||||
|
||||
#include "storages/parserse_base_utils.h"
|
||||
#include "storages/portable_storage_base.h"
|
||||
#include "storages/portable_storage.h"
|
||||
namespace
|
||||
{
|
||||
struct test_levin_connection_context : public epee::net_utils::connection_context_base
|
||||
|
|
@ -504,3 +506,61 @@ TEST_F(test_levin_protocol_handler__hanle_recv_with_invalid_data, handles_unexpe
|
|||
|
||||
ASSERT_FALSE(m_conn->m_protocol_handler.handle_recv(m_buf.data(), m_buf.size()));
|
||||
}
|
||||
|
||||
using epee::serialization::portable_storage;
|
||||
using epee::serialization::array_entry;
|
||||
using epee::serialization::section;
|
||||
using epee::serialization::throwable_buffer_reader;
|
||||
|
||||
/**
|
||||
* Purpose:
|
||||
* Verify what the deserialization of array_entry no longer uses memcpy to
|
||||
* overwrite the boost::variant memory directly. Instead, an unsupported-array-entry
|
||||
* path should throw an exception indicating array_entry deserialization isn't supported.
|
||||
*/
|
||||
TEST(levin_protocol_variant_memcpy, memcpy_variant_verify)
|
||||
{
|
||||
std::string buf; // raw buffer simulating an array_entry section
|
||||
|
||||
buf.push_back(static_cast<char>(SERIALIZE_FLAG_ARRAY | SERIALIZE_TYPE_ARRAY));
|
||||
buf.push_back(static_cast<char>(1 << 2));
|
||||
buf.append(sizeof(array_entry), char(0x41));
|
||||
|
||||
throwable_buffer_reader reader(reinterpret_cast<const uint8_t*>(buf.data()), buf.size());
|
||||
|
||||
EXPECT_THROW(
|
||||
reader.load_storage_array_entry(SERIALIZE_TYPE_ARRAY),
|
||||
std::runtime_error
|
||||
) << "Expected load_storage_array_entry to throw due to array_entry";
|
||||
}
|
||||
|
||||
/**
|
||||
* Purpose:
|
||||
* Construct a JSON string nested deeper than the built-in recursion limit (100 levels).
|
||||
*/
|
||||
TEST(json_parse_deep, parser_deep)
|
||||
{
|
||||
const int depth = 200;
|
||||
std::string json;
|
||||
json.reserve(depth * 10);
|
||||
|
||||
// Build a deeply nested JSON
|
||||
// {"level": {"level": { ... {"level":1} ... }}}
|
||||
for (int i = 0; i < depth; ++i)
|
||||
{
|
||||
json += '{';
|
||||
json += "\"level\":";
|
||||
}
|
||||
json += '1';
|
||||
|
||||
for (int i = 0; i < depth; ++i)
|
||||
{
|
||||
json += '}';
|
||||
}
|
||||
|
||||
portable_storage storage;
|
||||
bool ok = epee::serialization::json::load_from_json(json, storage);
|
||||
|
||||
EXPECT_FALSE(ok) << "Expected load_from_json to fail when depth " << depth
|
||||
<< " exceeds the 100-level recursion limit.";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue