forked from lthn/blockchain
Merge branch 'release2'
This commit is contained in:
commit
9f845bb73b
41 changed files with 929 additions and 366 deletions
|
|
@ -85,6 +85,18 @@ namespace epee
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// helper for blob-to-base64 serialization
|
||||
inline std::string transfrom_binbuf_to_base64(const std::string& a)
|
||||
{
|
||||
return epee::string_encoding::base64_encode(a);
|
||||
}
|
||||
|
||||
inline std::string transform_base64_to_binbuf(const std::string& a)
|
||||
{
|
||||
return epee::string_encoding::base64_decode(a);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
#pragma pack(push, 1)
|
||||
template<class first_t, class second_t>
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ public: \
|
|||
#define KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, val_name) \
|
||||
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transform_binbuf_to_hexstr, epee::transform_hexstr_to_binbuff, val_name)
|
||||
|
||||
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(varialble, val_name) \
|
||||
KV_SERIALIZE_CUSTOM_N(varialble, std::string, epee::transfrom_binbuf_to_base64, epee::transform_base64_to_binbuf, val_name)
|
||||
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
|
||||
epee::serialization::selector<is_store>::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
|
||||
|
|
@ -100,7 +102,8 @@ public: \
|
|||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_CUSTOM(varialble, stored_type, from_v_to_stored, from_stored_to_v) KV_SERIALIZE_CUSTOM_N(varialble, stored_type, from_v_to_stored, from_stored_to_v, #varialble)
|
||||
#define KV_SERIALIZE_POD_AS_HEX_STRING(varialble) KV_SERIALIZE_POD_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_HEX_STRING(varialble) KV_SERIALIZE_BLOB_AS_HEX_STRING_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_BLOB_AS_BASE64_STRING(variable) KV_SERIALIZE_BLOB_AS_BASE64_STRING_N(variable, #variable)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2548,7 +2548,7 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU
|
|||
CHECK_AND_ASSERT_MES(tx_ptr->tx.vout.size() > out_ptr->out_no, false, "internal error: in global outs index, transaction out index="
|
||||
<< out_ptr->out_no << " is greater than transaction outputs = " << tx_ptr->tx.vout.size() << ", for tx id = " << out_ptr->tx_id);
|
||||
|
||||
CHECK_AND_ASSERT_MES(amount != 0 || height_upper_limit != 0, false, "height_upper_limit must be nonzero for hidden amounts (amount = 0)");
|
||||
//CHECK_AND_ASSERT_MES(amount != 0 || height_upper_limit != 0, false, "height_upper_limit must be nonzero for hidden amounts (amount = 0)");
|
||||
|
||||
if (height_upper_limit != 0 && tx_ptr->m_keeper_block_height > height_upper_limit)
|
||||
return false;
|
||||
|
|
@ -2606,6 +2606,14 @@ bool blockchain_storage::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPU
|
|||
oen.amount_commitment = toz.amount_commitment;
|
||||
oen.concealing_point = toz.concealing_point;
|
||||
oen.blinded_asset_id = toz.blinded_asset_id; // TODO @#@# bad design, too much manual coping, consider redesign -- sowle
|
||||
if (is_coinbase(tx_ptr->tx))
|
||||
{
|
||||
oen.flags |= RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_COINBASE;
|
||||
if (is_pos_coinbase(tx_ptr->tx))
|
||||
{
|
||||
oen.flags |= RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_POS_COINBASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
VARIANT_SWITCH_END();
|
||||
|
||||
|
|
@ -2694,9 +2702,9 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
{
|
||||
size_t decoys_count = details.offsets.size();
|
||||
size_t decoys_count = details.global_offsets.size();
|
||||
uint64_t amount = details.amount;
|
||||
|
||||
uint64_t outs_container_size = m_db_outputs.get_item_size(details.amount);
|
||||
|
|
@ -2723,7 +2731,7 @@ bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RP
|
|||
if (up_index_limit >= decoys_count)
|
||||
{
|
||||
std::set<size_t> used;
|
||||
used.insert(details.own_global_index);
|
||||
//used.insert(details.own_global_index);
|
||||
for (uint64_t j = 0; j != decoys_count || used.size() >= up_index_limit;)
|
||||
{
|
||||
size_t g_index_initial = crypto::rand<size_t>() % up_index_limit;
|
||||
|
|
@ -2766,117 +2774,27 @@ bool blockchain_storage::get_target_outs_for_amount_prezarcanum(const COMMAND_RP
|
|||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
bool blockchain_storage::get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const
|
||||
{
|
||||
std::set<uint64_t> used;
|
||||
used.insert(details.own_global_index);
|
||||
for (auto offset : details.offsets)
|
||||
for (auto global_index : details.global_offsets)
|
||||
{
|
||||
|
||||
//perfectly we would need to find transaction's output on the given height, with the given probability
|
||||
//of being coinbase(coinbase outputs should be included less in decoy selection algorithm)
|
||||
bool is_coinbase = (crypto::rand<uint64_t>() % 101) > req.coinbase_percents ? false : true;
|
||||
|
||||
//TODO: Consider including PoW coinbase to transactions(does it needed?)
|
||||
|
||||
// convert offset to estimated height
|
||||
uint64_t estimated_h = this->get_current_blockchain_size() - 1 - offset;
|
||||
//make sure it's after zc hardfork
|
||||
if (estimated_h < m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM])
|
||||
{
|
||||
LOG_ERROR("Wrong estimated offset(" << offset << "), it hits zone before zarcanum hardfork");
|
||||
return false;
|
||||
}
|
||||
|
||||
#define TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN 10
|
||||
//try to find output around given H
|
||||
std::vector<uint64_t> selected_global_indexes;
|
||||
auto process_tx = [&](const crypto::hash& tx_id) {
|
||||
|
||||
auto tx_ptr = m_db_transactions.find(tx_id);
|
||||
CHECK_AND_ASSERT_THROW_MES(tx_ptr, "internal error: tx_id " << tx_id << " around estimated_h = " << estimated_h << " not found in db");
|
||||
//go through tx outputs
|
||||
for (size_t i = 0; i != tx_ptr->tx.vout.size(); i++)
|
||||
{
|
||||
if (tx_ptr->tx.vout[i].type() != typeid(tx_out_zarcanum))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const tx_out_zarcanum& z_out = boost::get<tx_out_zarcanum>(tx_ptr->tx.vout[i]);
|
||||
|
||||
// NOTE: second part of condition (mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND && ..) might be not accurate
|
||||
// since the wallet might want to request more inputs then it planning to do mixins. For now let's keep it this way and fix
|
||||
// it if we see the problems about it.
|
||||
if (z_out.mix_attr == CURRENCY_TO_KEY_OUT_FORCED_NO_MIX || (z_out.mix_attr >= CURRENCY_TO_KEY_OUT_FORCED_MIX_LOWER_BOUND && z_out.mix_attr < details.offsets.size()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip spent outptus
|
||||
if (tx_ptr->m_spent_flags[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (used.find(tx_ptr->m_global_output_indexes[i]) != used.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// add output
|
||||
// note: code that will process selected_global_indes will be revisiting transactions entries to obtain all
|
||||
// needed data, that should work relatively effective because of on-top-of-db cache keep daya unserialized
|
||||
selected_global_indexes.push_back(tx_ptr->m_global_output_indexes[i]);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
while (selected_global_indexes.size() < TARGET_RANDOM_OUTS_SELECTIOM_POOL_MIN)
|
||||
{
|
||||
auto block_ptr = m_db_blocks.get(estimated_h);
|
||||
if (is_coinbase && is_pos_block(block_ptr->bl) )
|
||||
{
|
||||
process_tx(get_transaction_hash(block_ptr->bl.miner_tx));
|
||||
}
|
||||
else
|
||||
{
|
||||
//looking for regular output of regular transactions
|
||||
for (auto tx_id : block_ptr->bl.tx_hashes)
|
||||
{
|
||||
process_tx(tx_id);
|
||||
}
|
||||
}
|
||||
if(estimated_h)
|
||||
estimated_h--;
|
||||
else
|
||||
{
|
||||
//likely unusual situation when blocks enumerated all way back to genesis
|
||||
//let's check if we have at least something
|
||||
if (!selected_global_indexes.size())
|
||||
{
|
||||
//need to regenerate offsets
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//pick up a random output from selected_global_indes
|
||||
uint64_t global_index = selected_global_indexes[crypto::rand<uint64_t>() % selected_global_indexes.size()];
|
||||
bool res = add_out_to_get_random_outs(result_outs, details.amount, global_index, details.offsets.size(), req.use_forced_mix_outs, req.height_upper_limit);
|
||||
CHECK_AND_ASSERT_THROW_MES(res, "Failed to add_out_to_get_random_outs([" << global_index << "]) at postzarcanum era");
|
||||
used.insert(global_index);
|
||||
bool res = add_out_to_get_random_outs(result_outs, details.amount, global_index, this->get_core_runtime_config().hf4_minimum_mixins, false);
|
||||
if (!res)
|
||||
{
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry{});
|
||||
oen.flags = RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_THROW_MES(details.global_offsets.size() == result_outs.outs.size(), "details.global_offsets.size() == result_outs.outs.size() check failed");
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const
|
||||
bool blockchain_storage::get_random_outs_for_amounts3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res)const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
LOG_PRINT_L3("[get_random_outs_for_amounts] amounts: " << req.amounts.size());
|
||||
std::map<uint64_t, uint64_t> amounts_to_up_index_limit_cache;
|
||||
uint64_t count_zarcanum_blocks = 0;
|
||||
if(is_hardfork_active(ZANO_HARDFORK_04_ZARCANUM))
|
||||
count_zarcanum_blocks = this->get_current_blockchain_size() - m_core_runtime_config.hard_forks.m_height_the_hardfork_n_active_after[ZANO_HARDFORK_04_ZARCANUM];
|
||||
|
||||
|
||||
for (size_t i = 0; i != req.amounts.size(); i++)
|
||||
|
|
@ -2887,7 +2805,7 @@ bool blockchain_storage::get_random_outs_for_amounts2(const COMMAND_RPC_GET_RAND
|
|||
result_outs.amount = amount;
|
||||
|
||||
bool r = false;
|
||||
if (amount == 0 && count_zarcanum_blocks > 20000)
|
||||
if (amount == 0)
|
||||
{
|
||||
//zarcanum era inputs
|
||||
r = get_target_outs_for_postzarcanum(req, req.amounts[i], result_outs, amounts_to_up_index_limit_cache);
|
||||
|
|
@ -3591,7 +3509,7 @@ bool blockchain_storage::get_est_height_from_date(uint64_t date, uint64_t& res_h
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height, bool need_global_indexes)const
|
||||
bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height)const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
blocks_direct_container blocks_direct;
|
||||
|
|
@ -3610,7 +3528,7 @@ bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height, bool request_coinbase_info)const
|
||||
bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height)const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
if (!find_blockchain_supplement(qblock_ids, start_height))
|
||||
|
|
@ -3627,8 +3545,7 @@ bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash
|
|||
std::list<crypto::hash> mis;
|
||||
get_transactions_direct(m_db_blocks[i]->bl.tx_hashes, blocks.back().second, mis);
|
||||
CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, block " << get_block_hash(m_db_blocks[i]->bl) << " [" << i << "] contains missing transactions: " << mis);
|
||||
if(request_coinbase_info)
|
||||
blocks.back().third = m_db_transactions.find(get_transaction_hash(m_db_blocks[i]->bl.miner_tx));
|
||||
blocks.back().third = m_db_transactions.find(get_transaction_hash(m_db_blocks[i]->bl.miner_tx));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3863,6 +3780,17 @@ uint64_t blockchain_storage::get_aliases_count() const
|
|||
return m_db_aliases.size();
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_asset_history(const crypto::public_key& asset_id, std::list<asset_descriptor_operation>& result) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
auto as_ptr = m_db_assets.find(asset_id);
|
||||
if (!as_ptr)
|
||||
return false;
|
||||
|
||||
result = *as_ptr;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& result) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -4084,7 +4012,7 @@ bool blockchain_storage::pop_asset_info(const crypto::public_key& asset_id)
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& avc)
|
||||
bool validate_ado_ownership(asset_op_verification_context& avc)
|
||||
{
|
||||
asset_operation_ownership_proof aoop = AUTO_VAL_INIT(aoop);
|
||||
bool r = get_type_in_variant_container(avc.tx.proofs, aoop);
|
||||
|
|
@ -4096,32 +4024,23 @@ bool blockchain_storage::validate_ado_ownership(asset_op_verification_context& a
|
|||
return crypto::verify_schnorr_sig(avc.tx_id, owner_key, aoop.gss);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado)
|
||||
bool blockchain_storage::validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
asset_op_verification_context avc = { tx, tx_id, ado };
|
||||
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed");
|
||||
avc.asset_op_history = m_db_assets.find(avc.asset_id);
|
||||
|
||||
const asset_descriptor_operation& ado = avc.ado;
|
||||
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_REGISTER)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed");
|
||||
|
||||
avc.asset_op_history = m_db_assets.find(avc.asset_id);
|
||||
CHECK_AND_ASSERT_MES(!avc.asset_op_history, false, "asset with id " << avc.asset_id << " has already been registered");
|
||||
|
||||
avc.amount_to_validate = ado.descriptor.current_supply;
|
||||
CHECK_AND_ASSERT_MES(validate_asset_operation_amount_commitment(avc), false, "asset operation validation failed!");
|
||||
|
||||
assets_container::t_value_type local_asset_history = AUTO_VAL_INIT(local_asset_history);
|
||||
local_asset_history.push_back(ado);
|
||||
m_db_assets.set(avc.asset_id, local_asset_history);
|
||||
LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
CHECK_AND_ASSERT_MES(validate_asset_operation_amount_commitment(avc), false, "validate_asset_operation_amount_commitment failed!");
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(get_or_calculate_asset_id(avc.ado, &avc.asset_id_pt, &avc.asset_id), false, "get_or_calculate_asset_id failed");
|
||||
avc.asset_op_history = m_db_assets.find(avc.asset_id);
|
||||
|
||||
CHECK_AND_ASSERT_MES(avc.asset_op_history && avc.asset_op_history->size(), false, "asset with id " << avc.asset_id << " has not been registered");
|
||||
// check ownership permission
|
||||
if (ado.operation_type == ASSET_DESCRIPTOR_OPERATION_EMIT || ado.operation_type == ASSET_DESCRIPTOR_OPERATION_UPDATE /*|| ado.operation_type == ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN*/)
|
||||
|
|
@ -4164,25 +4083,40 @@ bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::has
|
|||
bool r = validate_asset_operation_amount_commitment(avc);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Balance proof validation failed for asset_descriptor_operation");
|
||||
}
|
||||
}
|
||||
|
||||
assets_container::t_value_type local_asset_history = *avc.asset_op_history;
|
||||
local_asset_history.push_back(ado);
|
||||
m_db_assets.set(avc.asset_id, local_asset_history);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::put_asset_info(const transaction& tx, const crypto::hash& tx_id, const asset_descriptor_operation& ado)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
switch(ado.operation_type)
|
||||
{
|
||||
case ASSET_DESCRIPTOR_OPERATION_UPDATE:
|
||||
LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
case ASSET_DESCRIPTOR_OPERATION_EMIT:
|
||||
LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN:
|
||||
LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
|
||||
}
|
||||
asset_op_verification_context avc = { tx, tx_id, ado };
|
||||
CHECK_AND_ASSERT_MES(validate_asset_operation_against_current_blochain_state(avc), false, "asset operation validation failed");
|
||||
|
||||
assets_container::t_value_type local_asset_history{};
|
||||
if (avc.asset_op_history)
|
||||
local_asset_history = *avc.asset_op_history;
|
||||
local_asset_history.push_back(ado);
|
||||
m_db_assets.set(avc.asset_id, local_asset_history);
|
||||
|
||||
switch(ado.operation_type)
|
||||
{
|
||||
case ASSET_DESCRIPTOR_OPERATION_REGISTER:
|
||||
LOG_PRINT_MAGENTA("[ASSET_REGISTERED]: " << print_money_brief(ado.descriptor.current_supply, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
case ASSET_DESCRIPTOR_OPERATION_UPDATE:
|
||||
LOG_PRINT_MAGENTA("[ASSET_UPDATED]: " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
case ASSET_DESCRIPTOR_OPERATION_EMIT:
|
||||
LOG_PRINT_MAGENTA("[ASSET_EMITTED]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
case ASSET_DESCRIPTOR_OPERATION_PUBLIC_BURN:
|
||||
LOG_PRINT_MAGENTA("[ASSET_BURNT]: " << print_money_brief(avc.amount_to_validate, ado.descriptor.decimal_point) << ", " << avc.asset_id << ": " << ado.descriptor.ticker << ", \"" << ado.descriptor.full_name << "\"", LOG_LEVEL_1);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown operation type: " << (int)ado.operation_type);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5526,7 +5460,6 @@ std::shared_ptr<const transaction_chain_entry> blockchain_storage::find_key_imag
|
|||
//---------------------------------------------------------------
|
||||
bool blockchain_storage::fill_tx_rpc_details(tx_rpc_extended_info& tei, const transaction& tx, const transaction_chain_entry* ptce, const crypto::hash& h, uint64_t timestamp, bool is_short) const
|
||||
{
|
||||
//tei.blob = tx_ptr->tx
|
||||
tei.id = epee::string_tools::pod_to_hex(h);
|
||||
if (!tei.blob_size)
|
||||
tei.blob_size = get_object_blobsize(tx);
|
||||
|
|
@ -5543,6 +5476,9 @@ bool blockchain_storage::fill_tx_rpc_details(tx_rpc_extended_info& tei, const tr
|
|||
fill_tx_rpc_outputs(tei, tx, ptce);
|
||||
fill_tx_rpc_payload_items(tei.extra, tx.extra);
|
||||
fill_tx_rpc_payload_items(tei.attachments, tx.attachment);
|
||||
|
||||
tei.blob = t_serializable_object_to_blob(tx);
|
||||
tei.object_in_json = obj_to_json_str(tx);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -6478,11 +6414,16 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
tx.signatures.clear();
|
||||
tx.proofs.clear();
|
||||
}
|
||||
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
//std::vector<crypto::point_t&> tx_outs_commitments;
|
||||
if (!m_is_in_checkpoint_zone)
|
||||
{
|
||||
auto cleanup = [&](){ purge_block_data_from_blockchain(bl, tx_processed_count); bvc.m_verification_failed = true; };
|
||||
auto cleanup = [&](){
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
m_tx_pool.add_transaction_to_black_list(tx);
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
bvc.m_verification_failed = true;
|
||||
};
|
||||
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(collect_rangeproofs_data_from_tx(tx, tx_id, range_proofs_agregated), false, cleanup(),
|
||||
"block " << id << ", tx " << tx_id << ": collect_rangeproofs_data_from_tx failed");
|
||||
|
|
@ -6499,7 +6440,6 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
if(!check_tx_inputs(tx, tx_id))
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
if (taken_from_pool)
|
||||
{
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
|
|
|
|||
|
|
@ -280,13 +280,13 @@ namespace currency
|
|||
bool get_short_chain_history(std::list<crypto::hash>& ids)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, uint64_t& starter_offset)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0, bool need_global_indexes = false)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0, bool request_coinbase_info = false)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0)const;
|
||||
bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, blocks_direct_container& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count, uint64_t minimum_height = 0)const;
|
||||
//bool find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, std::list<std::pair<block, std::list<transaction> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count)const;
|
||||
bool handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp)const;
|
||||
bool handle_get_objects(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res)const;
|
||||
bool get_random_outs_for_amounts2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)const;
|
||||
bool get_random_outs_for_amounts3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res)const;
|
||||
bool get_backward_blocks_sizes(size_t from_height, std::vector<size_t>& sz, size_t count)const;
|
||||
bool get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<uint64_t>& indexs)const;
|
||||
bool get_alias_info(const std::string& alias, extra_alias_entry_base& info)const;
|
||||
|
|
@ -299,6 +299,7 @@ namespace currency
|
|||
uint64_t get_aliases_count()const;
|
||||
uint64_t get_block_h_older_then(uint64_t timestamp) const;
|
||||
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
|
||||
bool get_asset_history(const crypto::public_key& asset_id, std::list<asset_descriptor_operation>& result) const;
|
||||
bool get_asset_info(const crypto::public_key& asset_id, asset_descriptor_base& info)const;
|
||||
uint64_t get_assets_count() const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
|
|
@ -374,6 +375,8 @@ namespace currency
|
|||
bool for_altchain,
|
||||
const alt_chain_type& alt_chain = alt_chain_type(),
|
||||
uint64_t split_height = 0)const;
|
||||
bool validate_asset_operation_against_current_blochain_state(asset_op_verification_context& avc) const;
|
||||
|
||||
void set_core_runtime_config(const core_runtime_config& pc) const;
|
||||
const core_runtime_config& get_core_runtime_config()const;
|
||||
size_t get_current_sequence_factor(bool pos)const;
|
||||
|
|
@ -493,6 +496,7 @@ namespace currency
|
|||
bool print_tx_outputs_lookup(const crypto::hash& tx_id) const;
|
||||
uint64_t get_last_x_block_height(bool pos)const;
|
||||
bool is_tx_spendtime_unlocked(uint64_t unlock_time)const;
|
||||
|
||||
private:
|
||||
|
||||
//-------------- DB containers --------------
|
||||
|
|
@ -643,8 +647,8 @@ namespace currency
|
|||
bool push_transaction_to_global_outs_index(const transaction& tx, const crypto::hash& tx_id, std::vector<uint64_t>& global_indexes);
|
||||
bool pop_transaction_from_global_index(const transaction& tx, const crypto::hash& tx_id);
|
||||
bool add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i, uint64_t mix_count, bool use_only_forced_to_mix = false, uint64_t height_upper_limit = 0) const;
|
||||
bool get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool get_target_outs_for_amount_prezarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool get_target_outs_for_postzarcanum(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& details, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, std::map<uint64_t, uint64_t>& amounts_to_up_index_limit_cache) const;
|
||||
bool add_block_as_invalid(const block& bl, const crypto::hash& h);
|
||||
bool add_block_as_invalid(const block_extended_info& bei, const crypto::hash& h);
|
||||
size_t find_end_of_allowed_index(uint64_t amount)const;
|
||||
|
|
@ -669,7 +673,6 @@ namespace currency
|
|||
bool unprocess_blockchain_tx_extra(const transaction& tx);
|
||||
bool process_blockchain_tx_attachments(const transaction& tx, uint64_t h, const crypto::hash& bl_id, uint64_t timestamp);
|
||||
bool unprocess_blockchain_tx_attachments(const transaction& tx, uint64_t h, uint64_t timestamp);
|
||||
bool validate_ado_ownership(asset_op_verification_context& avc);
|
||||
bool pop_alias_info(const extra_alias_entry& ai);
|
||||
bool put_alias_info(const transaction& tx, extra_alias_entry& ai);
|
||||
bool pop_asset_info(const crypto::public_key& asset_id);
|
||||
|
|
|
|||
|
|
@ -249,13 +249,9 @@
|
|||
#define BC_OFFERS_CURRENT_OFFERS_SERVICE_ARCHIVE_VER CURRENCY_FORMATION_VERSION + BLOCKCHAIN_STORAGE_MAJOR_COMPATIBILITY_VERSION + 9
|
||||
#define BC_OFFERS_CURRENCY_MARKET_FILENAME "market.bin"
|
||||
|
||||
#ifndef TESTNET
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 163
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 163
|
||||
#else
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION (CURRENCY_FORMATION_VERSION+76)
|
||||
#endif
|
||||
|
||||
#define WALLET_FILE_SERIALIZATION_VERSION 165
|
||||
#define WALLET_FILE_LAST_SUPPORTED_VERSION 165
|
||||
|
||||
#define CURRENT_MEMPOOL_ARCHIVE_VER (CURRENCY_FORMATION_VERSION+31)
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ namespace currency
|
|||
//---------------------------------------------------------------
|
||||
// if cb returns true, it means "continue", false -- means "stop"
|
||||
template<typename specific_type_t, typename variant_container_t, typename callback_t>
|
||||
bool process_type_in_variant_container(const variant_container_t& av, callback_t& cb, bool return_value_if_none_found = true)
|
||||
bool process_type_in_variant_container(const variant_container_t& av, callback_t&& cb, bool return_value_if_none_found = true)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto& ai : av)
|
||||
|
|
@ -151,6 +151,27 @@ namespace currency
|
|||
return return_value_if_none_found;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// if cb returns false, stop immediately and return false
|
||||
template<typename specific_type_t, typename variant_container_t, typename callback_t>
|
||||
bool process_type_in_variant_container_and_make_sure_its_unique(const variant_container_t& av, callback_t&& cb, bool return_value_if_none_found = true)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto& ai : av)
|
||||
{
|
||||
if (ai.type() == typeid(specific_type_t))
|
||||
{
|
||||
if (found)
|
||||
return false; // already have it, type in not unique
|
||||
found = true;
|
||||
if (!cb(boost::get<specific_type_t>(ai)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
return true;
|
||||
return return_value_if_none_found;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
// callback should return true to continue iterating through the container
|
||||
template <typename A, typename B, typename container_t, typename callback_t>
|
||||
bool handle_2_alternative_types_in_variant_container(const container_t& container, callback_t cb)
|
||||
|
|
|
|||
|
|
@ -104,6 +104,20 @@ namespace currency
|
|||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core)
|
||||
{
|
||||
// ------------------ UNSECURE CODE FOR TESTS ---------------------
|
||||
if (m_unsecure_disable_tx_validation_on_addition)
|
||||
{
|
||||
uint64_t tx_fee = 0;
|
||||
CHECK_AND_ASSERT_MES(get_tx_fee(tx, tx_fee), false, "get_tx_fee failed");
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, null_hash, 0);
|
||||
tvc.m_added_to_pool = true;
|
||||
tvc.m_should_be_relayed = true;
|
||||
tvc.m_verification_failed = false;
|
||||
tvc.m_verification_impossible = false;
|
||||
return true;
|
||||
}
|
||||
// ---------------- END OF UNSECURE CODE FOR TESTS -------------------
|
||||
|
||||
bool r = false;
|
||||
|
||||
// defaults
|
||||
|
|
@ -224,6 +238,20 @@ namespace currency
|
|||
}
|
||||
TIME_MEASURE_FINISH_PD(check_inputs_time);
|
||||
|
||||
if (tx.version > TRANSACTION_VERSION_PRE_HF4)
|
||||
{
|
||||
TIME_MEASURE_START_PD(check_post_hf4_balance);
|
||||
r = check_tx_balance(tx, id);
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: balance proof is invalid");
|
||||
TIME_MEASURE_FINISH_PD(check_post_hf4_balance);
|
||||
|
||||
r = process_type_in_variant_container_and_make_sure_its_unique<asset_descriptor_operation>(tx.extra, [&](const asset_descriptor_operation& ado){
|
||||
asset_op_verification_context avc = { tx, id, ado };
|
||||
return m_blockchain.validate_asset_operation_against_current_blochain_state(avc);
|
||||
}, true);
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(r, false, { tvc.m_verification_failed = true; }, "post-HF4 tx: asset operation is invalid");
|
||||
}
|
||||
|
||||
do_insert_transaction(tx, id, blob_size, kept_by_block, tx_fee, ch_inp_res ? max_used_block_id : null_hash, ch_inp_res ? max_used_block_height : 0);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(tx_processing_time);
|
||||
|
|
@ -240,9 +268,11 @@ namespace currency
|
|||
<< "/" << m_performance_data.validate_alias_time.get_last_val()
|
||||
<< "/" << m_performance_data.check_keyimages_ws_ms_time.get_last_val()
|
||||
<< "/" << m_performance_data.check_inputs_time.get_last_val()
|
||||
<< "/b"<< m_performance_data.check_post_hf4_balance.get_last_val()
|
||||
<< "/" << m_performance_data.begin_tx_time.get_last_val()
|
||||
<< "/" << m_performance_data.update_db_time.get_last_val()
|
||||
<< "/" << m_performance_data.db_commit_time.get_last_val() << ")" );
|
||||
<< "/" << m_performance_data.db_commit_time.get_last_val()
|
||||
<< ")");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -875,7 +905,7 @@ namespace currency
|
|||
{
|
||||
//not the best implementation at this time, sorry :(
|
||||
|
||||
if (m_db_black_tx_list.get(get_transaction_hash(txd.tx)))
|
||||
if (is_tx_blacklisted(get_transaction_hash(txd.tx)))
|
||||
return false;
|
||||
|
||||
//check is ring_signature already checked ?
|
||||
|
|
@ -966,8 +996,8 @@ namespace currency
|
|||
return "(no transactions, the pool is empty)";
|
||||
// sort output by receive time
|
||||
txs.sort([](const std::pair<crypto::hash, tx_details>& lhs, const std::pair<crypto::hash, tx_details>& rhs) -> bool { return lhs.second.receive_time < rhs.second.receive_time; });
|
||||
ss << "# | transaction id | size | fee | ins | outs | outs money | live_time | max used block | last failed block | kept by a block?" << ENDL;
|
||||
// 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 87157 0.10000111 2000 2000 112000.12345678 d0.h10.m16.s17 123456 <12345..> 123456 <12345..> YES
|
||||
ss << "# | transaction id | size | fee | ins | outs | live_time | max used block | last failed block | ver | status " << ENDL;
|
||||
// 1234 f99fe6d4335fc0ddd69e6880a4d95e0f6ea398de0324a6837021a61c6a31cacd 187157 0.10000111 2000 2000 d0.h10.m16.s17 1234567 <12345..> 1234567 <12345..> 2 kept_by_block BLACKLISTED
|
||||
size_t i = 0;
|
||||
for (auto& tx : txs)
|
||||
{
|
||||
|
|
@ -975,17 +1005,17 @@ namespace currency
|
|||
ss << std::left
|
||||
<< std::setw(4) << i++ << " "
|
||||
<< tx.first << " "
|
||||
<< std::setw(5) << txd.blob_size << " "
|
||||
<< std::setw(6) << txd.blob_size << " "
|
||||
<< std::setw(10) << print_money_brief(txd.fee) << " "
|
||||
<< std::setw(4) << txd.tx.vin.size() << " "
|
||||
<< std::setw(4) << txd.tx.vout.size() << " "
|
||||
<< std::right << std::setw(15) << print_money(get_outs_money_amount(txd.tx)) << std::left << " "
|
||||
<< std::setw(14) << epee::misc_utils::get_time_interval_string(get_core_time() - txd.receive_time) << " "
|
||||
<< std::setw(6) << txd.max_used_block_height << " "
|
||||
<< std::setw(7) << txd.max_used_block_height << " "
|
||||
<< std::setw(9) << print16(txd.max_used_block_id) << " "
|
||||
<< std::setw(6) << txd.last_failed_height << " "
|
||||
<< std::setw(7) << txd.last_failed_height << " "
|
||||
<< std::setw(9) << print16(txd.last_failed_id) << " "
|
||||
<< (txd.kept_by_block ? "YES" : "no ")
|
||||
<< std::setw(3) << txd.tx.version << " "
|
||||
<< (txd.kept_by_block ? "kept_by_block " : "") << (is_tx_blacklisted(tx.first) ? "BLACKLISTED " : "")
|
||||
<< ENDL;
|
||||
}
|
||||
return ss.str();
|
||||
|
|
@ -1314,6 +1344,11 @@ namespace currency
|
|||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::is_tx_blacklisted(const crypto::hash& id) const
|
||||
{
|
||||
return m_db_black_tx_list.get(id) != nullptr;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::load_keyimages_cache()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ namespace currency
|
|||
epee::math_helper::average<uint64_t, 5> check_inputs_time;
|
||||
epee::math_helper::average<uint64_t, 5> begin_tx_time;
|
||||
epee::math_helper::average<uint64_t, 5> update_db_time;
|
||||
epee::math_helper::average<uint64_t, 5> db_commit_time;
|
||||
epee::math_helper::average<uint64_t, 5> db_commit_time;
|
||||
epee::math_helper::average<uint64_t, 1> check_post_hf4_balance;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<crypto::key_image, std::set<crypto::hash>> key_image_cache;
|
||||
|
|
@ -140,6 +141,12 @@ namespace currency
|
|||
|
||||
void remove_incompatible_txs(); // made public to be called after the BCS is loaded and hardfork info is ready
|
||||
|
||||
bool is_tx_blacklisted(const crypto::hash& id) const;
|
||||
|
||||
#ifdef TX_POOL_USE_UNSECURE_TEST_FUNCTIONS
|
||||
void unsecure_disable_tx_validation_on_addition(bool validation_disabled) { m_unsecure_disable_tx_validation_on_addition = validation_disabled; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool on_tx_remove(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block);
|
||||
|
|
@ -194,6 +201,7 @@ namespace currency
|
|||
key_image_cache m_key_images;
|
||||
mutable epee::critical_section m_remove_stuck_txs_lock;
|
||||
|
||||
bool m_unsecure_disable_tx_validation_on_addition = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, ph::_1), "Print block info, print_block <block_hash> | <block_height>");
|
||||
m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, ph::_1), "Print tx prunning info");
|
||||
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, ph::_1), "Print transaction, print_tx <transaction_hash>");
|
||||
m_cmd_binder.set_handler("print_asset_info", boost::bind(&daemon_commands_handler::print_asset_info, this, ph::_1), "Print information about the given asset by its id");
|
||||
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, ph::_1), "Start mining for specified address, start_mining <addr> [threads=1]");
|
||||
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, ph::_1), "Stop mining");
|
||||
m_cmd_binder.set_handler("print_pool", boost::bind(&daemon_commands_handler::print_pool, this, ph::_1), "Print transaction pool (long format)");
|
||||
|
|
@ -688,7 +689,7 @@ private:
|
|||
{
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "expected: print_tx <transaction hash>" << std::endl;
|
||||
std::cout << "usage: print_tx <transaction hash>" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -696,55 +697,74 @@ private:
|
|||
crypto::hash tx_hash;
|
||||
if (!parse_hash256(str_hash, tx_hash))
|
||||
{
|
||||
LOG_PRINT_RED_L0("invalid tx hash was given");
|
||||
return true;
|
||||
}
|
||||
|
||||
// std::vector<crypto::hash> tx_ids;
|
||||
// tx_ids.push_back(tx_hash);
|
||||
// std::list<currency::transaction> txs;
|
||||
// std::list<crypto::hash> missed_ids;
|
||||
// m_srv.get_payload_object().get_core().get_transactions(tx_ids, txs, missed_ids);
|
||||
|
||||
currency::transaction_chain_entry tx_entry = AUTO_VAL_INIT(tx_entry);
|
||||
|
||||
if (!m_srv.get_payload_object().get_core().get_blockchain_storage().get_tx_chain_entry(tx_hash, tx_entry))
|
||||
currency::tx_rpc_extended_info tx_rpc_ei{};
|
||||
currency::core& core = m_srv.get_payload_object().get_core();
|
||||
if (core.get_blockchain_storage().get_tx_rpc_details(tx_hash, tx_rpc_ei, 0, false))
|
||||
{
|
||||
LOG_PRINT_RED("transaction wasn't found: " << tx_hash, LOG_LEVEL_0);
|
||||
// pass
|
||||
}
|
||||
currency::block_extended_info bei = AUTO_VAL_INIT(bei);
|
||||
m_srv.get_payload_object().get_core().get_blockchain_storage().get_block_extended_info_by_height(tx_entry.m_keeper_block_height, bei);
|
||||
uint64_t timestamp = bei.bl.timestamp;
|
||||
|
||||
const currency::transaction& tx = tx_entry.tx;
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "------------------------------------------------------"
|
||||
<< ENDL << "tx_id: " << tx_hash
|
||||
<< ENDL << "keeper_block: " << tx_entry.m_keeper_block_height << ", timestamp (" << timestamp << ") " << epee::misc_utils::get_internet_time_str(timestamp)
|
||||
<< ENDL << currency::obj_to_json_str(tx)
|
||||
<< ENDL << "------------------------------------------------------"
|
||||
<< ENDL << epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(tx))
|
||||
<< ENDL << "------------------------------------------------------";
|
||||
|
||||
|
||||
ss << "ATTACHMENTS: " << ENDL;
|
||||
for (auto at : tx.attachment)
|
||||
else if (core.get_tx_pool().get_transaction_details(tx_hash, tx_rpc_ei))
|
||||
{
|
||||
if (at.type() == typeid(currency::tx_service_attachment))
|
||||
{
|
||||
const currency::tx_service_attachment& sa = boost::get<currency::tx_service_attachment>(at);
|
||||
ss << "++++++++++++++++++++++++++++++++ " << ENDL;
|
||||
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
|
||||
// pass
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_RED("transaction " << tx_hash << " was not found in either the blockchain or the pool", LOG_LEVEL_0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY))
|
||||
std::stringstream ss;
|
||||
ss << ENDL <<
|
||||
"----------------------TX-HEX--------------------------" << ENDL <<
|
||||
epee::string_tools::buff_to_hex_nodelimer(tx_rpc_ei.blob) << ENDL <<
|
||||
"------------------END-OF-TX-HEX-----------------------" << ENDL;
|
||||
|
||||
ss << ENDL <<
|
||||
"tx " << tx_hash << " ";
|
||||
|
||||
if (tx_rpc_ei.keeper_block == -1)
|
||||
{
|
||||
ss << "has been in the transaction pool for " << epee::misc_utils::get_time_interval_string(core.get_blockchain_storage().get_core_runtime_config().get_core_time() - tx_rpc_ei.timestamp) <<
|
||||
", added " << epee::misc_utils::get_internet_time_str(tx_rpc_ei.timestamp) << ", ts: " << tx_rpc_ei.timestamp << ", blob size: " << tx_rpc_ei.blob_size << ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "was added to block @ " << tx_rpc_ei.keeper_block << ", block time: " << epee::misc_utils::get_internet_time_str(tx_rpc_ei.timestamp) << ", ts: " << tx_rpc_ei.timestamp << ", blob size: " << tx_rpc_ei.blob_size << ENDL;
|
||||
}
|
||||
|
||||
ss << ENDL <<
|
||||
"-----------------------JSON---------------------------" << ENDL <<
|
||||
tx_rpc_ei.object_in_json << ENDL <<
|
||||
"--------------------END-OF-JSON-----------------------" << ENDL;
|
||||
|
||||
currency::transaction tx{};
|
||||
CHECK_AND_ASSERT_MES(currency::parse_and_validate_tx_from_blob(tx_rpc_ei.blob, tx), true, "parse_and_validate_tx_from_blob failed");
|
||||
|
||||
if (!tx.attachment.empty())
|
||||
{
|
||||
ss << "ATTACHMENTS: " << ENDL;
|
||||
for (auto at : tx.attachment)
|
||||
{
|
||||
if (at.type() == typeid(currency::tx_service_attachment))
|
||||
{
|
||||
std::string body = sa.body;
|
||||
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
const currency::tx_service_attachment& sa = boost::get<currency::tx_service_attachment>(at);
|
||||
ss << "++++++++++++++++++++++++++++++++ " << ENDL;
|
||||
ss << "[SERVICE_ATTACHMENT]: ID = \'" << sa.service_id << "\', INSTRUCTION: \'" << sa.instruction << "\'" << ENDL;
|
||||
|
||||
if (!(sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY))
|
||||
{
|
||||
bool r = epee::zlib_helper::unpack(sa.body, body);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
|
||||
std::string body = sa.body;
|
||||
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
|
||||
{
|
||||
bool r = epee::zlib_helper::unpack(sa.body, body);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to unpack");
|
||||
}
|
||||
ss << "BODY: " << body << ENDL;
|
||||
}
|
||||
ss << "BODY: " << body << ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -753,6 +773,56 @@ private:
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_asset_info(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty())
|
||||
{
|
||||
std::cout << "usage: print_asset_info <asset_id>" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& str_asset_id = args.front();
|
||||
crypto::public_key asset_id{};
|
||||
crypto::point_t asset_id_pt{};
|
||||
if (!crypto::parse_tpod_from_hex_string(str_asset_id, asset_id) || !asset_id_pt.from_public_key(asset_id))
|
||||
{
|
||||
LOG_PRINT_RED_L0("invalid asset id was given");
|
||||
return true;
|
||||
}
|
||||
|
||||
currency::core& core = m_srv.get_payload_object().get_core();
|
||||
|
||||
std::list<currency::asset_descriptor_operation> asset_history;
|
||||
if (!core.get_blockchain_storage().get_asset_history(asset_id, asset_history))
|
||||
{
|
||||
LOG_PRINT_RED_L0("asset id doesn't present in the blockchain");
|
||||
return true;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << ENDL <<
|
||||
"history for asset " << asset_id << ":" << ENDL;
|
||||
|
||||
size_t idx = 0;
|
||||
for(auto& aop: asset_history)
|
||||
{
|
||||
ss << "[" << std::setw(2) << idx << "] operation: " << currency::get_asset_operation_type_string(aop.operation_type) << " (" << (int)aop.operation_type << ")" << ENDL <<
|
||||
" ticker: \"" << aop.descriptor.ticker << "\"" << ENDL <<
|
||||
" full name: \"" << aop.descriptor.full_name << "\"" << ENDL <<
|
||||
" meta info: \"" << aop.descriptor.meta_info << "\"" << ENDL <<
|
||||
" current supply: " << currency::print_money_brief(aop.descriptor.current_supply, aop.descriptor.decimal_point) << ENDL <<
|
||||
" max supply: " << currency::print_money_brief(aop.descriptor.total_max_supply, aop.descriptor.decimal_point) << ENDL <<
|
||||
" decimal point: " << (int)aop.descriptor.decimal_point << ENDL <<
|
||||
" owner * 1/8: " << aop.descriptor.owner << ENDL <<
|
||||
" amount cmt * 1/8: " << aop.amount_commitment << ENDL <<
|
||||
" hidden supply: " << (aop.descriptor.hidden_supply ? "yes" : "no") << ENDL <<
|
||||
"";
|
||||
}
|
||||
|
||||
LOG_PRINT_L0(ss.str());
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_tx_outputs_usage(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty())
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ namespace currency
|
|||
}
|
||||
|
||||
blockchain_storage::blocks_direct_container bs;
|
||||
if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height, req.need_global_indexes))
|
||||
if(!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height))
|
||||
{
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
return false;
|
||||
|
|
@ -326,7 +326,7 @@ namespace currency
|
|||
}
|
||||
|
||||
blockchain_storage::blocks_direct_container bs;
|
||||
if (!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height, req.need_global_indexes))
|
||||
if (!m_core.get_blockchain_storage().find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, req.minimum_height))
|
||||
{
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
return false;
|
||||
|
|
@ -336,21 +336,15 @@ namespace currency
|
|||
{
|
||||
res.blocks.resize(res.blocks.size()+1);
|
||||
res.blocks.back().block = block_to_blob(b.first->bl);
|
||||
if (req.need_global_indexes)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(b.third.get(), false, "Internal error on handling COMMAND_RPC_GET_BLOCKS_FAST: b.third is empty, ie coinbase info is not prepared");
|
||||
res.blocks.back().coinbase_global_outs = b.third->m_global_output_indexes;
|
||||
res.blocks.back().tx_global_outs.resize(b.second.size());
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(b.third.get(), false, "Internal error on handling COMMAND_RPC_GET_BLOCKS_FAST: b.third is empty, ie coinbase info is not prepared");
|
||||
res.blocks.back().coinbase_global_outs = b.third->m_global_output_indexes;
|
||||
res.blocks.back().tx_global_outs.resize(b.second.size());
|
||||
size_t i = 0;
|
||||
|
||||
BOOST_FOREACH(auto& t, b.second)
|
||||
{
|
||||
res.blocks.back().txs.push_back(tx_to_blob(t->tx));
|
||||
if (req.need_global_indexes)
|
||||
{
|
||||
res.blocks.back().tx_global_outs[i].v = t->m_global_output_indexes;
|
||||
}
|
||||
res.blocks.back().tx_global_outs[i].v = t->m_global_output_indexes;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
|
@ -424,11 +418,11 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx)
|
||||
bool core_rpc_server::on_get_random_outs3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res, connection_context& cntx)
|
||||
{
|
||||
CHECK_CORE_READY();
|
||||
res.status = API_RETURN_CODE_FAIL;
|
||||
if (!m_core.get_blockchain_storage().get_random_outs_for_amounts2(req, res))
|
||||
if (!m_core.get_blockchain_storage().get_random_outs_for_amounts3(req, res))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -989,7 +983,7 @@ namespace currency
|
|||
res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height));
|
||||
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
|
||||
LOG_PRINT_L1("COMMAND_RPC_GETBLOCKTEMPLATE OK, response block: " << ENDL << currency::obj_to_json_str(resp.b));
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1339,6 +1333,20 @@ namespace currency
|
|||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_remove_tx_from_pool(const COMMAND_RPC_REMOVE_TX_FROM_POOL::request& req, COMMAND_RPC_REMOVE_TX_FROM_POOL::response& res, connection_context& cntx)
|
||||
{
|
||||
for (const auto& tx_id_str : req.tx_to_remove)
|
||||
{
|
||||
crypto::hash tx_id = epee::transform_str_to_t_pod<crypto::hash>(tx_id_str);
|
||||
currency::transaction tx; size_t dummy1 = 0; uint64_t dummy2 = 0;
|
||||
m_core.get_tx_pool().take_tx(tx_id, tx, dummy1, dummy2);
|
||||
}
|
||||
|
||||
res.status = API_RETURN_CODE_OK;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace currency
|
|||
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs1(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs2(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res, connection_context& cntx);
|
||||
bool on_get_random_outs3(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res, connection_context& cntx);
|
||||
bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx);
|
||||
bool on_set_maintainers_info(const COMMAND_RPC_SET_MAINTAINERS_INFO::request& req, COMMAND_RPC_SET_MAINTAINERS_INFO::response& res, connection_context& cntx);
|
||||
bool on_get_tx_pool(const COMMAND_RPC_GET_TX_POOL::request& req, COMMAND_RPC_GET_TX_POOL::response& res, connection_context& cntx);
|
||||
|
|
@ -75,6 +75,7 @@ namespace currency
|
|||
bool on_aliases_by_address(const COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& req, COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_alias_reward(const COMMAND_RPC_GET_ALIAS_REWARD::request& req, COMMAND_RPC_GET_ALIAS_REWARD::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_reset_transaction_pool(const COMMAND_RPC_RESET_TX_POOL::request& req, COMMAND_RPC_RESET_TX_POOL::response& res, connection_context& cntx);
|
||||
bool on_remove_tx_from_pool(const COMMAND_RPC_REMOVE_TX_FROM_POOL::request& req, COMMAND_RPC_REMOVE_TX_FROM_POOL::response& res, connection_context& cntx);
|
||||
bool 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);
|
||||
bool on_get_current_core_tx_expiration_median(const COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res, connection_context& cntx);
|
||||
bool on_get_tx_details(const COMMAND_RPC_GET_TX_DETAILS::request& req, COMMAND_RPC_GET_TX_DETAILS::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
|
|
@ -112,7 +113,7 @@ namespace currency
|
|||
MAP_URI_AUTO_BIN2("/get_o_indexes.bin", on_get_indexes, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs.bin", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs1.bin", on_get_random_outs1, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs2.bin", on_get_random_outs2, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2)
|
||||
MAP_URI_AUTO_BIN2("/getrandom_outs3.bin", on_get_random_outs3, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3)
|
||||
MAP_URI_AUTO_BIN2("/set_maintainers_info.bin", on_set_maintainers_info, COMMAND_RPC_SET_MAINTAINERS_INFO)
|
||||
MAP_URI_AUTO_BIN2("/get_tx_pool.bin", on_get_tx_pool, COMMAND_RPC_GET_TX_POOL)
|
||||
MAP_URI_AUTO_BIN2("/check_keyimages.bin", on_check_keyimages, COMMAND_RPC_CHECK_KEYIMAGES)
|
||||
|
|
@ -146,7 +147,7 @@ namespace currency
|
|||
MAP_JON_RPC ("get_pool_info", on_get_pool_info, COMMAND_RPC_GET_POOL_INFO)
|
||||
MAP_JON_RPC ("getrandom_outs", on_get_random_outs, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS_LEGACY)
|
||||
MAP_JON_RPC ("getrandom_outs1", on_get_random_outs1, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS)
|
||||
MAP_JON_RPC ("getrandom_outs2", on_get_random_outs2, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2)
|
||||
MAP_JON_RPC ("getrandom_outs3", on_get_random_outs3, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3)
|
||||
MAP_JON_RPC ("get_votes", on_get_votes, COMMAND_RPC_GET_VOTES)
|
||||
//assets api
|
||||
MAP_JON_RPC ("get_asset_info", on_get_asset_info, COMMAND_RPC_GET_ASSET_INFO)
|
||||
|
|
@ -156,6 +157,7 @@ namespace currency
|
|||
MAP_JON_RPC ("get_alt_blocks_details", on_get_alt_blocks_details, COMMAND_RPC_GET_ALT_BLOCKS_DETAILS)
|
||||
//
|
||||
MAP_JON_RPC ("reset_transaction_pool", on_reset_transaction_pool, COMMAND_RPC_RESET_TX_POOL)
|
||||
MAP_JON_RPC ("remove_tx_from_pool", on_remove_tx_from_pool, COMMAND_RPC_REMOVE_TX_FROM_POOL)
|
||||
MAP_JON_RPC ("get_current_core_tx_expiration_median", on_get_current_core_tx_expiration_median, COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN)
|
||||
//
|
||||
MAP_JON_RPC_WE("marketplace_global_get_offers_ex", on_get_offers_ex, COMMAND_RPC_GET_OFFERS_EX)
|
||||
|
|
|
|||
|
|
@ -161,12 +161,10 @@ namespace currency
|
|||
|
||||
struct request
|
||||
{
|
||||
bool need_global_indexes;
|
||||
uint64_t minimum_height;
|
||||
std::list<crypto::hash> block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(need_global_indexes)
|
||||
KV_SERIALIZE(minimum_height)
|
||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
|
@ -382,6 +380,11 @@ namespace currency
|
|||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
#define RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_COINBASE 0x0000000000000001LL
|
||||
#define RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_NOT_ALLOWED 0x0000000000000002LL
|
||||
#define RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_POS_COINBASE 0x0000000000000004LL
|
||||
|
||||
#pragma pack (push, 1)
|
||||
struct out_entry
|
||||
{
|
||||
|
|
@ -397,12 +400,13 @@ namespace currency
|
|||
crypto::public_key concealing_point; // premultiplied by 1/8
|
||||
crypto::public_key amount_commitment; // premultiplied by 1/8
|
||||
crypto::public_key blinded_asset_id; // premultiplied by 1/8
|
||||
uint64_t flags;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct outs_for_amount
|
||||
{
|
||||
uint64_t amount;
|
||||
uint64_t amount = 0;
|
||||
std::list<out_entry> outs;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
|
|
@ -422,18 +426,16 @@ namespace currency
|
|||
};
|
||||
};
|
||||
//-----------------------------------------------
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2
|
||||
struct COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3
|
||||
{
|
||||
struct offsets_distribution
|
||||
{
|
||||
uint64_t amount; //if amount is 0 then lookup in post-zarcanum zone only, if not 0 then pre-zarcanum only
|
||||
std::vector<uint64_t> offsets; //[i] = height, estimated location where to pickup output of transaction
|
||||
uint64_t own_global_index; //index to exclude from selection
|
||||
std::vector<uint64_t> global_offsets; //[i] = global_index to pick up
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(amount)
|
||||
KV_SERIALIZE(offsets)
|
||||
KV_SERIALIZE(own_global_index)
|
||||
KV_SERIALIZE(global_offsets)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
@ -1248,6 +1250,28 @@ namespace currency
|
|||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_REMOVE_TX_FROM_POOL
|
||||
{
|
||||
|
||||
struct request
|
||||
{
|
||||
std::list<std::string> tx_to_remove;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(tx_to_remove)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_POS_MINING_DETAILS
|
||||
{
|
||||
struct request
|
||||
|
|
@ -1342,7 +1366,7 @@ namespace currency
|
|||
std::string object_in_json;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(blob)
|
||||
KV_SERIALIZE_BLOB_AS_BASE64_STRING(blob)
|
||||
KV_SERIALIZE(blob_size)
|
||||
KV_SERIALIZE(timestamp)
|
||||
KV_SERIALIZE(keeper_block)
|
||||
|
|
@ -1354,7 +1378,7 @@ namespace currency
|
|||
KV_SERIALIZE(ins)
|
||||
KV_SERIALIZE(extra)
|
||||
KV_SERIALIZE(attachments)
|
||||
KV_SERIALIZE(object_in_json)
|
||||
KV_SERIALIZE_BLOB_AS_BASE64_STRING(object_in_json)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2113,11 +2113,11 @@ bool simple_wallet::emit_asset(const std::vector<std::string> &args)
|
|||
tx_destination_entry td = AUTO_VAL_INIT(td);
|
||||
td.addr.push_back(m_wallet->get_account().get_public_address());
|
||||
td.amount = amount;
|
||||
td.asset_id = asset_id;
|
||||
td.asset_id = currency::null_pkey;
|
||||
std::vector<currency::tx_destination_entry> destinations;
|
||||
destinations.push_back(td);
|
||||
currency::transaction result_tx = AUTO_VAL_INIT(result_tx);
|
||||
m_wallet->emmit_asset(asset_id, destinations, 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
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
#define PROJECT_REVISION "0"
|
||||
#define PROJECT_VERSION PROJECT_MAJOR_VERSION "." PROJECT_MINOR_VERSION "." PROJECT_REVISION
|
||||
|
||||
#define PROJECT_VERSION_BUILD_NO 284
|
||||
#define PROJECT_VERSION_BUILD_NO 290
|
||||
#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 "]"
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ namespace tools
|
|||
currency::COMMAND_RPC_GET_BLOCKS_FAST::request req;
|
||||
req.block_ids = rqt.block_ids;
|
||||
req.minimum_height = rqt.minimum_height;
|
||||
req.need_global_indexes = rqt.need_global_indexes;
|
||||
currency::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res);
|
||||
bool r = call_COMMAND_RPC_GET_BLOCKS_FAST(req, res);
|
||||
rsp.status = res.status;
|
||||
|
|
@ -77,9 +76,9 @@ namespace tools
|
|||
return invoke_http_bin_remote_command2_update_is_disconnect("/getrandom_outs1.bin", req, res);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res)
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res)
|
||||
{
|
||||
return invoke_http_bin_remote_command2_update_is_disconnect("/getrandom_outs2.bin", req, res);
|
||||
return invoke_http_bin_remote_command2_update_is_disconnect("/getrandom_outs3.bin", req, res);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& req, currency::COMMAND_RPC_SEND_RAW_TX::response& res)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ namespace tools
|
|||
bool call_COMMAND_RPC_GET_TX_POOL(const currency::COMMAND_RPC_GET_TX_POOL::request& rqt, currency::COMMAND_RPC_GET_TX_POOL::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(const currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& rqt, currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& rsp) override;
|
||||
bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& rqt, currency::COMMAND_RPC_SEND_RAW_TX::response& rsp) override;
|
||||
bool call_COMMAND_RPC_FORCE_RELAY_RAW_TXS(const currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& rqt, currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_ALL_ALIASES(currency::COMMAND_RPC_GET_ALL_ALIASES::response& rsp) override;
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ namespace tools
|
|||
return m_rpc.on_get_random_outs1(req, res, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& res) override
|
||||
bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& req, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& res) override
|
||||
{
|
||||
return m_rpc.on_get_random_outs2(req, res, m_cntxt_stub);
|
||||
return m_rpc.on_get_random_outs3(req, res, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& req, currency::COMMAND_RPC_SEND_RAW_TX::response& res) override
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace tools
|
|||
virtual bool call_COMMAND_RPC_GET_TX_POOL(const currency::COMMAND_RPC_GET_TX_POOL::request& rqt, currency::COMMAND_RPC_GET_TX_POOL::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_ALIASES_BY_ADDRESS(const currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::request& rqt, currency::COMMAND_RPC_GET_ALIASES_BY_ADDRESS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::response& rsp) { return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3(const currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request& rqt, currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::response& rsp) { return false; }
|
||||
virtual bool call_COMMAND_RPC_SEND_RAW_TX(const currency::COMMAND_RPC_SEND_RAW_TX::request& rqt, currency::COMMAND_RPC_SEND_RAW_TX::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_FORCE_RELAY_RAW_TXS(const currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::request& rqt, currency::COMMAND_RPC_FORCE_RELAY_RAW_TXS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_ALL_ALIASES(currency::COMMAND_RPC_GET_ALL_ALIASES::response& rsp){ return false; }
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ uint64_t scaler::scale(uint64_t h)
|
|||
|
||||
void decoy_selection_generator::init(uint64_t max_h)
|
||||
{
|
||||
|
||||
load_distribution(g_default_distribution, max_h);
|
||||
m_is_initialized = true;
|
||||
|
||||
m_max = max_h; // distribution INCLUDE m_max, count = m_max + 1
|
||||
}
|
||||
bool decoy_selection_generator::load_distribution_from_file(const char* path)
|
||||
{
|
||||
|
|
@ -66,6 +67,60 @@ std::vector<uint64_t> decoy_selection_generator::generate_distribution(uint64_t
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint64_t> decoy_selection_generator::generate_unique_reversed_distribution(uint64_t count)
|
||||
{
|
||||
std::set<uint64_t> set_to_extend;
|
||||
generate_unique_reversed_distribution(count, set_to_extend);
|
||||
return std::vector<uint64_t>(set_to_extend.begin(), set_to_extend.end());
|
||||
}
|
||||
|
||||
std::vector<uint64_t> decoy_selection_generator::generate_unique_reversed_distribution(uint64_t count, uint64_t preincluded_item)
|
||||
{
|
||||
std::set<uint64_t> set_to_extend;
|
||||
set_to_extend.insert(preincluded_item);
|
||||
generate_unique_reversed_distribution(count, set_to_extend);
|
||||
return std::vector<uint64_t>(set_to_extend.begin(), set_to_extend.end());
|
||||
}
|
||||
|
||||
#define DECOY_SELECTION_GENERATOR_MAX_ITERATIONS 1000000
|
||||
|
||||
void decoy_selection_generator::generate_unique_reversed_distribution(uint64_t count, std::set<uint64_t>& set_to_extend)
|
||||
{
|
||||
if (count + set_to_extend.size() > m_max)
|
||||
{
|
||||
throw std::runtime_error("generate_distribution_set with unexpected count");
|
||||
}
|
||||
|
||||
size_t attempt_count = 0;
|
||||
while (set_to_extend.size() != count)
|
||||
{
|
||||
attempt_count++;
|
||||
if (attempt_count > DECOY_SELECTION_GENERATOR_MAX_ITERATIONS)
|
||||
{
|
||||
throw std::runtime_error("generate_distribution_set: attempt_count hit DECOY_SELECTION_GENERATOR_MAX_ITERATIONS");
|
||||
}
|
||||
|
||||
uint64_t r = 0;
|
||||
crypto::generate_random_bytes(sizeof(r), &r);
|
||||
double r_ = map_uint_to_double(r);
|
||||
auto it = m_distribution_mapping.upper_bound(r_);
|
||||
if (it == m_distribution_mapping.end())
|
||||
{
|
||||
throw(std::runtime_error(std::string("_r not found in m_distribution_mapping: ") + std::to_string(r_)));
|
||||
}
|
||||
uint64_t h = it->second;
|
||||
if (it != m_distribution_mapping.begin())
|
||||
{
|
||||
uint64_t h_0 = (--it)->second;
|
||||
crypto::generate_random_bytes(sizeof(r), &r);
|
||||
h = h_0 + r % (h - h_0) + 1;
|
||||
}
|
||||
//scale from nominal to max_h
|
||||
set_to_extend.insert(m_max - h);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t get_distance(const std::vector<decoy_selection_generator::distribution_entry> entries, size_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
|
|
@ -79,7 +134,8 @@ bool decoy_selection_generator::load_distribution(const std::vector<decoy_select
|
|||
//do prescale of distribution
|
||||
std::vector<decoy_selection_generator::distribution_entry> derived_distribution;
|
||||
scaler scl;
|
||||
scl.config_scale(original_distribution.back().h, max_h);
|
||||
uint64_t adjustment_value = original_distribution[0].h;
|
||||
scl.config_scale(original_distribution.back().h - adjustment_value, max_h);
|
||||
|
||||
uint64_t last_scaled_h = 0;
|
||||
std::list<double> last_scaled_array;
|
||||
|
|
@ -87,7 +143,7 @@ bool decoy_selection_generator::load_distribution(const std::vector<decoy_select
|
|||
|
||||
for (size_t i = 0; i <= original_distribution.size(); i++)
|
||||
{
|
||||
if (i == original_distribution.size() || (scl.scale(original_distribution[i].h) != last_scaled_h && last_scaled_array.size()))
|
||||
if (i == original_distribution.size() || (scl.scale(original_distribution[i].h - adjustment_value) != last_scaled_h && last_scaled_array.size()))
|
||||
{
|
||||
//put avg to data_scaled
|
||||
double summ = 0;
|
||||
|
|
@ -96,7 +152,7 @@ bool decoy_selection_generator::load_distribution(const std::vector<decoy_select
|
|||
summ += item;
|
||||
}
|
||||
double avg = summ / last_scaled_array.size();
|
||||
uint64_t prev_h = scl.scale(original_distribution[i - 1].h);
|
||||
uint64_t prev_h = scl.scale(original_distribution[i - 1].h - adjustment_value);
|
||||
derived_distribution.push_back(decoy_selection_generator::distribution_entry{ prev_h, avg});
|
||||
last_scaled_array.clear();
|
||||
}
|
||||
|
|
@ -105,7 +161,7 @@ bool decoy_selection_generator::load_distribution(const std::vector<decoy_select
|
|||
break;
|
||||
}
|
||||
last_scaled_array.push_back(original_distribution[i].v);
|
||||
last_scaled_h = scl.scale(original_distribution[i].h);
|
||||
last_scaled_h = scl.scale(original_distribution[i].h - adjustment_value);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,10 +44,14 @@ public:
|
|||
void init(uint64_t max_h);
|
||||
bool load_distribution_from_file(const char* path);
|
||||
std::vector<uint64_t> generate_distribution(uint64_t count);
|
||||
std::vector<uint64_t> generate_unique_reversed_distribution(uint64_t count, uint64_t preincluded_item);
|
||||
std::vector<uint64_t> generate_unique_reversed_distribution(uint64_t count);
|
||||
void generate_unique_reversed_distribution(uint64_t count, std::set<uint64_t>& set_to_extend);
|
||||
bool is_initialized() { return m_is_initialized; }
|
||||
|
||||
private:
|
||||
bool load_distribution(const std::vector<decoy_selection_generator::distribution_entry>& entries, uint64_t max_h);
|
||||
bool m_is_initialized = false;
|
||||
uint64_t m_max = 0;
|
||||
std::map<double, uint64_t> m_distribution_mapping;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2023 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -62,6 +62,10 @@ using namespace currency;
|
|||
|
||||
#define WALLET_TX_MAX_ALLOWED_FEE (COIN * 100)
|
||||
|
||||
#define WALLET_FETCH_RANDOM_OUTS_SIZE 200
|
||||
|
||||
|
||||
|
||||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL "wallet"
|
||||
ENABLE_CHANNEL_BY_DEFAULT("wallet")
|
||||
|
|
@ -77,9 +81,11 @@ namespace tools
|
|||
, m_log_prefix("???")
|
||||
, m_watch_only(false)
|
||||
, m_required_decoys_count(CURRENCY_DEFAULT_DECOY_SET_SIZE)
|
||||
, m_defragmentation_tx_enabled(false)
|
||||
, m_max_allowed_output_amount_for_defragmentation_tx(CURRENCY_BLOCK_REWARD)
|
||||
, m_min_utxo_count_for_defragmentation_tx(WALLET_MIN_UTXO_COUNT_FOR_DEFRAGMENTATION_TX)
|
||||
, m_max_utxo_count_for_defragmentation_tx(WALLET_MAX_UTXO_COUNT_FOR_DEFRAGMENTATION_TX)
|
||||
, m_decoys_count_for_defragmentation_tx(WALLET_DEFAULT_DECOYS_COUNT_FOR_DEFRAGMENTATION_TX)
|
||||
, m_decoys_count_for_defragmentation_tx(SIZE_MAX)
|
||||
, m_use_deffered_global_outputs(false)
|
||||
#ifdef DISABLE_TOR
|
||||
, m_disable_tor_relay(true)
|
||||
|
|
@ -526,8 +532,18 @@ void wallet2::process_new_transaction(const currency::transaction& tx, uint64_t
|
|||
//PoW block don't have change, so all outs supposed to be marked as "mined"
|
||||
ptc.is_derived_from_coinbase = !ptc.is_pos_coinbase;
|
||||
ptc.height = height;
|
||||
|
||||
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(pglobal_indexes, "pglobal_indexes not set");
|
||||
if (this->is_in_hardfork_zone(ZANO_HARDFORK_04_ZARCANUM))
|
||||
{
|
||||
if (pglobal_indexes->size())
|
||||
{
|
||||
//store global index that is under coinage, so we can used in decoy selection algo
|
||||
if (ptc.height < m_last_known_daemon_height && m_last_known_daemon_height - ptc.height > WALLET_DEFAULT_TX_SPENDABLE_AGE)
|
||||
{
|
||||
m_last_zc_global_index = pglobal_indexes->back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& in : tx.vin)
|
||||
{
|
||||
|
|
@ -1917,8 +1933,6 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& stop)
|
|||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response res = AUTO_VAL_INIT(res);
|
||||
|
||||
req.minimum_height = get_wallet_minimum_height();
|
||||
if (is_auditable())
|
||||
req.need_global_indexes = true;
|
||||
if (req.minimum_height > m_height_of_start_sync)
|
||||
m_height_of_start_sync = req.minimum_height;
|
||||
|
||||
|
|
@ -1971,12 +1985,14 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop
|
|||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& res)
|
||||
{
|
||||
size_t current_index = res.start_height;
|
||||
m_last_known_daemon_height = res.current_height;
|
||||
bool been_matched_block = false;
|
||||
if (res.start_height == 0 && get_blockchain_current_size() == 1 && !res.blocks.empty())
|
||||
{
|
||||
const currency::block& genesis = res.blocks.front().block_ptr->bl;
|
||||
THROW_IF_TRUE_WALLET_EX(get_block_height(genesis) != 0, error::wallet_internal_error, "first block expected to be genesis");
|
||||
process_genesis_if_needed(genesis);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(res.blocks.front().coinbase_ptr, "Unexpected empty coinbase");
|
||||
process_genesis_if_needed(genesis, &(res.blocks.front().coinbase_ptr->m_global_output_indexes));
|
||||
res.blocks.pop_front();
|
||||
++current_index;
|
||||
been_matched_block = true;
|
||||
|
|
@ -3661,6 +3677,9 @@ void wallet2::get_transfers(transfer_container& incoming_transfers) const
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::generate_utxo_defragmentation_transaction_if_needed(currency::transaction& tx)
|
||||
{
|
||||
if (!m_defragmentation_tx_enabled)
|
||||
return false;
|
||||
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
ctp.create_utxo_defragmentation_tx = true;
|
||||
finalized_tx ftp{};
|
||||
|
|
@ -4939,7 +4958,7 @@ void wallet2::deploy_new_asset(const currency::asset_descriptor_base& asset_info
|
|||
m_custom_assets[new_asset_id] = ado.descriptor;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::emmit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx)
|
||||
void wallet2::emit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx)
|
||||
{
|
||||
|
||||
auto own_asset_entry_it = m_own_asset_descriptors.find(asset_id);
|
||||
|
|
@ -4961,6 +4980,12 @@ void wallet2::emmit_asset(const crypto::public_key asset_id, std::vector<currenc
|
|||
ctp.ado_current_asset_owner = rsp.asset_descriptor.owner;
|
||||
//ctp.asset_deploy_control_key = own_asset_entry_it->second.control_key;
|
||||
|
||||
for(auto& dst : ctp.dsts)
|
||||
{
|
||||
if (dst.asset_id == asset_id)
|
||||
dst.asset_id = null_pkey; // emit operation requires null_pkey for emitting asset outputs, fix it ad-hoc here
|
||||
}
|
||||
|
||||
finalized_tx ft = AUTO_VAL_INIT(ft);
|
||||
this->transfer(ctp, ft, true, nullptr);
|
||||
result_tx = ft.tx;
|
||||
|
|
@ -5926,8 +5951,8 @@ bool wallet2::decrypt_buffer(const std::string& buff, std::string& res_buff)
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
|
||||
{
|
||||
//prepare_free_transfers_cache(fake_outputs_count);
|
||||
//free_amounts_cache_type& free_amounts_for_native_coin = m_found_free_amounts[currency::native_coin_asset_id];
|
||||
if (!m_defragmentation_tx_enabled)
|
||||
return false;
|
||||
|
||||
std::stringstream ss;
|
||||
if (epee::log_space::log_singletone::get_log_detalisation_level() >= LOG_LEVEL_2)
|
||||
|
|
@ -5935,10 +5960,11 @@ bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx
|
|||
for (size_t i = 0, size = m_transfers.size(); i < size && selected_indicies.size() < m_max_utxo_count_for_defragmentation_tx; ++i)
|
||||
{
|
||||
const auto& td = m_transfers[i];
|
||||
if (!td.is_native_coin() || td.m_amount > CURRENCY_BLOCK_REWARD)
|
||||
if (!td.is_native_coin() || td.m_amount > m_max_allowed_output_amount_for_defragmentation_tx)
|
||||
continue;
|
||||
|
||||
if (is_transfer_ready_to_go(td, m_decoys_count_for_defragmentation_tx))
|
||||
uint64_t fake_outs_count_for_td = m_decoys_count_for_defragmentation_tx == SIZE_MAX ? (td.is_zc() ? m_core_runtime_config.hf4_minimum_mixins : CURRENCY_DEFAULT_DECOY_SET_SIZE) : m_decoys_count_for_defragmentation_tx;
|
||||
if (is_transfer_ready_to_go(td, fake_outs_count_for_td))
|
||||
{
|
||||
found_money += td.m_amount;
|
||||
selected_indicies.push_back(i);
|
||||
|
|
@ -5947,7 +5973,7 @@ bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx
|
|||
}
|
||||
}
|
||||
|
||||
if (selected_indicies.size() < m_min_utxo_count_for_defragmentation_tx)
|
||||
if (selected_indicies.size() < m_min_utxo_count_for_defragmentation_tx || found_money <= TX_MINIMUM_FEE)
|
||||
{
|
||||
// too few outputs were found, hence don't create a defragmentation tx
|
||||
selected_indicies.clear();
|
||||
|
|
@ -5957,7 +5983,7 @@ bool wallet2::prepare_tx_sources_for_defragmentation_tx(std::vector<currency::tx
|
|||
|
||||
WLT_LOG(ss.str(), LOG_LEVEL_2);
|
||||
|
||||
return prepare_tx_sources(m_decoys_count_for_defragmentation_tx, sources, selected_indicies);
|
||||
return prepare_tx_sources(m_decoys_count_for_defragmentation_tx == SIZE_MAX ? CURRENCY_DEFAULT_DECOY_SET_SIZE : m_decoys_count_for_defragmentation_tx, sources, selected_indicies);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies)
|
||||
|
|
@ -5970,17 +5996,18 @@ bool wallet2::prepare_tx_sources(assets_selection_context& needed_money_map, siz
|
|||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::prefetch_global_indicies_if_needed(const std::vector<uint64_t>& selected_indicies)
|
||||
{
|
||||
std::list<std::reference_wrapper<const currency::transaction>> txs;
|
||||
std::list<uint64_t> indices_that_requested_global_indicies;
|
||||
//std::list<std::reference_wrapper<const currency::transaction>> txs;
|
||||
//std::list<uint64_t> indices_that_requested_global_indicies;
|
||||
for (uint64_t i : selected_indicies)
|
||||
{
|
||||
if (m_transfers[i].m_global_output_index == WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED)
|
||||
{
|
||||
indices_that_requested_global_indicies.push_back(i);
|
||||
txs.push_back(m_transfers[i].m_ptx_wallet_info->m_tx);
|
||||
}
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers[i].m_global_output_index != WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED,
|
||||
"m_transfers[" << i << "].m_global_output_index is WALLET_GLOBAL_OUTPUT_INDEX_UNDEFINED");
|
||||
//indices_that_requested_global_indicies.push_back(i);
|
||||
//txs.push_back(m_transfers[i].m_ptx_wallet_info->m_tx);
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
std::vector<std::vector<uint64_t> > outputs_for_all_txs;
|
||||
fetch_tx_global_indixes(txs, outputs_for_all_txs);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(txs.size() == outputs_for_all_txs.size(), "missmatch sizes txs.size() == outputs_for_all_txs.size()");
|
||||
|
|
@ -5991,7 +6018,7 @@ void wallet2::prefetch_global_indicies_if_needed(const std::vector<uint64_t>& se
|
|||
transfer_details& td = m_transfers[*it_indices];
|
||||
td.m_global_output_index = (*it_ooutputs)[td.m_internal_output_index];
|
||||
it_ooutputs++; it_indices++;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies)
|
||||
|
|
@ -6011,26 +6038,26 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
if (current_size - 1 >= zarcanum_start_from)
|
||||
{
|
||||
//in Zarcanum era
|
||||
const uint64_t test_scale_size = current_size - 1 - zarcanum_start_from;
|
||||
zarcanum_decoy_set_generator.init(test_scale_size - 1);
|
||||
//const uint64_t test_scale_size = current_size - 1 - zarcanum_start_from;
|
||||
zarcanum_decoy_set_generator.init(m_last_zc_global_index);
|
||||
}
|
||||
|
||||
bool need_to_request = fake_outputs_count != 0;
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::request req = AUTO_VAL_INIT(req);
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::request req = AUTO_VAL_INIT(req);
|
||||
req.height_upper_limit = m_last_pow_block_h; // request decoys to be either older than, or the same age as stake output's height
|
||||
req.use_forced_mix_outs = false; // TODO: add this feature to UI later
|
||||
//req.decoys_count = fake_outputs_count + 1; // one more to be able to skip a decoy in case it hits the real output
|
||||
for (uint64_t i: selected_indicies)
|
||||
{
|
||||
req.amounts.push_back(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution());
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2::offsets_distribution& rdisttib = req.amounts.back();
|
||||
req.amounts.push_back(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution());
|
||||
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3::offsets_distribution& rdisttib = req.amounts.back();
|
||||
|
||||
auto it = m_transfers.begin() + i;
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it->m_ptx_wallet_info->m_tx.vout.size() > it->m_internal_output_index,
|
||||
"m_internal_output_index = " << it->m_internal_output_index <<
|
||||
" is greater or equal to outputs count = " << it->m_ptx_wallet_info->m_tx.vout.size());
|
||||
|
||||
rdisttib.own_global_index = it->m_global_output_index;
|
||||
//rdisttib.own_global_index = it->m_global_output_index;
|
||||
//check if we have Zarcanum era output of pre-Zarcanum
|
||||
if (it->is_zc())
|
||||
{
|
||||
|
|
@ -6039,15 +6066,14 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
//Zarcanum era
|
||||
rdisttib.amount = 0;
|
||||
//generate distribution in Zarcanum hardfork
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized");
|
||||
rdisttib.offsets = zarcanum_decoy_set_generator.generate_distribution(m_core_runtime_config.hf4_minimum_mixins);
|
||||
build_distribution_for_input(zarcanum_decoy_set_generator, rdisttib.global_offsets, it->m_global_output_index);
|
||||
need_to_request = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//for prezarcanum era use flat distribution
|
||||
rdisttib.amount = it->m_amount;
|
||||
rdisttib.offsets.resize(fake_outputs_count, 0);
|
||||
rdisttib.global_offsets.resize(fake_outputs_count + 1, 0);
|
||||
}
|
||||
}
|
||||
if (need_to_request)
|
||||
|
|
@ -6056,8 +6082,8 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
while (true)
|
||||
{
|
||||
daemon_resp = COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response();
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS2(req, daemon_resp);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs2.bin");
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS3(req, daemon_resp);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "getrandom_outs3.bin");
|
||||
if (daemon_resp.status == API_RETURN_CODE_FAIL)
|
||||
{
|
||||
if (attempt_count < 10)
|
||||
|
|
@ -6080,10 +6106,9 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
|
||||
std::vector<COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount> scanty_outs;
|
||||
THROW_IF_FALSE_WALLET_EX(daemon_resp.outs.size() == req.amounts.size(), error::not_enough_outs_to_mix, scanty_outs, fake_outputs_count);
|
||||
//for (COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_outs : daemon_resp.outs)
|
||||
for(size_t i = 0; i != daemon_resp.outs.size(); i++)
|
||||
{
|
||||
if (daemon_resp.outs[i].outs.size() != req.amounts[i].offsets.size())
|
||||
if (req.amounts[i].amount != 0 && daemon_resp.outs[i].outs.size() != req.amounts[i].global_offsets.size())
|
||||
{
|
||||
scanty_outs.push_back(daemon_resp.outs[i]);
|
||||
}
|
||||
|
|
@ -6093,6 +6118,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
}
|
||||
|
||||
//lets prefetch m_global_output_index for selected_indicies
|
||||
//this days doesn't prefetch, only validated that prefetch is not needed
|
||||
prefetch_global_indicies_if_needed(selected_indicies);
|
||||
|
||||
//prepare inputs
|
||||
|
|
@ -6116,6 +6142,16 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
//paste mixin transaction
|
||||
if (daemon_resp.outs.size())
|
||||
{
|
||||
if (td.is_zc())
|
||||
{
|
||||
//get rid of unneeded
|
||||
select_decoys(daemon_resp.outs[i], td.m_global_output_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: make sure we have exact count needed
|
||||
}
|
||||
|
||||
daemon_resp.outs[i].outs.sort([](const out_entry& a, const out_entry& b){return a.global_amount_index < b.global_amount_index; });
|
||||
for(out_entry& daemon_oe : daemon_resp.outs[i].outs)
|
||||
{
|
||||
|
|
@ -6126,7 +6162,7 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
oe.concealing_point = daemon_oe.concealing_point;
|
||||
oe.out_reference = daemon_oe.global_amount_index;
|
||||
oe.stealth_address = daemon_oe.stealth_address;
|
||||
oe.blinded_asset_id = daemon_oe.blinded_asset_id; // TODO @#@# BAD DESING, consider refactoring -- sowle
|
||||
oe.blinded_asset_id = daemon_oe.blinded_asset_id; // TODO @#@# BAD DESIGN, consider refactoring -- sowle
|
||||
src.outputs.push_back(oe);
|
||||
if (src.outputs.size() >= fake_outputs_count)
|
||||
break;
|
||||
|
|
@ -6188,6 +6224,72 @@ bool wallet2::prepare_tx_sources(size_t fake_outputs_count_, std::vector<currenc
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
template<typename t_obj_container>
|
||||
typename t_obj_container::value_type extract_random_from_container(t_obj_container& container)
|
||||
{
|
||||
auto it = container.begin();
|
||||
std::advance(it, (crypto::rand<size_t>() % container.size()));
|
||||
typename t_obj_container::value_type obj = *it;
|
||||
container.erase(it);
|
||||
return obj;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
void wallet2::select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& amount_entry, uint64_t own_g_index)
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(amount_entry.amount == 0, "Amount is not 0 in zc decoys entry");
|
||||
typedef currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
|
||||
|
||||
//TODO: This strategy would be a subject for continuous refactoring
|
||||
|
||||
//first take all real transactions if ther are some
|
||||
std::list<out_entry> local_outs;
|
||||
std::list<out_entry> coinbases;
|
||||
|
||||
while (amount_entry.outs.size() && local_outs.size() != m_core_runtime_config.hf4_minimum_mixins)
|
||||
{
|
||||
out_entry entry = extract_random_from_container(amount_entry.outs);
|
||||
|
||||
//skip auditable
|
||||
if ((entry.flags & (RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_NOT_ALLOWED)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (entry.flags & (RANDOM_OUTPUTS_FOR_AMOUNTS_FLAGS_COINBASE))
|
||||
{
|
||||
coinbases.push_back(entry);
|
||||
continue;
|
||||
}
|
||||
//
|
||||
if (entry.global_amount_index == own_g_index)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
local_outs.push_back(entry);
|
||||
}
|
||||
|
||||
//extend with coin base outs if needed
|
||||
while (coinbases.size() && local_outs.size() != m_core_runtime_config.hf4_minimum_mixins)
|
||||
{
|
||||
out_entry entry = extract_random_from_container(coinbases);
|
||||
local_outs.push_back(entry);
|
||||
}
|
||||
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(local_outs.size() == m_core_runtime_config.hf4_minimum_mixins, "Amount is not 0 in zc decoys entry");
|
||||
amount_entry.outs = local_outs;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
void wallet2::build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector<uint64_t>& offsets, uint64_t own_index)
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(zarcanum_decoy_set_generator.is_initialized(), "zarcanum_decoy_set_generator are not initialized");
|
||||
if (m_core_runtime_config.hf4_minimum_mixins)
|
||||
{
|
||||
offsets = zarcanum_decoy_set_generator.generate_unique_reversed_distribution(m_last_zc_global_index - 1 > WALLET_FETCH_RANDOM_OUTS_SIZE ? WALLET_FETCH_RANDOM_OUTS_SIZE: m_last_zc_global_index - 1, own_index);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(crypto::hash multisig_id, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money)
|
||||
{
|
||||
|
|
@ -6719,7 +6821,7 @@ bool wallet2::prepare_free_transfers_cache(uint64_t fake_outputs_count)
|
|||
if (td.m_zc_info_ptr)
|
||||
{
|
||||
//zarcanum out, redefine fake_outputs_count
|
||||
fake_outputs_count_local = this->is_auditable() ? 0 : CURRENCY_HF4_MANDATORY_DECOY_SET_SIZE;
|
||||
fake_outputs_count_local = this->is_auditable() ? 0 : m_core_runtime_config.hf4_minimum_mixins;
|
||||
}
|
||||
if (is_transfer_able_to_go(td, fake_outputs_count_local))
|
||||
{
|
||||
|
|
@ -6824,7 +6926,7 @@ bool wallet2::is_connected_to_net()
|
|||
return (res.synchronized_connections_count) ? true : false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::process_genesis_if_needed(const currency::block& genesis)
|
||||
void wallet2::process_genesis_if_needed(const currency::block& genesis, const std::vector<uint64_t>* pglobal_indexes)
|
||||
{
|
||||
if (!m_transfers.empty() || !m_key_images.empty())
|
||||
return;
|
||||
|
|
@ -6842,7 +6944,7 @@ void wallet2::process_genesis_if_needed(const currency::block& genesis)
|
|||
m_last_bc_timestamp = genesis.timestamp;
|
||||
|
||||
WLT_LOG_L2("Processing genesis block: " << genesis_hash);
|
||||
process_new_transaction(genesis.miner_tx, 0, genesis, nullptr);
|
||||
process_new_transaction(genesis.miner_tx, 0, genesis, pglobal_indexes);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::set_genesis(const crypto::hash& genesis_hash)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "currency_core/pos_mining.h"
|
||||
#include "view_iface.h"
|
||||
#include "wallet2_base.h"
|
||||
#include "decoy_selection.h"
|
||||
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE CURRENCY_HF4_MANDATORY_MIN_COINAGE
|
||||
#define WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL 1
|
||||
|
|
@ -147,6 +148,9 @@ namespace tools
|
|||
std::unordered_map<crypto::public_key, crypto::key_image> m_pending_key_images; // (out_pk -> ki) pairs of change outputs to be added in watch-only wallet without spend sec key
|
||||
uint64_t m_last_pow_block_h = 0;
|
||||
std::list<std::pair<uint64_t, wallet_event_t>> m_rollback_events;
|
||||
uint64_t m_last_zc_global_index = 0;
|
||||
|
||||
|
||||
|
||||
//variables that not being serialized
|
||||
std::atomic<uint64_t> m_last_bc_timestamp = 0;
|
||||
|
|
@ -218,6 +222,7 @@ namespace tools
|
|||
a & m_rollback_events;
|
||||
a & m_whitelisted_assets;
|
||||
a & m_use_assets_whitelisting;
|
||||
a & m_last_zc_global_index;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -389,7 +394,7 @@ namespace tools
|
|||
bool check_available_sources(std::list<uint64_t>& amounts);
|
||||
|
||||
void 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);
|
||||
void emmit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx);
|
||||
void emit_asset(const crypto::public_key asset_id, std::vector<currency::tx_destination_entry>& destinations, currency::transaction& result_tx);
|
||||
void update_asset(const crypto::public_key asset_id, const currency::asset_descriptor_base new_descriptor, currency::transaction& result_tx);
|
||||
void burn_asset(const crypto::public_key asset_id, uint64_t amount_to_burn, currency::transaction& result_tx);
|
||||
void transfer_asset_ownership(const crypto::public_key asset_id, const crypto::public_key& new_owner, currency::transaction& result_tx);
|
||||
|
|
@ -754,7 +759,7 @@ private:
|
|||
bool scan_not_compliant_unconfirmed_txs();
|
||||
const currency::transaction& get_transaction_by_id(const crypto::hash& tx_hash);
|
||||
void rise_on_transfer2(const wallet_public::wallet_transfer_info& wti);
|
||||
void process_genesis_if_needed(const currency::block& genesis);
|
||||
void process_genesis_if_needed(const currency::block& genesis, const std::vector<uint64_t>* pglobal_indexes);
|
||||
bool build_escrow_proposal(bc_services::contract_private_details& ecrow_details, uint64_t fee, uint64_t unlock_time, currency::tx_service_attachment& att, std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(assets_selection_context& needed_money_map, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies);
|
||||
bool prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, const std::vector<uint64_t>& selected_indicies);
|
||||
|
|
@ -850,6 +855,8 @@ private:
|
|||
void remove_transfer_from_amount_gindex_map(uint64_t tid);
|
||||
uint64_t get_alias_cost(const std::string& alias);
|
||||
detail::split_strategy_id_t get_current_split_strategy();
|
||||
void build_distribution_for_input(decoy_selection_generator& zarcanum_decoy_set_generator, std::vector<uint64_t>& offsets, uint64_t own_index);
|
||||
void select_decoys(currency::COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount & amount_entry, uint64_t own_g_index);
|
||||
|
||||
static void wti_to_csv_entry(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
static void wti_to_txt_line(std::ostream& ss, const wallet_public::wallet_transfer_info& wti, size_t index);
|
||||
|
|
@ -877,9 +884,13 @@ private:
|
|||
|
||||
|
||||
bool m_do_rise_transfer;
|
||||
|
||||
bool m_defragmentation_tx_enabled;
|
||||
uint64_t m_max_allowed_output_amount_for_defragmentation_tx;
|
||||
uint64_t m_min_utxo_count_for_defragmentation_tx;
|
||||
uint64_t m_max_utxo_count_for_defragmentation_tx;
|
||||
size_t m_decoys_count_for_defragmentation_tx;
|
||||
|
||||
size_t m_required_decoys_count;
|
||||
pending_ki_file_container_t m_pending_key_images_file_container;
|
||||
uint64_t m_upper_transaction_size_limit; //TODO: auto-calc this value or request from daemon, now use some fixed value
|
||||
|
|
@ -903,6 +914,8 @@ private:
|
|||
std::string m_votes_config_path;
|
||||
tools::wallet_public::wallet_vote_config m_votes_config;
|
||||
|
||||
uint64_t m_last_known_daemon_height = 0;
|
||||
|
||||
//this needed to access wallets state in coretests, for creating abnormal blocks and tranmsactions
|
||||
friend class test_generator;
|
||||
}; // class wallet2
|
||||
|
|
|
|||
|
|
@ -25,25 +25,25 @@ using namespace epee;
|
|||
catch (const tools::error::daemon_busy& e) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; \
|
||||
er.message = e.what(); \
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY") + e.what(); \
|
||||
return false; \
|
||||
} \
|
||||
catch (const tools::error::not_enough_money& e) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; \
|
||||
er.message = e.error_code(); \
|
||||
er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY; \
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY") + e.error_code(); \
|
||||
return false; \
|
||||
} \
|
||||
catch (const tools::error::wallet_error& e) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; \
|
||||
er.message = e.error_code(); \
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR") + e.error_code(); \
|
||||
return false; \
|
||||
} \
|
||||
catch (const std::exception& e) \
|
||||
{ \
|
||||
er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; \
|
||||
er.message = e.what(); \
|
||||
er.message = std::string("WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR") + e.what(); \
|
||||
return false; \
|
||||
} \
|
||||
catch (...) \
|
||||
|
|
|
|||
|
|
@ -13,3 +13,4 @@
|
|||
#define WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR -4
|
||||
#define WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID -5
|
||||
#define WALLET_RPC_ERROR_CODE_WRONG_ARGUMENT -6
|
||||
#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY -7
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#define TX_POOL_SCAN_INTERVAL 1
|
||||
#endif
|
||||
|
||||
#define HTTP_PROXY_TIMEOUT 2000
|
||||
#define HTTP_PROXY_TIMEOUT 4000
|
||||
#define HTTP_PROXY_ATTEMPTS_COUNT 1
|
||||
|
||||
const command_line::arg_descriptor<bool> arg_alloc_win_console ( "alloc-win-console", "Allocates debug console with GUI", false );
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ add_executable(net_load_tests_srv net_load_tests/srv.cpp)
|
|||
add_dependencies(coretests version)
|
||||
|
||||
target_link_libraries(coretests rpc wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(functional_tests rpc wallet currency_core crypto common zlibstatic ethash libminiupnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(functional_tests rpc wallet currency_core crypto common zlibstatic ethash libminiupnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(hash-tests crypto ethash)
|
||||
target_link_libraries(hash-target-tests crypto currency_core ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(performance_tests rpc wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(unit_tests wallet currency_core common crypto gtest_main zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(performance_tests rpc wallet currency_core common crypto zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(unit_tests wallet currency_core common crypto gtest_main zlibstatic ethash ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
target_link_libraries(net_load_tests_clt currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
target_link_libraries(net_load_tests_srv currency_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor 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.
|
||||
|
||||
#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests
|
||||
|
||||
#include "chaingen.h"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -553,12 +551,16 @@ bool test_generator::build_wallets(const blockchain_vector& blockchain,
|
|||
//skip genesis
|
||||
currency::block_direct_data_entry bdde = AUTO_VAL_INIT(bdde);
|
||||
std::shared_ptr<block_extended_info> bptr(new block_extended_info());
|
||||
bptr->bl = b->b;
|
||||
bptr->bl = b->b;
|
||||
bdde.block_ptr = bptr;
|
||||
std::shared_ptr<transaction_chain_entry> coinbase_tx_ptr(new transaction_chain_entry());
|
||||
coinbase_tx_ptr->m_global_output_indexes = get_tx_gindex_from_map(currency::get_transaction_hash(b->b.miner_tx), txs_outs);
|
||||
bdde.coinbase_ptr = coinbase_tx_ptr;
|
||||
for (auto& tx : b->m_transactions)
|
||||
{
|
||||
std::shared_ptr<transaction_chain_entry> tx_ptr(new transaction_chain_entry());
|
||||
tx_ptr->tx = tx;
|
||||
tx_ptr->m_global_output_indexes = get_tx_gindex_from_map(currency::get_transaction_hash(tx), txs_outs);
|
||||
bdde.txs_ptr.push_back(tx_ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2022 Zano Project
|
||||
// Copyright (c) 2014-2024 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
|
|
@ -9,7 +9,8 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests
|
||||
#define USE_INSECURE_RANDOM_RPNG_ROUTINES // turns on pseudorandom number generator manupulations for tests
|
||||
#define TX_POOL_USE_UNSECURE_TEST_FUNCTIONS // turns on special tests functions of tx pool
|
||||
|
||||
#include "currency_core/currency_basic.h"
|
||||
#include "currency_core/currency_core.h"
|
||||
|
|
@ -752,6 +753,17 @@ bool shuffle_source_entries(std::vector<currency::tx_source_entry>& sources);
|
|||
// one output will be created for each destination entry and one additional output to add up to old coinbase total amount
|
||||
bool replace_coinbase_in_genesis_block(const std::vector<currency::tx_destination_entry>& destinations, test_generator& generator, std::vector<test_event_entry>& events, currency::block& genesis_block);
|
||||
|
||||
template<typename t_map>
|
||||
const std::vector<uint64_t>& get_tx_gindex_from_map(const crypto::hash& tx_id, const t_map& id_to_vector)
|
||||
{
|
||||
auto it_global_indexes = id_to_vector.find(tx_id);
|
||||
if (it_global_indexes == id_to_vector.end())
|
||||
{
|
||||
throw std::runtime_error("TX ID NOT FOUND");
|
||||
}
|
||||
return it_global_indexes->second;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
template<class t_test_class>
|
||||
auto do_check_tx_verification_context(const currency::tx_verification_context& tvc, bool tx_added, size_t event_index, const currency::transaction& tx, t_test_class& validator, int)
|
||||
|
|
@ -994,6 +1006,7 @@ namespace crypto {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t get_sources_total_amount(const std::vector<currency::tx_source_entry>& s)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
|
|
|
|||
|
|
@ -1089,6 +1089,8 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY_HF(wallet_rpc_exchange_suite, "3,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-*");
|
||||
|
||||
|
||||
// GENERATE_AND_PLAY(emission_test); // simulate 1 year of blockchain, too long run (1 y ~= 1 hr), by demand only
|
||||
// LOG_ERROR2("print_reward_change_first_blocks.log", currency::print_reward_change_first_blocks(525601).str()); // outputs first 1 year of blocks' rewards (simplier)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,10 @@ bool hard_fork_4_consolidated_txs::generate(std::vector<test_event_entry>& event
|
|||
ADD_CUSTOM_EVENT(events, tx_0b);
|
||||
MAKE_NEXT_BLOCK_TX_LIST(events, blk_1, blk_0r, miner_acc, std::list<transaction>({tx_0a, tx_0b}));
|
||||
|
||||
size_t dhc = count_type_in_variant_container<tx_derivation_hint>(tx_0b.extra);
|
||||
CHECK_AND_ASSERT_MES(dhc == tx_0b.vout.size(), false, "unexpected derivation hints count: " << dhc);
|
||||
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// check Alice's balance
|
||||
|
|
@ -100,7 +104,7 @@ bool hard_fork_4_consolidated_txs::generate(std::vector<test_event_entry>& event
|
|||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*alice_wlt.get(), "alice", alice_amount, 0, alice_amount, 0, 0), false, "");
|
||||
|
||||
uint64_t miner_amount = MK_TEST_COINS(60);
|
||||
uint64_t bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE;
|
||||
m_bob_amount = miner_amount + alice_amount - TX_DEFAULT_FEE;
|
||||
|
||||
// Consolidated tx (TX_FLAG_SIGNATURE_MODE_SEPARATE).
|
||||
|
||||
|
|
@ -119,17 +123,33 @@ bool hard_fork_4_consolidated_txs::generate(std::vector<test_event_entry>& event
|
|||
std::vector<tx_destination_entry> destinations;
|
||||
if (miner_change != 0)
|
||||
destinations.push_back(tx_destination_entry(miner_change, miner_acc.get_public_address()));
|
||||
destinations.push_back(tx_destination_entry(bob_amount, bob_acc.get_public_address()));
|
||||
destinations.push_back(tx_destination_entry(m_bob_amount, bob_acc.get_public_address()));
|
||||
|
||||
add_flags_to_all_destination_entries(tx_destination_entry_flags::tdef_explicit_native_asset_id, destinations);
|
||||
r = construct_tx(miner_acc.get_keys(), sources, destinations, empty_extra, empty_attachment, tx_1, get_tx_version_from_events(events), one_time_secret_key,
|
||||
0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, TX_DEFAULT_FEE, gen_context);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
|
||||
dhc = count_type_in_variant_container<tx_derivation_hint>(tx_1.extra);
|
||||
CHECK_AND_ASSERT_MES(dhc == destinations.size(), false, "unexpected derivation hints count: " << dhc);
|
||||
|
||||
// partially completed tx_1 shouldn't be accepted
|
||||
//DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx_1);
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1r, miner_acc, tx_1);
|
||||
|
||||
// now we added a balance check to tx_memory_pool::add_tx() for post-HF4 txs, so the behaviour is the same -- partially completed consolidated tx won't be added to the pool -- sowle
|
||||
// (subject to change in future)
|
||||
|
||||
//if (m_post_hf4_zarcanum)
|
||||
//{
|
||||
// ADD_CUSTOM_EVENT(events, tx_1);
|
||||
// DO_CALLBACK(events, "mark_invalid_block");
|
||||
// MAKE_NEXT_BLOCK_TX1(events, blk_2a, blk_1r, miner_acc, tx_1);
|
||||
// DO_CALLBACK(events, "clear_tx_pool");
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
DO_CALLBACK(events, "mark_invalid_tx");
|
||||
ADD_CUSTOM_EVENT(events, tx_1);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -147,23 +167,25 @@ bool hard_fork_4_consolidated_txs::generate(std::vector<test_event_entry>& event
|
|||
0, 0, 0, true, TX_FLAG_SIGNATURE_MODE_SEPARATE, 0 /* note zero fee here */, gen_context);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
|
||||
size_t dhc_2 = count_type_in_variant_container<tx_derivation_hint>(tx_1.extra);
|
||||
CHECK_AND_ASSERT_MES(dhc_2 == dhc, false, "unexpected derivation hints count: " << dhc_2);
|
||||
|
||||
ADD_CUSTOM_EVENT(events, tx_1);
|
||||
}
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_2, blk_1r, miner_acc, tx_1);
|
||||
|
||||
//std::shared_ptr<tools::wallet2> bob_wlt;
|
||||
//r = generator.init_test_wallet(bob_acc, get_block_hash(blk_0), bob_wlt);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "init_test_wallet failed");
|
||||
//r = generator.refresh_test_wallet(events, bob_wlt.get(), get_block_hash(blk_2), 2 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 2);
|
||||
//CHECK_AND_ASSERT_MES(r, false, "refresh_test_wallet failed");
|
||||
//CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", bob_amount, 0, 0, 0, 0), false, "");
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hard_fork_4_consolidated_txs::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> bob_wlt = init_playtime_test_wallet(events, c, BOB_ACC_IDX);
|
||||
bob_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_balance_via_wallet(*bob_wlt.get(), "Bob", m_bob_amount, 0, 0, 0, 0), false, "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ struct hard_fork_4_consolidated_txs : public wallet_test
|
|||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
mutable bool m_post_hf4_zarcanum = false;
|
||||
mutable uint64_t m_bob_amount = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2014-2023 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.
|
||||
|
|
@ -142,9 +142,9 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
CHECK_AND_ASSERT_MES(asset_info2.meta_info == asset_info.meta_info, false, "Failed to find needed asset in result balances");
|
||||
|
||||
//test emmit function
|
||||
//test emit function
|
||||
//use same destinations as we used before
|
||||
miner_wlt->emmit_asset(asset_id, destinations, tx);
|
||||
miner_wlt->emit_asset(asset_id, destinations, tx);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
|
|
@ -186,7 +186,20 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
|
||||
asset_info.meta_info = "{\"some2\": \"info2\"}";
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "Test failed, broken ownership passed");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, 2);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "Test failed, broken ownership passed");
|
||||
c.get_tx_pool().purge_transactions();
|
||||
|
|
@ -202,25 +215,54 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
|
||||
asset_info.ticker = "XXX";
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
c.get_tx_pool().purge_transactions();
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added
|
||||
|
||||
|
||||
// check update_asset() with modified 'full_name'
|
||||
r = c.get_blockchain_storage().get_asset_info(asset_id, asset_info);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
|
||||
asset_info.full_name = "XXX";
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
c.get_tx_pool().purge_transactions();
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added
|
||||
miner_wlt->refresh();
|
||||
|
||||
|
||||
|
|
@ -229,13 +271,27 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(r, false, "Failed to get_asset_info");
|
||||
|
||||
asset_info.decimal_point = 3;
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "update_asset succeeded, but this shouldn't happened");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->update_asset(asset_id, asset_info, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added
|
||||
|
||||
|
||||
// check update_asset() with modified 'owner'
|
||||
|
|
@ -252,20 +308,35 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
//miner_wlt->refresh();
|
||||
|
||||
|
||||
// check emmit_asset() with modified 'current_supply'
|
||||
// check emit_asset() with modified 'current_supply'
|
||||
miner_wlt->get_debug_events_dispatcher().SUBSCIRBE_DEBUG_EVENT<wde_construct_tx_handle_asset_descriptor_operation_before_seal>([&](const wde_construct_tx_handle_asset_descriptor_operation_before_seal& o)
|
||||
{
|
||||
o.pado->descriptor.current_supply += 1000000;
|
||||
});
|
||||
//test emmit function but re-adjust current_supply to wrong amount
|
||||
miner_wlt->emmit_asset(asset_id, destinations, tx);
|
||||
//test emit function but re-adjust current_supply to wrong amount
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->emit_asset(asset_id, destinations, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "emit_asset succeeded, but this shouldn't happened");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->emit_asset(asset_id, destinations, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 0, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not added
|
||||
|
||||
//------------------- tests that trying to break stuff -------------------
|
||||
//test burn that burns more than tx has
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL();
|
||||
|
|
@ -276,11 +347,24 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
});
|
||||
|
||||
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
miner_wlt->burn_asset(asset_id, 10000000000000, tx);
|
||||
}
|
||||
catch(tools::error::tx_rejected&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "burn_asset succeeded, but this shouldn't happened");
|
||||
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(true);
|
||||
miner_wlt->burn_asset(asset_id, 10000000000000, tx);
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count());
|
||||
r = mine_next_pow_block_in_playtime(miner_wlt->get_account().get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "block with a bad tx was unexpectedly mined");
|
||||
CHECK_AND_ASSERT_MES(c.get_pool_transactions_count() == 1, false, "Unexpected number of txs in the pool: " << c.get_pool_transactions_count()); // make sure tx was not confirmed
|
||||
c.get_tx_pool().unsecure_disable_tx_validation_on_addition(false);
|
||||
c.get_tx_pool().purge_transactions();
|
||||
miner_wlt->refresh();
|
||||
miner_wlt->get_debug_events_dispatcher().UNSUBSCRIBE_ALL();
|
||||
|
|
@ -305,7 +389,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
uint64_t balance_alice_asset = alice_wlt->balance(asset_id);
|
||||
uint64_t balance_miner_asset = miner_wlt->balance(asset_id);
|
||||
|
||||
alice_wlt->emmit_asset(asset_id, destinations, tx);
|
||||
alice_wlt->emit_asset(asset_id, destinations, tx);
|
||||
r = mine_next_pow_blocks_in_playtime(miner_wlt->get_account().get_public_address(), c, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
CHECK_AND_ASSERT_MES(r, false, "mine_next_pow_blocks_in_playtime failed");
|
||||
|
||||
|
|
@ -315,7 +399,7 @@ bool multiassets_basic_test::c1(currency::core& c, size_t ev_index, const std::v
|
|||
CHECK_AND_ASSERT_MES(miner_wlt->balance(asset_id) == balance_miner_asset + destinations[0].amount, false, "Miner balance wrong");
|
||||
CHECK_AND_ASSERT_MES(alice_wlt->balance(asset_id) == balance_alice_asset + destinations[1].amount, false, "Alice balance wrong");
|
||||
|
||||
//TODO: attempt to emmmit from old key, attempt to emmit from more then max supply
|
||||
//TODO: attempt to emmmit from old key, attempt to emit from more then max supply
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,20 +99,30 @@ bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::CO
|
|||
{
|
||||
auto b = m_blocks[i];
|
||||
currency::block_complete_entry bce = AUTO_VAL_INIT(bce);
|
||||
for (auto tx : b->m_transactions)
|
||||
bce.tx_global_outs.resize(b->m_transactions.size());
|
||||
bce.coinbase_global_outs = get_tx_gindex(currency::get_transaction_hash(b->b.miner_tx));
|
||||
for (size_t j = 0; j != b->m_transactions.size(); j++)
|
||||
{
|
||||
const auto& tx = b->m_transactions[j];
|
||||
bce.txs.push_back(tx_to_blob(tx));
|
||||
bce.tx_global_outs[j].v = get_tx_gindex(currency::get_transaction_hash(tx));
|
||||
}
|
||||
bce.block = block_to_blob(b->b);
|
||||
rsp.blocks.push_back(bce);
|
||||
}
|
||||
rsp.current_height = m_blocks.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<uint64_t>& wallet_test_core_proxy::get_tx_gindex(const crypto::hash& tx_id)
|
||||
{
|
||||
return get_tx_gindex_from_map(tx_id, m_txs_outs);
|
||||
}
|
||||
bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_DIRECT(const currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& rsp)
|
||||
{
|
||||
currency::COMMAND_RPC_GET_BLOCKS_FAST::request req = AUTO_VAL_INIT(req);
|
||||
req.block_ids = rqt.block_ids;
|
||||
req.minimum_height = rqt.minimum_height;
|
||||
req.need_global_indexes = rqt.need_global_indexes;
|
||||
currency::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res);
|
||||
bool r = this->call_COMMAND_RPC_GET_BLOCKS_FAST(req, res);
|
||||
rsp.status = res.status;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ struct wallet_test_core_proxy : public tools::i_core_proxy
|
|||
virtual bool call_COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN(const currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::request& req, currency::COMMAND_RPC_GET_CURRENT_CORE_TX_EXPIRATION_MEDIAN::response& res) override;
|
||||
virtual bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id) override;
|
||||
|
||||
const std::vector<uint64_t>& get_tx_gindex(const crypto::hash& tx_id);
|
||||
|
||||
|
||||
test_generator::tx_global_indexes m_txs_outs;
|
||||
test_generator::blockchain_vector m_blocks;
|
||||
test_generator::outputs_index m_oi;
|
||||
|
|
|
|||
|
|
@ -3809,3 +3809,95 @@ bool wallet_and_sweep_below::c1(currency::core& c, size_t ev_index, const std::v
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
block_template_blacklist_test::block_template_blacklist_test()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(block_template_blacklist_test, c1);
|
||||
}
|
||||
|
||||
bool block_template_blacklist_test::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test idea: basic check for wallet2::sweep_below() functionality
|
||||
|
||||
uint64_t ts = test_core_time::get_time();
|
||||
m_accounts.resize(TOTAL_ACCS_COUNT);
|
||||
account_base preminer_acc;
|
||||
preminer_acc.generate();
|
||||
preminer_acc.set_createtime(ts);
|
||||
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, preminer_acc, ts);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_1, blk_0, preminer_acc);
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, 3 * CURRENCY_MINED_MONEY_UNLOCK_WINDOW - 1);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool block_template_blacklist_test::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);
|
||||
std::shared_ptr<tools::wallet2> alice_wlt = init_playtime_test_wallet(events, c, ALICE_ACC_IDX);
|
||||
|
||||
miner_wlt->refresh();
|
||||
miner_wlt->transfer(COIN / 10, alice_wlt->get_account().get_public_address());
|
||||
miner_wlt->transfer(COIN / 10, alice_wlt->get_account().get_public_address());
|
||||
|
||||
//take first transaction and corrupt it intentionalyy
|
||||
std::list<transaction> txs;
|
||||
c.get_tx_pool().get_transactions(txs);
|
||||
CHECK_AND_ASSERT_MES(txs.size() == 2, false, "wrong tx count");
|
||||
|
||||
|
||||
txs.resize(1);
|
||||
currency::transaction broken_tx;
|
||||
uint64_t blob_size = 0;
|
||||
uint64_t fee = 0;
|
||||
r = c.get_tx_pool().take_tx(currency::get_transaction_hash(*txs.begin()), broken_tx, blob_size, fee);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to take from pool");
|
||||
|
||||
|
||||
broken_tx.signatures.resize(broken_tx.signatures.size() - 1);
|
||||
//manually add completely broken tx to pool
|
||||
c.get_tx_pool().do_insert_transaction(broken_tx, get_transaction_hash(broken_tx), currency::get_object_blobsize(broken_tx), false, get_tx_fee(broken_tx), c.get_block_id_by_height(0), 0);
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_tx_pool().get_transactions_count() == 2, false, "wrong tx count");
|
||||
|
||||
|
||||
currency::create_block_template_params cbtp = AUTO_VAL_INIT(cbtp);
|
||||
cbtp.miner_address = miner_wlt->get_account().get_public_address();
|
||||
|
||||
{
|
||||
currency::create_block_template_response cbtr = AUTO_VAL_INIT(cbtr);
|
||||
r = c.get_block_template(cbtp, cbtr);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to create block template");
|
||||
CHECK_AND_ASSERT_MES(cbtr.b.tx_hashes.size() == 2, false, "failed to create block template");
|
||||
}
|
||||
|
||||
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(!r, false, "Unexpectedly created block");
|
||||
|
||||
//now let's check if broken tx actually added to next blocktemplate
|
||||
|
||||
{
|
||||
currency::create_block_template_response cbtr = AUTO_VAL_INIT(cbtr);
|
||||
r = c.get_block_template(cbtp, cbtr);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to create block template");
|
||||
CHECK_AND_ASSERT_MES(cbtr.b.tx_hashes.size() == 1, false, "failed to create block template");
|
||||
|
||||
}
|
||||
|
||||
r = mine_next_pow_block_in_playtime(m_accounts[MINER_ACC_IDX].get_public_address(), c);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Unexpectedly failed to create block");
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,3 +294,11 @@ struct wallet_and_sweep_below : public wallet_test
|
|||
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);
|
||||
};
|
||||
|
||||
|
||||
struct block_template_blacklist_test : public wallet_test
|
||||
{
|
||||
block_template_blacklist_test();
|
||||
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);
|
||||
};
|
||||
|
|
@ -27,12 +27,18 @@
|
|||
#include "wallet/plain_wallet_api.h"
|
||||
#include "wallet/view_iface.h"
|
||||
|
||||
|
||||
void test_plain_wallet()
|
||||
{
|
||||
std::string res = plain_wallet::init("195.201.107.230", "33336", "E:\\tmp\\", 0);
|
||||
//std::string res = plain_wallet::init("195.201.107.230", "33336", "E:\\tmp\\", 0);
|
||||
std::string res = plain_wallet::init("127.0.0.1", "12111", "C:\\Users\\roky\\home\\", 0);
|
||||
|
||||
uint64_t instance_id = 0;
|
||||
res = plain_wallet::open("test.zan", "111");
|
||||
res = plain_wallet::open("test_restored.zan", "111");
|
||||
//res = plain_wallet::restore("heart level clear fate sorrow childhood sent fate ceiling party third steel came ask mix neither message already almost vast date glide tumble color okay space",
|
||||
// "test_restored.zan", "111", "");
|
||||
|
||||
|
||||
while(true)
|
||||
{
|
||||
epee::misc_utils::sleep_no_w(2000);
|
||||
|
|
@ -44,9 +50,23 @@ void test_plain_wallet()
|
|||
}
|
||||
|
||||
|
||||
std::string invoke_body = "{\"method\":\"get_recent_txs_and_info\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}";
|
||||
|
||||
res = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
std::string invoke_body = "{\"method\":\"store\",\"params\":{}}";
|
||||
//std::string res1 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
invoke_body = "{\"method\":\"get_recent_txs_and_info\",\"params\":{\"offset\":0,\"count\":30,\"update_provision_info\":true}}";
|
||||
std::string res2 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
invoke_body = "{\"method\":\"getbalance\",\"params\":{}}";
|
||||
std::string res3 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
|
||||
invoke_body = "{\"method\":\"getbalance\",\"params\":{}}";
|
||||
std::string res4 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
|
||||
invoke_body = "{\r\n \"method\": \"transfer\",\r\n \"params\": {\r\n \"destinations\": [\r\n {\r\n \"amount\": \"1000000000000\",\r\n \"address\": \"ZxD9oVwGwW6ULix9Pqttnr7JDpaoLvDVA1KJ9eA9KRxPMRZT5X7WwtU94XH1Z6q6XTMxNbHmbV2xfZ429XxV6fST2DxEg4BQV\" }\r\n ],\r\n \"fee\": 10000000000,\r\n \"mixin\": 10,\r\n \"payment_id\": \"\",\r\n \"comment\": \"\",\r\n \"push_payer\": false,\r\n \"hide_receiver\": true\r\n }\r\n}";
|
||||
std::string res5 = plain_wallet::sync_call("invoke", instance_id, invoke_body);
|
||||
|
||||
LOG_PRINT_L0(res);
|
||||
|
||||
}
|
||||
|
|
@ -56,10 +76,10 @@ int main(int argc, char** argv)
|
|||
{
|
||||
epee::string_tools::set_module_name_and_folder(argv[0]);
|
||||
epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
|
||||
epee::log_space::log_singletone::add_logger(LOGGER_FILE,
|
||||
epee::log_space::log_singletone::get_default_log_file().c_str(),
|
||||
epee::log_space::log_singletone::get_default_log_folder().c_str());
|
||||
//epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
|
||||
//epee::log_space::log_singletone::add_logger(LOGGER_FILE,
|
||||
// epee::log_space::log_singletone::get_default_log_file().c_str(),
|
||||
// epee::log_space::log_singletone::get_default_log_folder().c_str());
|
||||
|
||||
test_plain_wallet();
|
||||
//parse_weird_tx();
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ public:
|
|||
m_bob.generate();
|
||||
|
||||
uint64_t block_reward_without_fee = 0;
|
||||
if (!construct_miner_tx(0, 0, 0, 2, 0, m_bob.get_keys().account_address, m_bob.get_keys().account_address, m_tx, block_reward_without_fee, TRANSACTION_VERSION_PRE_HF4, blobdata(), CURRENCY_MINER_TX_MAX_OUTS))
|
||||
return false;
|
||||
|
||||
uint64_t block_reward = 0;
|
||||
if(!construct_miner_tx(0, 0, 0, 2, 0, m_bob.get_keys().account_address, m_bob.get_keys().account_address, m_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, blobdata(), CURRENCY_MINER_TX_MAX_OUTS))
|
||||
return false;
|
||||
m_tx_pub_key = get_tx_pub_key_from_extra(m_tx);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,32 +10,39 @@ TEST(decoy_selection_test, decoy_selection_test)
|
|||
{
|
||||
const uint64_t test_scale_size = 20000;
|
||||
decoy_selection_generator dsg;
|
||||
dsg.init(test_scale_size - 1);
|
||||
dsg.init(100);
|
||||
std::map<uint64_t, uint64_t> hits;
|
||||
|
||||
|
||||
|
||||
//std::vector<uint64_t> decoys = dsg.generate_distribution(15);
|
||||
|
||||
std::cout << "";
|
||||
|
||||
//std::vector<uint64_t> hits(test_scale_size, 0);
|
||||
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// std::vector<uint64_t> decoys = dsg.generate_distribution(15);
|
||||
// for (auto d : decoys)
|
||||
// {
|
||||
// hits[d]++;
|
||||
// }
|
||||
//
|
||||
// if (hits[10] > 500)
|
||||
// break;
|
||||
//
|
||||
// }
|
||||
// std::stringstream ss;
|
||||
// for (auto it = hits.begin(); it != hits.end(); it++)
|
||||
// {
|
||||
// //if (hits[i] != 0)
|
||||
// {
|
||||
// ss << it->first << ", " << it->second << ENDL;
|
||||
// }
|
||||
// }
|
||||
// epee::file_io_utils::save_string_to_file("distribution.csv", ss.str());
|
||||
while (true)
|
||||
{
|
||||
std::vector<uint64_t> decoys = dsg.generate_distribution(15);
|
||||
for (auto d : decoys)
|
||||
{
|
||||
hits[d]++;
|
||||
}
|
||||
|
||||
if (hits[10] > 500)
|
||||
break;
|
||||
|
||||
}
|
||||
std::stringstream ss;
|
||||
for (auto it = hits.begin(); it != hits.end(); it++)
|
||||
{
|
||||
if (it->second != 0)
|
||||
{
|
||||
ss << it->first << ", " << it->second << std::endl;
|
||||
}
|
||||
}
|
||||
epee::file_io_utils::save_string_to_file("distribution.csv", ss.str());
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
1
utils/test_api_files/get_alias_by_address.json
Normal file
1
utils/test_api_files/get_alias_by_address.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"method": "get_alias_details","params": {"alias": "zoidb"}}
|
||||
|
|
@ -1 +1 @@
|
|||
{"method": "get_alias_details","params": {"alias": "zoidb"}}
|
||||
{"method": "get_alias_details","params": "ZxCjF84feY7GQZ1fdy9r3ZJABwaFjmb2Dd25H5qANWZ2VufpmyNu7ZnShMBDpiw8VW2k1EjPZswgFZnx3v1EYgJ32Rjn64mq9"}
|
||||
Loading…
Add table
Reference in a new issue