diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index cfcebed..93c34a0 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -810,6 +810,7 @@ class BlockchainDB */ virtual uint64_t get_block_timestamp(const uint64_t& height) const = 0; + virtual uint64_t get_block_timestamp1(const uint64_t& height) const = 0; /** * @brief fetch the top block's timestamp * diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 179b290..f30ca09 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -243,6 +243,7 @@ typedef struct mdb_block_info { uint64_t bi_height; uint64_t bi_timestamp; + uint64_t bi_timestamp1; uint64_t bi_coins; uint64_t bi_size; // a size_t really but we need 32-bit compat difficulty_type bi_diff; @@ -637,6 +638,7 @@ void BlockchainLMDB::add_block(const block& blk, const size_t& block_size, const mdb_block_info bi; bi.bi_height = m_height; bi.bi_timestamp = blk.timestamp; + bi.bi_timestamp1=time(NULL); bi.bi_coins = coins_generated; bi.bi_size = block_size; bi.bi_diff = cumulative_difficulty; @@ -1517,7 +1519,28 @@ uint64_t BlockchainLMDB::get_block_timestamp(const uint64_t& height) const TXN_POSTFIX_RDONLY(); return ret; } +uint64_t BlockchainLMDB::get_block_timestamp1(const uint64_t& height) const +{ + LOG_PRINT_L3("BlockchainLMDB::" << __func__); + check_open(); + + TXN_PREFIX_RDONLY(); + RCURSOR(block_info); + MDB_val_set(result, height); + auto get_result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &result, MDB_GET_BOTH); + if (get_result == MDB_NOTFOUND) + { + throw0(BLOCK_DNE(std::string("Attempt to get timestamp from height ").append(boost::lexical_cast(height)).append(" failed -- timestamp not in db").c_str())); + } + else if (get_result) + throw0(DB_ERROR("Error attempting to retrieve a timestamp from the db")); + + mdb_block_info *bi = (mdb_block_info *)result.mv_data; + uint64_t ret = bi->bi_timestamp1; + TXN_POSTFIX_RDONLY(); + return ret; +} uint64_t BlockchainLMDB::get_top_block_timestamp() const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 6f0c0cf..16044b9 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -180,6 +180,8 @@ class BlockchainLMDB : public BlockchainDB virtual uint64_t get_block_timestamp(const uint64_t& height) const; + virtual uint64_t get_block_timestamp1(const uint64_t& height) const; + virtual uint64_t get_top_block_timestamp() const; virtual size_t get_block_size(const uint64_t& height) const; diff --git a/src/bxb.ico b/src/bxb.ico index fc1ceb7..90ea2d4 100644 Binary files a/src/bxb.ico and b/src/bxb.ico differ diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 6951f66..c740967 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -90,7 +90,7 @@ static const char* get_builtin_ds(void) { return -". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"; + ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"; } /************************************************************ @@ -261,13 +261,14 @@ std::vector DNSResolver::get_record(const std::string& url, int rec dnssec_valid = result->secure && !result->bogus; if (result->havedata) { + for (size_t i=0; result->data[i] != NULL; i++) { + addresses.push_back((*reader)(result->data[i], result->len[i])); } } } - return addresses; } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index e94b98c..b6366fd 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -54,7 +54,7 @@ // MONEY_SUPPLY - total number coins to be generated #define MONEY_SUPPLY ((uint64_t)6880090000000) -#define EMISSION_SPEED_FACTOR 19 +#define EMISSION_SPEED_FACTOR 20 #define FINAL_SUBSIDY ((uint64_t)4190000) // 4 * pow(10, 9) #define GENESIS_BLOCK_REWARD ((uint64_t)353190000000) // ~5% dev premine @@ -114,7 +114,7 @@ #define ALLOW_DEBUG_COMMANDS -#define CRYPTONOTE_NAME "Bixbite" +#define CRYPTONOTE_NAME "bixbite" #define CRYPTONOTE_POOLDATA_FILENAME "poolstate.bin" #define CRYPTONOTE_BLOCKCHAINDATA_FILENAME "blockchain.bin" #define CRYPTONOTE_BLOCKCHAINDATA_TEMP_FILENAME "blockchain.bin.tmp" @@ -124,10 +124,11 @@ #define THREAD_STACK_SIZE 5 * 1024 * 1024 // coin emission change interval/speed configs -#define COIN_EMISSION_MONTH_INTERVAL 6 // months to change emission speed -#define COIN_EMISSION_HEIGHT_INTERVAL ((uint64_t) (COIN_EMISSION_MONTH_INTERVAL * (30.4375 * 24 * 3600) / DIFFICULTY_TARGET)) // calculated to # of heights to change emission speed -#define PEAK_COIN_EMISSION_YEAR 4 -#define PEAK_COIN_EMISSION_HEIGHT ((uint64_t) (((12 * 30.4375 * 24 * 3600)/DIFFICULTY_TARGET) * PEAK_COIN_EMISSION_YEAR)) // = (# of heights emmitted per year) * PEAK_COIN_EMISSION_YEAR +//#define COIN_EMISSION_INTERVAL ((uint64_t) (12*(30.4375 * 24 * 3600) / DIFFICULTY_TARGET)) +//#define COIN_EMISSION_MONTH_INTERVAL 6 // months to change emission speed +//#define COIN_EMISSION_HEIGHT_INTERVAL ((uint64_t) (COIN_EMISSION_MONTH_INTERVAL * (30.4375 * 24 * 3600) / DIFFICULTY_TARGET)) // calculated to # of heights to change emission speed 157788 +//#define PEAK_COIN_EMISSION_YEAR 4 +//#define PEAK_COIN_EMISSION_HEIGHT ((uint64_t) (((12 * 30.4375 * 24 * 3600)/DIFFICULTY_TARGET) * PEAK_COIN_EMISSION_YEAR)) // = (# of heights emmitted per year) * PEAK_COIN_EMISSION_YEAR 1262304 #define DEFAULT_MIXIN 1 // default & minimum mixin allowed #define MAX_MIXIN 240 @@ -135,6 +136,10 @@ #define TRANSACTION_SIZE_LIMIT ((uint64_t) ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 110 / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE)) #define BLOCK_SIZE_GROWTH_FAVORED_ZONE ((uint64_t) (CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 4)) +#define LAST_VALIDATE_BLOCK_COUNT 2 +#define TIME_DEVIATION 5 + + // New constants are intended to go here namespace config { @@ -163,7 +168,7 @@ namespace config uint16_t const P2P_DEFAULT_PORT = 44050; uint16_t const RPC_DEFAULT_PORT = 44051; boost::uuids::uuid const NETWORK_ID = { { - 0x37 ,0x15, 0x44, 0x87 , 0x89, 0x23 , 0x11, 0x53, 0x02, 0x34, 0x22, 0x09, 0x73, 0xB3, 0x23, 0x11 + 0x37 ,0x15, 0x44, 0x87 , 0x90, 0x23 , 0x11, 0x53, 0x02, 0x34, 0x22, 0x09, 0x73, 0xB3, 0x23, 0x11 } }; // Bender's daydream std::string const GENESIS_TX ="021401ff000180eb8edea30a02cb4ecfd57729698c1ef4593b72d0e69aaa4bb33af93c419d50620d6b62b35d45210168f648e40914f26388a9e14d2536d28bfc4850c0c6c920b9d62c7a082bff360800"; uint32_t const GENESIS_NONCE = 10001; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 38a378c..c2f3c1b 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -82,7 +82,7 @@ static const struct { uint8_t threshold; time_t time; } mainnet_hard_forks[] = { - { 3, 1, 0, 1522800000 } + { 3, 1, 0, 1522540800 } }; static const uint64_t mainnet_hard_fork_version_1_till = (uint64_t)-1; @@ -679,9 +679,11 @@ difficulty_type Blockchain::get_difficulty_for_next_block() std::vector difficulties; auto height = m_db->height(); // Diff for start testnet network hashrate - /* if (m_testnet && (uint64_t)height >= 1 && (uint64_t)height <= 1 + (uint64_t)DIFFICULTY_BLOCKS_COUNT_V2){ - return (difficulty_type) 10000000; - }*/ + + //if (m_testnet && (uint64_t)height >= 1 && (uint64_t)height <= 1 + (uint64_t)DIFFICULTY_BLOCKS_COUNT_V2){ + // if (m_testnet && (uint64_t)height >= 1){ + // return (difficulty_type) 3; + // } // Reset network hashrate to 2.0 MHz when hardfork v3 comes /* if (!m_testnet && (uint64_t)height >= MAINNET_HARDFORK_V3_HEIGHT && (uint64_t)height <= MAINNET_HARDFORK_V3_HEIGHT + (uint64_t)DIFFICULTY_BLOCKS_COUNT_V2){ return (difficulty_type) 480000000; @@ -1053,6 +1055,8 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m b.major_version = m_hardfork->get_current_version(); b.minor_version = m_hardfork->get_ideal_version(); b.prev_id = get_tail_id(); + + b.timestamp = time(NULL); diffic = get_difficulty_for_next_block(); @@ -1060,7 +1064,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m median_size = m_current_block_cumul_sz_limit / 2; - cal_height = height - height % COIN_EMISSION_HEIGHT_INTERVAL; + cal_height = height;// - height % COIN_EMISSION_HEIGHT_INTERVAL; already_generated_coins = cal_height ? m_db->get_block_already_generated_coins(cal_height - 1) : 0; CRITICAL_REGION_END(); @@ -2677,7 +2681,7 @@ bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const uint64_t fee_per_kb; uint64_t median = m_current_block_cumul_sz_limit / 2; uint64_t height = m_db->height(); - uint64_t cal_height = height - height % COIN_EMISSION_HEIGHT_INTERVAL; + uint64_t cal_height = height;// - height % COIN_EMISSION_HEIGHT_INTERVAL; uint64_t cal_generated_coins = cal_height ? m_db->get_block_already_generated_coins(cal_height - 1) : 0; uint64_t base_reward; if (!get_block_reward(median, 1, cal_generated_coins, base_reward, height)) @@ -2714,7 +2718,7 @@ uint64_t Blockchain::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) cons //uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0; uint64_t height = m_db->height(); - uint64_t cal_height = height - height % COIN_EMISSION_HEIGHT_INTERVAL; + uint64_t cal_height = height;// - height % COIN_EMISSION_HEIGHT_INTERVAL; uint64_t cal_generated_coins = cal_height ? m_db->get_block_already_generated_coins(cal_height - 1) : 0; uint64_t base_reward; if (!get_block_reward(median, 1, cal_generated_coins, base_reward, height)) @@ -3171,7 +3175,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash& TIME_MEASURE_START(vmt); uint64_t base_reward = 0; uint64_t height = m_db->height(); - uint64_t cal_height = height - height % COIN_EMISSION_HEIGHT_INTERVAL; + uint64_t cal_height = height;// - height % COIN_EMISSION_HEIGHT_INTERVAL; uint64_t cal_generated_coins = cal_height ? m_db->get_block_already_generated_coins(cal_height - 1) : 0; if (!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, cal_generated_coins, bvc.m_partial_block_reward, m_hardfork->get_current_version())) { diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 5644de4..2786c50 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -293,6 +293,8 @@ namespace cryptonote */ difficulty_type get_difficulty_for_next_block(); + uint64_t get_timestamp1(const uint64_t& height){return m_db->get_block_timestamp1(height);} + /** * @brief adds a block to the blockchain * diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_core/checkpoints.cpp index f2ab7aa..a0668fb 100644 --- a/src/cryptonote_core/checkpoints.cpp +++ b/src/cryptonote_core/checkpoints.cpp @@ -159,11 +159,13 @@ namespace cryptonote bool checkpoints::init_default_checkpoints() { - /* ADD_CHECKPOINT(1, "82e8f378ea29d152146b6317903249751b809e97c0b6655f86e120b9de95c38a"); - ADD_CHECKPOINT(10, "e097b62bba41e5fd583d3a68de074cddd77c85a6158b031d963232146494a2d6"); - ADD_CHECKPOINT(100, "f3bd44c626cc12d449183ca84b58615d792523ba229385ff6717ab29a3e88926"); - ADD_CHECKPOINT(1000, "d284c992cb570f86c2e0bcfaa552b1d73bd40417e1c2a40f82bc6432217f0873"); - ADD_CHECKPOINT(3000, "81e040955b710dc5a5056668c4eaf3fbc4da2f72c0a63763250ede32a92e0f06"); + ADD_CHECKPOINT(1, "d3d68753010c173597a73c7177cfd64541f22055f8f3e13d39576f52a2da8bbf"); + ADD_CHECKPOINT(10, "8fc767b945930057ce0810f316ffada68320b39875d668154e988372966a350d"); + ADD_CHECKPOINT(50, "069f8ebd911c1a0d5e0a4f96d556304bf2fb42f642b4d86bc764a6db2cfec28e"); + ADD_CHECKPOINT(100, "9689170e48b3c92b80e5ec5983abcd58f3b0ba4cf982a24e9c163420f893b0ab"); + ADD_CHECKPOINT(1000, "360b96c3d0a5202c548672d550700d982ca15ad5627f70bce0a89dda840b3611"); + + /*ADD_CHECKPOINT(3000, "81e040955b710dc5a5056668c4eaf3fbc4da2f72c0a63763250ede32a92e0f06"); ADD_CHECKPOINT(5000, "e838c077bc66356d9bb321d4eb60f0851ef766f0619ddc4c6568a0f149aacea0"); ADD_CHECKPOINT(10000, "360b96c3d0a5202c548672d550700d982ca15ad5627f70bce0a89dda840b3611"); ADD_CHECKPOINT(20000, "603a45b60dd92ef4524c80d58411d09480b4668c54bc08dd651d838832bd399e"); @@ -176,9 +178,9 @@ namespace cryptonote } bool checkpoints::init_testnet_default_checkpoints() { - ADD_CHECKPOINT(1, "39faefeba90914037057bf70877c2b27a0b70968f4e77d7494441d4689182ac8"); + /* ADD_CHECKPOINT(1, "39faefeba90914037057bf70877c2b27a0b70968f4e77d7494441d4689182ac8"); ADD_CHECKPOINT(10, "ae49b879c8e92dcbf519b762d5e8408a3b8a7d8df3cd62ead4715b39691dbe7d"); - /*ADD_CHECKPOINT(100, "f3bd44c626cc12d449183ca84b58615d792523ba229385ff6717ab29a3e88926"); + ADD_CHECKPOINT(100, "f3bd44c626cc12d449183ca84b58615d792523ba229385ff6717ab29a3e88926"); ADD_CHECKPOINT(1000, "d284c992cb570f86c2e0bcfaa552b1d73bd40417e1c2a40f82bc6432217f0873"); ADD_CHECKPOINT(3000, "81e040955b710dc5a5056668c4eaf3fbc4da2f72c0a63763250ede32a92e0f06"); ADD_CHECKPOINT(5000, "e838c077bc66356d9bb321d4eb60f0851ef766f0619ddc4c6568a0f149aacea0"); @@ -229,17 +231,11 @@ namespace cryptonote // All bixbitePulse domains have DNSSEC on and valid static const std::vector dns_urls = { - "checkpoints.bixbitepulse.stream" - , "checkpoints.bixbitepulse.download" - , "checkpoints.bixbitepulse.win" - , "checkpoints.bixbitepulse.bid" - }; - - static const std::vector testnet_dns_urls = { - "testpoints.bixbitepulse.stream" - , "testpoints.bixbitepulse.download" - , "testpoints.bixbitepulse.win" - , "testpoints.bixbitepulse.bid" + "checkpoints.bixbite.pro", + "checkpoints.bxbnetwork.biz", + "checkpoints.bixbite.cc", + "checkpoints.bxbnetwork.biz", + "checkpoints.bixbite.cc" }; std::vector > records; @@ -255,16 +251,11 @@ namespace cryptonote do { std::string url; - if (testnet) - { - url = testnet_dns_urls[cur_index]; - } - else + if (!testnet) { url = dns_urls[cur_index]; } - - records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid); + records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid); if (!avail) { records[cur_index].clear(); @@ -296,7 +287,7 @@ namespace cryptonote if (num_valid_records < 2) { - LOG_PRINT_L0("WARNING: no two valid bixbitePulse DNS checkpoint records were received"); + LOG_PRINT_L0("WARNING: no two valid bixbitePulse DNS checkpoint records were received "< 0) + { + base_reward = (MONEY_SUPPLY - already_generated_coins) >> EMISSION_SPEED_FACTOR; + base_reward=base_reward/1.4822; + } + else + { + base_reward = GENESIS_BLOCK_REWARD; + base_reward = base_reward / 1000 * 1000; + } + + if (median_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) { + median_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + } + + if (current_block_size > 2 * median_size) { + LOG_PRINT_L1("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); + return false; + } + + if (current_block_size <= (median_size < BLOCK_SIZE_GROWTH_FAVORED_ZONE ? median_size * 110 / 100 : median_size)) { + reward = base_reward; + return true; + } + + assert(median_size < std::numeric_limits::max()); + assert(current_block_size < std::numeric_limits::max()); + + uint64_t product_hi; + // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being + // treated as 32-bit by default. + uint64_t multiplicand = 2 * median_size - current_block_size; + multiplicand *= current_block_size; + uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi); + + uint64_t reward_hi; + uint64_t reward_lo; + div128_32(product_hi, product_lo, static_cast(median_size), &reward_hi, &reward_lo); + div128_32(reward_hi, reward_lo, static_cast(median_size), &reward_hi, &reward_lo); + assert(0 == reward_hi); + assert(reward_lo < base_reward); + + reward = reward_lo; + return true; + + /* uint64_t base_reward; uint64_t round_factor = 1000; // 1 * pow(10, 7) if (height > 0) { - if (height < (PEAK_COIN_EMISSION_HEIGHT + COIN_EMISSION_HEIGHT_INTERVAL)) { - uint64_t interval_num = height / COIN_EMISSION_HEIGHT_INTERVAL; - double money_supply_pct = 0.1888 + interval_num*(0.023 + interval_num*0.0032); - base_reward = ((uint64_t)(MONEY_SUPPLY * money_supply_pct)) >> EMISSION_SPEED_FACTOR; - } - else{ - base_reward = (MONEY_SUPPLY - already_generated_coins) >> EMISSION_SPEED_FACTOR; - } + if (height < (PEAK_COIN_EMISSION_HEIGHT + COIN_EMISSION_HEIGHT_INTERVAL)) { + uint64_t interval_num = height / COIN_EMISSION_HEIGHT_INTERVAL; + double money_supply_pct = 0.1888 + interval_num*(0.023 + interval_num*0.0032); + base_reward = ((uint64_t)(MONEY_SUPPLY * money_supply_pct)) >> EMISSION_SPEED_FACTOR; + } + else{ + base_reward = (MONEY_SUPPLY - already_generated_coins) >> EMISSION_SPEED_FACTOR; + } } else { - base_reward = GENESIS_BLOCK_REWARD; + base_reward = GENESIS_BLOCK_REWARD; } if (base_reward < FINAL_SUBSIDY){ - if (MONEY_SUPPLY > already_generated_coins){ - base_reward = FINAL_SUBSIDY; - } - else{ - base_reward = FINAL_SUBSIDY/2; - } + if (MONEY_SUPPLY > already_generated_coins){ + base_reward = FINAL_SUBSIDY; + } + else{ + base_reward = FINAL_SUBSIDY/2; + } } // rounding (floor) base reward @@ -110,17 +156,17 @@ namespace cryptonote { //make it soft if (median_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) { - median_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; + median_size = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; } if (current_block_size > 2 * median_size) { - LOG_PRINT_L1("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); - return false; + LOG_PRINT_L1("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size); + return false; } if (current_block_size <= (median_size < BLOCK_SIZE_GROWTH_FAVORED_ZONE ? median_size * 110 / 100 : median_size)) { - reward = base_reward; - return true; + reward = base_reward; + return true; } assert(median_size < std::numeric_limits::max()); @@ -141,213 +187,214 @@ namespace cryptonote { assert(reward_lo < base_reward); reward = reward_lo; - return true; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_address_checksum(const public_address_outer_blob& bl) - { + return true;*/ +} +//------------------------------------------------------------------------------------ +uint8_t get_account_address_checksum(const public_address_outer_blob& bl) +{ const unsigned char* pbuf = reinterpret_cast(&bl); uint8_t summ = 0; for(size_t i = 0; i!= sizeof(public_address_outer_blob)-1; i++) - summ += pbuf[i]; + summ += pbuf[i]; return summ; - } - //------------------------------------------------------------------------------------ - uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl) - { +} +//------------------------------------------------------------------------------------ +uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl) +{ const unsigned char* pbuf = reinterpret_cast(&bl); uint8_t summ = 0; for(size_t i = 0; i!= sizeof(public_integrated_address_outer_blob)-1; i++) - summ += pbuf[i]; + summ += pbuf[i]; return summ; - } - //----------------------------------------------------------------------- - std::string get_account_address_as_str( - bool testnet - , bool subaddress - , account_public_address const & adr - ) - { +} +//----------------------------------------------------------------------- +std::string get_account_address_as_str( + bool testnet + , bool subaddress + , account_public_address const & adr + ) +{ uint64_t address_prefix = testnet ? - (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : - (subaddress ? config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); + (subaddress ? config::testnet::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) : + (subaddress ? config::CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX); return tools::base58::encode_addr(address_prefix, t_serializable_object_to_blob(adr)); - } - //----------------------------------------------------------------------- - std::string get_account_integrated_address_as_str( - bool testnet - , bool subaddress - , account_public_address const & adr - , crypto::hash8 const & payment_id - ) - { +} +//----------------------------------------------------------------------- +std::string get_account_integrated_address_as_str( + bool testnet + , bool subaddress + , account_public_address const & adr + , crypto::hash8 const & payment_id + ) +{ uint64_t integrated_address_prefix = testnet ? config::testnet::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : config::CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX; integrated_address iadr = { - adr, payment_id + adr, payment_id }; return tools::base58::encode_addr(integrated_address_prefix, t_serializable_object_to_blob(iadr)); - } - //----------------------------------------------------------------------- - bool is_coinbase(const transaction& tx) - { +} +//----------------------------------------------------------------------- +bool is_coinbase(const transaction& tx) +{ if(tx.vin.size() != 1) - return false; + return false; if(tx.vin[0].type() != typeid(txin_gen)) - return false; + return false; return true; - } - //----------------------------------------------------------------------- - bool get_account_address_from_str( - address_parse_info& info - , bool testnet - , std::string const & str - ) - { +} +//----------------------------------------------------------------------- +bool get_account_address_from_str( + address_parse_info& info + , bool testnet + , std::string const & str + ) +{ + LOG_PRINT_L1("is tesnet? "<(buff.data()); + public_address_outer_blob blob = *reinterpret_cast(buff.data()); - if (blob.m_ver > CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER) - { - LOG_PRINT_L1("Unknown version of public address: " << blob.m_ver << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER); - return false; - } + if (blob.m_ver > CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER) + { + LOG_PRINT_L1("Unknown version of public address: " << blob.m_ver << ", expected " << CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER); + return false; + } - if (blob.check_sum != get_account_address_checksum(blob)) - { - LOG_PRINT_L1("Wrong public address checksum"); - return false; - } + if (blob.check_sum != get_account_address_checksum(blob)) + { + LOG_PRINT_L1("Wrong public address checksum"); + return false; + } - //we success - info.address = blob.m_address; - info.is_subaddress = false; - info.has_payment_id = false; + //we success + info.address = blob.m_address; + info.is_subaddress = false; + info.has_payment_id = false; } return true; - } - //-------------------------------------------------------------------------------- - bool get_account_address_from_str_or_url( - address_parse_info& info - , bool testnet - , const std::string& str_or_url - , bool cli_confirm - ) - { +} +//-------------------------------------------------------------------------------- +bool get_account_address_from_str_or_url( + address_parse_info& info + , bool testnet + , const std::string& str_or_url + , bool cli_confirm + ) +{ if (get_account_address_from_str(info, testnet, str_or_url)) - return true; + return true; bool dnssec_valid; std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, cli_confirm); return !address_str.empty() && - get_account_address_from_str(info, testnet, address_str); - } + get_account_address_from_str(info, testnet, address_str); +} - bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { +bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { return cryptonote::get_transaction_hash(a) == cryptonote::get_transaction_hash(b); - } +} - bool operator ==(const cryptonote::block& a, const cryptonote::block& b) { +bool operator ==(const cryptonote::block& a, const cryptonote::block& b) { return cryptonote::get_block_hash(a) == cryptonote::get_block_hash(b); - } +} } //-------------------------------------------------------------------------------- bool parse_hash256(const std::string str_hash, crypto::hash& hash) { - std::string buf; - bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); - if (!res || buf.size() != sizeof(crypto::hash)) - { - std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; - return false; - } - else - { - buf.copy(reinterpret_cast(&hash), sizeof(crypto::hash)); - return true; - } + std::string buf; + bool res = epee::string_tools::parse_hexstr_to_binbuff(str_hash, buf); + if (!res || buf.size() != sizeof(crypto::hash)) + { + std::cout << "invalid hash format: <" << str_hash << '>' << std::endl; + return false; + } + else + { + buf.copy(reinterpret_cast(&hash), sizeof(crypto::hash)); + return true; + } } diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 7fffa52..1a32b2f 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -55,966 +55,1044 @@ DISABLE_VS_WARNINGS(4355) namespace cryptonote { - //----------------------------------------------------------------------------------------------- - core::core(i_cryptonote_protocol* pprotocol): - m_mempool(m_blockchain_storage), - m_blockchain_storage(m_mempool), - m_miner(this), - m_miner_address(boost::value_initialized()), - m_starter_message_showed(false), - m_target_blockchain_height(0), - m_checkpoints_path(""), - m_last_dns_checkpoints_update(0), - m_last_json_checkpoints_update(0) - { - set_cryptonote_protocol(pprotocol); - } - void core::set_cryptonote_protocol(i_cryptonote_protocol* pprotocol) - { - if(pprotocol) - m_pprotocol = pprotocol; - else - m_pprotocol = &m_protocol_stub; - } - //----------------------------------------------------------------------------------- - void core::set_checkpoints(checkpoints&& chk_pts) - { - m_blockchain_storage.set_checkpoints(std::move(chk_pts)); - } - //----------------------------------------------------------------------------------- - void core::set_checkpoints_file_path(const std::string& path) - { - m_checkpoints_path = path; - } - //----------------------------------------------------------------------------------- - void core::set_enforce_dns_checkpoints(bool enforce_dns) - { - m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns); - } - //----------------------------------------------------------------------------------------------- - bool core::update_checkpoints() - { - if (m_testnet || m_fakechain) return true; - - if (m_checkpoints_updating.test_and_set()) return true; - - bool res = true; - if (time(NULL) - m_last_dns_checkpoints_update >= 3600) - { - res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, true); - m_last_dns_checkpoints_update = time(NULL); - m_last_json_checkpoints_update = time(NULL); - } - else if (time(NULL) - m_last_json_checkpoints_update >= 600) - { - res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, false); - m_last_json_checkpoints_update = time(NULL); - } - - m_checkpoints_updating.clear(); - - // if anything fishy happened getting new checkpoints, bring down the house - if (!res) - { - graceful_exit(); - } - return res; - } - //----------------------------------------------------------------------------------- - void core::stop() - { - m_blockchain_storage.cancel(); - } - //----------------------------------------------------------------------------------- - void core::init_options(boost::program_options::options_description& desc) - { - command_line::add_arg(desc, command_line::arg_data_dir, tools::get_default_data_dir()); - command_line::add_arg(desc, command_line::arg_testnet_data_dir, (boost::filesystem::path(tools::get_default_data_dir()) / "testnet").string()); - - command_line::add_arg(desc, command_line::arg_test_drop_download); - command_line::add_arg(desc, command_line::arg_test_drop_download_height); - - command_line::add_arg(desc, command_line::arg_testnet_on); - command_line::add_arg(desc, command_line::arg_dns_checkpoints); - command_line::add_arg(desc, command_line::arg_db_type); - command_line::add_arg(desc, command_line::arg_prep_blocks_threads); - command_line::add_arg(desc, command_line::arg_fast_block_sync); - command_line::add_arg(desc, command_line::arg_db_sync_mode); - command_line::add_arg(desc, command_line::arg_show_time_stats); - command_line::add_arg(desc, command_line::arg_db_auto_remove_logs); - command_line::add_arg(desc, command_line::arg_block_sync_size); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_command_line(const boost::program_options::variables_map& vm) - { - m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on); - - auto data_dir_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir; - m_config_folder = command_line::get_arg(vm, data_dir_arg); - - auto data_dir = boost::filesystem::path(m_config_folder); - - if (!m_testnet && !m_fakechain) - { - cryptonote::checkpoints checkpoints; - if (!checkpoints.init_default_checkpoints()) - { - throw std::runtime_error("Failed to initialize checkpoints"); - } - set_checkpoints(std::move(checkpoints)); - - boost::filesystem::path json(JSON_HASH_FILE_NAME); - boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json; - - set_checkpoints_file_path(checkpoint_json_hashfile_fullpath.string()); - }else if(m_testnet) - { - cryptonote::checkpoints checkpoints; - if (!checkpoints.init_default_checkpoints()) + //----------------------------------------------------------------------------------------------- + core::core(i_cryptonote_protocol* pprotocol): + m_mempool(m_blockchain_storage), + m_blockchain_storage(m_mempool), + m_miner(this), + m_miner_address(boost::value_initialized()), + m_starter_message_showed(false), + m_target_blockchain_height(0), + m_checkpoints_path(""), + m_last_dns_checkpoints_update(0), + m_last_json_checkpoints_update(0) + { + set_cryptonote_protocol(pprotocol); + } + void core::set_cryptonote_protocol(i_cryptonote_protocol* pprotocol) + { + if(pprotocol) + m_pprotocol = pprotocol; + else + m_pprotocol = &m_protocol_stub; + } + //----------------------------------------------------------------------------------- + void core::set_checkpoints(checkpoints&& chk_pts) + { + m_blockchain_storage.set_checkpoints(std::move(chk_pts)); + } + //----------------------------------------------------------------------------------- + void core::set_checkpoints_file_path(const std::string& path) + { + m_checkpoints_path = path; + } + //----------------------------------------------------------------------------------- + void core::set_enforce_dns_checkpoints(bool enforce_dns) + { + m_blockchain_storage.set_enforce_dns_checkpoints(enforce_dns); + } + //----------------------------------------------------------------------------------------------- + bool core::update_checkpoints() + { + if (m_testnet || m_fakechain) return true; + + if (m_checkpoints_updating.test_and_set()) return true; + + bool res = true; + if (time(NULL) - m_last_dns_checkpoints_update >= 3600) { - throw std::runtime_error("Failed to initialize checkpoints"); + res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, true); + m_last_dns_checkpoints_update = time(NULL); + m_last_json_checkpoints_update = time(NULL); } - set_checkpoints(std::move(checkpoints)); - - boost::filesystem::path json(JSON_HASH_FILE_NAME); - boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json; - - set_checkpoints_file_path(checkpoint_json_hashfile_fullpath.string()); - } - - - set_enforce_dns_checkpoints(command_line::get_arg(vm, command_line::arg_dns_checkpoints)); - test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height)); - - if (command_line::get_arg(vm, command_line::arg_test_drop_download) == true) - test_drop_download(); - - return true; - } - //----------------------------------------------------------------------------------------------- - uint64_t core::get_current_blockchain_height() const - { - return m_blockchain_storage.get_current_blockchain_height(); - } - //----------------------------------------------------------------------------------------------- - bool core::get_blockchain_top(uint64_t& height, crypto::hash& top_id) const - { - top_id = m_blockchain_storage.get_tail_id(height); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const - { - return m_blockchain_storage.get_blocks(start_offset, count, blocks, txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks) const - { - return m_blockchain_storage.get_blocks(start_offset, count, blocks); - } //----------------------------------------------------------------------------------------------- - bool core::get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs) const - { - return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_alternative_blocks(std::list& blocks) const - { - return m_blockchain_storage.get_alternative_blocks(blocks); - } - //----------------------------------------------------------------------------------------------- - size_t core::get_alternative_blocks_count() const - { - return m_blockchain_storage.get_alternative_blocks_count(); - } - //----------------------------------------------------------------------------------------------- - bool core::lock_db_directory(const boost::filesystem::path &path) - { - // boost doesn't like locking directories... - const boost::filesystem::path lock_path = path / ".daemon_lock"; - - try - { - // ensure the file exists - std::ofstream(lock_path.string(), std::ios::out).close(); - - db_lock = boost::interprocess::file_lock(lock_path.string().c_str()); - LOG_PRINT_L1("Locking " << lock_path.string()); - if (!db_lock.try_lock()) - { - LOG_ERROR("Failed to lock " << lock_path.string()); - return false; - } - return true; - } - catch (const std::exception &e) - { - LOG_ERROR("Error trying to lock " << lock_path.string() << ": " << e.what()); - return false; - } - } - //----------------------------------------------------------------------------------------------- - bool core::unlock_db_directory() - { - db_lock.unlock(); - db_lock = boost::interprocess::file_lock(); - LOG_PRINT_L1("Blockchain directory successfully unlocked"); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options) - { - m_fakechain = test_options != NULL; - bool r = handle_command_line(vm); - - r = m_mempool.init(m_fakechain ? std::string() : m_config_folder); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); - - std::string db_type = command_line::get_arg(vm, command_line::arg_db_type); - std::string db_sync_mode = command_line::get_arg(vm, command_line::arg_db_sync_mode); - bool fast_sync = command_line::get_arg(vm, command_line::arg_fast_block_sync) != 0; - uint64_t blocks_threads = command_line::get_arg(vm, command_line::arg_prep_blocks_threads); - - boost::filesystem::path folder(m_config_folder); - if (m_fakechain) - folder /= "fake"; - - // make sure the data directory exists, and try to lock it - CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false, - std::string("Failed to create directory ").append(folder.string()).c_str()); - if (!lock_db_directory (folder)) - { - LOG_ERROR ("Failed to lock " << folder); - return false; - } - - // check for blockchain.bin - try - { - const boost::filesystem::path old_files = folder; - if (boost::filesystem::exists(old_files / "blockchain.bin")) - { - LOG_PRINT_RED_L0("Found old-style blockchain.bin in " << old_files.string()); - LOG_PRINT_RED_L0("Monero now uses a new format. You can either remove blockchain.bin to start syncing"); - LOG_PRINT_RED_L0("the blockchain anew, or use bixbite-blockchain-export and bixbite-blockchain-import to"); - LOG_PRINT_RED_L0("convert your existing blockchain.bin to the new format. See README.md for instructions."); - return false; - } + else if (time(NULL) - m_last_json_checkpoints_update >= 600) + { + res = m_blockchain_storage.update_checkpoints(m_checkpoints_path, false); + m_last_json_checkpoints_update = time(NULL); + } + + m_checkpoints_updating.clear(); + + // if anything fishy happened getting new checkpoints, bring down the house + if (!res) + { + graceful_exit(); + } + return res; + } + //----------------------------------------------------------------------------------- + void core::stop() + { + m_blockchain_storage.cancel(); + } + //----------------------------------------------------------------------------------- + void core::init_options(boost::program_options::options_description& desc) + { + command_line::add_arg(desc, command_line::arg_data_dir, tools::get_default_data_dir()); + command_line::add_arg(desc, command_line::arg_testnet_data_dir, (boost::filesystem::path(tools::get_default_data_dir()) / "testnet").string()); + + command_line::add_arg(desc, command_line::arg_test_drop_download); + command_line::add_arg(desc, command_line::arg_test_drop_download_height); + + command_line::add_arg(desc, command_line::arg_testnet_on); + command_line::add_arg(desc, command_line::arg_dns_checkpoints); + command_line::add_arg(desc, command_line::arg_db_type); + command_line::add_arg(desc, command_line::arg_prep_blocks_threads); + command_line::add_arg(desc, command_line::arg_fast_block_sync); + command_line::add_arg(desc, command_line::arg_db_sync_mode); + command_line::add_arg(desc, command_line::arg_show_time_stats); + command_line::add_arg(desc, command_line::arg_db_auto_remove_logs); + command_line::add_arg(desc, command_line::arg_block_sync_size); } - // folder might not be a directory, etc, etc - catch (...) { } + //----------------------------------------------------------------------------------------------- + bool core::handle_command_line(const boost::program_options::variables_map& vm) + { + m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on); + + auto data_dir_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir; + m_config_folder = command_line::get_arg(vm, data_dir_arg); - BlockchainDB* db = nullptr; - uint64_t DBS_FAST_MODE = 0; - uint64_t DBS_FASTEST_MODE = 0; - uint64_t DBS_SAFE_MODE = 0; - if (db_type == "lmdb") + auto data_dir = boost::filesystem::path(m_config_folder); + + if (!m_testnet && !m_fakechain) + { + cryptonote::checkpoints checkpoints; + if (!checkpoints.init_default_checkpoints()) + { + throw std::runtime_error("Failed to initialize checkpoints"); + } + set_checkpoints(std::move(checkpoints)); + + boost::filesystem::path json(JSON_HASH_FILE_NAME); + boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json; + + set_checkpoints_file_path(checkpoint_json_hashfile_fullpath.string()); + }else if(m_testnet) + { + cryptonote::checkpoints checkpoints; + if (!checkpoints.init_default_checkpoints()) + { + throw std::runtime_error("Failed to initialize checkpoints"); + } + set_checkpoints(std::move(checkpoints)); + + boost::filesystem::path json(JSON_HASH_FILE_NAME); + boost::filesystem::path checkpoint_json_hashfile_fullpath = data_dir / json; + + set_checkpoints_file_path(checkpoint_json_hashfile_fullpath.string()); + } + + + set_enforce_dns_checkpoints(command_line::get_arg(vm, command_line::arg_dns_checkpoints)); + test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height)); + + if (command_line::get_arg(vm, command_line::arg_test_drop_download) == true) + test_drop_download(); + + return true; + } + //----------------------------------------------------------------------------------------------- + uint64_t core::get_current_blockchain_height() const + { + return m_blockchain_storage.get_current_blockchain_height(); + } + //----------------------------------------------------------------------------------------------- + bool core::get_blockchain_top(uint64_t& height, crypto::hash& top_id) const + { + top_id = m_blockchain_storage.get_tail_id(height); + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks, std::list& txs) const + { + return m_blockchain_storage.get_blocks(start_offset, count, blocks, txs); + } + //----------------------------------------------------------------------------------------------- + bool core::get_blocks(uint64_t start_offset, size_t count, std::list& blocks) const + { + return m_blockchain_storage.get_blocks(start_offset, count, blocks); + } //----------------------------------------------------------------------------------------------- + bool core::get_transactions(const std::vector& txs_ids, std::list& txs, std::list& missed_txs) const + { + return m_blockchain_storage.get_transactions(txs_ids, txs, missed_txs); + } + //----------------------------------------------------------------------------------------------- + bool core::get_alternative_blocks(std::list& blocks) const + { + return m_blockchain_storage.get_alternative_blocks(blocks); + } + //----------------------------------------------------------------------------------------------- + size_t core::get_alternative_blocks_count() const + { + return m_blockchain_storage.get_alternative_blocks_count(); + } + //----------------------------------------------------------------------------------------------- + bool core::lock_db_directory(const boost::filesystem::path &path) + { + // boost doesn't like locking directories... + const boost::filesystem::path lock_path = path / ".daemon_lock"; + + try + { + // ensure the file exists + std::ofstream(lock_path.string(), std::ios::out).close(); + + db_lock = boost::interprocess::file_lock(lock_path.string().c_str()); + LOG_PRINT_L1("Locking " << lock_path.string()); + if (!db_lock.try_lock()) + { + LOG_ERROR("Failed to lock " << lock_path.string()); + return false; + } + return true; + } + catch (const std::exception &e) + { + LOG_ERROR("Error trying to lock " << lock_path.string() << ": " << e.what()); + return false; + } + } + //----------------------------------------------------------------------------------------------- + bool core::unlock_db_directory() { - db = new BlockchainLMDB(); - DBS_SAFE_MODE = MDB_NORDAHEAD; - DBS_FAST_MODE = MDB_NORDAHEAD | MDB_NOSYNC; - DBS_FASTEST_MODE = MDB_NORDAHEAD | MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC; + db_lock.unlock(); + db_lock = boost::interprocess::file_lock(); + LOG_PRINT_L1("Blockchain directory successfully unlocked"); + return true; } - else if (db_type == "berkeley") + //----------------------------------------------------------------------------------------------- + bool core::init(const boost::program_options::variables_map& vm, const cryptonote::test_options *test_options) { + m_fakechain = test_options != NULL; + bool r = handle_command_line(vm); + + r = m_mempool.init(m_fakechain ? std::string() : m_config_folder); + CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); + + std::string db_type = command_line::get_arg(vm, command_line::arg_db_type); + std::string db_sync_mode = command_line::get_arg(vm, command_line::arg_db_sync_mode); + bool fast_sync = command_line::get_arg(vm, command_line::arg_fast_block_sync) != 0; + uint64_t blocks_threads = command_line::get_arg(vm, command_line::arg_prep_blocks_threads); + + boost::filesystem::path folder(m_config_folder); + if (m_fakechain) + folder /= "fake"; + + // make sure the data directory exists, and try to lock it + CHECK_AND_ASSERT_MES (boost::filesystem::exists(folder) || boost::filesystem::create_directories(folder), false, + std::string("Failed to create directory ").append(folder.string()).c_str()); + if (!lock_db_directory (folder)) + { + LOG_ERROR ("Failed to lock " << folder); + return false; + } + + // check for blockchain.bin + try + { + const boost::filesystem::path old_files = folder; + if (boost::filesystem::exists(old_files / "blockchain.bin")) + { + LOG_PRINT_RED_L0("Found old-style blockchain.bin in " << old_files.string()); + LOG_PRINT_RED_L0("Monero now uses a new format. You can either remove blockchain.bin to start syncing"); + LOG_PRINT_RED_L0("the blockchain anew, or use bixbite-blockchain-export and bixbite-blockchain-import to"); + LOG_PRINT_RED_L0("convert your existing blockchain.bin to the new format. See README.md for instructions."); + return false; + } + } + // folder might not be a directory, etc, etc + catch (...) { } + + BlockchainDB* db = nullptr; + uint64_t DBS_FAST_MODE = 0; + uint64_t DBS_FASTEST_MODE = 0; + uint64_t DBS_SAFE_MODE = 0; + if (db_type == "lmdb") + { + db = new BlockchainLMDB(); + DBS_SAFE_MODE = MDB_NORDAHEAD; + DBS_FAST_MODE = MDB_NORDAHEAD | MDB_NOSYNC; + DBS_FASTEST_MODE = MDB_NORDAHEAD | MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC; + } + else if (db_type == "berkeley") + { #if defined(BERKELEY_DB) - db = new BlockchainBDB(); - DBS_FAST_MODE = DB_TXN_WRITE_NOSYNC; - DBS_FASTEST_MODE = DB_TXN_NOSYNC; - DBS_SAFE_MODE = DB_TXN_SYNC; + db = new BlockchainBDB(); + DBS_FAST_MODE = DB_TXN_WRITE_NOSYNC; + DBS_FASTEST_MODE = DB_TXN_NOSYNC; + DBS_SAFE_MODE = DB_TXN_SYNC; #else - LOG_ERROR("BerkeleyDB support disabled."); - return false; + LOG_ERROR("BerkeleyDB support disabled."); + return false; #endif + } + else + { + LOG_ERROR("Attempted to use non-existent database type"); + return false; + } + + folder /= db->get_db_name(); + LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ..."); + + const std::string filename = folder.string(); + // temporarily default to fastest:async:1000 + blockchain_db_sync_mode sync_mode = db_async; + uint64_t blocks_per_sync = 1000; + + try + { + uint64_t db_flags = 0; + + std::vector options; + boost::trim(db_sync_mode); + boost::split(options, db_sync_mode, boost::is_any_of(" :")); + + for(const auto &option : options) + LOG_PRINT_L0("option: " << option); + + // default to fast:async:1000 + uint64_t DEFAULT_FLAGS = DBS_FAST_MODE; + + if(options.size() == 0) + { + // temporarily default to fastest:async:1000 + db_flags = DEFAULT_FLAGS; + } + + bool safemode = false; + if(options.size() >= 1) + { + if(options[0] == "safe") + { + safemode = true; + db_flags = DBS_SAFE_MODE; + sync_mode = db_nosync; + } + else if(options[0] == "fast") + db_flags = DBS_FAST_MODE; + else if(options[0] == "fastest") + db_flags = DBS_FASTEST_MODE; + else + db_flags = DEFAULT_FLAGS; + } + + if(options.size() >= 2 && !safemode) + { + if(options[1] == "sync") + sync_mode = db_sync; + else if(options[1] == "async") + sync_mode = db_async; + } + + if(options.size() >= 3 && !safemode) + { + char *endptr; + uint64_t bps = strtoull(options[2].c_str(), &endptr, 0); + if (*endptr == '\0') + blocks_per_sync = bps; + } + + bool auto_remove_logs = command_line::get_arg(vm, command_line::arg_db_auto_remove_logs) != 0; + db->set_auto_remove_logs(auto_remove_logs); + db->open(filename, db_flags); + if(!db->m_open) + return false; + } + catch (const DB_ERROR& e) + { + LOG_ERROR("Error opening database: " << e.what()); + return false; + } + + m_blockchain_storage.set_user_options(blocks_threads, + blocks_per_sync, sync_mode, fast_sync); + + r = m_blockchain_storage.init(db, m_testnet, test_options); + + // now that we have a valid m_blockchain_storage, we can clean out any + // transactions in the pool that do not conform to the current fork + m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version()); + + bool show_time_stats = command_line::get_arg(vm, command_line::arg_show_time_stats) != 0; + m_blockchain_storage.set_show_time_stats(show_time_stats); + CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); + + block_sync_size = command_line::get_arg(vm, command_line::arg_block_sync_size); + if (block_sync_size == 0) + block_sync_size = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; + + // load json & DNS checkpoints, and verify them + // with respect to what blocks we already have + CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); + + r = m_miner.init(vm, m_testnet); + CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); + + return load_state_data(); } - else + //----------------------------------------------------------------------------------------------- + bool core::set_genesis_block(const block& b) { - LOG_ERROR("Attempted to use non-existent database type"); - return false; + return m_blockchain_storage.reset_and_set_genesis_block(b); } + //----------------------------------------------------------------------------------------------- + bool core::load_state_data() + { + // may be some code later + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::deinit() + { + m_miner.stop(); + m_mempool.deinit(); + m_blockchain_storage.deinit(); + unlock_db_directory(); + return true; + } + //----------------------------------------------------------------------------------------------- + void core::test_drop_download() + { + m_test_drop_download = false; + } + //----------------------------------------------------------------------------------------------- + void core::test_drop_download_height(uint64_t height) + { + m_test_drop_download_height = height; + } + //----------------------------------------------------------------------------------------------- + bool core::get_test_drop_download() const + { + return m_test_drop_download; + } + //----------------------------------------------------------------------------------------------- + bool core::get_test_drop_download_height() const + { + if (m_test_drop_download_height == 0) + return true; - folder /= db->get_db_name(); - LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ..."); - - const std::string filename = folder.string(); - // temporarily default to fastest:async:1000 - blockchain_db_sync_mode sync_mode = db_async; - uint64_t blocks_per_sync = 1000; + if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height) + return true; - try + return false; + } + //----------------------------------------------------------------------------------------------- + bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed) { - uint64_t db_flags = 0; + tvc = boost::value_initialized(); + //want to process all transactions sequentially + CRITICAL_REGION_LOCAL(m_incoming_tx_lock); - std::vector options; - boost::trim(db_sync_mode); - boost::split(options, db_sync_mode, boost::is_any_of(" :")); + if(tx_blob.size() > get_max_tx_size()) + { + LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected"); + tvc.m_verifivation_failed = true; + tvc.m_too_big = true; + return false; + } - for(const auto &option : options) - LOG_PRINT_L0("option: " << option); + crypto::hash tx_hash = null_hash; + crypto::hash tx_prefixt_hash = null_hash; + transaction tx; - // default to fast:async:1000 - uint64_t DEFAULT_FLAGS = DBS_FAST_MODE; + if(!parse_tx_from_blob(tx, tx_hash, tx_prefixt_hash, tx_blob)) + { + LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected"); + tvc.m_verifivation_failed = true; + return false; + } + //std::cout << "!"<< tx.vin.size() << std::endl; - if(options.size() == 0) - { - // temporarily default to fastest:async:1000 - db_flags = DEFAULT_FLAGS; - } + //uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); + const size_t max_tx_version = CURRENT_TRANSACTION_VERSION; + if (tx.version == 0 || tx.version > max_tx_version) + { + // v2 is the latest one we know + tvc.m_verifivation_failed = true; + return false; + } - bool safemode = false; - if(options.size() >= 1) - { - if(options[0] == "safe") + if(!check_tx_syntax(tx)) { - safemode = true; - db_flags = DBS_SAFE_MODE; - sync_mode = db_nosync; + LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected"); + tvc.m_verifivation_failed = true; + return false; } - else if(options[0] == "fast") - db_flags = DBS_FAST_MODE; - else if(options[0] == "fastest") - db_flags = DBS_FASTEST_MODE; - else - db_flags = DEFAULT_FLAGS; - } - - if(options.size() >= 2 && !safemode) - { - if(options[1] == "sync") - sync_mode = db_sync; - else if(options[1] == "async") - sync_mode = db_async; - } - - if(options.size() >= 3 && !safemode) - { - char *endptr; - uint64_t bps = strtoull(options[2].c_str(), &endptr, 0); - if (*endptr == '\0') - blocks_per_sync = bps; - } - - bool auto_remove_logs = command_line::get_arg(vm, command_line::arg_db_auto_remove_logs) != 0; - db->set_auto_remove_logs(auto_remove_logs); - db->open(filename, db_flags); - if(!db->m_open) - return false; + + if(!check_tx_semantic(tx, keeped_by_block)) + { + LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected"); + tvc.m_verifivation_failed = true; + return false; + } + + bool r = add_new_tx(tx, tx_hash, tx_prefixt_hash, tx_blob.size(), tvc, keeped_by_block, relayed); + if(tvc.m_verifivation_failed) + {LOG_PRINT_RED_L1("Transaction verification failed: " << tx_hash);} + else if(tvc.m_verifivation_impossible) + {LOG_PRINT_RED_L1("Transaction verification impossible: " << tx_hash);} + + if(tvc.m_added_to_pool) + LOG_PRINT_L1("tx added: " << tx_hash); + return r; } - catch (const DB_ERROR& e) + //----------------------------------------------------------------------------------------------- + bool core::get_stat_info(core_stat_info& st_inf) const { - LOG_ERROR("Error opening database: " << e.what()); - return false; + st_inf.mining_speed = m_miner.get_speed(); + st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count(); + st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_height(); + st_inf.tx_pool_size = m_mempool.get_transactions_count(); + st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_tail_id()); + return true; } - m_blockchain_storage.set_user_options(blocks_threads, - blocks_per_sync, sync_mode, fast_sync); + //----------------------------------------------------------------------------------------------- + bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const + { + if(!tx.vin.size()) + { + LOG_PRINT_RED_L1("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx)); + return false; + } + + if(!check_inputs_types_supported(tx)) + { + LOG_PRINT_RED_L1("unsupported input types for tx id= " << get_transaction_hash(tx)); + return false; + } + + if(!check_outs_valid(tx)) + { + LOG_PRINT_RED_L1("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx)); + return false; + } + if (tx.version > 1) + { + if (tx.rct_signatures.outPk.size() != tx.vout.size()) + { + LOG_PRINT_RED_L1("tx with mismatched vout/outPk count, rejected for tx id= " << get_transaction_hash(tx)); + return false; + } + } - r = m_blockchain_storage.init(db, m_testnet, test_options); + if(!check_money_overflow(tx)) + { + LOG_PRINT_RED_L1("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx)); + return false; + } - // now that we have a valid m_blockchain_storage, we can clean out any - // transactions in the pool that do not conform to the current fork - m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version()); + if (tx.version == 1) + { + 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_L1("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx)); + return false; + } + } + // for version > 1, ringct signatures check verifies amounts match - bool show_time_stats = command_line::get_arg(vm, command_line::arg_show_time_stats) != 0; - m_blockchain_storage.set_show_time_stats(show_time_stats); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); + if(!keeped_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE) + { + LOG_PRINT_RED_L1("tx is too large " << get_object_blobsize(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); + return false; + } - block_sync_size = command_line::get_arg(vm, command_line::arg_block_sync_size); - if (block_sync_size == 0) - block_sync_size = BLOCKS_SYNCHRONIZING_DEFAULT_COUNT; + //check if tx use different key images + if(!check_tx_inputs_keyimages_diff(tx)) + { + LOG_PRINT_RED_L1("tx uses a single key image more than once"); + return false; + } - // load json & DNS checkpoints, and verify them - // with respect to what blocks we already have - CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); + if (!check_tx_inputs_keyimages_domain(tx)) + { + LOG_PRINT_RED_L1("tx uses key image not in the valid domain"); + return false; + } - r = m_miner.init(vm, m_testnet); - CHECK_AND_ASSERT_MES(r, false, "Failed to initialize miner instance"); - return load_state_data(); - } - //----------------------------------------------------------------------------------------------- - bool core::set_genesis_block(const block& b) - { - return m_blockchain_storage.reset_and_set_genesis_block(b); - } - //----------------------------------------------------------------------------------------------- - bool core::load_state_data() - { - // may be some code later - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::deinit() - { - m_miner.stop(); - m_mempool.deinit(); - m_blockchain_storage.deinit(); - unlock_db_directory(); - return true; - } - //----------------------------------------------------------------------------------------------- - void core::test_drop_download() - { - m_test_drop_download = false; - } - //----------------------------------------------------------------------------------------------- - void core::test_drop_download_height(uint64_t height) - { - m_test_drop_download_height = height; - } - //----------------------------------------------------------------------------------------------- - bool core::get_test_drop_download() const - { - return m_test_drop_download; - } - //----------------------------------------------------------------------------------------------- - bool core::get_test_drop_download_height() const - { - if (m_test_drop_download_height == 0) - return true; - - if (get_blockchain_storage().get_current_blockchain_height() <= m_test_drop_download_height) - return true; - - return false; - } - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block, bool relayed) - { - tvc = boost::value_initialized(); - //want to process all transactions sequentially - CRITICAL_REGION_LOCAL(m_incoming_tx_lock); - - if(tx_blob.size() > get_max_tx_size()) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_blob.size() << ", rejected"); - tvc.m_verifivation_failed = true; - tvc.m_too_big = true; - return false; - } - - crypto::hash tx_hash = null_hash; - crypto::hash tx_prefixt_hash = null_hash; - transaction tx; - - if(!parse_tx_from_blob(tx, tx_hash, tx_prefixt_hash, tx_blob)) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected"); - tvc.m_verifivation_failed = true; - return false; - } - //std::cout << "!"<< tx.vin.size() << std::endl; - - //uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); - const size_t max_tx_version = CURRENT_TRANSACTION_VERSION; - if (tx.version == 0 || tx.version > max_tx_version) - { - // v2 is the latest one we know - tvc.m_verifivation_failed = true; - return false; - } - - if(!check_tx_syntax(tx)) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " syntax, rejected"); - tvc.m_verifivation_failed = true; - return false; - } - - if(!check_tx_semantic(tx, keeped_by_block)) - { - LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected"); - tvc.m_verifivation_failed = true; - return false; - } - - bool r = add_new_tx(tx, tx_hash, tx_prefixt_hash, tx_blob.size(), tvc, keeped_by_block, relayed); - if(tvc.m_verifivation_failed) - {LOG_PRINT_RED_L1("Transaction verification failed: " << tx_hash);} - else if(tvc.m_verifivation_impossible) - {LOG_PRINT_RED_L1("Transaction verification impossible: " << tx_hash);} - - if(tvc.m_added_to_pool) - LOG_PRINT_L1("tx added: " << tx_hash); - return r; - } - //----------------------------------------------------------------------------------------------- - bool core::get_stat_info(core_stat_info& st_inf) const - { - st_inf.mining_speed = m_miner.get_speed(); - st_inf.alternative_blocks = m_blockchain_storage.get_alternative_blocks_count(); - st_inf.blockchain_height = m_blockchain_storage.get_current_blockchain_height(); - st_inf.tx_pool_size = m_mempool.get_transactions_count(); - st_inf.top_block_id_str = epee::string_tools::pod_to_hex(m_blockchain_storage.get_tail_id()); - return true; - } - - //----------------------------------------------------------------------------------------------- - bool core::check_tx_semantic(const transaction& tx, bool keeped_by_block) const - { - if(!tx.vin.size()) + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::is_key_image_spent(const crypto::key_image &key_image) const + { + return m_blockchain_storage.have_tx_keyimg_as_spent(key_image); + } + //----------------------------------------------------------------------------------------------- + bool core::are_key_images_spent(const std::vector& key_im, std::vector &spent) const + { + spent.clear(); + BOOST_FOREACH(auto& ki, key_im) + { + spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki)); + } + return true; + } + //----------------------------------------------------------------------------------------------- + std::pair core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count) + { + std::list blocks; + uint64_t coinbase_amount = 0; + uint64_t emission_amount = 0; + uint64_t total_fee_amount = 0; + uint64_t tx_fee_amount = 0; + this->get_blocks(start_offset, count, blocks); + BOOST_FOREACH(auto& b, blocks) + { + coinbase_amount = get_outs_money_amount(b.miner_tx); + std::list txs; + std::list missed_txs; + this->get_transactions(b.tx_hashes, txs, missed_txs); + BOOST_FOREACH(const auto& tx, txs) + { + tx_fee_amount += get_tx_fee(tx); + } + + emission_amount += coinbase_amount - tx_fee_amount; + total_fee_amount += tx_fee_amount; + coinbase_amount = 0; + tx_fee_amount = 0; + } + + return std::pair(emission_amount, total_fee_amount); + } + //----------------------------------------------------------------------------------------------- + bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const + { + std::unordered_set ki; + BOOST_FOREACH(const auto& in, tx.vin) + { + 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::check_tx_inputs_keyimages_domain(const transaction& tx) const { - LOG_PRINT_RED_L1("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx)); - return false; + std::unordered_set ki; + for(const auto& in: tx.vin) + { + CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); + if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity())) + return false; + } + return true; } - if(!check_inputs_types_supported(tx)) + //----------------------------------------------------------------------------------------------- + bool core::add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block, bool relayed) + { + crypto::hash tx_hash = get_transaction_hash(tx); + crypto::hash tx_prefix_hash = get_transaction_prefix_hash(tx); + blobdata bl; + t_serializable_object_to_blob(tx, bl); + return add_new_tx(tx, tx_hash, tx_prefix_hash, bl.size(), tvc, keeped_by_block, relayed); + } + //----------------------------------------------------------------------------------------------- + size_t core::get_blockchain_total_transactions() const { - LOG_PRINT_RED_L1("unsupported input types for tx id= " << get_transaction_hash(tx)); - return false; + return m_blockchain_storage.get_total_transactions(); } + //----------------------------------------------------------------------------------------------- + bool core::add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block, bool relayed) + { + if(m_mempool.have_tx(tx_hash)) + { + LOG_PRINT_L2("tx " << tx_hash << "already have transaction in tx_pool"); + return true; + } - if(!check_outs_valid(tx)) + if(m_blockchain_storage.have_tx(tx_hash)) + { + LOG_PRINT_L2("tx " << tx_hash << " already have transaction in blockchain"); + return true; + } + + uint8_t version = m_blockchain_storage.get_current_hard_fork_version(); + return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block, relayed, version); + } + //----------------------------------------------------------------------------------------------- + bool core::relay_txpool_transactions() { - LOG_PRINT_RED_L1("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx)); - return false; + // we attempt to relay txes that should be relayed, but were not + std::list> txs; + if (m_mempool.get_relayable_transactions(txs)) + { + cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context); + tx_verification_context tvc = AUTO_VAL_INIT(tvc); + NOTIFY_NEW_TRANSACTIONS::request r; + blobdata bl; + for (auto it = txs.begin(); it != txs.end(); ++it) + { + t_serializable_object_to_blob(it->second, bl); + r.txs.push_back(bl); + } + get_protocol()->relay_transactions(r, fake_context); + m_mempool.set_relayed(txs); + } + return true; } - if (tx.version > 1) + //----------------------------------------------------------------------------------------------- + void core::on_transaction_relayed(const cryptonote::blobdata& tx_blob) { - if (tx.rct_signatures.outPk.size() != tx.vout.size()) - { - LOG_PRINT_RED_L1("tx with mismatched vout/outPk count, rejected for tx id= " << get_transaction_hash(tx)); - return false; - } + std::list> txs; + cryptonote::transaction tx; + crypto::hash tx_hash, tx_prefix_hash; + if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash)) + { + LOG_ERROR("Failed to parse relayed transaction"); + return; + } + txs.push_back(std::make_pair(tx_hash, std::move(tx))); + m_mempool.set_relayed(txs); + } + //----------------------------------------------------------------------------------------------- + bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce) + { + return m_blockchain_storage.create_block_template(b, adr, diffic, height, ex_nonce); + } + //----------------------------------------------------------------------------------------------- + bool core::find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const + { + return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp); + } + //----------------------------------------------------------------------------------------------- + bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const + { + return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, max_count); + } + //----------------------------------------------------------------------------------------------- + void core::print_blockchain(uint64_t start_index, uint64_t end_index) const + { + m_blockchain_storage.print_blockchain(start_index, end_index); + } + //----------------------------------------------------------------------------------------------- + void core::print_blockchain_index() const + { + m_blockchain_storage.print_blockchain_index(); + } + //----------------------------------------------------------------------------------------------- + void core::print_blockchain_outs(const std::string& file) + { + m_blockchain_storage.print_blockchain_outs(file); + } + //----------------------------------------------------------------------------------------------- + bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const + { + return m_blockchain_storage.get_random_outs_for_amounts(req, res); + } + //----------------------------------------------------------------------------------------------- + bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const + { + return m_blockchain_storage.get_outs(req, res); + } + //----------------------------------------------------------------------------------------------- + bool core::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) const + { + return m_blockchain_storage.get_random_rct_outs(req, res); + } + //----------------------------------------------------------------------------------------------- + bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) const + { + return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs); + } + //----------------------------------------------------------------------------------------------- + void core::pause_mine() + { + m_miner.pause(); + } + //----------------------------------------------------------------------------------------------- + void core::resume_mine() + { + m_miner.resume(); + } + //----------------------------------------------------------------------------------------------- + bool core::handle_block_found(block& b) + { + /* if((get_timestamp_top_block()+(DIFFICULTY_TARGET/3))>=b.timestamp) + { + //bvc.m_verifivation_failed=true; + m_miner.pause(); + update_miner_block_template(); + m_miner.resume(); + return false; + }*/ + block_verification_context bvc = boost::value_initialized(); + m_miner.pause(); + m_blockchain_storage.add_new_block(b, bvc); + //anyway - update miner template + update_miner_block_template(); + m_miner.resume(); + + + CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "mined block failed verification"); + if(bvc.m_added_to_main_chain) + { + cryptonote_connection_context exclude_context = boost::value_initialized(); + NOTIFY_NEW_BLOCK::request arg = AUTO_VAL_INIT(arg); + arg.hop = 0; + arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height(); + std::list missed_txs; + std::list txs; + m_blockchain_storage.get_transactions(b.tx_hashes, txs, missed_txs); + if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) + { + LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block"); + return true; + } + CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "cant find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size() + << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size()); + + block_to_blob(b, arg.b.block); + //pack transactions + BOOST_FOREACH(auto& tx, txs) + arg.b.txs.push_back(t_serializable_object_to_blob(tx)); + + m_pprotocol->relay_block(arg, exclude_context); + } + return bvc.m_added_to_main_chain; + } + //----------------------------------------------------------------------------------------------- + void core::on_synchronized() + { + m_miner.on_synchronized(); + } + //----------------------------------------------------------------------------------------------- + bool core::add_new_block(const block& b, block_verification_context& bvc) + { + return m_blockchain_storage.add_new_block(b, bvc); } - if(!check_money_overflow(tx)) + //----------------------------------------------------------------------------------------------- + bool core::prepare_handle_incoming_blocks(const std::list &blocks) { - LOG_PRINT_RED_L1("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx)); - return false; + m_blockchain_storage.prepare_handle_incoming_blocks(blocks); + return true; } - if (tx.version == 1) + //----------------------------------------------------------------------------------------------- + bool core::cleanup_handle_incoming_blocks(bool force_sync) { - uint64_t amount_in = 0; - get_inputs_money_amount(tx, amount_in); - uint64_t amount_out = get_outs_money_amount(tx); + m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync); + return true; + } - if(amount_in <= amount_out) - { - LOG_PRINT_RED_L1("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx)); - return false; - } - } - // for version > 1, ringct signatures check verifies amounts match - - if(!keeped_by_block && get_object_blobsize(tx) >= m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE) - { - LOG_PRINT_RED_L1("tx is too large " << get_object_blobsize(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_blocksize_limit() - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE); - return false; - } - - //check if tx use different key images - if(!check_tx_inputs_keyimages_diff(tx)) - { - LOG_PRINT_RED_L1("tx uses a single key image more than once"); - return false; - } - - if (!check_tx_inputs_keyimages_domain(tx)) - { - LOG_PRINT_RED_L1("tx uses key image not in the valid domain"); - return false; - } - - - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::is_key_image_spent(const crypto::key_image &key_image) const - { - return m_blockchain_storage.have_tx_keyimg_as_spent(key_image); - } - //----------------------------------------------------------------------------------------------- - bool core::are_key_images_spent(const std::vector& key_im, std::vector &spent) const - { - spent.clear(); - BOOST_FOREACH(auto& ki, key_im) - { - spent.push_back(m_blockchain_storage.have_tx_keyimg_as_spent(ki)); - } - return true; - } - //----------------------------------------------------------------------------------------------- - std::pair core::get_coinbase_tx_sum(const uint64_t start_offset, const size_t count) - { - std::list blocks; - uint64_t coinbase_amount = 0; - uint64_t emission_amount = 0; - uint64_t total_fee_amount = 0; - uint64_t tx_fee_amount = 0; - this->get_blocks(start_offset, count, blocks); - BOOST_FOREACH(auto& b, blocks) - { - coinbase_amount = get_outs_money_amount(b.miner_tx); - std::list txs; - std::list missed_txs; - this->get_transactions(b.tx_hashes, txs, missed_txs); - BOOST_FOREACH(const auto& tx, txs) - { - tx_fee_amount += get_tx_fee(tx); - } - - emission_amount += coinbase_amount - tx_fee_amount; - total_fee_amount += tx_fee_amount; - coinbase_amount = 0; - tx_fee_amount = 0; - } - - return std::pair(emission_amount, total_fee_amount); - } - //----------------------------------------------------------------------------------------------- - bool core::check_tx_inputs_keyimages_diff(const transaction& tx) const - { - std::unordered_set ki; - BOOST_FOREACH(const auto& in, tx.vin) - { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - if(!ki.insert(tokey_in.k_image).second) - return false; + time_t core::request_datetime(){ + + time_t timeRecv; + + boost::asio::io_service io_service; + + boost::asio::ip::udp::resolver resolver(io_service); + boost::asio::ip::udp::resolver::query query( + boost::asio::ip::udp::v4(), + "pool.ntp.org", "123"); + + boost::asio::ip::udp::endpoint receiver_endpoint = *resolver.resolve(query); + + boost::asio::ip::udp::socket socket(io_service); + socket.open(boost::asio::ip::udp::v4()); + + ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + memset( &packet, 0, sizeof( ntp_packet ) ); + + *( ( char * ) &packet + 0 ) = 0x1b; + + socket.send_to(boost::asio::buffer(&packet,sizeof(ntp_packet)), receiver_endpoint); + + boost::asio::ip::udp::endpoint sender_endpoint; + + try{ + size_t len = socket.receive_from( + boost::asio::buffer(&packet,sizeof(ntp_packet)), + sender_endpoint + ); + + LOG_PRINT_L1("request_datetime receive " << len); + + packet.txTm_s = ntohl( packet.txTm_s ); + packet.txTm_f = ntohl( packet.txTm_f ); + + timeRecv = ( time_t )( packet.txTm_s - 2208988800ull); + LOG_PRINT_L1("Receive time: " << ctime(&timeRecv)); + + }catch (std::exception& e){ + + LOG_PRINT_L1("request_datetime failed " << e.what()); + + } + + return timeRecv; } - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::check_tx_inputs_keyimages_domain(const transaction& tx) const - { - std::unordered_set ki; - for(const auto& in: tx.vin) + time_t core::get_timestamp_top_block(){ + + crypto::hash prv_block=get_block_id_by_height(get_current_blockchain_height()-1); + block last_b; + get_block_by_hash(prv_block,last_b); + return last_b.timestamp; + + } + //----------------------------------------------------------------------------------------------- + bool core::handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate) { - CHECKED_GET_SPECIFIC_VARIANT(in, const txin_to_key, tokey_in, false); - if (!(rct::scalarmultKey(rct::ki2rct(tokey_in.k_image), rct::curveOrder()) == rct::identity())) - return false; + // load json & DNS checkpoints every 10min/hour respectively, + // and verify them with respect to what blocks we already have + CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); + + bvc = boost::value_initialized(); + if(block_blob.size() > get_max_block_size()) + { + LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); + bvc.m_verifivation_failed = true; + return false; + } + + block b = AUTO_VAL_INIT(b); + if(!parse_and_validate_block_from_blob(block_blob, b)) + { + LOG_PRINT_L1("Failed to parse and validate new block"); + bvc.m_verifivation_failed = true; + return false; + } + + uint64_t h=get_current_blockchain_height(); + if((m_target_blockchain_height-h)TIME_DEVIATION) + { + LOG_PRINT_L0("System time incorrect, please sync your time and restart deamon! delta: "<> txs; - if (m_mempool.get_relayable_transactions(txs)) - { - cryptonote_connection_context fake_context = AUTO_VAL_INIT(fake_context); - tx_verification_context tvc = AUTO_VAL_INIT(tvc); - NOTIFY_NEW_TRANSACTIONS::request r; - blobdata bl; - for (auto it = txs.begin(); it != txs.end(); ++it) - { - t_serializable_object_to_blob(it->second, bl); - r.txs.push_back(bl); - } - get_protocol()->relay_transactions(r, fake_context); - m_mempool.set_relayed(txs); - } - return true; - } - //----------------------------------------------------------------------------------------------- - void core::on_transaction_relayed(const cryptonote::blobdata& tx_blob) - { - std::list> txs; - cryptonote::transaction tx; - crypto::hash tx_hash, tx_prefix_hash; - if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash, tx_prefix_hash)) - { - LOG_ERROR("Failed to parse relayed transaction"); - return; - } - txs.push_back(std::make_pair(tx_hash, std::move(tx))); - m_mempool.set_relayed(txs); - } - //----------------------------------------------------------------------------------------------- - bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, const blobdata& ex_nonce) - { - return m_blockchain_storage.create_block_template(b, adr, diffic, height, ex_nonce); - } - //----------------------------------------------------------------------------------------------- - bool core::find_blockchain_supplement(const std::list& qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request& resp) const - { - return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp); - } - //----------------------------------------------------------------------------------------------- - bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list& qblock_ids, std::list > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const - { - return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, max_count); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain(uint64_t start_index, uint64_t end_index) const - { - m_blockchain_storage.print_blockchain(start_index, end_index); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain_index() const - { - m_blockchain_storage.print_blockchain_index(); - } - //----------------------------------------------------------------------------------------------- - void core::print_blockchain_outs(const std::string& file) - { - m_blockchain_storage.print_blockchain_outs(file); - } - //----------------------------------------------------------------------------------------------- - bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const - { - return m_blockchain_storage.get_random_outs_for_amounts(req, res); - } - //----------------------------------------------------------------------------------------------- - bool core::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const - { - return m_blockchain_storage.get_outs(req, res); - } - //----------------------------------------------------------------------------------------------- - bool core::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) const - { - return m_blockchain_storage.get_random_rct_outs(req, res); - } - //----------------------------------------------------------------------------------------------- - bool core::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector& indexs) const - { - return m_blockchain_storage.get_tx_outputs_gindexs(tx_id, indexs); - } - //----------------------------------------------------------------------------------------------- - void core::pause_mine() - { - m_miner.pause(); - } - //----------------------------------------------------------------------------------------------- - void core::resume_mine() - { - m_miner.resume(); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_block_found(block& b) - { - block_verification_context bvc = boost::value_initialized(); - m_miner.pause(); - m_blockchain_storage.add_new_block(b, bvc); - //anyway - update miner template - update_miner_block_template(); - m_miner.resume(); - - - CHECK_AND_ASSERT_MES(!bvc.m_verifivation_failed, false, "mined block failed verification"); - if(bvc.m_added_to_main_chain) - { - cryptonote_connection_context exclude_context = boost::value_initialized(); - NOTIFY_NEW_BLOCK::request arg = AUTO_VAL_INIT(arg); - arg.hop = 0; - arg.current_blockchain_height = m_blockchain_storage.get_current_blockchain_height(); - std::list missed_txs; - std::list txs; - m_blockchain_storage.get_transactions(b.tx_hashes, txs, missed_txs); - if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b)) - { - LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block"); + //----------------------------------------------------------------------------------------------- + // Used by the RPC server to check the size of an incoming + // block_blob + bool core::check_incoming_block_size(const blobdata& block_blob) const + { + if(block_blob.size() > get_max_block_size()) + { + LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); + return false; + } return true; - } - CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "cant find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size() - << ", b.tx_hashes.size()=" << b.tx_hashes.size() << ", missed_txs.size()" << missed_txs.size()); - - block_to_blob(b, arg.b.block); - //pack transactions - BOOST_FOREACH(auto& tx, txs) - arg.b.txs.push_back(t_serializable_object_to_blob(tx)); - - m_pprotocol->relay_block(arg, exclude_context); - } - return bvc.m_added_to_main_chain; - } - //----------------------------------------------------------------------------------------------- - void core::on_synchronized() - { - m_miner.on_synchronized(); - } - //----------------------------------------------------------------------------------------------- - bool core::add_new_block(const block& b, block_verification_context& bvc) - { - return m_blockchain_storage.add_new_block(b, bvc); - } - - //----------------------------------------------------------------------------------------------- - bool core::prepare_handle_incoming_blocks(const std::list &blocks) - { - m_blockchain_storage.prepare_handle_incoming_blocks(blocks); - return true; - } - - //----------------------------------------------------------------------------------------------- - bool core::cleanup_handle_incoming_blocks(bool force_sync) - { - m_blockchain_storage.cleanup_handle_incoming_blocks(force_sync); - return true; - } - - //----------------------------------------------------------------------------------------------- - bool core::handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate) - { - // load json & DNS checkpoints every 10min/hour respectively, - // and verify them with respect to what blocks we already have - CHECK_AND_ASSERT_MES(update_checkpoints(), false, "One or more checkpoints loaded from json or dns conflicted with existing checkpoints."); - - bvc = boost::value_initialized(); - if(block_blob.size() > get_max_block_size()) - { - LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); - bvc.m_verifivation_failed = true; - return false; - } - - block b = AUTO_VAL_INIT(b); - if(!parse_and_validate_block_from_blob(block_blob, b)) - { - LOG_PRINT_L1("Failed to parse and validate new block"); - bvc.m_verifivation_failed = true; - return false; - } - add_new_block(b, bvc); - if(update_miner_blocktemplate && bvc.m_added_to_main_chain) - update_miner_block_template(); - return true; - } - //----------------------------------------------------------------------------------------------- - // Used by the RPC server to check the size of an incoming - // block_blob - bool core::check_incoming_block_size(const blobdata& block_blob) const - { - if(block_blob.size() > get_max_block_size()) - { - LOG_PRINT_L1("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected"); - return false; - } - return true; - } - //----------------------------------------------------------------------------------------------- - crypto::hash core::get_tail_id() const - { - return m_blockchain_storage.get_tail_id(); - } - //----------------------------------------------------------------------------------------------- - size_t core::get_pool_transactions_count() const - { - return m_mempool.get_transactions_count(); - } - //----------------------------------------------------------------------------------------------- - bool core::have_block(const crypto::hash& id) const - { - return m_blockchain_storage.have_block(id); - } - //----------------------------------------------------------------------------------------------- - bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash, const blobdata& blob) const - { - return parse_and_validate_tx_from_blob(blob, tx, tx_hash, tx_prefix_hash); - } - //----------------------------------------------------------------------------------------------- - bool core::check_tx_syntax(const transaction& tx) const - { - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::get_pool_transactions(std::list& txs) const - { - m_mempool.get_transactions(txs); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const - { - return m_mempool.get_transaction(id, tx); - } - //----------------------------------------------------------------------------------------------- - bool core::get_pool_transactions_and_spent_keys_info(std::vector& tx_infos, std::vector& key_image_infos) const - { - return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos); - } - //----------------------------------------------------------------------------------------------- - bool core::get_short_chain_history(std::list& ids) const - { - return m_blockchain_storage.get_short_chain_history(ids); - } - //----------------------------------------------------------------------------------------------- - bool core::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, cryptonote_connection_context& context) - { - return m_blockchain_storage.handle_get_objects(arg, rsp); - } - //----------------------------------------------------------------------------------------------- - crypto::hash core::get_block_id_by_height(uint64_t height) const - { - return m_blockchain_storage.get_block_id_by_height(height); - } - //----------------------------------------------------------------------------------------------- - bool core::get_block_by_hash(const crypto::hash &h, block &blk) const - { - return m_blockchain_storage.get_block_by_hash(h, blk); - } - //----------------------------------------------------------------------------------------------- - std::string core::print_pool(bool short_format) const - { - return m_mempool.print_pool(short_format); - } - //----------------------------------------------------------------------------------------------- - bool core::update_miner_block_template() - { - m_miner.on_block_chain_update(); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::on_idle() - { - if(!m_starter_message_showed) - { - LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL - << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL - << ENDL - << "You can set the level of process detailization* through \"set_log \" command*, where is between 0 (no details) and 4 (very verbose)." << ENDL - << ENDL - << "Use \"help\" command to see the list of available commands." << ENDL - << ENDL - << "Note: in case you need to interrupt the process, use \"exit\" command. Otherwise, the current progress won't be saved." << ENDL - << "**********************************************************************"); - m_starter_message_showed = true; - } - - m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this)); - m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this)); - m_miner.on_idle(); - m_mempool.on_idle(); - return true; - } - //----------------------------------------------------------------------------------------------- - bool core::check_fork_time() - { - /*HardFork::State state = m_blockchain_storage.get_hard_fork_state(); + } + //----------------------------------------------------------------------------------------------- + crypto::hash core::get_tail_id() const + { + return m_blockchain_storage.get_tail_id(); + } + //----------------------------------------------------------------------------------------------- + size_t core::get_pool_transactions_count() const + { + return m_mempool.get_transactions_count(); + } + //----------------------------------------------------------------------------------------------- + bool core::have_block(const crypto::hash& id) const + { + return m_blockchain_storage.have_block(id); + } + //----------------------------------------------------------------------------------------------- + bool core::parse_tx_from_blob(transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash, const blobdata& blob) const + { + return parse_and_validate_tx_from_blob(blob, tx, tx_hash, tx_prefix_hash); + } + //----------------------------------------------------------------------------------------------- + bool core::check_tx_syntax(const transaction& tx) const + { + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::get_pool_transactions(std::list& txs) const + { + m_mempool.get_transactions(txs); + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const + { + return m_mempool.get_transaction(id, tx); + } + //----------------------------------------------------------------------------------------------- + bool core::get_pool_transactions_and_spent_keys_info(std::vector& tx_infos, std::vector& key_image_infos) const + { + return m_mempool.get_transactions_and_spent_keys_info(tx_infos, key_image_infos); + } + //----------------------------------------------------------------------------------------------- + bool core::get_short_chain_history(std::list& ids) const + { + return m_blockchain_storage.get_short_chain_history(ids); + } + //----------------------------------------------------------------------------------------------- + bool core::handle_get_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, NOTIFY_RESPONSE_GET_OBJECTS::request& rsp, cryptonote_connection_context& context) + { + return m_blockchain_storage.handle_get_objects(arg, rsp); + } + //----------------------------------------------------------------------------------------------- + crypto::hash core::get_block_id_by_height(uint64_t height) const + { + return m_blockchain_storage.get_block_id_by_height(height); + } + //----------------------------------------------------------------------------------------------- + bool core::get_block_by_hash(const crypto::hash &h, block &blk) const + { + return m_blockchain_storage.get_block_by_hash(h, blk); + } + //----------------------------------------------------------------------------------------------- + std::string core::print_pool(bool short_format) const + { + return m_mempool.print_pool(short_format); + } + //----------------------------------------------------------------------------------------------- + bool core::update_miner_block_template() + { + m_miner.on_block_chain_update(); + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::on_idle() + { + if(!m_starter_message_showed) + { + LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL + << "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL + << ENDL + << "You can set the level of process detailization* through \"set_log \" command*, where is between 0 (no details) and 4 (very verbose)." << ENDL + << ENDL + << "Use \"help\" command to see the list of available commands." << ENDL + << ENDL + << "Note: in case you need to interrupt the process, use \"exit\" command. Otherwise, the current progress won't be saved." << ENDL + << "**********************************************************************"); + m_starter_message_showed = true; + } + + m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this)); + m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this)); + m_miner.on_idle(); + m_mempool.on_idle(); + return true; + } + //----------------------------------------------------------------------------------------------- + bool core::check_fork_time() + { + /*HardFork::State state = m_blockchain_storage.get_hard_fork_state(); switch (state) { case HardFork::LikelyForked: LOG_PRINT_RED_L0(ENDL @@ -1032,21 +1110,21 @@ namespace cryptonote default: break; }*/ - return true; - } - //----------------------------------------------------------------------------------------------- - void core::set_target_blockchain_height(uint64_t target_blockchain_height) - { - m_target_blockchain_height = target_blockchain_height; - } - //----------------------------------------------------------------------------------------------- - uint64_t core::get_target_blockchain_height() const - { - return m_target_blockchain_height; - } - //----------------------------------------------------------------------------------------------- - void core::graceful_exit() - { - raise(SIGTERM); - } + return true; + } + //----------------------------------------------------------------------------------------------- + void core::set_target_blockchain_height(uint64_t target_blockchain_height) + { + m_target_blockchain_height = target_blockchain_height; + } + //----------------------------------------------------------------------------------------------- + uint64_t core::get_target_blockchain_height() const + { + return m_target_blockchain_height; + } + //----------------------------------------------------------------------------------------------- + void core::graceful_exit() + { + raise(SIGTERM); + } } diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 0584db3..f1b1f98 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -52,6 +52,37 @@ DISABLE_VS_WARNINGS(4355) namespace cryptonote { + typedef struct + { + + uint8_t li_vn_mode; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + uint8_t stratum; // Eight bits. Stratum level of the local clock. + uint8_t poll; // Eight bits. Maximum interval between successive messages. + uint8_t precision; // Eight bits. Precision of the local clock. + + uint32_t rootDelay; // 32 bits. Total round trip delay time. + uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. + uint32_t refId; // 32 bits. Reference clock identifier. + + uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. + uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. + + uint32_t origTm_s; // 32 bits. Originate time-stamp seconds. + uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second. + + uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. + uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. + + uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. + + } ntp_packet; // Total: 384 bits or 48 bytes + + struct test_options { const std::pair *hard_forks; }; @@ -141,14 +172,17 @@ namespace cryptonote * @note see Blockchain::cleanup_handle_incoming_blocks */ bool cleanup_handle_incoming_blocks(bool force_sync = false); - + + time_t request_datetime(); + time_t get_timestamp_top_block(); + /** * @brief check the size of a block against the current maximum * * @param block_blob the block to check * * @return whether or not the block is too big - */ + */ bool check_incoming_block_size(const blobdata& block_blob) const; /** diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp index ffb1300..c4f0ad4 100644 --- a/src/cryptonote_core/cryptonote_format_utils.cpp +++ b/src/cryptonote_core/cryptonote_format_utils.cpp @@ -1224,7 +1224,7 @@ namespace cryptonote bl = boost::value_initialized(); account_public_address addr = boost::value_initialized(); construct_miner_tx(0, 0, 0, 0, 0, addr, bl.miner_tx); // zero fee in genesis - std::string genesis_coinbase_tx_hex = genesis_tx;// config::GENESIS_TX; + std::string genesis_coinbase_tx_hex = genesis_tx; blobdata tx_bl; string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl); bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx); diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp index 5e3e96b..bff258e 100644 --- a/src/cryptonote_core/miner.cpp +++ b/src/cryptonote_core/miner.cpp @@ -354,7 +354,6 @@ namespace cryptonote uint32_t local_template_ver = 0; block b; cn_pow_hash_v2 hash_ctx; - while(!m_stop) { if(m_pausers_count)//anti split workaround @@ -371,6 +370,7 @@ namespace cryptonote CRITICAL_REGION_END(); local_template_ver = m_template_no; nonce = m_starter_nonce + th_local_index; + } if(!local_template_ver)//no any set_block_template call @@ -398,6 +398,7 @@ namespace cryptonote if (!m_config_folder_path.empty()) epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME); } + } nonce+=m_threads_total; ++m_hashes; diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 3e10372..f97ce6d 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -124,11 +124,11 @@ namespace nodetool virtual std::map get_blocked_ips() { CRITICAL_REGION_LOCAL(m_blocked_ips_lock); return m_blocked_ips; } private: const std::vector m_seed_nodes_list = - { "107.181.174.45", - "89.163.214.63", - "91.226.83.104", - "54.39.96.162", - "139.99.42.231" + {"seed0.bxbnetwork.biz", + "seed1.bxbnetwork.biz", + "seed2.bxbnetwork.biz", + "seed3.bxbnetwork.biz", + "seed4.bxbnetwork.biz" }; bool islimitup=false; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index dc2644f..64e2be6 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -394,12 +394,11 @@ namespace nodetool if (testnet) { memcpy(&m_network_id, &::config::testnet::NETWORK_ID, 16); - full_addrs.insert("107.181.174.45:44050"); - full_addrs.insert("89.163.214.63:44050"); - full_addrs.insert("91.226.83.104:44050"); - full_addrs.insert("54.39.96.162:44050"); - full_addrs.insert("139.99.42.231:44050"); - + full_addrs.insert("seed0.bxbnetwork.biz:44050"); + full_addrs.insert("seed1.bxbnetwork.biz:44050"); + full_addrs.insert("seed2.bxbnetwork.biz:44050"); + full_addrs.insert("seed3.bxbnetwork.biz:44050"); + full_addrs.insert("seed4.bxbnetwork.biz:44050"); } else @@ -476,12 +475,11 @@ namespace nodetool if (!full_addrs.size()) { LOG_PRINT_L0("DNS seed node lookup either timed out or failed, falling back to defaults"); - full_addrs.insert("107.181.174.45:44040"); - full_addrs.insert("89.163.214.63:44040"); - full_addrs.insert("91.226.83.104:44040"); - full_addrs.insert("54.39.96.162:44040"); - full_addrs.insert("139.99.42.231:44040"); - + full_addrs.insert("seed0.bxbnetwork.biz:44040"); + full_addrs.insert("seed1.bxbnetwork.biz:44040"); + full_addrs.insert("seed2.bxbnetwork.biz:44040"); + full_addrs.insert("seed3.bxbnetwork.biz:44040"); + full_addrs.insert("seed4.bxbnetwork.biz:44040"); } } diff --git a/src/version.h b/src/version.h index 325eb96..d8028c2 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define Bixbite_VERSION_TAG "testnet" -#define Bixbite_VERSION "0.0.0.3" -#define Bixbite_RELEASE_NAME "test" +#define Bixbite_VERSION_TAG "release" +#define Bixbite_VERSION "0.0.0.5b" +#define Bixbite_RELEASE_NAME "Violet Claim" #define Bixbite_VERSION_FULL Bixbite_VERSION "-" Bixbite_VERSION_TAG diff --git a/src/version.h.in b/src/version.h.in index ba4b782..41d1773 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define Bixbite_VERSION_TAG "@VERSIONTAG@" -#define Bixbite_VERSION "0.0.0.3" -#define Bixbite_RELEASE_NAME "test" +#define Bixbite_VERSION "0.0.0.5b" +#define Bixbite_RELEASE_NAME "Violet Claim" #define Bixbite_VERSION_FULL Bixbite_VERSION "-" Bixbite_VERSION_TAG diff --git a/src/version.rc b/src/version.rc index aca9873..48b6b16 100644 --- a/src/version.rc +++ b/src/version.rc @@ -1,6 +1,6 @@ VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,0,3 - PRODUCTVERSION 0,0,0,3 + FILEVERSION 0,0,0,5 + PRODUCTVERSION 0,0,0,5 FILEFLAGSMASK 0x003L FILEFLAGS 0x0L FILEOS 0x4L @@ -14,12 +14,12 @@ BEGIN VALUE "Comments", "Bixbite\0" VALUE "CompanyName", "Bixbite\0" VALUE "FileDescription", "Bixbite\0" - VALUE "FileVersion", "0.0.0.3b\0" + VALUE "FileVersion", "0.0.0.5b\0" VALUE "InternalName", "Bixbite\0" VALUE "LegalCopyright", "Copyright (C) 2018\0" VALUE "OriginalFilename", "\0" VALUE "ProductName", "Bixbite\0" - VALUE "ProductVersion", "0.0.0.3b\0" + VALUE "ProductVersion", "0.0.0.5b\0" END END BLOCK "VarFileInfo" diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e3943b1..13ab86c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -721,7 +721,7 @@ static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation & case rct::RCTTypeFull: return rct::decodeRct(rv, rct::sk2rct(scalar1), i, mask); default: - LOG_ERROR("Unsupported rct type: " << rv.type); + //LOG_ERROR("Unsupported rct type: " << rv.type); return 0; } }