Merge pull request #276 from wowario/upstream

Upstream
lite
jw 4 years ago committed by GitHub
commit 2f8ccfe0ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -196,7 +196,7 @@ namespace misc_utils
uint32_t dst = 0; uint32_t dst = 0;
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
const unsigned char tmp = isx[(int)*++it]; const unsigned char tmp = isx[(unsigned char)*++it];
CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding"); CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding");
dst = dst << 4 | tmp; dst = dst << 4 | tmp;
} }

@ -100,7 +100,7 @@ static const char *get_default_categories(int level)
switch (level) switch (level)
{ {
case 0: case 0:
categories = "*:WARNING,net:FATAL,net.http:FATAL,net.ssl:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,serialization:FATAL,daemon.rpc.payment:ERROR,stacktrace:INFO,logging:INFO,msgwriter:INFO"; categories = "*:WARNING,net:FATAL,net.http:FATAL,net.ssl:FATAL,net.p2p:FATAL,net.cn:FATAL,daemon.rpc:FATAL,global:INFO,verify:FATAL,serialization:FATAL,daemon.rpc.payment:ERROR,stacktrace:INFO,logging:INFO,msgwriter:INFO";
break; break;
case 1: case 1:
categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG"; categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG";

@ -86,7 +86,7 @@ DISABLE_VS_WARNINGS(4267)
//------------------------------------------------------------------ //------------------------------------------------------------------
Blockchain::Blockchain(tx_memory_pool& tx_pool) : Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0), m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_reset_timestamps_and_difficulties_height(true), m_current_block_cumul_weight_limit(0), m_current_block_cumul_weight_median(0),
m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false), m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_sync_on_blocks(true), m_db_sync_threshold(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_bytes_to_sync(0), m_cancel(false),
m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE), m_long_term_block_weights_window(CRYPTONOTE_LONG_TERM_BLOCK_WEIGHT_WINDOW_SIZE),
m_long_term_effective_median_block_weight(0), m_long_term_effective_median_block_weight(0),
@ -427,6 +427,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
if (num_popped_blocks > 0) if (num_popped_blocks > 0)
{ {
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
m_hardfork->reorganize_from_chain_height(get_current_blockchain_height()); m_hardfork->reorganize_from_chain_height(get_current_blockchain_height());
uint64_t top_block_height; uint64_t top_block_height;
crypto::hash top_block_hash = get_tail_id(top_block_height); crypto::hash top_block_hash = get_tail_id(top_block_height);
@ -567,6 +568,7 @@ block Blockchain::pop_block_from_blockchain()
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
block popped_block; block popped_block;
std::vector<transaction> popped_txs; std::vector<transaction> popped_txs;
@ -644,6 +646,7 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
invalidate_block_template_cache(); invalidate_block_template_cache();
m_db->reset(); m_db->reset();
m_db->drop_alt_blocks(); m_db->drop_alt_blocks();
@ -860,6 +863,8 @@ start:
// pop the oldest one from the list. This only requires 1x read per height instead // pop the oldest one from the list. This only requires 1x read per height instead
// of doing 735 (DIFFICULTY_BLOCKS_COUNT). // of doing 735 (DIFFICULTY_BLOCKS_COUNT).
bool check = false; bool check = false;
if (m_reset_timestamps_and_difficulties_height)
m_timestamps_and_difficulties_height = 0;
if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficulty_blocks_count) if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= difficulty_blocks_count)
{ {
uint64_t index = height - 1; uint64_t index = height - 1;
@ -1006,6 +1011,7 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
} }
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
// remove blocks from blockchain until we get back to where we should be. // remove blocks from blockchain until we get back to where we should be.
while (m_db->height() != rollback_height) while (m_db->height() != rollback_height)
@ -1042,6 +1048,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
// if empty alt chain passed (not sure how that could happen), return false // if empty alt chain passed (not sure how that could happen), return false
CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed"); CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
@ -1755,6 +1762,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0; m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = true;
uint64_t block_height = get_block_height(b); uint64_t block_height = get_block_height(b);
if(0 == block_height) if(0 == block_height)
{ {
@ -2609,6 +2617,7 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
} }
db_rtxn_guard rtxn_guard(m_db); db_rtxn_guard rtxn_guard(m_db);
total_height = get_current_blockchain_height();
blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height))); blocks.reserve(std::min(std::min(max_count, (size_t)10000), (size_t)(total_height - start_height)));
CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash), CHECK_AND_ASSERT_MES(m_db->get_blocks_from(start_height, 3, max_count, FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE, blocks, pruned, true, get_miner_tx_hash),
false, "Error getting blocks"); false, "Error getting blocks");
@ -4453,7 +4462,14 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
try try
{ {
if (m_batch_success) if (m_batch_success)
{
m_db->batch_stop(); m_db->batch_stop();
if (m_reset_timestamps_and_difficulties_height)
{
m_timestamps_and_difficulties_height = 0;
m_reset_timestamps_and_difficulties_height = false;
}
}
else else
m_db->batch_abort(); m_db->batch_abort();
success = true; success = true;

@ -1067,6 +1067,7 @@ namespace cryptonote
std::vector<uint64_t> m_timestamps; std::vector<uint64_t> m_timestamps;
std::vector<difficulty_type> m_difficulties; std::vector<difficulty_type> m_difficulties;
uint64_t m_timestamps_and_difficulties_height; uint64_t m_timestamps_and_difficulties_height;
bool m_reset_timestamps_and_difficulties_height;
uint64_t m_long_term_block_weights_window; uint64_t m_long_term_block_weights_window;
uint64_t m_long_term_effective_median_block_weight; uint64_t m_long_term_effective_median_block_weight;
mutable crypto::hash m_long_term_block_weights_cache_tip_hash; mutable crypto::hash m_long_term_block_weights_cache_tip_hash;

@ -650,7 +650,7 @@ namespace cryptonote
r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints); r = m_blockchain_storage.init(db.release(), m_nettype, m_offline, regtest ? &regtest_test_options : test_options, fixed_difficulty, get_checkpoints);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage"); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
r = m_mempool.init(max_txpool_weight); r = m_mempool.init(max_txpool_weight, m_nettype == FAKECHAIN);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool"); CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
// now that we have a valid m_blockchain_storage, we can clean out any // now that we have a valid m_blockchain_storage, we can clean out any

@ -116,7 +116,7 @@ namespace cryptonote
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_cookie(0) tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false)
{ {
} }
@ -1351,13 +1351,18 @@ namespace cryptonote
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it) for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
{ {
txpool_tx_meta_t meta; txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta) && !meta.matches(relay_category::legacy)) if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
{ {
MERROR(" failed to find tx meta"); MERROR(" failed to find tx meta");
continue; continue;
} }
LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase)); LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method());
if (!meta.matches(relay_category::legacy) && !(m_mine_stem_txes && meta.get_relay_method() == relay_method::stem))
{
LOG_PRINT_L2(" tx relay method is " << (unsigned)meta.get_relay_method());
continue;
}
if (meta.pruned) if (meta.pruned)
{ {
LOG_PRINT_L2(" tx is pruned"); LOG_PRINT_L2(" tx is pruned");
@ -1522,7 +1527,7 @@ namespace cryptonote
return n_removed; return n_removed;
} }
//--------------------------------------------------------------------------------- //---------------------------------------------------------------------------------
bool tx_memory_pool::init(size_t max_txpool_weight) bool tx_memory_pool::init(size_t max_txpool_weight, bool mine_stem_txes)
{ {
CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain); CRITICAL_REGION_LOCAL1(m_blockchain);
@ -1578,6 +1583,7 @@ namespace cryptonote
lock.commit(); lock.commit();
} }
m_mine_stem_txes = mine_stem_txes;
m_cookie = 0; m_cookie = 0;
// Ignore deserialization error // Ignore deserialization error

