forked from lthn/blockchain
Merge branch 'txpool_optimisation' into develop
This commit is contained in:
commit
52083f20b0
40 changed files with 843 additions and 298 deletions
|
|
@ -393,7 +393,21 @@ namespace misc_utils
|
|||
|
||||
auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type())));
|
||||
return res.first->second;
|
||||
}
|
||||
}
|
||||
|
||||
template<class t_container_type>
|
||||
typename t_container_type::iterator it_get_or_insert_value_initialized(t_container_type& container, const typename t_container_type::key_type& key)
|
||||
{
|
||||
auto it = container.find(key);
|
||||
if (it != container.end())
|
||||
{
|
||||
return it;
|
||||
}
|
||||
|
||||
auto res = container.insert(typename t_container_type::value_type(key, AUTO_VAL_INIT(typename t_container_type::mapped_type())));
|
||||
return res.first;
|
||||
}
|
||||
|
||||
} // namespace misc_utils
|
||||
} // namespace epee
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ namespace epee
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
//basic helpers for pod-to-hex serialization
|
||||
template<class t_pod_type>
|
||||
std::string transform_t_pod_to_str(const t_pod_type & a)
|
||||
|
|
|
|||
41
contrib/epee/include/serialization/keyvalue_hexemizer.h
Normal file
41
contrib/epee/include/serialization/keyvalue_hexemizer.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2006-2019, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include "keyvalue_serialization.h"
|
||||
namespace epee
|
||||
{
|
||||
|
||||
struct hexemizer
|
||||
{
|
||||
std::string blob;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(blob)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -698,6 +698,9 @@ namespace epee
|
|||
#define CRITICAL_REGION_BEGIN1(x) CRITICAL_REGION_BEGIN_VAR(x, critical_region_var1)
|
||||
#define CRITICAL_REGION_END() }
|
||||
|
||||
|
||||
#define CIRITCAL_OPERATION(obj,op) {obj##_lock.lock();obj . op;obj##_lock.unlock();}
|
||||
|
||||
#define SHARED_CRITICAL_REGION_LOCAL(x) boost::shared_lock< boost::shared_mutex > critical_region_var(x)
|
||||
#define EXCLUSIVE_CRITICAL_REGION_LOCAL(x) boost::unique_lock< boost::shared_mutex > critical_region_var(x)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ if(POLICY CMP0043)
|
|||
cmake_policy(SET CMP0043 OLD)
|
||||
endif()
|
||||
|
||||
|
||||
###########
|
||||
# using shared PCH -- this is unusual case for MSVC... so mystery, such hack, many wow. See also: https://stackoverflow.com/questions/645747/sharing-precompiled-headers-between-projects-in-visual-studio/4170902#4170902
|
||||
# define USE_PCH to YES for using precomiled headers
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "storages/portable_storage_template_helper.h"
|
||||
#include "basic_pow_helpers.h"
|
||||
#include "version.h"
|
||||
#include "tx_semantic_validation.h"
|
||||
|
||||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL "core"
|
||||
|
|
@ -438,7 +439,7 @@ bool blockchain_storage::deinit()
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::pop_block_from_blockchain()
|
||||
bool blockchain_storage::pop_block_from_blockchain(transactions_map& onboard_transactions)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -448,7 +449,7 @@ bool blockchain_storage::pop_block_from_blockchain()
|
|||
CHECK_AND_ASSERT_MES(bei_ptr.get(), false, "pop_block_from_blockchain: can't pop from blockchain");
|
||||
|
||||
uint64_t fee_total = 0;
|
||||
bool r = purge_block_data_from_blockchain(bei_ptr->bl, bei_ptr->bl.tx_hashes.size(), fee_total);
|
||||
bool r = purge_block_data_from_blockchain(bei_ptr->bl, bei_ptr->bl.tx_hashes.size(), fee_total, onboard_transactions);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to purge_block_data_from_blockchain for block " << get_block_hash(bei_ptr->bl) << " on height " << h);
|
||||
|
||||
pop_block_from_per_block_increments(bei_ptr->height);
|
||||
|
|
@ -648,7 +649,7 @@ bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const trans
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee)
|
||||
bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee, transaction& tx_)
|
||||
{
|
||||
fee = 0;
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
|
@ -656,6 +657,7 @@ bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& t
|
|||
auto tx_res_ptr = m_db_transactions.find(tx_id);
|
||||
CHECK_AND_ASSERT_MES(tx_res_ptr != m_db_transactions.end(), false, "transaction " << tx_id << " is not found in blockchain index!!");
|
||||
const transaction& tx = tx_res_ptr->tx;
|
||||
tx_ = tx;
|
||||
|
||||
fee = get_tx_fee(tx_res_ptr->tx);
|
||||
purge_transaction_keyimages_from_blockchain(tx, true);
|
||||
|
|
@ -686,10 +688,11 @@ bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& t
|
|||
bool blockchain_storage::purge_block_data_from_blockchain(const block& b, size_t processed_tx_count)
|
||||
{
|
||||
uint64_t total_fee = 0;
|
||||
return purge_block_data_from_blockchain(b, processed_tx_count, total_fee);
|
||||
transactions_map onboard_transactions;
|
||||
return purge_block_data_from_blockchain(b, processed_tx_count, total_fee, onboard_transactions);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::purge_block_data_from_blockchain(const block& bl, size_t processed_tx_count, uint64_t& fee_total)
|
||||
bool blockchain_storage::purge_block_data_from_blockchain(const block& bl, size_t processed_tx_count, uint64_t& fee_total, transactions_map& onboard_transactions)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
fee_total = 0;
|
||||
|
|
@ -698,11 +701,13 @@ bool blockchain_storage::purge_block_data_from_blockchain(const block& bl, size_
|
|||
CHECK_AND_ASSERT_MES(processed_tx_count <= bl.tx_hashes.size(), false, "wrong processed_tx_count in purge_block_data_from_blockchain");
|
||||
for(size_t count = 0; count != processed_tx_count; count++)
|
||||
{
|
||||
res = purge_transaction_from_blockchain(bl.tx_hashes[(processed_tx_count -1)- count], fee) && res;
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
res = purge_transaction_from_blockchain(bl.tx_hashes[(processed_tx_count -1)- count], fee, tx) && res;
|
||||
fee_total += fee;
|
||||
onboard_transactions[bl.tx_hashes[(processed_tx_count - 1) - count]] = tx;
|
||||
}
|
||||
|
||||
res = purge_transaction_from_blockchain(get_transaction_hash(bl.miner_tx), fee) && res;
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
res = purge_transaction_from_blockchain(get_transaction_hash(bl.miner_tx), fee, tx) && res;
|
||||
return res;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -865,20 +870,22 @@ bool blockchain_storage::get_block_by_height(uint64_t h, block &blk) const
|
|||
// invalid.push_back(v.first);
|
||||
// }
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::rollback_blockchain_switching(std::list<block>& original_chain, size_t rollback_height)
|
||||
bool blockchain_storage::rollback_blockchain_switching(std::list<block_ws_txs>& original_chain, size_t rollback_height)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
//remove failed subchain
|
||||
for(size_t i = m_db_blocks.size()-1; i >=rollback_height; i--)
|
||||
{
|
||||
bool r = pop_block_from_blockchain();
|
||||
transactions_map ot;
|
||||
bool r = pop_block_from_blockchain(ot);
|
||||
CHECK_AND_ASSERT_MES(r, false, "PANIC!!! failed to remove block while chain switching during the rollback!");
|
||||
}
|
||||
//return back original chain
|
||||
BOOST_FOREACH(auto& bl, original_chain)
|
||||
BOOST_FOREACH(auto& oce, original_chain)
|
||||
{
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
bool r = handle_block_to_main_chain(bl, bvc);
|
||||
bvc.m_onboard_transactions.swap(oce.onboard_transactions);
|
||||
bool r = handle_block_to_main_chain(oce.b, bvc);
|
||||
CHECK_AND_ASSERT_MES(r && bvc.m_added_to_main_chain, false, "PANIC!!! failed to add (again) block while chain switching during the rollback!");
|
||||
}
|
||||
|
||||
|
|
@ -941,13 +948,15 @@ bool blockchain_storage::switch_to_alternative_blockchain(alt_chain_type& alt_ch
|
|||
);
|
||||
|
||||
//disconnecting old chain
|
||||
std::list<block> disconnected_chain;
|
||||
std::list<block_ws_txs> disconnected_chain;
|
||||
for(size_t i = m_db_blocks.size()-1; i >=split_height; i--)
|
||||
{
|
||||
block b = m_db_blocks[i]->bl;
|
||||
bool r = pop_block_from_blockchain();
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to remove block " << get_block_hash(b) << " @ " << get_block_height(b) << " on chain switching");
|
||||
disconnected_chain.push_front(b);
|
||||
disconnected_chain.push_front(block_ws_txs());
|
||||
block_ws_txs& bwt = disconnected_chain.front();
|
||||
bwt.b = m_db_blocks[i]->bl;
|
||||
bool r = pop_block_from_blockchain(bwt.onboard_transactions);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to remove block " << get_block_hash(bwt.b) << " @ " << get_block_height(bwt.b) << " on chain switching");
|
||||
|
||||
CHECK_AND_ASSERT_MES(validate_blockchain_prev_links(), false, "EPIC FAIL!");
|
||||
}
|
||||
|
||||
|
|
@ -956,6 +965,7 @@ bool blockchain_storage::switch_to_alternative_blockchain(alt_chain_type& alt_ch
|
|||
{
|
||||
auto ch_ent = *alt_ch_iter;
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
bvc.m_onboard_transactions = ch_ent->second.onboard_transactions;
|
||||
bool r = handle_block_to_main_chain(ch_ent->second.bl, bvc);
|
||||
if(!r || !bvc.m_added_to_main_chain)
|
||||
{
|
||||
|
|
@ -977,7 +987,8 @@ bool blockchain_storage::switch_to_alternative_blockchain(alt_chain_type& alt_ch
|
|||
for(auto& old_ch_ent : disconnected_chain)
|
||||
{
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
|
||||
bvc.m_onboard_transactions.swap(old_ch_ent.onboard_transactions);
|
||||
bool r = handle_alternative_block(old_ch_ent.b, get_block_hash(old_ch_ent.b), bvc);
|
||||
if(!r)
|
||||
{
|
||||
LOG_ERROR("Failed to push ex-main chain blocks to alternative chain ");
|
||||
|
|
@ -1347,11 +1358,11 @@ bool blockchain_storage::create_block_template(const create_block_template_param
|
|||
|
||||
CRITICAL_REGION_END();
|
||||
|
||||
size_t txs_size;
|
||||
uint64_t fee;
|
||||
size_t txs_size = 0;
|
||||
uint64_t fee = 0;
|
||||
bool block_filled = false;
|
||||
if (pcustom_fill_block_template_func == nullptr)
|
||||
block_filled = m_tx_pool.fill_block_template(b, pos, median_size, already_generated_coins, txs_size, fee, height);
|
||||
block_filled = m_tx_pool.fill_block_template(b, pos, median_size, already_generated_coins, txs_size, fee, height, params.explicit_txs);
|
||||
else
|
||||
block_filled = (*pcustom_fill_block_template_func)(b, pos, median_size, already_generated_coins, txs_size, fee, height);
|
||||
|
||||
|
|
@ -1601,6 +1612,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
|
||||
alt_block_extended_info abei = AUTO_VAL_INIT(abei);
|
||||
abei.bl = b;
|
||||
abei.onboard_transactions.swap(bvc.m_onboard_transactions);
|
||||
abei.timestamp = m_core_runtime_config.get_core_time();
|
||||
abei.height = alt_chain.size() ? it_prev->second.height + 1 : *ptr_main_prev + 1;
|
||||
CHECK_AND_ASSERT_MES_CUSTOM(coinbase_height == abei.height, false, bvc.m_verification_failed = true, "block coinbase height doesn't match with altchain height, declined");
|
||||
|
|
@ -1715,7 +1727,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
alt_chain.push_back(i_res.first);
|
||||
//check if difficulty bigger then in main chain
|
||||
|
||||
bvc.height_difference = get_top_block_height() >= abei.height ? get_top_block_height() - abei.height : 0;
|
||||
bvc.m_height_difference = get_top_block_height() >= abei.height ? get_top_block_height() - abei.height : 0;
|
||||
|
||||
crypto::hash proof = null_hash;
|
||||
std::stringstream ss_pow_pos_info;
|
||||
|
|
@ -1752,7 +1764,7 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
|||
bvc.m_verification_failed = true;
|
||||
return r;
|
||||
}
|
||||
bvc.added_to_altchain = true;
|
||||
bvc.m_added_to_altchain = true;
|
||||
|
||||
//protect ourself from altchains container flood
|
||||
if (m_alternative_chains.size() > m_core_runtime_config.max_alt_blocks)
|
||||
|
|
@ -4762,6 +4774,18 @@ wide_difficulty_type blockchain_storage::get_last_alt_x_block_cumulative_precise
|
|||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool get_tx_from_cache(const crypto::hash& tx_id, transactions_map& tx_cache, transaction& tx, size_t& blob_size, uint64_t& fee)
|
||||
{
|
||||
auto it = tx_cache.find(tx_id);
|
||||
if (it == tx_cache.end())
|
||||
return false;
|
||||
|
||||
tx = it->second;
|
||||
blob_size = get_object_blobsize(tx);
|
||||
fee = get_tx_fee(tx);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypto::hash& id, block_verification_context& bvc)
|
||||
{
|
||||
TIME_MEASURE_START_PD_MS(block_processing_time_0_ms);
|
||||
|
|
@ -4876,13 +4900,17 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
size_t tx_processed_count = 0;
|
||||
uint64_t fee_summary = 0;
|
||||
uint64_t burned_coins = 0;
|
||||
std::list<crypto::key_image> block_summary_kimages;
|
||||
|
||||
for(const crypto::hash& tx_id : bl.tx_hashes)
|
||||
{
|
||||
transaction tx;
|
||||
size_t blob_size = 0;
|
||||
uint64_t fee = 0;
|
||||
if(!m_tx_pool.take_tx(tx_id, tx, blob_size, fee))
|
||||
|
||||
bool taken_from_cache = get_tx_from_cache(tx_id, bvc.m_onboard_transactions, tx, blob_size, fee);
|
||||
bool taken_from_pool = m_tx_pool.take_tx(tx_id, tx, blob_size, fee);
|
||||
if(!taken_from_cache && !taken_from_pool)
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
|
|
@ -4891,6 +4919,15 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!validate_tx_semantic(tx, blob_size))
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id << " has at least one transaction with wrong semantic, tx_id: " << tx_id);
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
//add_block_as_invalid(bl, id);
|
||||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
append_per_block_increments_for_tx(tx, gindices);
|
||||
|
||||
//If we under checkpoints, ring signatures should be pruned
|
||||
|
|
@ -4905,9 +4942,12 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
{
|
||||
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);
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
m_tx_pool.add_transaction_to_black_list(tx);
|
||||
CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool");
|
||||
if (taken_from_pool)
|
||||
{
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
m_tx_pool.add_transaction_to_black_list(tx);
|
||||
CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool");
|
||||
}
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
add_block_as_invalid(bl, id);
|
||||
LOG_PRINT_L0("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
||||
|
|
@ -4925,10 +4965,13 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
if(!add_transaction_from_block(tx, tx_id, id, current_bc_size, actual_timestamp))
|
||||
{
|
||||
LOG_PRINT_L0("Block with id: " << id << " failed to add transaction to blockchain storage");
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
m_tx_pool.add_transaction_to_black_list(tx);
|
||||
CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool");
|
||||
if (taken_from_pool)
|
||||
{
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
bool add_res = m_tx_pool.add_tx(tx, tvc, true, true);
|
||||
m_tx_pool.add_transaction_to_black_list(tx);
|
||||
CHECK_AND_ASSERT_MES_NO_RET(add_res, "handle_block_to_main_chain: failed to add transaction back to transaction pool");
|
||||
}
|
||||
purge_block_data_from_blockchain(bl, tx_processed_count);
|
||||
bvc.m_verification_failed = true;
|
||||
return false;
|
||||
|
|
@ -4941,6 +4984,8 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
++tx_processed_count;
|
||||
if (fee)
|
||||
block_fees.push_back(fee);
|
||||
|
||||
read_keyimages_from_tx(tx, block_summary_kimages);
|
||||
}
|
||||
TIME_MEASURE_FINISH_PD(all_txs_insert_time_5);
|
||||
|
||||
|
|
@ -4975,8 +5020,6 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
if (is_pos_bl)
|
||||
bei.stake_hash = proof_hash;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//old style cumulative difficulty collecting
|
||||
|
|
@ -5114,17 +5157,17 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
|||
<< "/" << etc_stuff_6
|
||||
<< "))");
|
||||
|
||||
on_block_added(bei, id);
|
||||
on_block_added(bei, id, block_summary_kimages);
|
||||
|
||||
bvc.m_added_to_main_chain = true;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::on_block_added(const block_extended_info& bei, const crypto::hash& id)
|
||||
void blockchain_storage::on_block_added(const block_extended_info& bei, const crypto::hash& id, const std::list<crypto::key_image>& bsk)
|
||||
{
|
||||
update_next_comulative_size_limit();
|
||||
m_timestamps_median_cache.clear();
|
||||
m_tx_pool.on_blockchain_inc(bei.height, id);
|
||||
m_tx_pool.on_blockchain_inc(bei.height, id, bsk);
|
||||
|
||||
update_targetdata_cache_on_block_added(bei);
|
||||
|
||||
|
|
@ -5313,7 +5356,8 @@ bool blockchain_storage::truncate_blockchain(uint64_t to_height)
|
|||
uint64_t inital_height = get_current_blockchain_size();
|
||||
while (get_current_blockchain_size() > to_height)
|
||||
{
|
||||
pop_block_from_blockchain();
|
||||
transactions_map ot;
|
||||
pop_block_from_blockchain(ot);
|
||||
}
|
||||
CRITICAL_REGION_LOCAL(m_alternative_chains_lock);
|
||||
m_alternative_chains.clear();
|
||||
|
|
@ -6033,8 +6077,12 @@ bool blockchain_storage::validate_alt_block_txs(const block& b, const crypto::ha
|
|||
for (auto tx_id : b.tx_hashes)
|
||||
{
|
||||
std::shared_ptr<transaction> tx_ptr;
|
||||
CHECK_AND_ASSERT_MES(get_transaction_from_pool_or_db(tx_id, tx_ptr, split_height), false, "failed to get alt block tx " << tx_id << " with split_height == " << split_height);
|
||||
transaction& tx = *tx_ptr;
|
||||
auto it = abei.onboard_transactions.find(tx_id);
|
||||
if (it == abei.onboard_transactions.end())
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(get_transaction_from_pool_or_db(tx_id, tx_ptr, split_height), false, "failed to get alt block tx " << tx_id << " with split_height == " << split_height);
|
||||
}
|
||||
const transaction& tx = it == abei.onboard_transactions.end() ? *tx_ptr : it->second;
|
||||
CHECK_AND_ASSERT_MES(tx.signatures.size() == tx.vin.size(), false, "invalid tx: tx.signatures.size() == " << tx.signatures.size() << ", tx.vin.size() == " << tx.vin.size());
|
||||
for (size_t n = 0; n < tx.vin.size(); ++n)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ namespace currency
|
|||
|
||||
//date added to alt chain storage
|
||||
uint64_t timestamp;
|
||||
|
||||
//transactions associated with the block
|
||||
transactions_map onboard_transactions;
|
||||
};
|
||||
typedef std::unordered_map<crypto::hash, alt_block_extended_info> alt_chain_container;
|
||||
//typedef std::list<alt_chain_container::iterator> alt_chain_type;
|
||||
|
|
@ -543,10 +546,10 @@ namespace currency
|
|||
bool switch_to_alternative_blockchain(alt_chain_type& alt_chain);
|
||||
void purge_alt_block_txs_hashs(const block& b);
|
||||
void add_alt_block_txs_hashs(const block& b);
|
||||
bool pop_block_from_blockchain();
|
||||
bool pop_block_from_blockchain(transactions_map& onboard_transactions);
|
||||
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count);
|
||||
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count, uint64_t& fee);
|
||||
bool purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee);
|
||||
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count, uint64_t& fee, transactions_map& onboard_transactions);
|
||||
bool purge_transaction_from_blockchain(const crypto::hash& tx_id, uint64_t& fee, transaction& tx);
|
||||
bool purge_transaction_keyimages_from_blockchain(const transaction& tx, bool strict_check);
|
||||
wide_difficulty_type get_next_difficulty_for_alternative_chain(const alt_chain_type& alt_chain, block_extended_info& bei, bool pos) const;
|
||||
bool handle_block_to_main_chain(const block& bl, block_verification_context& bvc);
|
||||
|
|
@ -565,7 +568,7 @@ namespace currency
|
|||
bool get_transaction_from_pool_or_db(const crypto::hash& tx_id, std::shared_ptr<transaction>& tx_ptr, uint64_t min_allowed_block_height = 0) const;
|
||||
void get_last_n_x_blocks(uint64_t n, bool pos_blocks, std::list<std::shared_ptr<const block_extended_info>>& blocks) const;
|
||||
bool prevalidate_miner_transaction(const block& b, uint64_t height, bool pos)const;
|
||||
bool rollback_blockchain_switching(std::list<block>& original_chain, size_t rollback_height);
|
||||
bool rollback_blockchain_switching(std::list<block_ws_txs>& original_chain, size_t rollback_height);
|
||||
bool add_transaction_from_block(const transaction& tx, const crypto::hash& tx_id, const crypto::hash& bl_id, uint64_t bl_height, uint64_t timestamp);
|
||||
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);
|
||||
|
|
@ -578,7 +581,7 @@ namespace currency
|
|||
bool check_block_timestamp(std::vector<uint64_t> timestamps, const block& b)const;
|
||||
std::vector<uint64_t> get_last_n_blocks_timestamps(size_t n)const;
|
||||
const std::vector<txin_etc_details_v>& get_txin_etc_options(const txin_v& in)const;
|
||||
void on_block_added(const block_extended_info& bei, const crypto::hash& id);
|
||||
void on_block_added(const block_extended_info& bei, const crypto::hash& id, const std::list<crypto::key_image>& bsk);
|
||||
void on_block_removed(const block_extended_info& bei);
|
||||
void update_targetdata_cache_on_block_added(const block_extended_info& bei);
|
||||
void update_targetdata_cache_on_block_removed(const block_extended_info& bei);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include <unordered_map>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
|
||||
|
|
@ -145,6 +146,12 @@ namespace currency
|
|||
uint64_t height;
|
||||
};
|
||||
|
||||
|
||||
typedef std::unordered_map<crypto::hash, transaction> transactions_map;
|
||||
|
||||
struct block_ws_txs
|
||||
{
|
||||
block b;
|
||||
transactions_map onboard_transactions;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ using namespace epee;
|
|||
#include "currency_format_utils.h"
|
||||
#include "misc_language.h"
|
||||
#include "string_coding.h"
|
||||
#include "tx_semantic_validation.h"
|
||||
|
||||
#define MINIMUM_REQUIRED_FREE_SPACE_BYTES (1024 * 1024 * 100)
|
||||
|
||||
|
|
@ -185,13 +186,15 @@ namespace currency
|
|||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool kept_by_block)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(!kept_by_block, false, "Transaction associated with block came throw handle_incoming_tx!(not allowed anymore)");
|
||||
|
||||
tvc = boost::value_initialized<tx_verification_context>();
|
||||
//want to process all transactions sequentially
|
||||
TIME_MEASURE_START_MS(wait_lock_time);
|
||||
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
|
||||
TIME_MEASURE_FINISH_MS(wait_lock_time);
|
||||
|
||||
if(tx_blob.size() > get_max_tx_size())
|
||||
if(tx_blob.size() > CURRENCY_MAX_TRANSACTION_BLOB_SIZE)
|
||||
{
|
||||
LOG_PRINT_L0("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected");
|
||||
tvc.m_verification_failed = true;
|
||||
|
|
@ -210,19 +213,10 @@ namespace currency
|
|||
TIME_MEASURE_FINISH_MS(parse_tx_time);
|
||||
|
||||
|
||||
TIME_MEASURE_START_MS(check_tx_syntax_time);
|
||||
if(!check_tx_syntax(tx))
|
||||
{
|
||||
LOG_PRINT_L0("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
TIME_MEASURE_FINISH_MS(check_tx_syntax_time);
|
||||
|
||||
TIME_MEASURE_START_MS(check_tx_semantic_time);
|
||||
if(!check_tx_semantic(tx, kept_by_block))
|
||||
if(!validate_tx_semantic(tx, tx_blob.size()))
|
||||
{
|
||||
LOG_PRINT_L0("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
|
||||
LOG_PRINT_L0("WRONG TRANSACTION SEMANTICS, Failed to check tx " << tx_hash << " semantic, rejected");
|
||||
tvc.m_verification_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -243,7 +237,6 @@ namespace currency
|
|||
}
|
||||
LOG_PRINT_L2("[CORE HANDLE_INCOMING_TX]: timing " << wait_lock_time
|
||||
<< "/" << parse_tx_time
|
||||
<< "/" << check_tx_syntax_time
|
||||
<< "/" << check_tx_semantic_time
|
||||
<< "/" << add_new_tx_time);
|
||||
return r;
|
||||
|
|
@ -296,88 +289,9 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::check_tx_semantic(const transaction& tx, bool kept_by_block)
|
||||
{
|
||||
if(!tx.vin.size())
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!check_inputs_types_supported(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("unsupported input types for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!check_outs_valid(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!check_money_overflow(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t amount_in = 0;
|
||||
get_inputs_money_amount(tx, amount_in);
|
||||
uint64_t amount_out = get_outs_money_amount(tx);
|
||||
|
||||
if(amount_in < amount_out)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!kept_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_comulative_blocksize_limit() - CURRENCY_COINBASE_BLOB_RESERVED_SIZE)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has too big size " << get_object_blobsize(tx) << ", expected no bigger than " << m_blockchain_storage.get_current_comulative_blocksize_limit() - CURRENCY_COINBASE_BLOB_RESERVED_SIZE);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if tx use different key images
|
||||
if(!check_tx_inputs_keyimages_diff(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx inputs have the same key images");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!check_tx_extra(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has wrong extra, rejected");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::check_tx_extra(const transaction& tx)
|
||||
{
|
||||
tx_extra_info ei = AUTO_VAL_INIT(ei);
|
||||
bool r = parse_and_validate_tx_extra(tx, ei);
|
||||
if(!r)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::check_tx_inputs_keyimages_diff(const transaction& tx)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
|
||||
if (!ki.insert(tokey_in.k_image).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::add_new_tx(const transaction& tx, tx_verification_context& tvc, bool kept_by_block)
|
||||
{
|
||||
|
|
@ -419,6 +333,11 @@ namespace currency
|
|||
return m_blockchain_storage.create_block_template(b, adr, stakeholder_address, diffic, height, ex_nonce, pos, pe);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_block_template(const create_block_template_params& params, create_block_template_response& resp)
|
||||
{
|
||||
return m_blockchain_storage.create_block_template(params, resp);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const
|
||||
{
|
||||
return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
|
||||
|
|
@ -589,7 +508,6 @@ namespace currency
|
|||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate)
|
||||
{
|
||||
bvc = AUTO_VAL_INIT_T(block_verification_context);
|
||||
block b = AUTO_VAL_INIT(b);
|
||||
if (!parse_block(block_blob, b, bvc))
|
||||
{
|
||||
|
|
@ -627,11 +545,6 @@ namespace currency
|
|||
{
|
||||
return parse_and_validate_tx_from_blob(blob, tx, tx_hash);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::check_tx_syntax(const transaction& tx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool core::get_pool_transactions(std::list<transaction>& txs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ namespace currency
|
|||
|
||||
//-------------------- i_miner_handler -----------------------
|
||||
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr);
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
|
||||
virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp);
|
||||
bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry());
|
||||
|
||||
miner& get_miner(){ return m_miner; }
|
||||
static void init_options(boost::program_options::options_description& desc);
|
||||
|
|
@ -118,12 +119,6 @@ namespace currency
|
|||
bool add_new_block(const block& b, block_verification_context& bvc);
|
||||
bool load_state_data();
|
||||
bool parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, const blobdata& blob);
|
||||
bool check_tx_extra(const transaction& tx);
|
||||
|
||||
bool check_tx_syntax(const transaction& tx);
|
||||
//check correct values, amounts and all lightweight checks not related with database
|
||||
bool check_tx_semantic(const transaction& tx, bool kept_by_block);
|
||||
//check if tx already in memory pool or in main blockchain
|
||||
|
||||
bool is_key_image_spent(const crypto::key_image& key_im);
|
||||
|
||||
|
|
@ -132,7 +127,6 @@ namespace currency
|
|||
bool update_miner_block_template();
|
||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||
bool on_update_blocktemplate_interval();
|
||||
bool check_tx_inputs_keyimages_diff(const transaction& tx);
|
||||
|
||||
void notify_blockchain_update_listeners();
|
||||
|
||||
|
|
|
|||
|
|
@ -2434,11 +2434,6 @@ namespace currency
|
|||
return CURRENCY_MAX_BLOCK_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_max_tx_size()
|
||||
{
|
||||
return CURRENCY_MAX_TRANSACTION_BLOB_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t get_base_block_reward(bool is_pos, const boost::multiprecision::uint128_t& already_generated_coins, uint64_t height)
|
||||
{
|
||||
if (!height)
|
||||
|
|
|
|||
|
|
@ -193,6 +193,16 @@ namespace currency
|
|||
return get_object_blobsize(t, tx_blob_size);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
size_t get_objects_blobsize(const std::list<transaction>& ls)
|
||||
{
|
||||
size_t total = 0;
|
||||
for (const auto& tx : ls)
|
||||
{
|
||||
total += get_object_blobsize(tx);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size)
|
||||
{
|
||||
size_t tx_blob_size = prefix_blob_size;
|
||||
|
|
@ -246,5 +256,20 @@ namespace currency
|
|||
{
|
||||
return t_serializable_object_to_blob(tx, b_blob);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
|
||||
if (!ki.insert(tokey_in.k_image).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -92,7 +92,7 @@ namespace currency
|
|||
inline void set_tx_flags(transaction& tx, uint64_t v) { set_tx_x_detail<etc_tx_details_flags>(tx, v); }
|
||||
inline void set_tx_expiration_time(transaction& tx, uint64_t v) { set_tx_x_detail<etc_tx_details_expiration_time>(tx, v); }
|
||||
account_public_address get_crypt_address_from_destinations(const account_keys& sender_account_keys, const std::vector<tx_destination_entry>& destinations);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
bool is_tx_expired(const transaction& tx, uint64_t expiration_ts_median);
|
||||
uint64_t get_burned_amount(const transaction& tx);
|
||||
|
|
@ -104,7 +104,11 @@ namespace currency
|
|||
bool get_transaction_hash(const transaction& t, crypto::hash& res);
|
||||
bool get_transaction_hash(const transaction& t, crypto::hash& res, uint64_t& blob_size);
|
||||
size_t get_object_blobsize(const transaction& t);
|
||||
size_t get_objects_blobsize(const std::list<transaction>& ls);
|
||||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
bool read_keyimages_from_tx(const transaction& tx, std::list<crypto::key_image>& kil);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace currency
|
|||
struct i_miner_handler
|
||||
{
|
||||
virtual bool handle_block_found(const block& b, block_verification_context* p_verification_result = nullptr) = 0;
|
||||
virtual bool get_block_template(const create_block_template_params& params, create_block_template_response& resp) = 0;
|
||||
virtual bool get_block_template(block& b, const account_public_address& adr, const account_public_address& stakeholder_address, wide_difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce, bool pos = false, const pos_entry& pe = pos_entry()) = 0;
|
||||
protected:
|
||||
~i_miner_handler(){};
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ namespace currency
|
|||
m_db_transactions(m_db),
|
||||
m_db_black_tx_list(m_db),
|
||||
m_db_solo_options(m_db),
|
||||
m_db_key_images_set(m_db),
|
||||
// m_db_key_images_set(m_db),
|
||||
m_db_alias_names(m_db),
|
||||
m_db_alias_addresses(m_db),
|
||||
m_db_storage_major_compatibility_version(TRANSACTION_POOL_OPTIONS_ID_STORAGE_MAJOR_COMPATIBILITY_VERSION, m_db_solo_options)
|
||||
|
|
@ -255,7 +255,7 @@ namespace currency
|
|||
td.receive_time = get_core_time();
|
||||
|
||||
m_db_transactions.set(id, td);
|
||||
on_tx_add(tx, kept_by_block);
|
||||
on_tx_add(id, tx, kept_by_block);
|
||||
|
||||
TIME_MEASURE_FINISH_PD(update_db_time);
|
||||
return true;
|
||||
|
|
@ -385,7 +385,7 @@ namespace currency
|
|||
blob_size = txe_tr->blob_size;
|
||||
fee = txe_tr->fee;
|
||||
m_db_transactions.erase(id);
|
||||
on_tx_remove(tx, txe_tr->kept_by_block);
|
||||
on_tx_remove(id, tx, txe_tr->kept_by_block);
|
||||
set_taken(id);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -472,7 +472,7 @@ namespace currency
|
|||
for (auto& e : to_delete)
|
||||
{
|
||||
m_db_transactions.erase(e.hash);
|
||||
on_tx_remove(e.tx, e.kept_by_block);
|
||||
on_tx_remove(e.hash, e.tx, e.kept_by_block);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -613,8 +613,10 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id)
|
||||
bool tx_memory_pool::on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id, const std::list<crypto::key_image>& bsk)
|
||||
{
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
|
|
@ -694,36 +696,33 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::insert_key_images(const transaction& tx, bool kept_by_block)
|
||||
bool tx_memory_pool::insert_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, true);//should never fail
|
||||
uint64_t count = 0;
|
||||
auto ki_entry_ptr = m_db_key_images_set.get(tokey_in.k_image);
|
||||
if (ki_entry_ptr.get())
|
||||
count = *ki_entry_ptr;
|
||||
uint64_t count_before = count;
|
||||
++count;
|
||||
m_db_key_images_set.set(tokey_in.k_image, count);
|
||||
LOG_PRINT_L2("tx pool: key image added: " << tokey_in.k_image << ", from tx " << get_transaction_hash(tx) << ", counter: " << count_before << " -> " << count);
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
auto& id_set = m_key_images[tokey_in.k_image];
|
||||
size_t sz_before = id_set.size();
|
||||
id_set.insert(tx_id);
|
||||
LOG_PRINT_L2("tx pool: key image added: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << sz_before << " -> " << id_set.size());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::on_tx_add(const transaction& tx, bool kept_by_block)
|
||||
bool tx_memory_pool::on_tx_add(crypto::hash tx_id, const transaction& tx, bool kept_by_block)
|
||||
{
|
||||
insert_key_images(tx, kept_by_block);
|
||||
insert_key_images(tx_id, tx, kept_by_block);
|
||||
insert_alias_info(tx);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::on_tx_remove(const transaction& tx, bool kept_by_block)
|
||||
bool tx_memory_pool::on_tx_remove(const crypto::hash &id, const transaction& tx, bool kept_by_block)
|
||||
{
|
||||
remove_key_images(tx, kept_by_block);
|
||||
remove_key_images(id, tx, kept_by_block);
|
||||
remove_alias_info(tx);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -757,34 +756,33 @@ namespace currency
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::remove_key_images(const transaction& tx, bool kept_by_block)
|
||||
bool tx_memory_pool::remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
for(const auto& in : tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, true);//should never fail
|
||||
uint64_t count = 0;
|
||||
auto ki_entry_ptr = m_db_key_images_set.get(tokey_in.k_image);
|
||||
if (!ki_entry_ptr.get() || *ki_entry_ptr == 0)
|
||||
{
|
||||
LOG_ERROR("INTERNAL_ERROR: for tx " << get_transaction_hash(tx) << " key image " << tokey_in.k_image << " not found");
|
||||
continue;
|
||||
}
|
||||
count = *ki_entry_ptr;
|
||||
uint64_t count_before = count;
|
||||
--count;
|
||||
if (count)
|
||||
m_db_key_images_set.set(tokey_in.k_image, count);
|
||||
else
|
||||
m_db_key_images_set.erase(tokey_in.k_image);
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << tokey_in.k_image << ", from tx " << get_transaction_hash(tx) << ", counter: " << count_before << " -> " << count);
|
||||
{
|
||||
const txin_to_key& tokey_in = boost::get<txin_to_key>(in);
|
||||
|
||||
auto it_map = epee::misc_utils::it_get_or_insert_value_initialized(m_key_images, tokey_in.k_image);
|
||||
auto& id_set = it_map->second;
|
||||
size_t count_before = id_set.size();
|
||||
auto it_set = id_set.find(tx_id);
|
||||
if(it_set != id_set.end())
|
||||
id_set.erase(it_set);
|
||||
|
||||
size_t count_after = id_set.size();
|
||||
if (id_set.size() == 0)
|
||||
m_key_images.erase(it_map);
|
||||
|
||||
LOG_PRINT_L2("tx pool: key image removed: " << tokey_in.k_image << ", from tx " << tx_id << ", counter: " << count_before << " -> " << count_after);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::get_key_images_from_tx_pool(std::unordered_set<crypto::key_image>& key_images) const
|
||||
bool tx_memory_pool::get_key_images_from_tx_pool(key_image_cache& key_images) const
|
||||
{
|
||||
|
||||
m_db_transactions.enumerate_items([&](uint64_t i, const crypto::hash& h, const tx_details &tx_entry)
|
||||
|
|
@ -793,7 +791,7 @@ namespace currency
|
|||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
key_images.insert(boost::get<txin_to_key>(in).k_image);
|
||||
key_images[boost::get<txin_to_key>(in).k_image].insert(h);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -804,9 +802,9 @@ namespace currency
|
|||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::have_tx_keyimg_as_spent(const crypto::key_image& key_im)const
|
||||
{
|
||||
|
||||
auto ptr = m_db_key_images_set.find(key_im);
|
||||
if (ptr)
|
||||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
auto it = m_key_images.find(key_im);
|
||||
if (it != m_key_images.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -826,9 +824,9 @@ namespace currency
|
|||
|
||||
m_db.begin_transaction();
|
||||
m_db_transactions.clear();
|
||||
m_db_key_images_set.clear();
|
||||
m_db.commit_transaction();
|
||||
// should m_db_black_tx_list be cleared here?
|
||||
CIRITCAL_OPERATION(m_key_images,clear());
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
void tx_memory_pool::clear()
|
||||
|
|
@ -836,8 +834,8 @@ namespace currency
|
|||
m_db.begin_transaction();
|
||||
m_db_transactions.clear();
|
||||
m_db_black_tx_list.clear();
|
||||
m_db_key_images_set.clear();
|
||||
m_db.commit_transaction();
|
||||
CIRITCAL_OPERATION(m_key_images,clear());
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::is_transaction_ready_to_go(tx_details& txd, const crypto::hash& id)const
|
||||
|
|
@ -987,7 +985,9 @@ namespace currency
|
|||
const boost::multiprecision::uint128_t& already_generated_coins,
|
||||
size_t &total_size,
|
||||
uint64_t &fee,
|
||||
uint64_t height)
|
||||
uint64_t height,
|
||||
const std::list<transaction>& explicit_txs
|
||||
)
|
||||
{
|
||||
LOCAL_READONLY_TRANSACTION();
|
||||
//typedef transactions_container::value_type txv;
|
||||
|
|
@ -998,8 +998,8 @@ namespace currency
|
|||
txs_v.reserve(m_db_transactions.size());
|
||||
std::vector<txv*> txs;
|
||||
|
||||
//std::transform(m_transactions.begin(), m_transactions.end(), txs.begin(), [](txv &a) -> txv * { return &a; });
|
||||
//keep getting it as a values cz db items cache will keep it as unserialied object stored by shared ptrs
|
||||
|
||||
//keep getting it as a values cz db items cache will keep it as unserialised object stored by shared ptrs
|
||||
m_db_transactions.enumerate_keys([&](uint64_t i, crypto::hash& k){txs_v.resize(i + 1); txs_v[i].first = k; return true;});
|
||||
txs.resize(txs_v.size(), nullptr);
|
||||
|
||||
|
|
@ -1024,7 +1024,9 @@ namespace currency
|
|||
return a_ > b_;
|
||||
});
|
||||
|
||||
size_t current_size = 0;
|
||||
|
||||
size_t explicit_total_size = get_objects_blobsize(explicit_txs);
|
||||
size_t current_size = explicit_total_size;
|
||||
uint64_t current_fee = 0;
|
||||
uint64_t best_money;
|
||||
if (!get_block_reward(pos, median_size, CURRENCY_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, best_money, height)) {
|
||||
|
|
@ -1133,6 +1135,12 @@ namespace currency
|
|||
}
|
||||
}
|
||||
}
|
||||
// add explicit transactions
|
||||
for (const auto& tx : explicit_txs)
|
||||
{
|
||||
fee += get_tx_fee(tx);
|
||||
bl.tx_hashes.push_back(get_transaction_hash(tx));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
|
|
@ -1184,8 +1192,8 @@ namespace currency
|
|||
|
||||
res = m_db_transactions.init(TRANSACTION_POOL_CONTAINER_TRANSACTIONS);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
|
||||
res = m_db_key_images_set.init(TRANSACTION_POOL_CONTAINER_KEY_IMAGES);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
|
||||
// res = m_db_key_images_set.init(TRANSACTION_POOL_CONTAINER_KEY_IMAGES);
|
||||
// CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
|
||||
res = m_db_black_tx_list.init(TRANSACTION_POOL_CONTAINER_BLACK_TX_LIST);
|
||||
CHECK_AND_ASSERT_MES(res, false, "Unable to init db container");
|
||||
res = m_db_alias_names.init(TRANSACTION_POOL_CONTAINER_ALIAS_NAMES);
|
||||
|
|
@ -1211,7 +1219,7 @@ namespace currency
|
|||
{
|
||||
LOG_PRINT_L1("DB at " << db_folder_path << " is about to be deleted and re-created...");
|
||||
m_db_transactions.deinit();
|
||||
m_db_key_images_set.deinit();
|
||||
// m_db_key_images_set.deinit();
|
||||
m_db_black_tx_list.deinit();
|
||||
m_db_alias_names.deinit();
|
||||
m_db_alias_addresses.deinit();
|
||||
|
|
@ -1243,9 +1251,17 @@ namespace currency
|
|||
});
|
||||
LOG_PRINT_L2(ss.str());
|
||||
}
|
||||
|
||||
load_keyimages_cache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::load_keyimages_cache()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_key_images_lock);
|
||||
return get_key_images_from_tx_pool(m_key_images);
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::deinit()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ namespace currency
|
|||
epee::math_helper::average<uint64_t, 5> db_commit_time;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<crypto::key_image, std::set<crypto::hash>> key_image_cache;
|
||||
|
||||
tx_memory_pool(blockchain_storage& bchs, i_currency_protocol* pprotocol);
|
||||
bool add_tx(const transaction &tx, const crypto::hash &id, uint64_t blob_size, tx_verification_context& tvc, bool kept_by_block, bool from_core = false);
|
||||
|
|
@ -99,7 +100,7 @@ namespace currency
|
|||
|
||||
bool check_tx_multisig_ins_and_outs(const transaction& tx, bool check_against_pool_txs)const;
|
||||
|
||||
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id);
|
||||
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id, const std::list<crypto::key_image>& bsk);
|
||||
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id);
|
||||
bool on_finalize_db_transaction();
|
||||
bool add_transaction_to_black_list(const transaction& tx);
|
||||
|
|
@ -117,7 +118,7 @@ namespace currency
|
|||
// load/store operations
|
||||
bool init(const std::string& config_folder, const boost::program_options::variables_map& vm);
|
||||
bool deinit();
|
||||
bool fill_block_template(block &bl, bool pos, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height);
|
||||
bool fill_block_template(block &bl, bool pos, size_t median_size, const boost::multiprecision::uint128_t& already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t height, const std::list<transaction>& explicit_txs);
|
||||
bool get_transactions(std::list<transaction>& txs) const;
|
||||
bool get_all_transactions_details(std::list<tx_rpc_extended_info>& txs)const;
|
||||
bool get_all_transactions_brief_details(std::list<tx_rpc_brief_info>& txs)const;
|
||||
|
|
@ -139,10 +140,10 @@ namespace currency
|
|||
bool remove_stuck_transactions(); // made public to be called from coretests
|
||||
|
||||
private:
|
||||
bool on_tx_add(const transaction& tx, bool kept_by_block);
|
||||
bool on_tx_remove(const transaction& tx, bool kept_by_block);
|
||||
bool insert_key_images(const transaction& tx, bool kept_by_block);
|
||||
bool remove_key_images(const transaction& tx, bool kept_by_block);
|
||||
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);
|
||||
bool insert_key_images(const crypto::hash& tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool remove_key_images(const crypto::hash &tx_id, const transaction& tx, bool kept_by_block);
|
||||
bool insert_alias_info(const transaction& tx);
|
||||
bool remove_alias_info(const transaction& tx);
|
||||
|
||||
|
|
@ -150,16 +151,15 @@ namespace currency
|
|||
void store_db_solo_options_values();
|
||||
bool is_transaction_ready_to_go(tx_details& txd, const crypto::hash& id)const;
|
||||
bool validate_alias_info(const transaction& tx, bool is_in_block)const;
|
||||
bool get_key_images_from_tx_pool(std::unordered_set<crypto::key_image>& key_images)const;
|
||||
//bool push_alias_info(const transaction& tx);
|
||||
//bool pop_alias_info(const transaction& tx);
|
||||
bool get_key_images_from_tx_pool(key_image_cache& key_images) const;
|
||||
bool check_is_taken(const crypto::hash& id) const;
|
||||
void set_taken(const crypto::hash& id);
|
||||
void reset_all_taken();
|
||||
bool load_keyimages_cache();
|
||||
|
||||
typedef tools::db::cached_key_value_accessor<crypto::hash, tx_details, true, false> transactions_container;
|
||||
typedef tools::db::cached_key_value_accessor<crypto::hash, bool, false, false> hash_container;
|
||||
typedef tools::db::cached_key_value_accessor<crypto::key_image, uint64_t, false, false> key_images_container;
|
||||
//typedef tools::db::cached_key_value_accessor<crypto::key_image, uint64_t, false, false> key_images_container;
|
||||
typedef tools::db::cached_key_value_accessor<uint64_t, uint64_t, false, true> solo_options_container;
|
||||
typedef tools::db::cached_key_value_accessor<std::string, bool, false, false> aliases_container;
|
||||
typedef tools::db::cached_key_value_accessor<account_public_address, bool, false, false> address_to_aliases_container;
|
||||
|
|
@ -172,7 +172,7 @@ namespace currency
|
|||
|
||||
transactions_container m_db_transactions;
|
||||
hash_container m_db_black_tx_list;
|
||||
key_images_container m_db_key_images_set;
|
||||
//key_images_container m_db_key_images_set;
|
||||
aliases_container m_db_alias_names;
|
||||
address_to_aliases_container m_db_alias_addresses;
|
||||
solo_options_container m_db_solo_options;
|
||||
|
|
@ -189,6 +189,9 @@ namespace currency
|
|||
//in memory containers
|
||||
mutable epee::critical_section m_taken_txs_lock;
|
||||
std::unordered_set<crypto::hash> m_taken_txs;
|
||||
|
||||
mutable epee::critical_section m_key_images_lock;
|
||||
key_image_cache m_key_images;
|
||||
mutable epee::critical_section m_remove_stuck_txs_lock;
|
||||
|
||||
|
||||
|
|
|
|||
94
src/currency_core/tx_semantic_validation.cpp
Normal file
94
src/currency_core/tx_semantic_validation.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
||||
|
||||
#include "tx_semantic_validation.h"
|
||||
#include "currency_format_utils.h"
|
||||
|
||||
namespace currency
|
||||
{
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool check_tx_extra(const transaction& tx)
|
||||
{
|
||||
tx_extra_info ei = AUTO_VAL_INIT(ei);
|
||||
bool r = parse_and_validate_tx_extra(tx, ei);
|
||||
if (!r)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool check_tx_inputs_keyimages_diff(const transaction& tx)
|
||||
{
|
||||
std::unordered_set<crypto::key_image> ki;
|
||||
BOOST_FOREACH(const auto& in, tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(txin_to_key))
|
||||
{
|
||||
CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false);
|
||||
if (!ki.insert(tokey_in.k_image).second)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool validate_tx_semantic(const transaction& tx, size_t tx_block_size)
|
||||
{
|
||||
if (!tx.vin.size())
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_inputs_types_supported(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("unsupported input types for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_outs_valid(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_money_overflow(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t amount_in = 0;
|
||||
get_inputs_money_amount(tx, amount_in);
|
||||
uint64_t amount_out = get_outs_money_amount(tx);
|
||||
|
||||
if (amount_in < amount_out)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tx_block_size >= CURRENCY_MAX_TRANSACTION_BLOB_SIZE)
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has too big size " << tx_block_size << ", expected no bigger than " << CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
//check if tx use different key images
|
||||
if (!check_tx_inputs_keyimages_diff(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx inputs have the same key images");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!check_tx_extra(tx))
|
||||
{
|
||||
LOG_PRINT_RED_L0("tx has wrong extra, rejected");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
16
src/currency_core/tx_semantic_validation.h
Normal file
16
src/currency_core/tx_semantic_validation.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2018-2019 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "currency_format_utils_transactions.h"
|
||||
|
||||
|
||||
namespace currency
|
||||
{
|
||||
//check correct values, amounts and all lightweight checks not related with database
|
||||
bool validate_tx_semantic(const transaction& tx, size_t tx_block_size);
|
||||
}
|
||||
|
|
@ -25,7 +25,11 @@ namespace currency
|
|||
bool m_verification_failed; //bad block, should drop connection
|
||||
bool m_marked_as_orphaned;
|
||||
bool m_already_exists;
|
||||
bool added_to_altchain;
|
||||
uint64_t height_difference;
|
||||
bool m_added_to_altchain;
|
||||
uint64_t m_height_difference;
|
||||
//this is work like a first-level cache for transactions while block is getting handled. It lets transactions
|
||||
//associated with the block to get handled directly to core without being handled by tx_pool(which makes full
|
||||
//inputs validation, including signatures check)
|
||||
transactions_map m_onboard_transactions;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,14 +305,22 @@ namespace currency
|
|||
//now actually process block
|
||||
for(auto tx_blob_it = arg.b.txs.begin(); tx_blob_it!=arg.b.txs.end();tx_blob_it++)
|
||||
{
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
m_core.handle_incoming_tx(*tx_blob_it, tvc, true);
|
||||
if(tvc.m_verification_failed)
|
||||
if (tx_blob_it->size() > CURRENCY_MAX_TRANSACTION_BLOB_SIZE)
|
||||
{
|
||||
LOG_PRINT_L0("Block verification failed: transaction verification failed, dropping connection");
|
||||
LOG_ERROR("WRONG TRANSACTION BLOB, too big size " << tx_blob_it->size() << ", rejected");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
|
||||
crypto::hash tx_hash = null_hash;
|
||||
transaction tx;
|
||||
if (!parse_and_validate_tx_from_blob(*tx_blob_it, tx, tx_hash))
|
||||
{
|
||||
LOG_ERROR("WRONG TRANSACTION BLOB, Failed to parse, rejected");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
bvc.m_onboard_transactions[tx_hash] = tx;
|
||||
}
|
||||
|
||||
m_core.pause_mine();
|
||||
|
|
@ -327,10 +335,10 @@ namespace currency
|
|||
LOG_PRINT_GREEN("[HANDLE]NOTIFY_NEW_BLOCK EXTRA " << block_id
|
||||
<< " bvc.m_added_to_main_chain=" << bvc.m_added_to_main_chain
|
||||
//<< ", prevalidate_result=" << prevalidate_relayed
|
||||
<< ", bvc.added_to_altchain=" << bvc.added_to_altchain
|
||||
<< ", bvc.added_to_altchain=" << bvc.m_added_to_altchain
|
||||
<< ", bvc.m_marked_as_orphaned=" << bvc.m_marked_as_orphaned, LOG_LEVEL_2);
|
||||
|
||||
if (bvc.m_added_to_main_chain || (bvc.added_to_altchain && bvc.height_difference < 2))
|
||||
if (bvc.m_added_to_main_chain || (bvc.m_added_to_altchain && bvc.m_height_difference < 2))
|
||||
{
|
||||
if (true/*!prevalidate_relayed*/)
|
||||
{
|
||||
|
|
@ -521,27 +529,36 @@ namespace currency
|
|||
{
|
||||
CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Blocks processing interrupted, connection dropped");
|
||||
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
//process transactions
|
||||
TIME_MEASURE_START(transactions_process_time);
|
||||
for (const auto& tx_blob : block_entry.txs)
|
||||
{
|
||||
CHECK_STOP_FLAG__DROP_AND_RETURN_IF_SET(1, "Block txs processing interrupted, connection dropped");
|
||||
|
||||
tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
m_core.handle_incoming_tx(tx_blob, tvc, true);
|
||||
if(tvc.m_verification_failed)
|
||||
crypto::hash tx_id = null_hash;
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_id))
|
||||
{
|
||||
LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
|
||||
LOG_ERROR_CCONTEXT("failed to parse tx: "
|
||||
<< string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
||||
m_p2p->drop_connection(context);
|
||||
return 1;
|
||||
}
|
||||
bvc.m_onboard_transactions[tx_id] = tx;
|
||||
// tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
// m_core.handle_incoming_tx(tx_blob, tvc, true);
|
||||
// if(tvc.m_verification_failed)
|
||||
// {
|
||||
// LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
|
||||
// << string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
||||
// m_p2p->drop_connection(context);
|
||||
// return 1;
|
||||
// }
|
||||
}
|
||||
TIME_MEASURE_FINISH(transactions_process_time);
|
||||
|
||||
//process block
|
||||
TIME_MEASURE_START(block_process_time);
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
|
||||
m_core.handle_incoming_block(block_entry.block, bvc, false);
|
||||
if (count > 2 && bvc.m_already_exists)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,11 @@ namespace tools
|
|||
return m_rpc.on_submitblock(req, rsp, m_err_stub, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_SUBMITBLOCK2(const currency::COMMAND_RPC_SUBMITBLOCK2::request& req, currency::COMMAND_RPC_SUBMITBLOCK2::response& rsp) override
|
||||
{
|
||||
return m_rpc.on_submitblock2(req, rsp, m_err_stub, m_cntxt_stub);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool call_COMMAND_RPC_GET_POS_MINING_DETAILS(const currency::COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, currency::COMMAND_RPC_GET_POS_MINING_DETAILS::response& rsp) override
|
||||
{
|
||||
return m_rpc.on_get_pos_mining_details(req, rsp, m_cntxt_stub);
|
||||
|
|
|
|||
|
|
@ -383,12 +383,12 @@ public:
|
|||
struct get_recent_transfers_request
|
||||
{
|
||||
uint64_t wallet_id;
|
||||
uint64_t offest;
|
||||
uint64_t offset;
|
||||
uint64_t count;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(wallet_id)
|
||||
KV_SERIALIZE(offest)
|
||||
KV_SERIALIZE(offset)
|
||||
KV_SERIALIZE(count)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -277,14 +277,14 @@ namespace nodetool
|
|||
#ifndef TESTNET
|
||||
//TODO:
|
||||
//ADD_HARDCODED_SEED_NODE(std::string("0.0.0.0:") + std::to_string(P2P_DEFAULT_PORT));
|
||||
ADD_HARDCODED_SEED_NODE("95.217.43.225:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("94.130.137.230:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("95.217.42.247:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("94.130.160.115:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("195.201.107.230:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("95.217.46.49:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("159.69.76.144:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("144.76.183.143:", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("95.217.43.225", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("94.130.137.230", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("95.217.42.247", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("94.130.160.115", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("195.201.107.230", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("95.217.46.49", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("159.69.76.144", P2P_DEFAULT_PORT);
|
||||
ADD_HARDCODED_SEED_NODE("144.76.183.143", P2P_DEFAULT_PORT);
|
||||
#else
|
||||
//TODO:
|
||||
ADD_HARDCODED_SEED_NODE("95.217.43.225", P2P_DEFAULT_PORT);
|
||||
|
|
|
|||
|
|
@ -793,28 +793,45 @@ namespace currency
|
|||
return false;
|
||||
}
|
||||
|
||||
block b = AUTO_VAL_INIT(b);
|
||||
wide_difficulty_type dt = 0;
|
||||
currency::pos_entry pe = AUTO_VAL_INIT(pe);
|
||||
pe.amount = req.pos_amount;
|
||||
pe.index = req.pos_index;
|
||||
pe.stake_unlock_time = req.stake_unlock_time;
|
||||
//pe.keyimage key image will be set in the wallet
|
||||
//pe.wallet_index is not included in serialization map, TODO: refactoring here
|
||||
|
||||
if (!m_core.get_block_template(b, miner_address, stakeholder_address, dt, res.height, req.extra_text, req.pos_block, pe))
|
||||
create_block_template_params params = AUTO_VAL_INIT(params);
|
||||
params.miner_address = miner_address;
|
||||
params.stakeholder_address = stakeholder_address;
|
||||
params.ex_nonce = req.extra_text;
|
||||
params.pos = req.pos_block;
|
||||
params.pe.amount = req.pos_amount;
|
||||
params.pe.index = req.pos_index;
|
||||
params.pe.stake_unlock_time = req.stake_unlock_time;
|
||||
//params.pe.keyimage key image will be set in the wallet
|
||||
//params.pe.wallet_index is not included in serialization map, TODO: refactoring here
|
||||
params.pcustom_fill_block_template_func = nullptr;
|
||||
if (req.explicit_transaction.size())
|
||||
{
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
if (!parse_and_validate_tx_from_blob(req.explicit_transaction, tx))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
error_resp.message = "Wrong parameters: explicit_transaction is invalid";
|
||||
LOG_ERROR("Failed to parse explicit_transaction blob");
|
||||
return false;
|
||||
}
|
||||
params.explicit_txs.push_back(tx);
|
||||
}
|
||||
|
||||
create_block_template_response resp = AUTO_VAL_INIT(resp);
|
||||
if (!m_core.get_block_template(params, resp))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
error_resp.message = "Internal error: failed to create block template";
|
||||
LOG_ERROR("Failed to create block template");
|
||||
return false;
|
||||
}
|
||||
res.difficulty = dt.convert_to<std::string>();
|
||||
blobdata block_blob = t_serializable_object_to_blob(b);
|
||||
|
||||
res.difficulty = resp.diffic.convert_to<std::string>();
|
||||
blobdata block_blob = t_serializable_object_to_blob(resp.b);
|
||||
res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
||||
res.prev_hash = string_tools::pod_to_hex(b.prev_id);
|
||||
|
||||
res.prev_hash = string_tools::pod_to_hex(resp.b.prev_id);
|
||||
res.height = resp.height;
|
||||
//calculate epoch seed
|
||||
res.seed = currency::ethash_epoch_to_seed(currency::ethash_height_to_epoch(res.height));
|
||||
|
||||
|
|
@ -851,7 +868,64 @@ namespace currency
|
|||
block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
if(!m_core.handle_block_found(b, &bvc))
|
||||
{
|
||||
if (bvc.added_to_altchain)
|
||||
if (bvc.m_added_to_altchain)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_ADDED_AS_ALTERNATIVE;
|
||||
error_resp.message = "Block added as alternative";
|
||||
return false;
|
||||
}
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED;
|
||||
error_resp.message = "Block not accepted";
|
||||
return false;
|
||||
}
|
||||
//@#@
|
||||
//temporary double check timestamp
|
||||
if (time(NULL) - get_actual_timestamp(b) > 5)
|
||||
{
|
||||
LOG_PRINT_RED_L0("Found block (" << get_block_hash(b) << ") timestamp (" << get_actual_timestamp(b)
|
||||
<< ") is suspiciously less (" << time(NULL) - get_actual_timestamp(b) << ") then curren time( " << time(NULL) << ")");
|
||||
//mark node to make it easier to find it via scanner
|
||||
m_core.get_blockchain_storage().get_performnce_data().epic_failure_happend = true;
|
||||
}
|
||||
//
|
||||
|
||||
|
||||
res.status = "OK";
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool core_rpc_server::on_submitblock2(const COMMAND_RPC_SUBMITBLOCK2::request& req, COMMAND_RPC_SUBMITBLOCK2::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||
{
|
||||
CHECK_CORE_READY();
|
||||
|
||||
|
||||
block b = AUTO_VAL_INIT(b);
|
||||
if (!parse_and_validate_block_from_blob(req.b, b))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
|
||||
error_resp.message = "Wrong block blob";
|
||||
return false;
|
||||
}
|
||||
|
||||
block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
for (const auto& txblob : req.explicit_txs)
|
||||
{
|
||||
|
||||
crypto::hash tx_hash = AUTO_VAL_INIT(tx_hash);
|
||||
transaction tx = AUTO_VAL_INIT(tx);
|
||||
if (!parse_and_validate_tx_from_blob(txblob.blob, tx, tx_hash))
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
|
||||
error_resp.message = "Wrong explicit tx blob";
|
||||
return false;
|
||||
}
|
||||
bvc.m_onboard_transactions[tx_hash] = tx;
|
||||
}
|
||||
|
||||
|
||||
if (!m_core.handle_block_found(b, &bvc))
|
||||
{
|
||||
if (bvc.m_added_to_altchain)
|
||||
{
|
||||
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_ADDED_AS_ALTERNATIVE;
|
||||
error_resp.message = "Block added as alternative";
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ namespace currency
|
|||
bool on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_submitblock2(const COMMAND_RPC_SUBMITBLOCK2::request& req, COMMAND_RPC_SUBMITBLOCK2::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||
|
|
@ -125,6 +126,7 @@ namespace currency
|
|||
MAP_JON_RPC_WE("on_getblockhash", on_getblockhash, COMMAND_RPC_GETBLOCKHASH)
|
||||
MAP_JON_RPC_WE("getblocktemplate", on_getblocktemplate, COMMAND_RPC_GETBLOCKTEMPLATE)
|
||||
MAP_JON_RPC_WE("submitblock", on_submitblock, COMMAND_RPC_SUBMITBLOCK)
|
||||
MAP_JON_RPC_WE("submitblock2", on_submitblock2, COMMAND_RPC_SUBMITBLOCK2)
|
||||
MAP_JON_RPC_WE("getlastblockheader", on_get_last_block_header, COMMAND_RPC_GET_LAST_BLOCK_HEADER)
|
||||
MAP_JON_RPC_WE("getblockheaderbyhash", on_get_block_header_by_hash, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH)
|
||||
MAP_JON_RPC_WE("getblockheaderbyheight", on_get_block_header_by_height, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include "serialization/keyvalue_hexemizer.h"
|
||||
#include "currency_protocol/currency_protocol_defs.h"
|
||||
#include "currency_core/currency_basic.h"
|
||||
#include "currency_core/difficulty.h"
|
||||
|
|
@ -770,7 +771,7 @@ namespace currency
|
|||
{
|
||||
struct request
|
||||
{
|
||||
//uint64_t reserve_size; //max 255 bytes
|
||||
blobdata explicit_transaction;
|
||||
std::string extra_text;
|
||||
std::string wallet_address;
|
||||
std::string stakeholder_address;
|
||||
|
|
@ -780,6 +781,7 @@ namespace currency
|
|||
uint64_t stake_unlock_time;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(explicit_transaction)
|
||||
KV_SERIALIZE(extra_text)
|
||||
KV_SERIALIZE(wallet_address)
|
||||
KV_SERIALIZE(stakeholder_address);
|
||||
|
|
@ -824,6 +826,29 @@ namespace currency
|
|||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_SUBMITBLOCK2
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string b; //hex encoded block blob
|
||||
std::list<epee::hexemizer> explicit_txs; //hex encoded tx blobs
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_BLOB_AS_HEX_STRING(b)
|
||||
KV_SERIALIZE(explicit_txs)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string status;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(status)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct block_header_response
|
||||
{
|
||||
uint8_t major_version;
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ simple_wallet::simple_wallet()
|
|||
m_cmd_binder.set_handler("fix_collisions", boost::bind(&simple_wallet::fix_collisions, this, _1), "Rescan transfers for key image collisions");
|
||||
m_cmd_binder.set_handler("scan_transfers_for_id", boost::bind(&simple_wallet::scan_transfers_for_id, this, _1), "Rescan transfers for tx_id");
|
||||
m_cmd_binder.set_handler("scan_transfers_for_ki", boost::bind(&simple_wallet::scan_transfers_for_ki, this, _1), "Rescan transfers for key image");
|
||||
m_cmd_binder.set_handler("print_utxo_distribution", boost::bind(&simple_wallet::print_utxo_distribution, this, _1), "Prints utxo distribution");
|
||||
|
||||
m_cmd_binder.set_handler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address");
|
||||
m_cmd_binder.set_handler("integrated_address", boost::bind(&simple_wallet::integrated_address, this, _1), "integrated_address [<payment_id>|<integrated_address] - encodes given payment_id along with wallet's address into an integrated address (random payment_id will be used if none is provided). Decodes given integrated_address into standard address");
|
||||
|
|
@ -951,6 +952,18 @@ bool simple_wallet::scan_transfers_for_ki(const std::vector<std::string> &args)
|
|||
print_td_list(td);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::print_utxo_distribution(const std::vector<std::string> &args)
|
||||
{
|
||||
std::map<uint64_t, uint64_t> distribution;
|
||||
m_wallet->get_utxo_distribution(distribution);
|
||||
for (auto& e : distribution)
|
||||
{
|
||||
message_writer() << std::left << setw(25) << print_money(e.first) << "|" << e.second;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::get_transfer_info(const std::vector<std::string> &args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ namespace currency
|
|||
bool fix_collisions(const std::vector<std::string> &args );
|
||||
bool scan_transfers_for_id(const std::vector<std::string> &args);
|
||||
bool scan_transfers_for_ki(const std::vector<std::string> &args);
|
||||
bool print_utxo_distribution(const std::vector<std::string> &args);
|
||||
bool show_blockchain_height(const std::vector<std::string> &args);
|
||||
bool show_wallet_bcheight(const std::vector<std::string> &args);
|
||||
bool transfer(const std::vector<std::string> &args);
|
||||
|
|
|
|||
|
|
@ -532,7 +532,7 @@ namespace
|
|||
r = m_p_core->handle_block_found(m_block_template, &bvc, false);
|
||||
if (r)
|
||||
{
|
||||
if (!bvc.m_verification_failed && !bvc.added_to_altchain && bvc.m_added_to_main_chain && !bvc.m_already_exists && !bvc.m_marked_as_orphaned)
|
||||
if (!bvc.m_verification_failed && !bvc.m_added_to_altchain && bvc.m_added_to_main_chain && !bvc.m_already_exists && !bvc.m_marked_as_orphaned)
|
||||
{
|
||||
LP_CC_WORKER_GREEN(p_ph->get_context(), "found block " << block_hash << " at height " << height << " was successfully added to the blockchain, difficulty " << m_network_difficulty, LOG_LEVEL_0);
|
||||
r = update_block_template();
|
||||
|
|
@ -544,7 +544,7 @@ namespace
|
|||
{
|
||||
LP_CC_WORKER_RED(p_ph->get_context(), "block " << block_hash << " at height " << height << " was NOT added to the blockchain:" << ENDL <<
|
||||
" verification_failed: " << bvc.m_verification_failed << ENDL <<
|
||||
" added_to_altchain: " << bvc.added_to_altchain << ENDL <<
|
||||
" added_to_altchain: " << bvc.m_added_to_altchain << ENDL <<
|
||||
" added_to_main_chain: " << bvc.m_added_to_main_chain << ENDL <<
|
||||
" already_exists: " << bvc.m_already_exists << ENDL <<
|
||||
" marked_as_orphaned: " << bvc.m_marked_as_orphaned, LOG_LEVEL_0);
|
||||
|
|
|
|||
|
|
@ -116,6 +116,11 @@ namespace tools
|
|||
return invoke_http_json_rpc_update_is_disconnect("submitblock", req, rsp);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::call_COMMAND_RPC_SUBMITBLOCK2(const currency::COMMAND_RPC_SUBMITBLOCK2::request& req, currency::COMMAND_RPC_SUBMITBLOCK2::response& rsp)
|
||||
{
|
||||
return invoke_http_json_rpc_update_is_disconnect("submitblock2", req, rsp);
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool default_http_core_proxy::check_connection()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace tools
|
|||
bool call_COMMAND_RPC_SCAN_POS(const currency::COMMAND_RPC_SCAN_POS::request& req, currency::COMMAND_RPC_SCAN_POS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GETBLOCKTEMPLATE(const currency::COMMAND_RPC_GETBLOCKTEMPLATE::request& req, currency::COMMAND_RPC_GETBLOCKTEMPLATE::response& rsp) override;
|
||||
bool call_COMMAND_RPC_SUBMITBLOCK(const currency::COMMAND_RPC_SUBMITBLOCK::request& req, currency::COMMAND_RPC_SUBMITBLOCK::response& rsp) override;
|
||||
bool call_COMMAND_RPC_SUBMITBLOCK2(const currency::COMMAND_RPC_SUBMITBLOCK2::request& req, currency::COMMAND_RPC_SUBMITBLOCK2::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_POS_MINING_DETAILS(const currency::COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, currency::COMMAND_RPC_GET_POS_MINING_DETAILS::response& rsp) override;
|
||||
bool call_COMMAND_RPC_GET_BLOCKS_DETAILS(const currency::COMMAND_RPC_GET_BLOCKS_DETAILS::request& req, currency::COMMAND_RPC_GET_BLOCKS_DETAILS::response& res) override;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace tools
|
|||
virtual bool call_COMMAND_RPC_SCAN_POS(const currency::COMMAND_RPC_SCAN_POS::request& req, currency::COMMAND_RPC_SCAN_POS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GETBLOCKTEMPLATE(const currency::COMMAND_RPC_GETBLOCKTEMPLATE::request& req, currency::COMMAND_RPC_GETBLOCKTEMPLATE::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_SUBMITBLOCK(const currency::COMMAND_RPC_SUBMITBLOCK::request& req, currency::COMMAND_RPC_SUBMITBLOCK::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_SUBMITBLOCK2(const currency::COMMAND_RPC_SUBMITBLOCK2::request& req, currency::COMMAND_RPC_SUBMITBLOCK2::response& rsp) { return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_POS_MINING_DETAILS(const currency::COMMAND_RPC_GET_POS_MINING_DETAILS::request& req, currency::COMMAND_RPC_GET_POS_MINING_DETAILS::response& rsp){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_BLOCKS_DETAILS(const currency::COMMAND_RPC_GET_BLOCKS_DETAILS::request& req, currency::COMMAND_RPC_GET_BLOCKS_DETAILS::response& res){ return false; }
|
||||
virtual bool call_COMMAND_RPC_GET_OFFERS_EX(const currency::COMMAND_RPC_GET_OFFERS_EX::request& req, currency::COMMAND_RPC_GET_OFFERS_EX::response& res){ return false; }
|
||||
|
|
|
|||
|
|
@ -147,6 +147,11 @@ bool wallet2::set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy)
|
|||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::set_pos_mint_packing_size(uint64_t new_size)
|
||||
{
|
||||
m_pos_mint_packing_size = new_size;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::shared_ptr<i_core_proxy> wallet2::get_core_proxy()
|
||||
{
|
||||
return m_core_proxy;
|
||||
|
|
@ -2315,6 +2320,34 @@ void wallet2::get_transfers(wallet2::transfer_container& incoming_transfers) con
|
|||
incoming_transfers = m_transfers;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::generate_packing_transaction_if_needed(currency::transaction& tx, uint64_t fake_outputs_number)
|
||||
{
|
||||
prepare_free_transfers_cache(0);
|
||||
auto it = m_found_free_amounts.find(CURRENCY_BLOCK_REWARD);
|
||||
if (it == m_found_free_amounts.end() || it->second.size() < m_pos_mint_packing_size)
|
||||
return false;
|
||||
|
||||
//let's check if we have at least WALLET_POS_MINT_PACKING_SIZE transactions which is ready to go
|
||||
size_t count = 0;
|
||||
for (auto it_ind = it->second.begin(); it_ind != it->second.end() && count < m_pos_mint_packing_size; it_ind++)
|
||||
{
|
||||
if (is_transfer_ready_to_go(m_transfers[*it_ind], fake_outputs_number))
|
||||
++count;
|
||||
}
|
||||
if (count < m_pos_mint_packing_size)
|
||||
return false;
|
||||
construct_tx_param ctp = get_default_construct_tx_param();
|
||||
currency::tx_destination_entry de = AUTO_VAL_INIT(de);
|
||||
de.addr.push_back(m_account.get_public_address());
|
||||
de.amount = m_pos_mint_packing_size*CURRENCY_BLOCK_REWARD;
|
||||
ctp.dsts.push_back(de);
|
||||
ctp.perform_packing = true;
|
||||
|
||||
transfer(ctp, tx, false, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_transfers_str(bool include_spent /*= true*/, bool include_unspent /*= true*/) const
|
||||
{
|
||||
static const char* header = "index amount g_index flags block tx out# key image";
|
||||
|
|
@ -2433,6 +2466,16 @@ void wallet2::sign_transfer_files(const std::string& tx_sources_file, const std:
|
|||
THROW_IF_FALSE_WALLET_CMN_ERR_EX(r, "failed to store signed tx to file " << signed_tx_file);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::get_utxo_distribution(std::map<uint64_t, uint64_t>& distribution)
|
||||
{
|
||||
prepare_free_transfers_cache(0);
|
||||
for (auto ent : m_found_free_amounts)
|
||||
{
|
||||
distribution[ent.first] = ent.second.size();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::submit_transfer(const std::string& signed_tx_blob, currency::transaction& tx)
|
||||
{
|
||||
// decrypt sources
|
||||
|
|
@ -2783,6 +2826,13 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
tmpl_req.pos_index = req.pos_entries[rsp.index].index;
|
||||
tmpl_req.extra_text = m_miner_text_info;
|
||||
tmpl_req.stake_unlock_time = req.pos_entries[rsp.index].stake_unlock_time;
|
||||
//generate packing tx
|
||||
transaction pack_tx = AUTO_VAL_INIT(pack_tx);
|
||||
if (generate_packing_transaction_if_needed(pack_tx, 0))
|
||||
{
|
||||
tx_to_blob(pack_tx, tmpl_req.explicit_transaction);
|
||||
WLT_LOG_GREEN("Pacling inputs: " << pack_tx.vin.size() << " inputs consolidated", LOG_LEVEL_0);
|
||||
}
|
||||
m_core_proxy->call_COMMAND_RPC_GETBLOCKTEMPLATE(tmpl_req, tmpl_rsp);
|
||||
WLT_CHECK_AND_ASSERT_MES(tmpl_rsp.status == CORE_RPC_STATUS_OK, false, "Failed to create block template after kernel hash found!");
|
||||
|
||||
|
|
@ -2826,10 +2876,13 @@ bool wallet2::build_minted_block(const currency::COMMAND_RPC_SCAN_POS::request&
|
|||
|
||||
WLT_LOG_GREEN("Block constructed <" << get_block_hash(b) << ">, sending to core...", LOG_LEVEL_0);
|
||||
|
||||
currency::COMMAND_RPC_SUBMITBLOCK::request subm_req = AUTO_VAL_INIT(subm_req);
|
||||
currency::COMMAND_RPC_SUBMITBLOCK::response subm_rsp = AUTO_VAL_INIT(subm_rsp);
|
||||
subm_req.push_back(epee::string_tools::buff_to_hex_nodelimer(t_serializable_object_to_blob(b)));
|
||||
m_core_proxy->call_COMMAND_RPC_SUBMITBLOCK(subm_req, subm_rsp);
|
||||
currency::COMMAND_RPC_SUBMITBLOCK2::request subm_req = AUTO_VAL_INIT(subm_req);
|
||||
currency::COMMAND_RPC_SUBMITBLOCK2::response subm_rsp = AUTO_VAL_INIT(subm_rsp);
|
||||
subm_req.b = t_serializable_object_to_blob(b);
|
||||
if (tmpl_req.explicit_transaction.size())
|
||||
subm_req.explicit_txs.push_back(hexemizer{ tmpl_req.explicit_transaction });
|
||||
|
||||
m_core_proxy->call_COMMAND_RPC_SUBMITBLOCK2(subm_req, subm_rsp);
|
||||
if (subm_rsp.status != CORE_RPC_STATUS_OK)
|
||||
{
|
||||
WLT_LOG_ERROR("Constructed block is not accepted by core, status: " << subm_rsp.status);
|
||||
|
|
@ -3417,11 +3470,41 @@ void wallet2::send_escrow_proposal(const bc_services::contract_private_details&
|
|||
print_tx_sent_message(tx, "(from multisig)", fee);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
|
||||
{
|
||||
prepare_free_transfers_cache(fake_outputs_count);
|
||||
auto it = m_found_free_amounts.find(CURRENCY_BLOCK_REWARD);
|
||||
if (it == m_found_free_amounts.end() || it->second.size() < m_pos_mint_packing_size)
|
||||
return false;
|
||||
|
||||
for (auto set_it = it->second.begin(); set_it != it->second.end() && selected_indicies.size() <= m_pos_mint_packing_size; )
|
||||
{
|
||||
if (is_transfer_ready_to_go(m_transfers[*set_it], fake_outputs_count))
|
||||
{
|
||||
found_money += it->first;
|
||||
selected_indicies.push_back(*set_it);
|
||||
WLT_LOG_L2("Selected index: " << *set_it << ", transfer_details: " << ENDL << epee::serialization::store_t_to_json(m_transfers[*set_it]));
|
||||
|
||||
it->second.erase(set_it++);
|
||||
}
|
||||
else
|
||||
set_it++;
|
||||
}
|
||||
if (!it->second.size())
|
||||
m_found_free_amounts.erase(it);
|
||||
|
||||
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies, found_money);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(uint64_t needed_money, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
|
||||
{
|
||||
found_money = select_transfers(needed_money, fake_outputs_count, dust_threshold, selected_indicies);
|
||||
THROW_IF_FALSE_WALLET_EX_MES(found_money >= needed_money, error::not_enough_money, "wallet_dump: " << ENDL << dump_trunsfers(false), found_money, needed_money, 0);
|
||||
|
||||
return prepare_tx_sources(fake_outputs_count, sources, selected_indicies, found_money);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money)
|
||||
{
|
||||
typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry;
|
||||
typedef currency::tx_source_entry::output_entry tx_output_entry;
|
||||
|
||||
|
|
@ -4060,7 +4143,9 @@ void wallet2::prepare_transaction(const construct_tx_param& ctp, finalize_tx_par
|
|||
uint64_t found_money = 0;
|
||||
|
||||
TIME_MEASURE_START_MS(prepare_tx_sources_time);
|
||||
if (ctp.multisig_id == currency::null_hash)
|
||||
if (ctp.perform_packing)
|
||||
prepare_tx_sources_for_packing(WALLET_DEFAULT_POS_MINT_PACKING_SIZE, 0, ftp.sources, ftp.selected_transfers, found_money);
|
||||
else if (ctp.multisig_id == currency::null_hash)
|
||||
prepare_tx_sources(needed_money, ctp.fake_outputs_count, ctp.dust_policy.dust_threshold, ftp.sources, ftp.selected_transfers, found_money);
|
||||
else
|
||||
prepare_tx_sources(ctp.multisig_id, ftp.sources, found_money);
|
||||
|
|
@ -4174,7 +4259,7 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
bool send_to_network,
|
||||
std::string* p_signed_tx_blob_str)
|
||||
{
|
||||
TIME_MEASURE_START(precalculation_time);
|
||||
//TIME_MEASURE_START(precalculation_time);
|
||||
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
|
||||
ctp.attachments = attachments;
|
||||
ctp.crypt_address = currency::get_crypt_address_from_destinations(m_account.get_keys(), dsts);
|
||||
|
|
@ -4190,8 +4275,33 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
ctp.split_strategy_id = destination_split_strategy_id;
|
||||
ctp.tx_outs_attr = tx_outs_attr;
|
||||
ctp.unlock_time = unlock_time;
|
||||
TIME_MEASURE_FINISH(precalculation_time);
|
||||
//TIME_MEASURE_FINISH(precalculation_time);
|
||||
transfer(ctp, tx, send_to_network, p_signed_tx_blob_str);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
construct_tx_param wallet2::get_default_construct_tx_param_inital()
|
||||
{
|
||||
construct_tx_param ctp = AUTO_VAL_INIT(ctp);
|
||||
|
||||
ctp.fee = m_core_runtime_config.tx_default_fee;
|
||||
ctp.dust_policy = tools::tx_dust_policy(DEFAULT_DUST_THRESHOLD);
|
||||
ctp.split_strategy_id = tools::detail::ssi_digit;
|
||||
ctp.tx_outs_attr = CURRENCY_TO_KEY_OUT_RELAXED;
|
||||
ctp.shuffle = 0;
|
||||
return ctp;
|
||||
}
|
||||
const construct_tx_param& wallet2::get_default_construct_tx_param()
|
||||
{
|
||||
static construct_tx_param ctp = get_default_construct_tx_param_inital();
|
||||
return ctp;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::transfer(const construct_tx_param& ctp,
|
||||
currency::transaction &tx,
|
||||
bool send_to_network,
|
||||
std::string* p_signed_tx_blob_str)
|
||||
{
|
||||
TIME_MEASURE_START(prepare_transaction_time);
|
||||
finalize_tx_param ftp = AUTO_VAL_INIT(ftp);
|
||||
prepare_transaction(ctp, ftp);
|
||||
|
|
@ -4216,7 +4326,7 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
TIME_MEASURE_FINISH(mark_transfers_as_spent_time);
|
||||
|
||||
WLT_LOG_GREEN("[wallet::transfer]"
|
||||
<< " precalculation_time: " << print_fixed_decimal_point(precalculation_time, 3)
|
||||
//<< " precalculation_time: " << print_fixed_decimal_point(precalculation_time, 3)
|
||||
<< ", prepare_transaction_time: " << print_fixed_decimal_point(prepare_transaction_time, 3)
|
||||
<< ", store_unsigned_tx_time: " << print_fixed_decimal_point(store_unsigned_tx_time, 3)
|
||||
<< ", mark_transfers_as_spent_time: " << print_fixed_decimal_point(mark_transfers_as_spent_time, 3)
|
||||
|
|
@ -4244,13 +4354,13 @@ void wallet2::transfer(const std::vector<currency::tx_destination_entry>& dsts,
|
|||
|
||||
|
||||
WLT_LOG_GREEN("[wallet::transfer]"
|
||||
<< " precalculation_time: " << print_fixed_decimal_point(precalculation_time, 3)
|
||||
//<< " precalculation_time: " << print_fixed_decimal_point(precalculation_time, 3)
|
||||
<< ", prepare_transaction_time: " << print_fixed_decimal_point(prepare_transaction_time, 3)
|
||||
<< ", finalize_transaction_time: " << print_fixed_decimal_point(finalize_transaction_time, 3)
|
||||
<< ", mark_transfers_as_spent_time: " << print_fixed_decimal_point(mark_transfers_as_spent_time, 3)
|
||||
, LOG_LEVEL_0);
|
||||
|
||||
print_tx_sent_message(tx, std::string() + "(transfer)", fee);
|
||||
print_tx_sent_message(tx, std::string() + "(transfer)", ctp.fee);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE 10
|
||||
#define WALLET_POS_MINT_CHECK_HEIGHT_INTERVAL 1
|
||||
|
||||
#define WALLET_DEFAULT_POS_MINT_PACKING_SIZE 100
|
||||
|
||||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL "wallet"
|
||||
ENABLE_CHANNEL_BY_DEFAULT("wallet");
|
||||
|
|
@ -256,6 +258,7 @@ namespace tools
|
|||
currency::account_public_address crypt_address;
|
||||
uint8_t tx_outs_attr;
|
||||
bool shuffle;
|
||||
bool perform_packing;
|
||||
};
|
||||
|
||||
struct finalize_tx_param
|
||||
|
|
@ -313,7 +316,8 @@ namespace tools
|
|||
m_last_sync_percent(0),
|
||||
m_do_rise_transfer(false),
|
||||
m_watch_only(false),
|
||||
m_last_pow_block_h(0)
|
||||
m_last_pow_block_h(0),
|
||||
m_pos_mint_packing_size(WALLET_DEFAULT_POS_MINT_PACKING_SIZE)
|
||||
{};
|
||||
public:
|
||||
wallet2() : m_stop(false),
|
||||
|
|
@ -326,7 +330,8 @@ namespace tools
|
|||
m_do_rise_transfer(false),
|
||||
m_log_prefix("???"),
|
||||
m_watch_only(false),
|
||||
m_last_pow_block_h(0)
|
||||
m_last_pow_block_h(0),
|
||||
m_pos_mint_packing_size(WALLET_DEFAULT_POS_MINT_PACKING_SIZE)
|
||||
{
|
||||
m_core_runtime_config = currency::get_default_core_runtime_config();
|
||||
};
|
||||
|
|
@ -491,6 +496,7 @@ namespace tools
|
|||
|
||||
|
||||
bool set_core_proxy(const std::shared_ptr<i_core_proxy>& proxy);
|
||||
void set_pos_mint_packing_size(uint64_t new_size);
|
||||
std::shared_ptr<i_core_proxy> get_core_proxy();
|
||||
uint64_t balance() const;
|
||||
uint64_t balance(uint64_t& unloked, uint64_t& awaiting_in, uint64_t& awaiting_out, uint64_t& mined) const;
|
||||
|
|
@ -538,6 +544,11 @@ namespace tools
|
|||
const std::vector<currency::attachment_v>& attachments,
|
||||
currency::transaction& tx);
|
||||
|
||||
void transfer(const construct_tx_param& ctp,
|
||||
currency::transaction &tx,
|
||||
bool send_to_network,
|
||||
std::string* p_signed_tx_blob_str);
|
||||
|
||||
template<typename destination_split_strategy_t>
|
||||
void transfer_from_contract(
|
||||
const std::list<currency::account_keys>& owner_keys,
|
||||
|
|
@ -728,6 +739,7 @@ namespace tools
|
|||
|
||||
std::string get_log_prefix() const { return m_log_prefix; }
|
||||
static uint64_t get_max_unlock_time_from_receive_indices(const currency::transaction& tx, const money_transfer2_details& td);
|
||||
bool get_utxo_distribution(std::map<uint64_t, uint64_t>& distribution);
|
||||
|
||||
private:
|
||||
void add_transfers_to_expiration_list(const std::vector<uint64_t>& selected_transfers, uint64_t expiration, uint64_t change_amount, const crypto::hash& related_tx_id);
|
||||
|
|
@ -783,7 +795,9 @@ private:
|
|||
void process_genesis_if_needed(const currency::block& genesis);
|
||||
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(uint64_t needed_money, size_t fake_outputs_count, uint64_t dust_threshold, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
|
||||
bool prepare_tx_sources(size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
|
||||
bool prepare_tx_sources(crypto::hash multisig_id, std::vector<currency::tx_source_entry>& sources, uint64_t& found_money);
|
||||
bool prepare_tx_sources_for_packing(uint64_t items_to_pack, size_t fake_outputs_count, std::vector<currency::tx_source_entry>& sources, std::vector<uint64_t>& selected_indicies, uint64_t& found_money);
|
||||
uint64_t get_needed_money(uint64_t fee, const std::vector<currency::tx_destination_entry>& dsts);
|
||||
void prepare_tx_destinations(uint64_t needed_money,
|
||||
uint64_t found_money,
|
||||
|
|
@ -799,7 +813,9 @@ private:
|
|||
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const wallet_public::wallet_transfer_info& wti) const;
|
||||
void change_contract_state(wallet_public::escrow_contract_details_basic& contract, uint32_t new_state, const crypto::hash& contract_id, const std::string& reason = "internal intention") const;
|
||||
|
||||
|
||||
construct_tx_param get_default_construct_tx_param_inital();
|
||||
const construct_tx_param& get_default_construct_tx_param();
|
||||
|
||||
uint64_t get_tx_expiration_median() const;
|
||||
|
||||
|
|
@ -841,7 +857,7 @@ private:
|
|||
void exception_handler() const;
|
||||
uint64_t get_minimum_allowed_fee_for_contract(const crypto::hash& ms_id);
|
||||
void check_for_free_space_and_throw_if_it_lacks(const std::wstring& path, uint64_t exact_size_needed_if_known = UINT64_MAX);
|
||||
|
||||
bool generate_packing_transaction_if_needed(currency::transaction& tx, uint64_t fake_outputs_number);
|
||||
|
||||
|
||||
currency::account_base m_account;
|
||||
|
|
@ -854,6 +870,7 @@ private:
|
|||
std::atomic<uint64_t> m_local_bc_height; //temporary workaround
|
||||
std::atomic<uint64_t> m_last_bc_timestamp;
|
||||
bool m_do_rise_transfer;
|
||||
uint64_t m_pos_mint_packing_size;
|
||||
|
||||
transfer_container m_transfers;
|
||||
multisig_transfer_container m_multisig_transfers;
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ bool gen_and_play_intermitted_by_blockchain_saveload(const char* const genclass_
|
|||
|
||||
|
||||
#define GENERATE_AND_PLAY(genclass) \
|
||||
if(!postponed_tests.count(#genclass) && (run_single_test.empty() || run_single_test == #genclass)) \
|
||||
if(!postponed_tests.count(#genclass) && (run_single_test.empty() || std::string::npos != std::string(#genclass).find(run_single_test))) \
|
||||
{ \
|
||||
TIME_MEASURE_START_MS(t); \
|
||||
++tests_count; \
|
||||
|
|
@ -359,6 +359,7 @@ private:
|
|||
size_t m_ev_index;
|
||||
test_core_listener* m_core_listener;
|
||||
|
||||
mutable std::unordered_map<crypto::hash, currency::transaction> m_onboard_txs;
|
||||
bool m_txs_kept_by_block;
|
||||
bool m_skip_txs_blobsize_check;
|
||||
|
||||
|
|
@ -389,11 +390,19 @@ public:
|
|||
|
||||
size_t pool_size = m_c.get_pool_transactions_count();
|
||||
currency::tx_verification_context tvc = AUTO_VAL_INIT(tvc);
|
||||
m_c.handle_incoming_tx(tx_blob, tvc, m_txs_kept_by_block);
|
||||
bool tx_added = pool_size + 1 == m_c.get_pool_transactions_count();
|
||||
bool r = check_tx_verification_context(tvc, tx_added, m_ev_index, tx, m_validator);
|
||||
LOCAL_ASSERT(r);
|
||||
CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed");
|
||||
if (m_txs_kept_by_block)
|
||||
{
|
||||
m_onboard_txs[get_transaction_hash(tx)] = tx;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_c.handle_incoming_tx(tx_blob, tvc, m_txs_kept_by_block);
|
||||
bool tx_added = pool_size + 1 == m_c.get_pool_transactions_count();
|
||||
bool r = check_tx_verification_context(tvc, tx_added, m_ev_index, tx, m_validator);
|
||||
LOCAL_ASSERT(r);
|
||||
CHECK_AND_NO_ASSERT_MES(r, false, "tx verification context check failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -403,6 +412,7 @@ public:
|
|||
m_core_listener->before_block_pushed_to_core(b, blob_blk, m_c);
|
||||
|
||||
currency::block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
||||
bvc.m_onboard_transactions.swap(m_onboard_txs);
|
||||
m_c.handle_incoming_block(blob_blk, bvc);
|
||||
bool r = check_block_verification_context(bvc, m_ev_index, b, m_validator);
|
||||
CHECK_AND_NO_ASSERT_MES(r, false, "block verification context check failed");
|
||||
|
|
@ -846,6 +856,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(wallet_outputs_with_same_key_image);
|
||||
GENERATE_AND_PLAY(wallet_unconfirmed_tx_expiration);
|
||||
GENERATE_AND_PLAY(wallet_unconfimed_tx_balance);
|
||||
GENERATE_AND_PLAY(packing_outputs_on_pos_minting_wallet);
|
||||
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address);
|
||||
GENERATE_AND_PLAY(wallet_rpc_integrated_address_transfer);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct gen_double_spend_in_the_same_block : public gen_double_spend_base< gen_do
|
|||
{
|
||||
static const uint64_t send_amount = MK_TEST_COINS(17);
|
||||
static const bool has_invalid_tx = !txs_kept_by_block;
|
||||
static const size_t expected_pool_txs_count = has_invalid_tx ? 1 : 2;
|
||||
static const size_t expected_pool_txs_count = 1;
|
||||
static const uint64_t expected_bob_balance = send_amount;
|
||||
static const uint64_t expected_alice_balance = 0;
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ struct gen_double_spend_in_different_blocks : public gen_double_spend_base< gen_
|
|||
{
|
||||
static const uint64_t send_amount = MK_TEST_COINS(17);
|
||||
static const bool has_invalid_tx = !txs_kept_by_block;
|
||||
static const size_t expected_pool_txs_count = has_invalid_tx ? 0 : 1;
|
||||
static const size_t expected_pool_txs_count = 0;
|
||||
static const uint64_t expected_bob_balance = 0;
|
||||
static const uint64_t expected_alice_balance = send_amount - TESTS_DEFAULT_FEE;
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ struct gen_double_spend_in_alt_chain_in_the_same_block : public gen_double_spend
|
|||
{
|
||||
static const uint64_t send_amount = MK_TEST_COINS(17);
|
||||
static const bool has_invalid_tx = !txs_kept_by_block;
|
||||
static const size_t expected_pool_txs_count = has_invalid_tx ? 1 : 2;
|
||||
static const size_t expected_pool_txs_count = txs_kept_by_block ? 0 :1;
|
||||
static const uint64_t expected_bob_balance = send_amount;
|
||||
static const uint64_t expected_alice_balance = 0;
|
||||
|
||||
|
|
@ -81,14 +81,12 @@ struct gen_double_spend_in_alt_chain_in_different_blocks : public gen_double_spe
|
|||
{
|
||||
static const uint64_t send_amount = MK_TEST_COINS(17);
|
||||
static const bool has_invalid_tx = !txs_kept_by_block;
|
||||
static const size_t expected_pool_txs_count = has_invalid_tx ? 1 : 2;
|
||||
static const size_t expected_pool_txs_count = txs_kept_by_block ? 0:1;
|
||||
static const uint64_t expected_bob_balance = send_amount;
|
||||
static const uint64_t expected_alice_balance = 0;
|
||||
|
||||
static const uint64_t expected_alice_balance = 0;
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
||||
|
||||
class gen_double_spend_in_different_chains : public test_chain_unit_base
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -2361,7 +2361,7 @@ bool multisig_out_make_and_spent_in_altchain::generate(std::vector<test_event_en
|
|||
MAKE_NEXT_BLOCK(events, blk_5b, blk_4b, miner_acc);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_top_block", params_top_block(get_block_height(blk_5b), get_block_hash(blk_5b)));
|
||||
size_t tx_count = 1;
|
||||
size_t tx_count = 0;
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", tx_count);
|
||||
DO_CALLBACK(events, "clear_tx_pool");
|
||||
|
||||
|
|
|
|||
|
|
@ -1514,12 +1514,12 @@ bool tx_key_image_pool_conflict::generate(std::vector<test_event_entry>& events)
|
|||
events.push_back(tx_2);
|
||||
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(3));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
// make a block with tx_0 and put tx_0 to the blockchain
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, m_miner_acc, tx_0);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(2));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
// tx_1 and tx_2 is still in the pool
|
||||
// it can never be added to any block as long as blk_1 is in the blockchain due to key image conflict
|
||||
|
|
@ -1531,7 +1531,7 @@ bool tx_key_image_pool_conflict::generate(std::vector<test_event_entry>& events)
|
|||
MAKE_NEXT_BLOCK_TX1(events, blk_1a, blk_0r, m_miner_acc, tx_1);
|
||||
|
||||
// however, it does not remove tx from the pool
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(2));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
//
|
||||
// make sure stuck tx will be removed from the pool when it's too old
|
||||
|
|
@ -1541,7 +1541,7 @@ bool tx_key_image_pool_conflict::generate(std::vector<test_event_entry>& events)
|
|||
|
||||
// remove_stuck_txs should not remove anything, tx_1 and tx_2 should be in the pool
|
||||
DO_CALLBACK(events, "remove_stuck_txs");
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(2));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
// shift time by CURRENCY_MEMPOOL_TX_LIVETIME
|
||||
events.push_back(event_core_time(CURRENCY_MEMPOOL_TX_LIVETIME + 1, true));
|
||||
|
|
@ -1562,11 +1562,11 @@ bool tx_key_image_pool_conflict::generate(std::vector<test_event_entry>& events)
|
|||
events.push_back(tx_2);
|
||||
events.push_back(event_visitor_settings(event_visitor_settings::set_txs_kept_by_block, false));
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(2));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
// remove_stuck_txs should not remove anything, tx_1 and tx_2 should be in the pool
|
||||
DO_CALLBACK(events, "remove_stuck_txs");
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(2));
|
||||
DO_CALLBACK_PARAMS(events, "check_tx_pool_count", static_cast<size_t>(1));
|
||||
|
||||
// rewind 50 blocks so tx_0 spending its key image will be deep enough
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_3r, blk_3, m_miner_acc, 50);
|
||||
|
|
|
|||
|
|
@ -3297,3 +3297,79 @@ bool wallet_unconfimed_tx_balance::c1(currency::core& c, size_t ev_index, const
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
packing_outputs_on_pos_minting_wallet::packing_outputs_on_pos_minting_wallet()
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(packing_outputs_on_pos_minting_wallet, c1);
|
||||
REGISTER_CALLBACK_METHOD(packing_outputs_on_pos_minting_wallet, set_core_config);
|
||||
}
|
||||
bool packing_outputs_on_pos_minting_wallet::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
|
||||
// 0 10 11 21 22 <- blockchain height (assuming CURRENCY_MINED_MONEY_UNLOCK_WINDOW == 10)
|
||||
// (0 )... (0r)- (1 )... (1r)- <- main chain
|
||||
// tx_0 <- txs
|
||||
|
||||
GENERATE_ACCOUNT(miner_acc);
|
||||
m_accounts.push_back(miner_acc);
|
||||
//GENERATE_ACCOUNT(alice_acc);
|
||||
//m_accounts.push_back(alice_acc);
|
||||
|
||||
// don't use MAKE_GENESIS_BLOCK here because it will mask 'generator'
|
||||
currency::block blk_0 = AUTO_VAL_INIT(blk_0);
|
||||
generator.construct_genesis_block(blk_0, miner_acc, test_core_time::get_time());
|
||||
events.push_back(blk_0);
|
||||
|
||||
DO_CALLBACK(events, "set_core_config");
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW+5);
|
||||
|
||||
//MAKE_TX_FEE(events, tx_0, miner_acc, alice_acc, MK_TEST_COINS(2000), TESTS_DEFAULT_FEE, blk_0r);
|
||||
//MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
|
||||
//REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, WALLET_DEFAULT_TX_SPENDABLE_AGE);
|
||||
|
||||
DO_CALLBACK(events, "c1");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool packing_outputs_on_pos_minting_wallet::set_core_config(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
core_runtime_config crc = c.get_blockchain_storage().get_core_runtime_config();
|
||||
crc.pos_minimum_heigh = TESTS_POS_CONFIG_POS_MINIMUM_HEIGH;
|
||||
crc.min_coinstake_age = TESTS_POS_CONFIG_MIN_COINSTAKE_AGE;
|
||||
c.get_blockchain_storage().set_core_runtime_config(crc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool packing_outputs_on_pos_minting_wallet::c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
std::shared_ptr<tools::wallet2> miner_wlt = init_playtime_test_wallet(events, c, MINER_ACC_IDX);
|
||||
size_t blocks_fetched = 0;
|
||||
bool received_money;
|
||||
std::atomic<bool> atomic_false = ATOMIC_VAR_INIT(false);
|
||||
miner_wlt->refresh(blocks_fetched, received_money, atomic_false);
|
||||
CHECK_AND_ASSERT_MES(blocks_fetched == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 5, false, "Incorrect numbers of blocks fetched");
|
||||
|
||||
miner_wlt->set_pos_mint_packing_size(4);
|
||||
check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", MK_TEST_COINS(2000), 0, MK_TEST_COINS(2000), 0, 0);
|
||||
|
||||
miner_wlt->try_mint_pos();
|
||||
|
||||
CHECK_AND_ASSERT_MES(c.get_current_blockchain_size() == CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 7, false, "Incorrect blockchain height:" << c.get_current_blockchain_size());
|
||||
miner_wlt->refresh(blocks_fetched, received_money, atomic_false);
|
||||
CHECK_AND_ASSERT_MES(blocks_fetched == 1, false, "Incorrect numbers of blocks fetched");
|
||||
|
||||
block top_block = AUTO_VAL_INIT(top_block);
|
||||
bool r = c.get_blockchain_storage().get_top_block(top_block);
|
||||
CHECK_AND_ASSERT_MES(r && is_pos_block(top_block), false, "get_top_block failed or smth goes wrong");
|
||||
uint64_t top_block_reward = get_outs_money_amount(top_block.miner_tx);
|
||||
check_balance_via_wallet(*miner_wlt.get(), "miner_wlt", uint64_max, MK_TEST_COINS(2000) + top_block_reward, 0, 0, 0);
|
||||
|
||||
miner_wlt->reset_password(g_wallet_password);
|
||||
miner_wlt->store(g_wallet_filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -251,3 +251,11 @@ struct wallet_unconfimed_tx_balance : 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 packing_outputs_on_pos_minting_wallet : public wallet_test
|
||||
{
|
||||
packing_outputs_on_pos_minting_wallet();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
bool set_core_config(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
bool c1(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue