json rpc for wallet and bugfix

This commit is contained in:
Antonio Juarez
2014-04-02 17:00:17 +01:00
parent 8efa1313f3
commit 29c2859a3e
43 changed files with 2299 additions and 845 deletions
+46 -76
View File
@@ -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;
}
//------------------------------------------------------------------