@ -205,10 +205,11 @@ namespace cryptonote
* @brief loads pool state (if any) from disk, and initializes pool * @brief loads pool state (if any) from disk, and initializes pool
* *
* @param max_txpool_weight the max weight in bytes * @param max_txpool_weight the max weight in bytes
* @param mine_stem_txes whether to mine txes in stem relay mode
* *
* @return true * @return true
*/ */
bool init(size_t max_txpool_weight = 0); bool init(size_t max_txpool_weight = 0, bool mine_stem_txes = false);
/** /**
* @brief attempts to save the transaction pool state to disk * @brief attempts to save the transaction pool state to disk
@ -603,6 +604,7 @@ private:
size_t m_txpool_max_weight; size_t m_txpool_max_weight;
size_t m_txpool_weight; size_t m_txpool_weight;
bool m_mine_stem_txes;
mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache; mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;

@ -511,7 +511,7 @@ bool t_rpc_command_executor::show_status() {
} }
std::stringstream str; std::stringstream str;
str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections") str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %u(out)+%u(in) connections")
% (unsigned long long)ires.height % (unsigned long long)ires.height
% (unsigned long long)net_height % (unsigned long long)net_height
% get_sync_percentage(ires) % get_sync_percentage(ires)
@ -521,7 +521,6 @@ bool t_rpc_command_executor::show_status() {
% get_mining_speed(cryptonote::difficulty_type(ires.wide_difficulty) / ires.target) % get_mining_speed(cryptonote::difficulty_type(ires.wide_difficulty) / ires.target)
% (unsigned)hfres.version % (unsigned)hfres.version
% get_fork_extra_info(hfres.earliest_height, net_height, ires.target) % get_fork_extra_info(hfres.earliest_height, net_height, ires.target)
% (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked")
% (unsigned)ires.outgoing_connections_count % (unsigned)ires.outgoing_connections_count
% (unsigned)ires.incoming_connections_count % (unsigned)ires.incoming_connections_count
; ;

@ -1468,8 +1468,8 @@ namespace hw {
offset = set_command_header(INS_PREFIX_HASH,2,cnt); offset = set_command_header(INS_PREFIX_HASH,2,cnt);
len = pref_length - pref_offset; len = pref_length - pref_offset;
//options //options
if (len > (BUFFER_SEND_SIZE-7)) { if (len > (BUFFER_SEND_SIZE-offset-3)) {
len = BUFFER_SEND_SIZE-7; len = BUFFER_SEND_SIZE-offset-3;
this->buffer_send[offset] = 0x80; this->buffer_send[offset] = 0x80;
} else { } else {
this->buffer_send[offset] = 0x00; this->buffer_send[offset] = 0x00;

@ -270,25 +270,25 @@ namespace cryptonote
{ {
if (!m_restricted && nettype() != FAKECHAIN) if (!m_restricted && nettype() != FAKECHAIN)
{ {
MERROR("RPC payment enabled, but server is not restricted, anyone can adjust their balance to bypass payment"); MFATAL("RPC payment enabled, but server is not restricted, anyone can adjust their balance to bypass payment");
return false; return false;
} }
cryptonote::address_parse_info info; cryptonote::address_parse_info info;
if (!get_account_address_from_str(info, nettype(), address)) if (!get_account_address_from_str(info, nettype(), address))
{ {
MERROR("Invalid payment address: " << address); MFATAL("Invalid payment address: " << address);
return false; return false;
} }
if (info.is_subaddress) if (info.is_subaddress)
{ {
MERROR("Payment address may not be a subaddress: " << address); MFATAL("Payment address may not be a subaddress: " << address);
return false; return false;
} }
uint64_t diff = command_line::get_arg(vm, arg_rpc_payment_difficulty); uint64_t diff = command_line::get_arg(vm, arg_rpc_payment_difficulty);
uint64_t credits = command_line::get_arg(vm, arg_rpc_payment_credits); uint64_t credits = command_line::get_arg(vm, arg_rpc_payment_credits);
if (diff == 0 || credits == 0) if (diff == 0 || credits == 0)
{ {
MERROR("Payments difficulty and/or payments credits are 0, but a payment address was given"); MFATAL("Payments difficulty and/or payments credits are 0, but a payment address was given");
return false; return false;
} }
m_rpc_payment_allow_free_loopback = command_line::get_arg(vm, arg_rpc_payment_allow_free_loopback); m_rpc_payment_allow_free_loopback = command_line::get_arg(vm, arg_rpc_payment_allow_free_loopback);
@ -308,7 +308,7 @@ namespace cryptonote
if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address), if (!set_bootstrap_daemon(command_line::get_arg(vm, arg_bootstrap_daemon_address),
command_line::get_arg(vm, arg_bootstrap_daemon_login))) command_line::get_arg(vm, arg_bootstrap_daemon_login)))
{ {
MERROR("Failed to parse bootstrap daemon address"); MFATAL("Failed to parse bootstrap daemon address");
return false; return false;
} }
@ -2817,7 +2817,7 @@ namespace cryptonote
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data()); crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
cryptonote::blobdata txblob; cryptonote::blobdata txblob;
if (!m_core.get_pool_transaction(txid, txblob, relay_category::legacy)) if (m_core.get_pool_transaction(txid, txblob, relay_category::legacy))
{ {
NOTIFY_NEW_TRANSACTIONS::request r; NOTIFY_NEW_TRANSACTIONS::request r;
r.txs.push_back(std::move(txblob)); r.txs.push_back(std::move(txblob));

@ -290,7 +290,7 @@ namespace cryptonote
TRY_ENTRY(); TRY_ENTRY();
boost::lock_guard<boost::mutex> lock(mutex); boost::lock_guard<boost::mutex> lock(mutex);
m_directory = std::move(directory); m_directory = std::move(directory);
std::string state_file_path = directory + "/" + RPC_PAYMENTS_DATA_FILENAME; std::string state_file_path = m_directory + "/" + RPC_PAYMENTS_DATA_FILENAME;
MINFO("loading rpc payments data from " << state_file_path); MINFO("loading rpc payments data from " << state_file_path);
std::ifstream data; std::ifstream data;
data.open(state_file_path, std::ios_base::binary | std::ios_base::in); data.open(state_file_path, std::ios_base::binary | std::ios_base::in);
@ -366,7 +366,7 @@ namespace cryptonote
for (std::unordered_map<crypto::public_key, client_info>::iterator i = m_client_info.begin(); i != m_client_info.end(); ) for (std::unordered_map<crypto::public_key, client_info>::iterator i = m_client_info.begin(); i != m_client_info.end(); )
{ {
std::unordered_map<crypto::public_key, client_info>::iterator j = i++; std::unordered_map<crypto::public_key, client_info>::iterator j = i++;
const time_t t = std::max(j->second.last_request_timestamp, j->second.update_time); const time_t t = std::max(j->second.last_request_timestamp / 1000000, j->second.update_time);
const bool erase = t < ((j->second.credits == 0) ? threshold0 : threshold); const bool erase = t < ((j->second.credits == 0) ? threshold0 : threshold);
if (erase) if (erase)
{ {

@ -7389,6 +7389,32 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx"; success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_wownero_tx";
} }
} }
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
{
try
{
tools::wallet2::signed_tx_set signed_tx;
std::vector<cryptonote::address_parse_info> dsts_info;
dsts_info.push_back(info);
if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){
fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet");
return true;
}
commit_or_save(signed_tx.ptx, m_do_not_relay);
success_msg_writer(true) << tr("Money successfully sent, transaction: ") << get_transaction_hash(ptx_vector[0].tx);
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon());
}
catch (...)
{
LOG_ERROR("Unknown error");
fail_msg_writer() << tr("unknown error");
}
}
else if (m_wallet->watch_only()) else if (m_wallet->watch_only())
{ {
bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx"); bool r = m_wallet->save_tx(ptx_vector, "unsigned_wownero_tx");

@ -9032,7 +9032,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
continue; continue;
} }
if (!is_spent(td2, false) && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index) if (!is_spent(td2, false) && !td2.m_frozen && !td2.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
{ {
// update our picks if those outputs are less related than any we // update our picks if those outputs are less related than any we
// already found. If the same, don't update, and oldest suitable outputs // already found. If the same, don't update, and oldest suitable outputs

@ -241,6 +241,17 @@ class TransferTest():
assert x.fee == txes[txid].fee assert x.fee == txes[txid].fee
assert x.tx_blob == txes[txid].tx_blob assert x.tx_blob == txes[txid].tx_blob
print('Checking relaying txes')
res = daemon.get_transaction_pool_hashes()
assert len(res.tx_hashes) > 0
txid = res.tx_hashes[0]
daemon.relay_tx([txid])
res = daemon.get_transactions([txid])
assert len(res.txs) == 1
assert res.txs[0].tx_hash == txid
assert res.txs[0].in_pool
assert res.txs[0].relayed
daemon.flush_txpool() daemon.flush_txpool()
self.check_empty_pool() self.check_empty_pool()

Loading…
Cancel
Save