diff options
Diffstat (limited to 'src')
22 files changed, 541 insertions, 132 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9bab56200..f332af3d3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -129,6 +129,7 @@ add_subdirectory(cryptonote_protocol) if(NOT IOS) add_subdirectory(simplewallet) add_subdirectory(gen_multisig) + add_subdirectory(gen_ssl_cert) add_subdirectory(daemonizer) add_subdirectory(daemon) add_subdirectory(blockchain_utilities) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 8e2b5bebf..f978ef307 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -2994,8 +2994,6 @@ bool BlockchainLMDB::get_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd return false; else if (get_result) throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", get_result).c_str())); - else if (result1.mv_size == 0) - return false; bd.assign(reinterpret_cast<char*>(result0.mv_data), result0.mv_size); bd.append(reinterpret_cast<char*>(result1.mv_data), result1.mv_size); diff --git a/src/blockchain_utilities/blockchain_utilities.h b/src/blockchain_utilities/blockchain_utilities.h index 78487b995..e8615cf86 100644 --- a/src/blockchain_utilities/blockchain_utilities.h +++ b/src/blockchain_utilities/blockchain_utilities.h @@ -33,7 +33,7 @@ // bounds checking is done before writing to buffer, but buffer size // should be a sensible maximum -#define BUFFER_SIZE 1000000 +#define BUFFER_SIZE (2 * 1024 * 1024) #define CHUNK_SIZE_WARNING_THRESHOLD 500000 #define NUM_BLOCKS_PER_CHUNK 1 #define BLOCKCHAIN_RAW "blockchain.raw" diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c index 59bd89d13..a7a459ad3 100644 --- a/src/crypto/rx-slow-hash.c +++ b/src/crypto/rx-slow-hash.c @@ -34,6 +34,7 @@ #include <stdio.h> #include <stdlib.h> #include <unistd.h> +#include <limits.h> #include "randomx.h" #include "c_threads.h" @@ -74,84 +75,41 @@ static void local_abort(const char *msg) #endif } -/** - * @brief uses cpuid to determine if the CPU supports the AES instructions - * @return true if the CPU supports AES, false otherwise - */ +static inline int disabled_flags(void) { + static int flags = -1; -static inline int force_software_aes(void) -{ - static int use = -1; - - if (use != -1) - return use; + if (flags != -1) { + return flags; + } - const char *env = getenv("MONERO_USE_SOFTWARE_AES"); + const char *env = getenv("MONERO_RANDOMX_UMASK"); if (!env) { - use = 0; - } - else if (!strcmp(env, "0") || !strcmp(env, "no")) { - use = 0; + flags = 0; } else { - use = 1; + char* endptr; + long int value = strtol(env, &endptr, 0); + if (endptr != env && value >= 0 && value < INT_MAX) { + flags = value; + } + else { + flags = 0; + } } - return use; -} -static void cpuid(int CPUInfo[4], int InfoType) -{ -#if defined(__x86_64__) - __asm __volatile__ - ( - "cpuid": - "=a" (CPUInfo[0]), - "=b" (CPUInfo[1]), - "=c" (CPUInfo[2]), - "=d" (CPUInfo[3]) : - "a" (InfoType), "c" (0) - ); -#endif + return flags; } -static inline int check_aes_hw(void) -{ -#if defined(__x86_64__) - int cpuid_results[4]; - static int supported = -1; - if(supported >= 0) - return supported; +static inline int enabled_flags(void) { + static int flags = -1; - cpuid(cpuid_results,1); - return supported = cpuid_results[2] & (1 << 25); -#else - return 0; -#endif -} - -static volatile int use_rx_jit_flag = -1; - -static inline int use_rx_jit(void) -{ -#if defined(__x86_64__) + if (flags != -1) { + return flags; + } - if (use_rx_jit_flag != -1) - return use_rx_jit_flag; + flags = randomx_get_flags(); - const char *env = getenv("MONERO_USE_RX_JIT"); - if (!env) { - use_rx_jit_flag = 1; - } - else if (!strcmp(env, "0") || !strcmp(env, "no")) { - use_rx_jit_flag = 0; - } - else { - use_rx_jit_flag = 1; - } - return use_rx_jit_flag; -#else - return 0; -#endif + return flags; } #define SEEDHASH_EPOCH_BLOCKS 2048 /* Must be same as BLOCKS_SYNCHRONIZING_MAX_COUNT in cryptonote_config.h */ @@ -236,7 +194,7 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch char *hash, int miners, int is_alt) { uint64_t s_height = rx_seedheight(mainheight); int toggle = (s_height & SEEDHASH_EPOCH_BLOCKS) != 0; - randomx_flags flags = RANDOMX_FLAG_DEFAULT; + randomx_flags flags = enabled_flags() & ~disabled_flags(); rx_state *rx_sp; randomx_cache *cache; @@ -263,8 +221,6 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch cache = rx_sp->rs_cache; if (cache == NULL) { - if (use_rx_jit()) - flags |= RANDOMX_FLAG_JIT; if (cache == NULL) { cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES); if (cache == NULL) { @@ -282,14 +238,12 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch memcpy(rx_sp->rs_hash, seedhash, HASH_SIZE); } if (rx_vm == NULL) { - randomx_flags flags = RANDOMX_FLAG_DEFAULT; - if (use_rx_jit()) { - flags |= RANDOMX_FLAG_JIT; - if (!miners) - flags |= RANDOMX_FLAG_SECURE; + if ((flags & RANDOMX_FLAG_JIT) && !miners) { + flags |= RANDOMX_FLAG_SECURE & ~disabled_flags(); + } + if (miners && (disabled_flags() & RANDOMX_FLAG_FULL_MEM)) { + miners = 0; } - if(!force_software_aes() && check_aes_hw()) - flags |= RANDOMX_FLAG_HARD_AES; if (miners) { CTHR_MUTEX_LOCK(rx_dataset_mutex); if (rx_dataset == NULL) { diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index d8de65b81..9bafcfc86 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -110,9 +110,6 @@ namespace cryptonote { return false; } - assert(median_weight < std::numeric_limits<uint32_t>::max()); - assert(current_block_weight < std::numeric_limits<uint32_t>::max()); - uint64_t product_hi; // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being // treated as 32-bit by default. @@ -122,8 +119,8 @@ namespace cryptonote { uint64_t reward_hi; uint64_t reward_lo; - div128_32(product_hi, product_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo); - div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo); + div128_64(product_hi, product_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL); + div128_64(reward_hi, reward_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL); assert(0 == reward_hi); assert(reward_lo < base_reward); diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 3501c66c8..138cf49f4 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -103,6 +103,26 @@ namespace cryptonote ge_p1p1_to_p3(&A2, &tmp3); ge_p3_tobytes(&AB, &A2); } + + uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs) + { + const rct::rctSig &rv = tx.rct_signatures; + const uint64_t bp_base = 368; + const size_t n_outputs = tx.vout.size(); + if (n_padded_outputs <= 2) + return 0; + size_t nlr = 0; + while ((1u << nlr) < n_padded_outputs) + ++nlr; + nlr += 6; + const size_t bp_size = 32 * (9 + 2 * nlr); + CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction"); + CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback: bp_base " + std::to_string(bp_base) + ", n_padded_outputs " + + std::to_string(n_padded_outputs) + ", bp_size " + std::to_string(bp_size)); + const uint64_t bp_clawback = (bp_base * n_padded_outputs - bp_size) * 4 / 5; + return bp_clawback; + } + //--------------------------------------------------------------- } namespace cryptonote @@ -386,27 +406,61 @@ namespace cryptonote //--------------------------------------------------------------- uint64_t get_transaction_weight(const transaction &tx, size_t blob_size) { + CHECK_AND_ASSERT_MES(!tx.pruned, std::numeric_limits<uint64_t>::max(), "get_transaction_weight does not support pruned txes"); if (tx.version < 2) return blob_size; const rct::rctSig &rv = tx.rct_signatures; if (!rct::is_rct_bulletproof(rv.type)) return blob_size; - const size_t n_outputs = tx.vout.size(); - if (n_outputs <= 2) - return blob_size; - const uint64_t bp_base = 368; const size_t n_padded_outputs = rct::n_bulletproof_max_amounts(rv.p.bulletproofs); - size_t nlr = 0; - for (const auto &bp: rv.p.bulletproofs) - nlr += bp.L.size() * 2; - const size_t bp_size = 32 * (9 + nlr); - CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction"); - CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback"); - const uint64_t bp_clawback = (bp_base * n_padded_outputs - bp_size) * 4 / 5; + uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs); CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow"); return blob_size + bp_clawback; } //--------------------------------------------------------------- + uint64_t get_pruned_transaction_weight(const transaction &tx) + { + CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes"); + CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes"); + CHECK_AND_ASSERT_MES(tx.rct_signatures.type >= rct::RCTTypeBulletproof2, + std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support older range proof types"); + CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin"); + CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin"); + + // get pruned data size + std::ostringstream s; + binary_archive<true> a(s); + ::serialization::serialize(a, const_cast<transaction&>(tx)); + uint64_t weight = s.str().size(), extra; + + // nbps (technically varint) + weight += 1; + + // calculate deterministic bulletproofs size (assumes canonical BP format) + size_t nrl = 0, n_padded_outputs; + while ((n_padded_outputs = (1u << nrl)) < tx.vout.size()) + ++nrl; + nrl += 6; + extra = 32 * (9 + 2 * nrl) + 2; + weight += extra; + + // calculate deterministic MLSAG data size + const size_t ring_size = boost::get<cryptonote::txin_to_key>(tx.vin[0]).key_offsets.size(); + extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */); + weight += extra; + + // calculate deterministic pseudoOuts size + extra = 32 * (tx.vin.size()); + weight += extra; + + // clawback + uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs); + CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - weight, "Weight overflow"); + weight += bp_clawback; + + return weight; + } + //--------------------------------------------------------------- uint64_t get_transaction_weight(const transaction &tx) { size_t blob_size; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 284494299..29e4def64 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -127,6 +127,7 @@ namespace cryptonote bool parse_amount(uint64_t& amount, const std::string& str_amount); uint64_t get_transaction_weight(const transaction &tx); uint64_t get_transaction_weight(const transaction &tx, size_t blob_size); + uint64_t get_pruned_transaction_weight(const transaction &tx); bool check_money_overflow(const transaction& tx); bool check_outs_overflow(const transaction& tx); diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 69551934a..86e6c99d1 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -165,6 +165,7 @@ #define HF_VERSION_SAME_MIXIN 12 #define HF_VERSION_REJECT_SIGS_IN_COINBASE 12 #define HF_VERSION_ENFORCE_MIN_AGE 12 +#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8 diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index e3450491b..b7e9f4ca2 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1176,9 +1176,18 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl } } - std::vector<uint64_t> last_blocks_weights; - get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); - if (!get_block_reward(epee::misc_utils::median(last_blocks_weights), cumulative_block_weight, already_generated_coins, base_reward, version)) + uint64_t median_weight; + if (version >= HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY) + { + median_weight = m_current_block_cumul_weight_median; + } + else + { + std::vector<uint64_t> last_blocks_weights; + get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); + median_weight = epee::misc_utils::median(last_blocks_weights); + } + if (!get_block_reward(median_weight, cumulative_block_weight, already_generated_coins, base_reward, version)) { MERROR_VER("block weight " << cumulative_block_weight << " is bigger than allowed for this blockchain"); return false; @@ -1694,7 +1703,8 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id // Check the block's hash against the difficulty target for its alt chain difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei); CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); - crypto::hash proof_of_work = null_hash; + crypto::hash proof_of_work; + memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data)); if (b.major_version >= RX_BLOCK_VERSION) { crypto::hash seedhash = null_hash; @@ -1750,6 +1760,34 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id } bei.cumulative_difficulty += current_diff; + bei.block_cumulative_weight = cryptonote::get_transaction_weight(b.miner_tx); + for (const crypto::hash &txid: b.tx_hashes) + { + cryptonote::tx_memory_pool::tx_details td; + cryptonote::blobdata blob; + if (m_tx_pool.get_transaction_info(txid, td)) + { + bei.block_cumulative_weight += td.weight; + } + else if (m_db->get_pruned_tx_blob(txid, blob)) + { + cryptonote::transaction tx; + if (!cryptonote::parse_and_validate_tx_base_from_blob(blob, tx)) + { + MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) refers to unparsable transaction hash " << txid << "."); + bvc.m_verifivation_failed = true; + return false; + } + bei.block_cumulative_weight += cryptonote::get_pruned_transaction_weight(tx); + } + else + { + // we can't determine the block weight, set it to 0 and break out of the loop + bei.block_cumulative_weight = 0; + break; + } + } + // add block to alternate blocks storage, // as well as the current "alt chain" container CHECK_AND_ASSERT_MES(!m_db->get_alt_block(id, NULL, NULL), false, "insertion of new alternative block returned as it already exists"); @@ -3319,8 +3357,8 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b if (version >= HF_VERSION_PER_BYTE_FEE) { lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi); - div128_32(hi, lo, min_block_weight, &hi, &lo); - div128_32(hi, lo, median_block_weight, &hi, &lo); + div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); + div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); assert(hi == 0); lo /= 5; return lo; @@ -3330,12 +3368,7 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight); lo = mul128(unscaled_fee_base, block_reward, &hi); - static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000"); - static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large"); - - // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't - div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo); - div128_32(hi, lo, 1000000, &hi, &lo); + div128_64(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD, &hi, &lo, NULL, NULL); assert(hi == 0); // quantize fee up to 8 decimals @@ -3702,7 +3735,8 @@ leave: TIME_MEASURE_START(longhash_calculating_time); - crypto::hash proof_of_work = null_hash; + crypto::hash proof_of_work; + memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data)); // Formerly the code below contained an if loop with the following condition // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index b831cc9ff..5a303a67e 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1027,11 +1027,7 @@ namespace cryptonote if (already_have[i]) continue; - // if it's a pruned tx from an incoming block, we'll get a weight that's technically - // different from the actual transaction weight, but it's OK for our use. Those txes - // will be ignored when mining, and using that "pruned" weight seems appropriate for - // keeping the txpool size constrained - const uint64_t weight = results[i].tx.pruned ? 0 : get_transaction_weight(results[i].tx, it->blob.size()); + const uint64_t weight = results[i].tx.pruned ? get_pruned_transaction_weight(results[i].tx) : get_transaction_weight(results[i].tx, it->blob.size()); ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i].blob, weight, tvc[i], keeped_by_block, relayed, do_not_relay); if(tvc[i].m_verifivation_failed) {MERROR_VER("Transaction verification failed: " << results[i].hash);} @@ -1367,6 +1363,7 @@ namespace cryptonote { block_complete_entry bce; bce.block = cryptonote::block_to_blob(b); + bce.block_weight = 0; // we can leave it to 0, those txes aren't pruned for (const auto &tx_hash: b.tx_hashes) { cryptonote::blobdata txblob; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 3a6a3833d..0d70f2992 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -259,7 +259,7 @@ namespace cryptonote m_blockchain.add_txpool_tx(id, blob, meta); if (!insert_key_images(tx, id, kept_by_block)) return false; - m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); lock.commit(); } catch (const std::exception &e) @@ -305,7 +305,7 @@ namespace cryptonote m_blockchain.add_txpool_tx(id, blob, meta); if (!insert_key_images(tx, id, kept_by_block)) return false; - m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); lock.commit(); } catch (const std::exception &e) @@ -518,6 +518,59 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- + bool tx_memory_pool::get_transaction_info(const crypto::hash &txid, tx_details &td) const + { + PERF_TIMER(get_transaction_info); + CRITICAL_REGION_LOCAL(m_transactions_lock); + CRITICAL_REGION_LOCAL1(m_blockchain); + + try + { + LockedTXN lock(m_blockchain); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(txid, meta)) + { + MERROR("Failed to find tx in txpool"); + return false; + } + cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); + auto ci = m_parsed_tx_cache.find(txid); + if (ci != m_parsed_tx_cache.end()) + { + td.tx = ci->second; + } + else if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(txblob, td.tx) : parse_and_validate_tx_from_blob(txblob, td.tx))) + { + MERROR("Failed to parse tx from txpool"); + return false; + } + else + { + td.tx.set_hash(txid); + } + td.blob_size = txblob.size(); + td.weight = meta.weight; + td.fee = meta.fee; + td.max_used_block_id = meta.max_used_block_id; + td.max_used_block_height = meta.max_used_block_height; + td.kept_by_block = meta.kept_by_block; + td.last_failed_height = meta.last_failed_height; + td.last_failed_id = meta.last_failed_id; + td.receive_time = meta.receive_time; + td.last_relayed_time = meta.last_relayed_time; + td.relayed = meta.relayed; + td.do_not_relay = meta.do_not_relay; + td.double_spend_seen = meta.double_spend_seen; + } + catch (const std::exception &e) + { + MERROR("Failed to get tx from txpool: " << e.what()); + return false; + } + + return true; + } + //--------------------------------------------------------------------------------- void tx_memory_pool::on_idle() { m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();}); diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 99182cd0d..dec7e3cd9 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -429,6 +429,11 @@ namespace cryptonote bool double_spend_seen; //!< true iff another tx was seen double spending this one }; + /** + * @brief get infornation about a single transaction + */ + bool get_transaction_info(const crypto::hash &txid, tx_details &td) const; + private: /** diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index 3d594bf83..dcd108626 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -160,7 +160,7 @@ namespace cryptonote } END_KV_SERIALIZE_MAP() - block_complete_entry(): pruned(false) {} + block_complete_entry(): pruned(false), block_weight(0) {} }; diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index bc5c8d6de..35b2d2a39 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -1723,7 +1723,7 @@ skip: return false; } const uint32_t local_stripe = tools::get_pruning_stripe(m_core.get_blockchain_pruning_seed()); - if (m_sync_pruned_blocks && peer_stripe == local_stripe) + if (m_sync_pruned_blocks && local_stripe && next_stripe != local_stripe) { MDEBUG(context << "We can sync pruned blocks off this peer, not dropping"); return false; @@ -1836,7 +1836,7 @@ skip: next_block_height = next_needed_height; else next_block_height = context.m_last_response_height - context.m_needed_objects.size() + 1; - bool stripe_proceed_main = ((m_sync_pruned_blocks && peer_stripe == local_stripe) || add_stripe == 0 || peer_stripe == 0 || add_stripe == peer_stripe) && (next_block_height < bc_height + BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS || next_needed_height < bc_height + BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS); + bool stripe_proceed_main = ((m_sync_pruned_blocks && local_stripe && add_stripe != local_stripe) || add_stripe == 0 || peer_stripe == 0 || add_stripe == peer_stripe) && (next_block_height < bc_height + BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS || next_needed_height < bc_height + BLOCK_QUEUE_FORCE_DOWNLOAD_NEAR_BLOCKS); bool stripe_proceed_secondary = tools::has_unpruned_block(next_block_height, context.m_remote_blockchain_height, context.m_pruning_seed); bool proceed = stripe_proceed_main || (queue_proceed && stripe_proceed_secondary); if (!stripe_proceed_main && !stripe_proceed_secondary && should_drop_connection(context, tools::get_pruning_stripe(next_block_height, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES))) @@ -2043,7 +2043,7 @@ skip: const uint32_t peer_stripe = tools::get_pruning_stripe(context.m_pruning_seed); const uint32_t first_stripe = tools::get_pruning_stripe(span.first, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES); const uint32_t last_stripe = tools::get_pruning_stripe(span.first + span.second - 1, context.m_remote_blockchain_height, CRYPTONOTE_PRUNING_LOG_STRIPES); - if ((first_stripe && peer_stripe != first_stripe) || (last_stripe && peer_stripe != last_stripe)) + if ((((first_stripe && peer_stripe != first_stripe) || (last_stripe && peer_stripe != last_stripe)) && !m_sync_pruned_blocks) || (m_sync_pruned_blocks && req.prune)) { MDEBUG(context << "We need full data, but the peer does not have it, dropping peer"); return false; diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp index 757e072a4..e44ce9137 100644 --- a/src/daemon/command_server.cpp +++ b/src/daemon/command_server.cpp @@ -65,7 +65,7 @@ t_command_server::t_command_server( m_command_lookup.set_handler( "print_pl" , std::bind(&t_command_parser_executor::print_peer_list, &m_parser, p::_1) - , "print_pl [white] [gray] [<limit>]" + , "print_pl [white] [gray] [pruned] [publicrpc] [<limit>]" , "Print the current peer list." ); m_command_lookup.set_handler( diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index 014865730..273d78619 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -91,13 +91,15 @@ namespace { << "height: " << boost::lexical_cast<std::string>(header.height) << std::endl << "depth: " << boost::lexical_cast<std::string>(header.depth) << std::endl << "hash: " << header.hash << std::endl - << "difficulty: " << header.wide_difficulty << std::endl + << "difficulty: " << cryptonote::difficulty_type(header.wide_difficulty) << std::endl + << "cumulative difficulty: " << cryptonote::difficulty_type(header.wide_cumulative_difficulty) << std::endl << "POW hash: " << header.pow_hash << std::endl << "block size: " << header.block_size << std::endl << "block weight: " << header.block_weight << std::endl << "long term weight: " << header.long_term_weight << std::endl << "num txes: " << header.num_txes << std::endl - << "reward: " << cryptonote::print_money(header.reward); + << "reward: " << cryptonote::print_money(header.reward) << std::endl + << "miner tx hash: " << header.miner_tx_hash; } std::string get_human_time_ago(time_t t, time_t now) @@ -355,8 +357,8 @@ bool t_rpc_command_executor::show_difficulty() { tools::success_msg_writer() << "BH: " << res.height << ", TH: " << res.top_block_hash - << ", DIFF: " << res.wide_difficulty - << ", CUM_DIFF: " << res.wide_cumulative_difficulty + << ", DIFF: " << cryptonote::difficulty_type(res.wide_difficulty) + << ", CUM_DIFF: " << cryptonote::difficulty_type(res.wide_cumulative_difficulty) << ", HR: " << cryptonote::difficulty_type(res.wide_difficulty) / res.target << " H/s"; return true; @@ -769,7 +771,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u << ", size: " << header.block_size << ", weight: " << header.block_weight << " (long term " << header.long_term_weight << "), transactions: " << header.num_txes << std::endl << "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl << "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl - << "difficulty: " << header.wide_difficulty << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; + << "difficulty: " << cryptonote::difficulty_type(header.wide_difficulty) << ", nonce " << header.nonce << ", reward " << cryptonote::print_money(header.reward) << std::endl; first = false; } @@ -960,10 +962,11 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash, if (1 == res.txs.size()) { // only available for new style answers + bool pruned = res.txs.front().prunable_as_hex.empty() && res.txs.front().prunable_hash != epee::string_tools::pod_to_hex(crypto::null_hash); if (res.txs.front().in_pool) tools::success_msg_writer() << "Found in pool"; else - tools::success_msg_writer() << "Found in blockchain at height " << res.txs.front().block_height << (res.txs.front().prunable_as_hex.empty() ? " (pruned)" : ""); + tools::success_msg_writer() << "Found in blockchain at height " << res.txs.front().block_height << (pruned ? " (pruned)" : ""); } const std::string &as_hex = (1 == res.txs.size()) ? res.txs.front().as_hex : res.txs_as_hex.front(); @@ -1901,7 +1904,7 @@ bool t_rpc_command_executor::alt_chain_info(const std::string &tip, size_t above const auto &chain = chains[idx]; const uint64_t start_height = (chain.height - chain.length + 1); tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1) - << " deep), diff " << chain.wide_difficulty << ": " << chain.block_hash; + << " deep), diff " << cryptonote::difficulty_type(chain.wide_difficulty) << ": " << chain.block_hash; } } else @@ -1914,7 +1917,7 @@ bool t_rpc_command_executor::alt_chain_info(const std::string &tip, size_t above tools::success_msg_writer() << "Found alternate chain with tip " << tip; uint64_t start_height = (chain.height - chain.length + 1); tools::msg_writer() << chain.length << " blocks long, from height " << start_height << " (" << (ires.height - start_height - 1) - << " deep), diff " << chain.wide_difficulty << ":"; + << " deep), diff " << cryptonote::difficulty_type(chain.wide_difficulty) << ":"; for (const std::string &block_id: chain.block_hashes) tools::msg_writer() << " " << block_id; tools::msg_writer() << "Chain parent on main chain: " << chain.main_chain_parent_block; @@ -2018,7 +2021,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks) } } - tools::msg_writer() << "Height: " << ires.height << ", diff " << ires.wide_difficulty << ", cum. diff " << ires.wide_cumulative_difficulty + tools::msg_writer() << "Height: " << ires.height << ", diff " << cryptonote::difficulty_type(ires.wide_difficulty) << ", cum. diff " << cryptonote::difficulty_type(ires.wide_cumulative_difficulty) << ", target " << ires.target << " sec" << ", dyn fee " << cryptonote::print_money(feres.fee) << "/" << (hfres.enabled ? "byte" : "kB"); if (nblocks > 0) diff --git a/src/gen_ssl_cert/CMakeLists.txt b/src/gen_ssl_cert/CMakeLists.txt new file mode 100644 index 000000000..471df021b --- /dev/null +++ b/src/gen_ssl_cert/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright (c) 2017-2019, The Monero Project +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are +# permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation and/or other +# materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors may be +# used to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set(gen_ssl_cert_sources + gen_ssl_cert.cpp) + +monero_add_executable(gen_ssl_cert + ${gen_ssl_cert_sources}) +target_link_libraries(gen_ssl_cert + PRIVATE + common + epee + version + ${EPEE_READLINE} + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_FILESYSTEM_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${EXTRA_LIBRARIES}) +add_dependencies(gen_ssl_cert + version) +set_property(TARGET gen_ssl_cert + PROPERTY + OUTPUT_NAME "monero-gen-ssl-cert") +install(TARGETS gen_ssl_cert DESTINATION bin) diff --git a/src/gen_ssl_cert/gen_ssl_cert.cpp b/src/gen_ssl_cert/gen_ssl_cert.cpp new file mode 100644 index 000000000..7a9b01700 --- /dev/null +++ b/src/gen_ssl_cert/gen_ssl_cert.cpp @@ -0,0 +1,254 @@ +// Copyright (c) 2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <boost/program_options.hpp> +#include <boost/format.hpp> +#include <boost/algorithm/string.hpp> +#include <openssl/ssl.h> +#include <openssl/pem.h> +#include "include_base_utils.h" +#include "file_io_utils.h" +#include "net/net_ssl.h" +#include "crypto/crypto.h" +#include "common/util.h" +#include "common/i18n.h" +#include "common/command_line.h" +#include "common/scoped_message_writer.h" +#include "common/password.h" +#include "version.h" + +namespace po = boost::program_options; + +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "gen_ssl_cert" + +namespace gencert +{ + const char* tr(const char* str) + { + return i18n_translate(str, "tools::gen_ssl_cert"); + } + +} + +namespace +{ + const command_line::arg_descriptor<std::string> arg_certificate_filename = {"certificate-filename", gencert::tr("Filename to save the certificate"), ""}; + const command_line::arg_descriptor<std::string> arg_private_key_filename = {"private-key-filename", gencert::tr("Filename to save the private key"), ""}; + const command_line::arg_descriptor<std::string> arg_passphrase = {"passphrase", gencert::tr("Passphrase with which to encrypt the private key"), ""}; + const command_line::arg_descriptor<std::string> arg_passphrase_file = {"passphrase-file", gencert::tr("File containing the passphrase with which to encrypt the private key"), ""}; + const command_line::arg_descriptor<bool> arg_prompt_for_passphrase = {"prompt-for-passphrase", gencert::tr("Prompt for a passphrase with which to encrypt the private key"), false}; +} + +// adapted from openssl's apps/x509.c +static std::string get_fingerprint(X509 *cert, const EVP_MD *fdig) +{ + unsigned int j; + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + std::string fingerprint; + + if (!X509_digest(cert, fdig, md, &n)) + { + tools::fail_msg_writer() << tr("Failed to create fingerprint: ") << ERR_reason_error_string(ERR_get_error()); + return fingerprint; + } + fingerprint.resize(n * 3 - 1); + char *out = &fingerprint[0]; + for (j = 0; j < n; ++j) + { + snprintf(out, 3 + (j + 1 < n), "%02X%s", md[j], (j + 1 == n) ? "" : ":"); + out += 3; + } + return fingerprint; +} + +int main(int argc, char* argv[]) +{ + TRY_ENTRY(); + + tools::on_startup(); + + po::options_description desc_cmd_only("Command line options"); + po::options_description desc_cmd_sett("Command line options and settings options"); + + command_line::add_arg(desc_cmd_sett, arg_certificate_filename); + command_line::add_arg(desc_cmd_sett, arg_private_key_filename); + command_line::add_arg(desc_cmd_sett, arg_passphrase); + command_line::add_arg(desc_cmd_sett, arg_passphrase_file); + command_line::add_arg(desc_cmd_sett, arg_prompt_for_passphrase); + + command_line::add_arg(desc_cmd_only, command_line::arg_help); + command_line::add_arg(desc_cmd_only, command_line::arg_version); + + po::options_description desc_options("Allowed options"); + desc_options.add(desc_cmd_only).add(desc_cmd_sett); + + po::variables_map vm; + bool r = command_line::handle_error_helper(desc_options, [&]() + { + po::store(po::parse_command_line(argc, argv, desc_options), vm); + po::notify(vm); + return true; + }); + if (!r) + return 1; + + if (command_line::get_arg(vm, command_line::arg_help)) + { + std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; + std::cout << desc_options << std::endl; + return 0; + } + if (command_line::get_arg(vm, command_line::arg_version)) + { + std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL; + return 0; + } + + const std::string certificate_filename = command_line::get_arg(vm, arg_certificate_filename); + if (certificate_filename.empty()) + { + tools::fail_msg_writer() << gencert::tr("Argument is needed: ") << "--" << arg_certificate_filename.name; + return 1; + } + const std::string private_key_filename = command_line::get_arg(vm, arg_private_key_filename); + if (private_key_filename.empty()) + { + tools::fail_msg_writer() << gencert::tr("Argument is needed: ") << "--" << arg_private_key_filename.name; + return 1; + } + + epee::wipeable_string private_key_passphrase; + if (command_line::get_arg(vm, arg_prompt_for_passphrase)) + { + auto pwd_container = tools::password_container::prompt(true, "Enter passphrase for the new SSL private key"); + if (!pwd_container) + { + tools::fail_msg_writer() << gencert::tr("Failed to read passphrase"); + return 1; + } + private_key_passphrase = pwd_container->password(); + } + else if (!command_line::is_arg_defaulted(vm, arg_passphrase_file)) + { + std::string passphrase_file = command_line::get_arg(vm, arg_passphrase_file); + if (!passphrase_file.empty()) + { + std::string passphrase; + if (!epee::file_io_utils::load_file_to_string(passphrase_file, passphrase)) + { + MERROR("Failed to load passphrase"); + return 1; + } + + // Remove line breaks the user might have inserted + boost::trim_right_if(passphrase, boost::is_any_of("\r\n")); + private_key_passphrase = passphrase; + memwipe(&passphrase[0], passphrase.size()); + } + } + else + { + private_key_passphrase = command_line::get_arg(vm, arg_passphrase); + } + if (private_key_passphrase.empty()) + tools::msg_writer(epee::console_color_yellow) << (boost::format(tr("Empty passphrase, the private key will be saved to disk unencrypted, use --%s to set a passphrase or --%s to prompt for one")) % arg_passphrase.name % arg_prompt_for_passphrase.name).str(); + + EVP_PKEY *pkey; + X509 *cert; + r = epee::net_utils::create_rsa_ssl_certificate(pkey, cert); + if (!r) + { + tools::fail_msg_writer() << gencert::tr("Failed to create certificate"); + return 1; + } + + // write cert + BIO *bio_cert = BIO_new(BIO_s_mem()); + r = PEM_write_bio_X509(bio_cert, cert); + if (!r) + { + BIO_free(bio_cert); + tools::fail_msg_writer() << gencert::tr("Failed to write certificate: ") << ERR_reason_error_string(ERR_get_error()); + return 1; + } + BUF_MEM *buf = NULL; + BIO_get_mem_ptr(bio_cert, &buf); + if (!buf || !buf->data || !buf->length) + { + BIO_free(bio_cert); + tools::fail_msg_writer() << gencert::tr("Failed to write certificate: ") << ERR_reason_error_string(ERR_get_error()); + return 1; + } + const std::string certificate(std::string(buf->data, buf->length)); + BIO_free(bio_cert); + + // write private key + BIO *bio_pkey = BIO_new(BIO_s_mem()); + r = PEM_write_bio_PKCS8PrivateKey(bio_pkey, pkey, private_key_passphrase.empty() ? NULL : EVP_aes_128_cfb(), private_key_passphrase.data(), private_key_passphrase.size(), NULL, NULL); + if (!r) + { + BIO_free(bio_pkey); + tools::fail_msg_writer() << gencert::tr("Failed to write private key: ") << ERR_reason_error_string(ERR_get_error()); + return 1; + } + buf = NULL; + BIO_get_mem_ptr(bio_pkey, &buf); + if (!buf || !buf->data || !buf->length) + { + BIO_free(bio_pkey); + tools::fail_msg_writer() << gencert::tr("Failed to write private key: ") << ERR_reason_error_string(ERR_get_error()); + return 1; + } + const std::string private_key(std::string(buf->data, buf->length)); + BIO_free(bio_pkey); + + // write files + tools::set_strict_default_file_permissions(true); + r = epee::file_io_utils::save_string_to_file(certificate_filename, certificate); + if (!r) + { + tools::fail_msg_writer() << gencert::tr("Failed to save certificate file"); + return 1; + } + r = epee::file_io_utils::save_string_to_file(private_key_filename, private_key); + if (!r) + { + tools::fail_msg_writer() << gencert::tr("Failed to save private key file"); + return 1; + } + + tools::success_msg_writer() << tr("New certificate created:"); + tools::success_msg_writer() << tr("Certificate: ") << certificate_filename; + tools::success_msg_writer() << tr("SHA-256 Fingerprint: ") << get_fingerprint(cert, EVP_sha256()); + tools::success_msg_writer() << tr("Private key: ") << private_key_filename << " (" << (private_key_passphrase.empty() ? "unencrypted" : "encrypted") << ")"; + + return 0; + CATCH_ENTRY_L0("main", 1); +} diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 5fccdca5a..9150ebb1b 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -604,11 +604,13 @@ namespace nodetool full_addrs.insert("163.172.182.165:28080"); full_addrs.insert("195.154.123.123:28080"); full_addrs.insert("212.83.172.165:28080"); + full_addrs.insert("192.110.160.146:28080"); } else if (nettype == cryptonote::STAGENET) { full_addrs.insert("162.210.173.150:38080"); full_addrs.insert("162.210.173.151:38080"); + full_addrs.insert("192.110.160.146:38080"); } else if (nettype == cryptonote::FAKECHAIN) { @@ -623,6 +625,7 @@ namespace nodetool full_addrs.insert("198.74.231.92:18080"); full_addrs.insert("195.154.123.123:18080"); full_addrs.insert("212.83.172.165:18080"); + full_addrs.insert("192.110.160.146:18080"); } return full_addrs; } diff --git a/src/ringct/rctTypes.h b/src/ringct/rctTypes.h index f8729b872..bf4b7b4aa 100644 --- a/src/ringct/rctTypes.h +++ b/src/ringct/rctTypes.h @@ -321,6 +321,7 @@ namespace rct { std::vector<mgSig> MGs; // simple rct has N, full has 1 keyV pseudoOuts; //C - for simple rct + // when changing this function, update cryptonote::get_pruned_transaction_weight template<bool W, template <bool> class Archive> bool serialize_rctsig_prunable(Archive<W> &ar, uint8_t type, size_t inputs, size_t outputs, size_t mixin) { diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 6f5f912cd..dfc4d4cf3 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1951,7 +1951,6 @@ namespace cryptonote error_resp.message = "Internal error: can't produce valid response."; return false; } - res.miner_tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.miner_tx)); for (size_t n = 0; n < blk.tx_hashes.size(); ++n) { res.tx_hashes.push_back(epee::string_tools::pod_to_hex(blk.tx_hashes[n])); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 0174104be..6a54c24fb 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -144,6 +144,7 @@ namespace const command_line::arg_descriptor<std::string> arg_mnemonic_language = {"mnemonic-language", sw::tr("Language for mnemonic"), ""}; const command_line::arg_descriptor<std::string> arg_electrum_seed = {"electrum-seed", sw::tr("Specify Electrum seed for wallet recovery/creation"), ""}; const command_line::arg_descriptor<bool> arg_restore_deterministic_wallet = {"restore-deterministic-wallet", sw::tr("Recover wallet using Electrum-style mnemonic seed"), false}; + const command_line::arg_descriptor<bool> arg_restore_from_seed = {"restore-from-seed", sw::tr("alias for --restore-deterministic-wallet"), false}; const command_line::arg_descriptor<bool> arg_restore_multisig_wallet = {"restore-multisig-wallet", sw::tr("Recover multisig wallet using Electrum-style mnemonic seed"), false}; const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", sw::tr("Generate non-deterministic view and spend keys"), false}; const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false}; @@ -4280,7 +4281,7 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_ m_generate_from_json = command_line::get_arg(vm, arg_generate_from_json); m_mnemonic_language = command_line::get_arg(vm, arg_mnemonic_language); m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed); - m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); + m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet) || command_line::get_arg(vm, arg_restore_from_seed); m_restore_multisig_wallet = command_line::get_arg(vm, arg_restore_multisig_wallet); m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic); m_allow_mismatched_daemon_version = command_line::get_arg(vm, arg_allow_mismatched_daemon_version); @@ -5131,7 +5132,7 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, tr("WARNING: this transaction uses an unencrypted payment ID: these are obsolete and ignored. Use subaddresses instead."); } } - if (unlock_time) + if (unlock_time && !cryptonote::is_coinbase(tx)) message_writer() << tr("NOTE: This transaction is locked, see details with: show_transfer ") + epee::string_tools::pod_to_hex(txid); if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); @@ -5334,6 +5335,9 @@ bool simple_wallet::refresh_main(uint64_t start_height, enum ResetType reset, bo fail_msg_writer() << tr("refresh failed: ") << ss.str() << ". " << tr("Blocks received: ") << fetched_blocks; } + // prevent it from triggering the idle screen due to waiting for a foreground refresh + m_last_activity_time = time(NULL); + return true; } //---------------------------------------------------------------------------------------------------- @@ -9713,6 +9717,7 @@ int main(int argc, char* argv[]) command_line::add_arg(desc_params, arg_command); command_line::add_arg(desc_params, arg_restore_deterministic_wallet ); + command_line::add_arg(desc_params, arg_restore_from_seed ); command_line::add_arg(desc_params, arg_restore_multisig_wallet ); command_line::add_arg(desc_params, arg_non_deterministic ); command_line::add_arg(desc_params, arg_electrum_seed ); |