mirror of
https://github.com/monero-project/monero.git
synced 2025-07-24 14:45:21 -04:00
json rpc for wallet and bugfix
This commit is contained in:
parent
8efa1313f3
commit
29c2859a3e
43 changed files with 2299 additions and 845 deletions
|
@ -44,6 +44,7 @@ bool blockchain_storage::have_tx_keyimg_as_spent(const crypto::key_image &key_im
|
|||
//------------------------------------------------------------------
|
||||
transaction *blockchain_storage::get_tx(const crypto::hash &id)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
auto it = m_transactions.find(id);
|
||||
if (it == m_transactions.end())
|
||||
return NULL;
|
||||
|
@ -65,26 +66,12 @@ bool blockchain_storage::init(const std::string& config_folder)
|
|||
const std::string filename = m_config_folder + "/" CRYPTONOTE_BLOCKCHAINDATA_FILENAME;
|
||||
if(!tools::unserialize_obj_from_file(*this, filename))
|
||||
{
|
||||
const std::string temp_filename = m_config_folder + "/" CRYPTONOTE_BLOCKCHAINDATA_TEMP_FILENAME;
|
||||
if(tools::unserialize_obj_from_file(*this, temp_filename))
|
||||
{
|
||||
LOG_PRINT_L0("Blockchain storage loaded from temporary file");
|
||||
std::error_code ec = tools::replace_file(temp_filename, filename);
|
||||
if (ec)
|
||||
{
|
||||
LOG_ERROR("Failed to rename blockchain data file " << temp_filename << " to " << filename << ": " << ec.message() << ':' << ec.value());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_PRINT_L0("Blockchain storage file not found, generating genesis block.");
|
||||
LOG_PRINT_L0("Can't load blockchain storage from file, generating genesis block.");
|
||||
block bl = boost::value_initialized<block>();
|
||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||
generate_genesis_block(bl);
|
||||
add_new_block(bl, bvc);
|
||||
CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed && bvc.m_added_to_main_chain, false, "Failed to add genesis block to blockchain");
|
||||
}
|
||||
}
|
||||
if(!m_blocks.size())
|
||||
{
|
||||
|
@ -177,6 +164,7 @@ bool blockchain_storage::reset_and_set_genesis_block(const block& b)
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const transaction& tx, bool strict_check)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
struct purge_transaction_visitor: public boost::static_visitor<bool>
|
||||
{
|
||||
key_images_container& m_spent_keys;
|
||||
|
@ -221,6 +209,7 @@ bool blockchain_storage::purge_transaction_keyimages_from_blockchain(const trans
|
|||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::purge_transaction_from_blockchain(const crypto::hash& tx_id)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
auto tx_index_it = m_transactions.find(tx_id);
|
||||
CHECK_AND_ASSERT_MES(tx_index_it != m_transactions.end(), false, "purge_block_data_from_blockchain: transaction not found in blockchain index!!");
|
||||
transaction& tx = tx_index_it->second.tx;
|
||||
|
@ -525,9 +514,7 @@ bool blockchain_storage::validate_miner_transaction(const block& b, size_t cumul
|
|||
|
||||
std::vector<size_t> last_blocks_sizes;
|
||||
get_last_n_blocks_sizes(last_blocks_sizes, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
|
||||
bool block_too_big = false;
|
||||
base_reward = get_block_reward(last_blocks_sizes, cumulative_block_size, block_too_big, already_generated_coins);
|
||||
if(block_too_big)
|
||||
if(!get_block_reward(misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward))
|
||||
{
|
||||
LOG_PRINT_L0("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
|
||||
return false;
|
||||
|
@ -568,18 +555,15 @@ bool blockchain_storage::get_last_n_blocks_sizes(std::vector<size_t>& sz, size_t
|
|||
//------------------------------------------------------------------
|
||||
uint64_t blockchain_storage::get_current_comulative_blocksize_limit()
|
||||
{
|
||||
return m_current_block_comul_sz_limit;
|
||||
return m_current_block_cumul_sz_limit;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::create_block_template(block& b, const account_public_address& miner_address, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce)
|
||||
{
|
||||
size_t txs_cumulative_size = 0;
|
||||
uint64_t fee = 0;
|
||||
size_t comul_sz_limit = 0;
|
||||
std::vector<size_t> sz;
|
||||
size_t median_size;
|
||||
uint64_t already_generated_coins;
|
||||
|
||||
CRITICAL_REGION_BEGIN(m_blockchain_lock);
|
||||
get_last_n_blocks_sizes(sz, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
|
||||
b.major_version = CURRENT_BLOCK_MAJOR_VERSION;
|
||||
b.minor_version = CURRENT_BLOCK_MINOR_VERSION;
|
||||
b.prev_id = get_tail_id();
|
||||
|
@ -588,72 +572,73 @@ bool blockchain_storage::create_block_template(block& b, const account_public_ad
|
|||
diffic = get_difficulty_for_next_block();
|
||||
CHECK_AND_ASSERT_MES(diffic, false, "difficulty owverhead.");
|
||||
|
||||
comul_sz_limit = m_current_block_comul_sz_limit - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
||||
median_size = m_current_block_cumul_sz_limit;
|
||||
already_generated_coins = m_blocks.back().already_generated_coins;
|
||||
|
||||
CRITICAL_REGION_END();
|
||||
|
||||
m_tx_pool.fill_block_template(b, txs_cumulative_size, comul_sz_limit, fee);
|
||||
size_t txs_size;
|
||||
uint64_t fee;
|
||||
if (!m_tx_pool.fill_block_template(b, median_size, already_generated_coins, txs_size, fee)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
two-phase miner transaction generation: we don't know exact block size until we prepare block, but we don't know reward until we know
|
||||
block size, so first miner transaction generated with fake amount of money, and with phase we know think we know expected block size
|
||||
*/
|
||||
//make blocks coin-base tx looks close to real coinbase tx to get truthful blob size
|
||||
bool r = construct_miner_tx(height, m_blocks.back().already_generated_coins, miner_address, b.miner_tx, fee, sz, txs_cumulative_size, ex_nonce, 11);
|
||||
bool r = construct_miner_tx(height, median_size, already_generated_coins, txs_size, fee, miner_address, b.miner_tx, ex_nonce, 11);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, first chance");
|
||||
#ifdef _DEBUG
|
||||
std::list<size_t> try_val;
|
||||
try_val.push_back(get_object_blobsize(b.miner_tx));
|
||||
#endif
|
||||
|
||||
size_t cumulative_size = txs_cumulative_size + get_object_blobsize(b.miner_tx);
|
||||
size_t try_count = 0;
|
||||
for(; try_count != 10; ++try_count)
|
||||
{
|
||||
r = construct_miner_tx(height, m_blocks.back().already_generated_coins, miner_address, b.miner_tx, fee, sz, cumulative_size, ex_nonce, 11);
|
||||
size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
|
||||
for (size_t try_count = 0; try_count != 10; ++try_count) {
|
||||
r = construct_miner_tx(height, median_size, already_generated_coins, cumulative_size, fee, miner_address, b.miner_tx, ex_nonce, 11);
|
||||
#ifdef _DEBUG
|
||||
try_val.push_back(get_object_blobsize(b.miner_tx));
|
||||
#endif
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to construc miner tx, second chance");
|
||||
size_t coinbase_blob_size = get_object_blobsize(b.miner_tx);
|
||||
if(coinbase_blob_size > cumulative_size - txs_cumulative_size )
|
||||
{
|
||||
cumulative_size = txs_cumulative_size + coinbase_blob_size;
|
||||
if (coinbase_blob_size > cumulative_size - txs_size) {
|
||||
cumulative_size = txs_size + coinbase_blob_size;
|
||||
continue;
|
||||
}else
|
||||
{
|
||||
if(coinbase_blob_size < cumulative_size - txs_cumulative_size )
|
||||
{
|
||||
size_t delta = cumulative_size - txs_cumulative_size - coinbase_blob_size;
|
||||
b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
|
||||
//here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
|
||||
if(cumulative_size != txs_cumulative_size + get_object_blobsize(b.miner_tx))
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(cumulative_size + 1== txs_cumulative_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " + 1 is not equal txs_cumulative_size=" << txs_cumulative_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx) );
|
||||
b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1 );
|
||||
if(cumulative_size != txs_cumulative_size + get_object_blobsize(b.miner_tx))
|
||||
{//fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
|
||||
LOG_PRINT_RED("Miner tx creation have no luck with delta_extra size = " << delta << " and " << delta - 1 , LOG_LEVEL_2);
|
||||
cumulative_size += delta + 1;
|
||||
continue;
|
||||
}
|
||||
LOG_PRINT_GREEN("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count, LOG_LEVEL_1);
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(cumulative_size == txs_cumulative_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_cumulative_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx) );
|
||||
return true;
|
||||
}
|
||||
|
||||
if (coinbase_blob_size < cumulative_size - txs_size) {
|
||||
size_t delta = cumulative_size - txs_size - coinbase_blob_size;
|
||||
b.miner_tx.extra.insert(b.miner_tx.extra.end(), delta, 0);
|
||||
//here could be 1 byte difference, because of extra field counter is varint, and it can become from 1-byte len to 2-bytes len.
|
||||
if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx)) {
|
||||
CHECK_AND_ASSERT_MES(cumulative_size + 1 == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " + 1 is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
|
||||
b.miner_tx.extra.resize(b.miner_tx.extra.size() - 1);
|
||||
if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx)) {
|
||||
//fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
|
||||
LOG_PRINT_RED("Miner tx creation have no luck with delta_extra size = " << delta << " and " << delta - 1 , LOG_LEVEL_2);
|
||||
cumulative_size += delta - 1;
|
||||
continue;
|
||||
}
|
||||
LOG_PRINT_GREEN("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count, LOG_LEVEL_1);
|
||||
}
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
|
||||
return true;
|
||||
}
|
||||
LOG_ERROR("Failed to create_block_template with " << try_count << " tries");
|
||||
LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps)
|
||||
{
|
||||
|
||||
if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
|
||||
return true;
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size();
|
||||
CHECK_AND_ASSERT_MES(start_top_height < m_blocks.size(), false, "internal error: passed start_height = " << start_top_height << " not less then m_blocks.size()=" << m_blocks.size());
|
||||
size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements:0;
|
||||
|
@ -947,22 +932,6 @@ bool blockchain_storage::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDO
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
//bool blockchain_storage::get_outs_for_amounts(uint64_t amount, std::vector<std::pair<crypto::hash, size_t> >& keys, std::map<crypto::hash, transaction>& txs)
|
||||
//{
|
||||
// auto it = m_outputs.find(amount);
|
||||
// if(it == m_outputs.end())
|
||||
// return false;
|
||||
// keys = it->second;
|
||||
// typedef std::pair<crypto::hash, size_t> pair;
|
||||
// BOOST_FOREACH(pair& pr, keys)
|
||||
// {
|
||||
// auto it = m_transactions.find(pr.first);
|
||||
// CHECK_AND_ASSERT_MES(it != m_transactions.end(), false, "internal error: transaction with id " << pr.first << " not found in internal index, but have refference for amount " << amount);
|
||||
// txs[pr.first] = it->second.tx;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::find_blockchain_supplement(const std::list<crypto::hash>& qblock_ids, uint64_t& starter_offset)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
|
@ -1036,7 +1005,8 @@ void blockchain_storage::print_blockchain(uint64_t start_index, uint64_t end_ind
|
|||
<< "\nid\t\t" << get_block_hash(m_blocks[i].bl)
|
||||
<< "\ndifficulty\t\t" << block_difficulty(i) << ", nonce " << m_blocks[i].bl.nonce << ", tx_count " << m_blocks[i].bl.tx_hashes.size() << ENDL;
|
||||
}
|
||||
LOG_PRINT_L0("Current blockchain:" << ENDL << ss.str());
|
||||
LOG_PRINT_L1("Current blockchain:" << ENDL << ss.str());
|
||||
LOG_PRINT_L0("Blockchain printed with log level 1");
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
void blockchain_storage::print_blockchain_index()
|
||||
|
@ -1605,7 +1575,7 @@ bool blockchain_storage::update_next_comulative_size_limit()
|
|||
if(median <= CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE)
|
||||
median = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE;
|
||||
|
||||
m_current_block_comul_sz_limit = median*2;
|
||||
m_current_block_cumul_sz_limit = median*2;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace cryptonote
|
|||
uint64_t already_generated_coins;
|
||||
};
|
||||
|
||||
blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_comul_sz_limit(0), m_is_in_checkpoint_zone(false)
|
||||
blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false)
|
||||
{};
|
||||
|
||||
bool init() { return init(tools::get_default_data_dir()); }
|
||||
|
@ -175,7 +175,7 @@ namespace cryptonote
|
|||
blocks_by_id_index m_blocks_index; // crypto::hash -> height
|
||||
transactions_container m_transactions;
|
||||
key_images_container m_spent_keys;
|
||||
size_t m_current_block_comul_sz_limit;
|
||||
size_t m_current_block_cumul_sz_limit;
|
||||
|
||||
|
||||
// all alternative chains
|
||||
|
@ -235,12 +235,12 @@ namespace cryptonote
|
|||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
#define CURRENT_BLOCKCHAIN_STORAGE_ARCHIVE_VER 11
|
||||
#define CURRENT_BLOCKCHAIN_STORAGE_ARCHIVE_VER 12
|
||||
|
||||
template<class archive_t>
|
||||
void blockchain_storage::serialize(archive_t & ar, const unsigned int version)
|
||||
{
|
||||
if(version < CURRENT_BLOCKCHAIN_STORAGE_ARCHIVE_VER)
|
||||
if(version < 11)
|
||||
return;
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
ar & m_blocks;
|
||||
|
@ -250,14 +250,54 @@ namespace cryptonote
|
|||
ar & m_alternative_chains;
|
||||
ar & m_outputs;
|
||||
ar & m_invalid_blocks;
|
||||
ar & m_current_block_comul_sz_limit;
|
||||
ar & m_current_block_cumul_sz_limit;
|
||||
/*serialization bug workaround*/
|
||||
if(version > 11)
|
||||
{
|
||||
uint64_t total_check_count = m_blocks.size() + m_blocks_index.size() + m_transactions.size() + m_spent_keys.size() + m_alternative_chains.size() + m_outputs.size() + m_invalid_blocks.size() + m_current_block_cumul_sz_limit;
|
||||
if(archive_t::is_saving::value)
|
||||
{
|
||||
ar & total_check_count;
|
||||
}else
|
||||
{
|
||||
uint64_t total_check_count_loaded = 0;
|
||||
ar & total_check_count_loaded;
|
||||
if(total_check_count != total_check_count_loaded)
|
||||
{
|
||||
LOG_ERROR("Blockchain storage data corruption detected. total_count loaded from file = " << total_check_count_loaded << ", expected = " << total_check_count);
|
||||
|
||||
LOG_PRINT_L0("Blockchain storage:" << ENDL <<
|
||||
"m_blocks: " << m_blocks.size() << ENDL <<
|
||||
"m_blocks_index: " << m_blocks_index.size() << ENDL <<
|
||||
"m_transactions: " << m_transactions.size() << ENDL <<
|
||||
"m_spent_keys: " << m_spent_keys.size() << ENDL <<
|
||||
"m_alternative_chains: " << m_alternative_chains.size() << ENDL <<
|
||||
"m_outputs: " << m_outputs.size() << ENDL <<
|
||||
"m_invalid_blocks: " << m_invalid_blocks.size() << ENDL <<
|
||||
"m_current_block_cumul_sz_limit: " << m_current_block_cumul_sz_limit);
|
||||
|
||||
throw std::runtime_error("Blockchain data corruption");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LOG_PRINT_L2("Blockchain storage:" << ENDL <<
|
||||
"m_blocks: " << m_blocks.size() << ENDL <<
|
||||
"m_blocks_index: " << m_blocks_index.size() << ENDL <<
|
||||
"m_transactions: " << m_transactions.size() << ENDL <<
|
||||
"m_spent_keys: " << m_spent_keys.size() << ENDL <<
|
||||
"m_alternative_chains: " << m_alternative_chains.size() << ENDL <<
|
||||
"m_outputs: " << m_outputs.size() << ENDL <<
|
||||
"m_invalid_blocks: " << m_invalid_blocks.size() << ENDL <<
|
||||
"m_current_block_cumul_sz_limit: " << m_current_block_cumul_sz_limit);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
template<class visitor_t>
|
||||
bool blockchain_storage::scan_outputkeys_for_indexes(const txin_to_key& tx_in_to_key, visitor_t& vis, uint64_t* pmax_related_block_height)
|
||||
{
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
auto it = m_outputs.find(tx_in_to_key.amount);
|
||||
if(it == m_outputs.end() || !tx_in_to_key.key_offsets.size())
|
||||
return false;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace cryptonote {
|
|||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_max_block_size()
|
||||
{
|
||||
return CRYPTONOTE_MAX_BLOCK_SIZE;
|
||||
return CRYPTONOTE_MAX_BLOCK_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_max_tx_size()
|
||||
|
@ -33,46 +33,39 @@ namespace cryptonote {
|
|||
return CRYPTONOTE_MAX_TX_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
uint64_t get_block_reward(std::vector<size_t>& last_blocks_sizes, size_t current_block_size, bool& block_too_big, uint64_t already_generated_coins)
|
||||
{
|
||||
block_too_big = false;
|
||||
|
||||
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward) {
|
||||
uint64_t base_reward = (MONEY_SUPPLY - already_generated_coins) >> 18;
|
||||
|
||||
if(current_block_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE)
|
||||
return base_reward;
|
||||
|
||||
size_t med_sz = misc_utils::median(last_blocks_sizes);
|
||||
|
||||
//make it soft
|
||||
if(med_sz < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE)
|
||||
med_sz = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE;
|
||||
if (median_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) {
|
||||
median_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE;
|
||||
}
|
||||
|
||||
if(current_block_size > med_sz)
|
||||
{
|
||||
if(current_block_size > med_sz*2)
|
||||
{
|
||||
LOG_PRINT_L0("Block cumulative size is too big: " << current_block_size << ", expected less than " << med_sz*2);
|
||||
block_too_big = true;
|
||||
return 0;
|
||||
}
|
||||
if (current_block_size <= median_size) {
|
||||
reward = base_reward;
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(med_sz < std::numeric_limits<uint32_t>::max());
|
||||
assert(current_block_size < std::numeric_limits<uint32_t>::max());
|
||||
if(current_block_size > 2 * median_size) {
|
||||
LOG_PRINT_L4("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t product_hi;
|
||||
uint64_t product_lo = mul128(base_reward, current_block_size * (2 * med_sz - current_block_size), &product_hi);
|
||||
assert(median_size < std::numeric_limits<uint32_t>::max());
|
||||
assert(current_block_size < std::numeric_limits<uint32_t>::max());
|
||||
|
||||
uint64_t reward_hi;
|
||||
uint64_t reward_lo;
|
||||
div128_32(product_hi, product_lo, static_cast<uint32_t>(med_sz), &reward_hi, &reward_lo);
|
||||
div128_32(reward_hi, reward_lo, static_cast<uint32_t>(med_sz), &reward_hi, &reward_lo);
|
||||
assert(0 == reward_hi);
|
||||
assert(reward_lo < base_reward);
|
||||
uint64_t product_hi;
|
||||
uint64_t product_lo = mul128(base_reward, current_block_size * (2 * median_size - current_block_size), &product_hi);
|
||||
|
||||
return reward_lo;
|
||||
}else
|
||||
return base_reward;
|
||||
uint64_t reward_hi;
|
||||
uint64_t reward_lo;
|
||||
div128_32(product_hi, product_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo);
|
||||
div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo);
|
||||
assert(0 == reward_hi);
|
||||
assert(reward_lo < base_reward);
|
||||
|
||||
reward = reward_lo;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl)
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace cryptonote {
|
|||
/************************************************************************/
|
||||
size_t get_max_block_size();
|
||||
size_t get_max_tx_size();
|
||||
uint64_t get_block_reward(std::vector<size_t>& last_blocks_sizes, size_t current_block_size, bool& block_too_big, uint64_t already_generated_coins);
|
||||
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward);
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl);
|
||||
std::string get_account_address_as_str(const account_public_address& adr);
|
||||
bool get_account_address_from_str(account_public_address& adr, const std::string& str);
|
||||
|
|
|
@ -54,13 +54,7 @@ namespace cryptonote
|
|||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(uint64_t height, uint64_t already_generated_coins, const account_public_address& miner_address, transaction& tx, uint64_t fee, std::vector<size_t>& blocks_sizes, size_t current_block_size, size_t max_outs)
|
||||
{
|
||||
return construct_miner_tx(height, already_generated_coins, miner_address, tx, fee, blocks_sizes, current_block_size, blobdata(), max_outs);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool construct_miner_tx(uint64_t height, uint64_t already_generated_coins, const account_public_address& miner_address, transaction& tx, uint64_t fee, std::vector<size_t>& blocks_sizes, size_t current_block_size, const blobdata& extra_nonce, size_t max_outs)
|
||||
{
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs) {
|
||||
tx.vin.clear();
|
||||
tx.vout.clear();
|
||||
tx.extra.clear();
|
||||
|
@ -74,13 +68,13 @@ namespace cryptonote
|
|||
txin_gen in;
|
||||
in.height = height;
|
||||
|
||||
bool block_too_big = false;
|
||||
uint64_t block_reward = get_block_reward(blocks_sizes, current_block_size, block_too_big, already_generated_coins) + fee;
|
||||
if(block_too_big)
|
||||
uint64_t block_reward;
|
||||
if(!get_block_reward(median_size, current_block_size, already_generated_coins, block_reward))
|
||||
{
|
||||
LOG_PRINT_L0("Block is too big");
|
||||
return false;
|
||||
}
|
||||
block_reward += fee;
|
||||
|
||||
std::vector<size_t> out_amounts;
|
||||
decompose_amount_into_digits(block_reward, DEFAULT_FEE,
|
||||
|
@ -120,7 +114,7 @@ namespace cryptonote
|
|||
//lock
|
||||
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||
tx.vin.push_back(in);
|
||||
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
|
||||
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
|
||||
// << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
|
||||
return true;
|
||||
}
|
||||
|
@ -152,33 +146,37 @@ namespace cryptonote
|
|||
//---------------------------------------------------------------
|
||||
bool parse_amount(uint64_t& amount, const std::string& str_amount_)
|
||||
{
|
||||
std::vector<std::string> pars;
|
||||
std::string str_amount = str_amount_;
|
||||
boost::algorithm::trim(str_amount);
|
||||
if(!str_amount.size())
|
||||
return false;
|
||||
if(str_amount[0] == '-')
|
||||
|
||||
size_t point_index = str_amount.find_first_of('.');
|
||||
size_t fraction_size;
|
||||
if (std::string::npos != point_index)
|
||||
{
|
||||
fraction_size = str_amount.size() - point_index - 1;
|
||||
while (CRYPTONOTE_DISPLAY_DECIMAL_POINT < fraction_size && '0' == str_amount.back())
|
||||
{
|
||||
str_amount.erase(str_amount.size() - 1, 1);
|
||||
--fraction_size;
|
||||
}
|
||||
if (CRYPTONOTE_DISPLAY_DECIMAL_POINT < fraction_size)
|
||||
return false;
|
||||
str_amount.erase(point_index, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fraction_size = 0;
|
||||
}
|
||||
|
||||
if (str_amount.empty())
|
||||
return false;
|
||||
|
||||
boost::split(pars, str_amount, boost::is_any_of("."), boost::token_compress_on );
|
||||
if(pars.size() > 2 || pars.size() < 1)
|
||||
return false;
|
||||
uint64_t left = 0;
|
||||
if(!string_tools::get_xtype_from_string(left, pars[0]))
|
||||
return false;
|
||||
amount = left * power_integral(10, CRYPTONOTE_DISPLAY_DECIMAL_POINT);
|
||||
if(pars.size() == 2)
|
||||
if (fraction_size < CRYPTONOTE_DISPLAY_DECIMAL_POINT)
|
||||
{
|
||||
uint64_t right = 0;
|
||||
if(pars[1].size() > 8 )
|
||||
return false;
|
||||
if(pars[1].size() < 8 )
|
||||
pars[1].append(8 - pars[1].size(), '0');
|
||||
if(!string_tools::get_xtype_from_string(right, pars[1]))
|
||||
return false;
|
||||
amount += right;
|
||||
str_amount.append(CRYPTONOTE_DISPLAY_DECIMAL_POINT - fraction_size, '0');
|
||||
}
|
||||
return true;
|
||||
|
||||
return string_tools::get_xtype_from_string(amount, str_amount);
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
bool get_tx_fee(const transaction& tx, uint64_t & fee)
|
||||
|
@ -218,7 +216,7 @@ namespace cryptonote
|
|||
tx_pub_key = null_pkey;
|
||||
bool padding_started = false; //let the padding goes only at the end
|
||||
bool tx_extra_tag_pubkey_found = false;
|
||||
bool tx_extra_extra_nonce_found = false;
|
||||
bool tx_extra_extra_nonce_found = false;
|
||||
for(size_t i = 0; i != tx.extra.size();)
|
||||
{
|
||||
if(padding_started)
|
||||
|
@ -573,7 +571,7 @@ namespace cryptonote
|
|||
blobdata get_block_hashing_blob(const block& b)
|
||||
{
|
||||
blobdata blob = t_serializable_object_to_blob(static_cast<block_header>(b));
|
||||
crypto::hash tree_root_hash = get_tx_tree_hash(b);
|
||||
crypto::hash tree_root_hash = get_tx_tree_hash(b);
|
||||
blob.append((const char*)&tree_root_hash, sizeof(tree_root_hash ));
|
||||
blob.append(tools::get_varint_data(b.tx_hashes.size()+1));
|
||||
return blob;
|
||||
|
@ -599,7 +597,7 @@ namespace cryptonote
|
|||
|
||||
account_public_address ac = boost::value_initialized<account_public_address>();
|
||||
std::vector<size_t> sz;
|
||||
construct_miner_tx(0, 0, ac, bl.miner_tx, 0, sz, 0, 1); // zero fee in genesis
|
||||
construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis
|
||||
blobdata txb = tx_to_blob(bl.miner_tx);
|
||||
std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb);
|
||||
|
||||
|
|
|
@ -17,9 +17,8 @@ namespace cryptonote
|
|||
void get_transaction_prefix_hash(const transaction_prefix& tx, crypto::hash& h);
|
||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool construct_miner_tx(uint64_t height, uint64_t already_generated_coins, const account_public_address& miner_address, transaction& tx, uint64_t fee, std::vector<size_t>& blocks_sizes, size_t current_block_size, const blobdata& extra_nonce, size_t max_outs = 1);
|
||||
bool construct_miner_tx(uint64_t height, uint64_t already_generated_coins, const account_public_address& miner_address, transaction& tx, uint64_t fee, std::vector<size_t>& blocks_sizes, size_t current_block_size, size_t max_outs = 1);
|
||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||
bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 1);
|
||||
|
||||
struct tx_source_entry
|
||||
{
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "tx_pool.h"
|
||||
#include "cryptonote_format_utils.h"
|
||||
|
@ -11,6 +13,7 @@
|
|||
#include "cryptonote_config.h"
|
||||
#include "blockchain_storage.h"
|
||||
#include "common/boost_serialization_helper.h"
|
||||
#include "common/int-util.h"
|
||||
#include "misc_language.h"
|
||||
#include "warnings.h"
|
||||
#include "crypto/hash.h"
|
||||
|
@ -345,31 +348,60 @@ namespace cryptonote
|
|||
return ss.str();
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
bool tx_memory_pool::fill_block_template(block& bl, size_t& cumulative_sizes, size_t max_comulative_sz, uint64_t& fee)
|
||||
{
|
||||
bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee) {
|
||||
typedef transactions_container::value_type txv;
|
||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||
|
||||
std::vector<txv *> txs(m_transactions.size());
|
||||
std::transform(m_transactions.begin(), m_transactions.end(), txs.begin(), [](txv &a) -> txv * { return &a; });
|
||||
std::sort(txs.begin(), txs.end(), [](txv *a, txv *b) -> bool {
|
||||
uint64_t a_hi, a_lo = mul128(a->second.fee, b->second.blob_size, &a_hi);
|
||||
uint64_t b_hi, b_lo = mul128(b->second.fee, a->second.blob_size, &b_hi);
|
||||
return a_hi > b_hi || (a_hi == b_hi && a_lo > b_lo);
|
||||
});
|
||||
|
||||
size_t current_size = 0;
|
||||
uint64_t current_fee = 0;
|
||||
uint64_t best_money;
|
||||
if (!get_block_reward(median_size, CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, best_money)) {
|
||||
LOG_ERROR("Block with just a miner transaction is already too large!");
|
||||
return false;
|
||||
}
|
||||
size_t best_position = 0;
|
||||
total_size = 0;
|
||||
fee = 0;
|
||||
|
||||
std::unordered_set<crypto::key_image> k_images;
|
||||
|
||||
BOOST_FOREACH(transactions_container::value_type& tx, m_transactions)
|
||||
{
|
||||
if(cumulative_sizes + tx.second.blob_size > max_comulative_sz)
|
||||
continue;
|
||||
for (size_t i = 0; i < txs.size(); i++) {
|
||||
txv &tx(*txs[i]);
|
||||
|
||||
if(!is_transaction_ready_to_go(tx.second))
|
||||
if(!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx)) {
|
||||
txs[i] = NULL;
|
||||
continue;
|
||||
|
||||
if(have_key_images(k_images, tx.second.tx))
|
||||
continue;
|
||||
|
||||
bl.tx_hashes.push_back(tx.first);
|
||||
cumulative_sizes += tx.second.blob_size;
|
||||
fee += tx.second.fee;
|
||||
}
|
||||
append_key_images(k_images, tx.second.tx);
|
||||
|
||||
if(cumulative_sizes >= max_comulative_sz)
|
||||
current_size += tx.second.blob_size;
|
||||
current_fee += tx.second.fee;
|
||||
|
||||
uint64_t current_reward;
|
||||
if (!get_block_reward(median_size, current_size + CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, current_reward)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (best_money < current_reward + current_fee) {
|
||||
best_money = current_reward + current_fee;
|
||||
best_position = i + 1;
|
||||
total_size = current_size;
|
||||
fee = current_fee;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < best_position; i++) {
|
||||
if (txs[i]) {
|
||||
bl.tx_hashes.push_back(txs[i]->first);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace cryptonote
|
|||
// load/store operations
|
||||
bool init(const std::string& config_folder);
|
||||
bool deinit();
|
||||
bool fill_block_template(block& bl, size_t& cumulative_sizes, size_t max_comulative_sz, uint64_t& fee);
|
||||
bool fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee);
|
||||
bool get_transactions(std::list<transaction>& txs);
|
||||
bool get_transaction(const crypto::hash& h, transaction& tx);
|
||||
size_t get_transactions_count();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue