Merge pull request #2920

bd5cce07 network_throttle: fix ineffective locking (moneromooo-monero)
e0a61299 network_throttle: remove unused xxx static member (moneromooo-monero)
24f584d9 cryptonote_core: remove unused functions with off by one bugs (moneromooo-monero)
b1634aa3 blockchain: don't leave dangling pointers in this (moneromooo-monero)
8e60b81c cryptonote_core: fix db leak on error (moneromooo-monero)
213e326c abstract_tcp_server2: log init_server errors as fatal (moneromooo-monero)
b51dc566 use const refs in for loops for non tiny types (moneromooo-monero)
f0568ca6 net_parse_helpers: fix regex error checking (moneromooo-monero)
b49ddc76 check accessing an element past the end of a container (moneromooo-monero)
2305bf26 check return value for generate_key_derivation and derive_public_key (moneromooo-monero)
a4240d9f catch const exceptions (moneromooo-monero)
45a1c4c0 add empty container sanity checks when using front() and back() (moneromooo-monero)
56fa6ce1 tests: fix a buffer overread in a unit test (moneromooo-monero)
b4524892 rpc: guard against json parsing a non object (moneromooo-monero)
c2ed8618 easylogging++: avoid buffer underflow (moneromooo-monero)
187a6ab2 epee: trap failure to parse URI from request (moneromooo-monero)
061789b5 checkpoints: trap failure to load JSON checkpoints (moneromooo-monero)
ba2fefb9 checkpoints: pass std::string by const ref, not const value (moneromooo-monero)
38c8f4e0 mlog: terminate a string at last char, just in case (moneromooo-monero)
d753d716 fix a few leaks by throwing objects, not newed pointers to objects (moneromooo-monero)
fe568db8 p2p: use size_t for arbitrary counters instead of uint8_t (moneromooo-monero)
46d6fa35 cryptonote_protocol: sanity check chain hashes from peer (moneromooo-monero)
25584f86 cryptonote_protocol: print peer versions when unexpected (moneromooo-monero)
490a5d41 rpc: do not try to use an invalid txid in relay_tx (moneromooo-monero)
This commit is contained in:
Riccardo Spagni 2017-12-25 21:17:52 +02:00
commit 2b00899bb2
No known key found for this signature in database
GPG key ID: 55432DF31CCD4FCD
39 changed files with 197 additions and 191 deletions

View file

@ -305,7 +305,7 @@ namespace net_utils
m_connections.back().powner = this;
m_connections.back().m_self_it = --m_connections.end();
m_connections.back().m_context.m_remote_address = remote_address;
m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back());
m_connections.back().m_htread = threads_helper::create_thread(ConnectionHandlerProc, &m_connections.back()); // ugh, seems very risky
return true;
}

View file

@ -735,7 +735,17 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::placeholders::error));
return true;
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::init_server", false);
}
catch (const std::exception &e)
{
MFATAL("Error starting server: " << e.what());
return false;
}
catch (...)
{
MFATAL("Error starting server");
return false;
}
}
//-----------------------------------------------------------------------------
PUSH_WARNINGS

View file

@ -345,7 +345,12 @@ namespace net_utils
{
analize_http_method(result, m_query_info.m_http_method, m_query_info.m_http_ver_hi, m_query_info.m_http_ver_hi);
m_query_info.m_URI = result[10];
parse_uri(m_query_info.m_URI, m_query_info.m_uri_content);
if (!parse_uri(m_query_info.m_URI, m_query_info.m_uri_content))
{
m_state = http_state_error;
MERROR("Failed to parse URI: m_query_info.m_URI");
return false;
}
m_query_info.m_http_method_str = result[2];
m_query_info.m_full_request_str = result[0];

View file

@ -103,7 +103,7 @@ namespace net_utils
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal);
boost::smatch result;
if(!boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched)
if(!(boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched))
{
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << uri);
content.m_path = uri;
@ -139,7 +139,7 @@ namespace net_utils
// 12 34 5 6 7
content.port = 0;
boost::smatch result;
if(!boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched)
if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched))
{
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << rexp_match_uri);
//content.m_path = uri;

View file

@ -121,8 +121,6 @@ class network_throttle_manager {
friend class connection_basic; // FRIEND - to directly access global throttle-s. !! REMEMBER TO USE LOCKS!
friend class connection_basic_pimpl; // ditto
static int xxx;
public:
static i_network_throttle & get_global_throttle_in(); ///< singleton ; for friend class ; caller MUST use proper locks! like m_lock_get_global_throttle_in
static i_network_throttle & get_global_throttle_inreq(); ///< ditto ; use lock ... use m_lock_get_global_throttle_inreq obviously

View file

@ -161,7 +161,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
val = boost::lexical_cast<XType>(str_id);
return true;
}
catch(std::exception& /*e*/)
catch(const std::exception& /*e*/)
{
//const char* pmsg = e.what();
return false;

View file

@ -59,6 +59,7 @@ static std::string generate_log_filename(const char *base)
strcpy(tmp, "unknown");
else
strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm);
tmp[sizeof(tmp) - 1] = 0;
filename += "-";
filename += tmp;
return filename;

View file

@ -231,8 +231,10 @@ network_time_seconds network_throttle::get_sleep_time_after_tick(size_t packet_s
}
void network_throttle::logger_handle_net(const std::string &filename, double time, size_t size) {
boost::mutex mutex;
mutex.lock(); {
static boost::mutex mutex;
boost::lock_guard<boost::mutex> lock(mutex);
{
std::fstream file;
file.open(filename.c_str(), std::ios::app | std::ios::out );
file.precision(6);
@ -240,7 +242,7 @@ void network_throttle::logger_handle_net(const std::string &filename, double tim
_warn("Can't open file " << filename);
file << static_cast<int>(time) << " " << static_cast<double>(size/1024) << "\n";
file.close();
} mutex.unlock();
}
}
// fine tune this to decide about sending speed:

View file

@ -71,9 +71,6 @@ boost::mutex network_throttle_manager::m_lock_get_global_throttle_in;
boost::mutex network_throttle_manager::m_lock_get_global_throttle_inreq;
boost::mutex network_throttle_manager::m_lock_get_global_throttle_out;
int network_throttle_manager::xxx;
// ================================================================================================
// methods:
i_network_throttle & network_throttle_manager::get_global_throttle_in() {

View file

@ -1016,8 +1016,9 @@ const std::string OS::getBashOutput(const char* command) {
char hBuff[4096];
if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) {
pclose(proc);
if (hBuff[strlen(hBuff) - 1] == '\n') {
hBuff[strlen(hBuff) - 1] = '\0';
const size_t len = strlen(hBuff);
if (len > 0 && hBuff[len - 1] == '\n') {
hBuff[len- 1] = '\0';
}
return std::string(hBuff);
}

View file

@ -197,7 +197,7 @@ uint64_t BlockchainDB::add_block( const block& blk
{
// sanity
if (blk.tx_hashes.size() != txs.size())
throw new std::runtime_error("Inconsistent tx/hashes sizes");
throw std::runtime_error("Inconsistent tx/hashes sizes");
block_txn_start(false);
@ -283,7 +283,7 @@ block BlockchainDB::get_block_from_height(const uint64_t& height) const
blobdata bd = get_block_blob_from_height(height);
block b;
if (!parse_and_validate_block_from_blob(bd, b))
throw new DB_ERROR("Failed to parse block from blob retrieved from the db");
throw DB_ERROR("Failed to parse block from blob retrieved from the db");
return b;
}
@ -293,7 +293,7 @@ block BlockchainDB::get_block(const crypto::hash& h) const
blobdata bd = get_block_blob(h);
block b;
if (!parse_and_validate_block_from_blob(bd, b))
throw new DB_ERROR("Failed to parse block from blob retrieved from the db");
throw DB_ERROR("Failed to parse block from blob retrieved from the db");
return b;
}
@ -304,7 +304,7 @@ bool BlockchainDB::get_tx(const crypto::hash& h, cryptonote::transaction &tx) co
if (!get_tx_blob(h, bd))
return false;
if (!parse_and_validate_tx_from_blob(bd, tx))
throw new DB_ERROR("Failed to parse transaction from blob retrieved from the db");
throw DB_ERROR("Failed to parse transaction from blob retrieved from the db");
return true;
}
@ -313,7 +313,7 @@ transaction BlockchainDB::get_tx(const crypto::hash& h) const
{
transaction tx;
if (!get_tx(h, tx))
throw new TX_DNE(std::string("tx with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str());
throw TX_DNE(std::string("tx with hash ").append(epee::string_tools::pod_to_hex(h)).append(" not found in db").c_str());
return tx;
}

View file

@ -2894,7 +2894,7 @@ uint64_t BlockchainLMDB::add_block(const block& blk, const size_t& block_size, c
{
BlockchainDB::add_block(blk, block_size, cumulative_difficulty, coins_generated, txs);
}
catch (DB_ERROR_TXN_START& e)
catch (const DB_ERROR_TXN_START& e)
{
throw;
}

View file

@ -459,7 +459,7 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
// tx number 1: coinbase tx
// tx number 2 onwards: archived_txs
for (transaction tx : archived_txs)
for (const transaction &tx : archived_txs)
{
// add blocks with verification.
// for Blockchain and blockchain_storage add_new_block().

View file

@ -204,7 +204,7 @@ namespace cryptonote
return true;
}
bool checkpoints::load_checkpoints_from_json(const std::string json_hashfile_fullpath)
bool checkpoints::load_checkpoints_from_json(const std::string &json_hashfile_fullpath)
{
boost::system::error_code errcode;
if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
@ -218,7 +218,11 @@ namespace cryptonote
uint64_t prev_max_height = get_max_height();
LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
t_hash_json hashes;
epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
if (!epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath))
{
MERROR("Error loading checkpoints from " << json_hashfile_fullpath);
return false;
}
for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
{
uint64_t height;
@ -286,7 +290,7 @@ namespace cryptonote
return true;
}
bool checkpoints::load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet, bool dns)
bool checkpoints::load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet, bool dns)
{
bool result;

View file

@ -165,7 +165,7 @@ namespace cryptonote
*
* @return true if loading successful and no conflicts
*/
bool load_new_checkpoints(const std::string json_hashfile_fullpath, bool testnet=false, bool dns=true);
bool load_new_checkpoints(const std::string &json_hashfile_fullpath, bool testnet=false, bool dns=true);
/**
* @brief load new checkpoints from json
@ -174,7 +174,7 @@ namespace cryptonote
*
* @return true if loading successful and no conflicts
*/
bool load_checkpoints_from_json(const std::string json_hashfile_fullpath);
bool load_checkpoints_from_json(const std::string &json_hashfile_fullpath);
/**
* @brief load new checkpoints from DNS

View file

@ -259,7 +259,7 @@ namespace cryptonote
ar.tag("rctsig_prunable");
ar.begin_object();
r = rct_signatures.p.serialize_rctsig_prunable(ar, rct_signatures.type, vin.size(), vout.size(),
vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
vin.size() > 0 && vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(vin[0]).key_offsets.size() - 1 : 0);
if (!r || !ar.stream().good()) return false;
ar.end_object();
}

View file

@ -630,17 +630,21 @@ namespace cryptonote
bool is_out_to_acc(const account_keys& acc, const txout_to_key& out_key, const crypto::public_key& tx_pub_key, const std::vector<crypto::public_key>& additional_tx_pub_keys, size_t output_index)
{
crypto::key_derivation derivation;
generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
bool r = generate_key_derivation(tx_pub_key, acc.m_view_secret_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
crypto::public_key pk;
derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
if (pk == out_key.key)
return true;
// try additional tx pubkeys if available
if (!additional_tx_pub_keys.empty())
{
CHECK_AND_ASSERT_MES(output_index < additional_tx_pub_keys.size(), false, "wrong number of additional tx pubkeys");
generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
r = generate_key_derivation(additional_tx_pub_keys[output_index], acc.m_view_secret_key, derivation);
CHECK_AND_ASSERT_MES(r, false, "Failed to generate key derivation");
r = derive_public_key(derivation, output_index, acc.m_account_address.m_spend_public_key, pk);
CHECK_AND_ASSERT_MES(r, false, "Failed to derive public key");
return pk == out_key.key;
}
return false;

View file

@ -321,6 +321,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, bool offline, const
if (!db->is_open())
{
LOG_ERROR("Attempted to init Blockchain with unopened DB");
delete db;
return false;
}
@ -471,7 +472,7 @@ bool Blockchain::deinit()
// memory operation), otherwise we may cause a loop.
if (m_db == NULL)
{
throw new DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
throw DB_ERROR("The db pointer is null in Blockchain, the blockchain may be corrupt!");
}
try
@ -489,7 +490,9 @@ bool Blockchain::deinit()
}
delete m_hardfork;
m_hardfork = NULL;
delete m_db;
m_db = NULL;
return true;
}
//------------------------------------------------------------------
@ -2050,49 +2053,6 @@ bool Blockchain::get_transactions(const t_ids_container& txs_ids, t_tx_container
return true;
}
//------------------------------------------------------------------
void Blockchain::print_blockchain(uint64_t start_index, uint64_t end_index) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
std::stringstream ss;
CRITICAL_REGION_LOCAL(m_blockchain_lock);
auto h = m_db->height();
if(start_index > h)
{
MERROR("Wrong starter index set: " << start_index << ", expected max index " << h);
return;
}
for(size_t i = start_index; i <= h && i != end_index; i++)
{
ss << "height " << i << ", timestamp " << m_db->get_block_timestamp(i) << ", cumul_dif " << m_db->get_block_cumulative_difficulty(i) << ", size " << m_db->get_block_size(i) << "\nid\t\t" << m_db->get_block_hash_from_height(i) << "\ndifficulty\t\t" << m_db->get_block_difficulty(i) << ", nonce " << m_db->get_block_from_height(i).nonce << ", tx_count " << m_db->get_block_from_height(i).tx_hashes.size() << std::endl;
}
MCINFO("globlal", "Current blockchain:" << std::endl << ss.str());
}
//------------------------------------------------------------------
void Blockchain::print_blockchain_index() const
{
LOG_PRINT_L3("Blockchain::" << __func__);
std::stringstream ss;
CRITICAL_REGION_LOCAL(m_blockchain_lock);
auto height = m_db->height();
if (height != 0)
{
for(uint64_t i = 0; i <= height; i++)
{
ss << "height: " << i << ", hash: " << m_db->get_block_hash_from_height(i);
}
}
MINFO("Current blockchain index:" << std::endl << ss.str());
}
//------------------------------------------------------------------
//TODO: remove this function and references to it
void Blockchain::print_blockchain_outs(const std::string& file) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
return;
}
//------------------------------------------------------------------
// Find the split point between us and foreign blockchain and return
// (by reference) the most recent common block hash along with up to
// BLOCKS_IDS_SYNCHRONIZING_DEFAULT_COUNT additional (more recent) hashes.
@ -2338,7 +2298,7 @@ void Blockchain::on_new_tx_from_block(const cryptonote::transaction &tx)
TIME_MEASURE_FINISH(a);
if(m_show_time_stats)
{
size_t ring_size = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
}
}
@ -2373,7 +2333,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, uint64_t& max_used_block_heigh
TIME_MEASURE_FINISH(a);
if(m_show_time_stats)
{
size_t ring_size = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
size_t ring_size = !tx.vin.empty() && tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() : 0;
MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << ring_size << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx));
}
if (!res)
@ -2466,6 +2426,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
// mixRing - full and simple store it in opposite ways
if (rv.type == rct::RCTTypeFull || rv.type == rct::RCTTypeFullBulletproof)
{
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys[0].size());
for (size_t m = 0; m < pubkeys[0].size(); ++m)
rv.mixRing[m].clear();
@ -2480,6 +2441,7 @@ bool Blockchain::expand_transaction_2(transaction &tx, const crypto::hash &tx_pr
}
else if (rv.type == rct::RCTTypeSimple || rv.type == rct::RCTTypeSimpleBulletproof)
{
CHECK_AND_ASSERT_MES(!pubkeys.empty() && !pubkeys[0].empty(), false, "empty pubkeys");
rv.mixRing.resize(pubkeys.size());
for (size_t n = 0; n < pubkeys.size(); ++n)
{
@ -2811,7 +2773,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
for (size_t n = 0; n < tx.vin.size(); ++n)
{
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
if (rv.p.MGs[n].II.empty() || memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
{
MERROR_VER("Failed to check ringct signatures: mismatched key image");
return false;
@ -2864,7 +2826,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
MERROR_VER("Failed to check ringct signatures: Bad MGs size");
return false;
}
if (rv.p.MGs[0].II.size() != tx.vin.size())
if (rv.p.MGs.empty() || rv.p.MGs[0].II.size() != tx.vin.size())
{
MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes");
return false;

View file

@ -679,32 +679,6 @@ namespace cryptonote
//debug functions
/**
* @brief prints data about a snippet of the blockchain
*
* if start_index is greater than the blockchain height, do nothing
*
* @param start_index height on chain to start at
* @param end_index height on chain to end at
*/
void print_blockchain(uint64_t start_index, uint64_t end_index) const;
/**
* @brief prints every block's hash
*
* WARNING: This function will absolutely crush a terminal in prints, so
* it is recommended to redirect this output to a log file (or null sink
* if a log file is already set up, as should be the default)
*/
void print_blockchain_index() const;
/**
* @brief currently does nothing, candidate for removal
*
* @param file
*/
void print_blockchain_outs(const std::string& file) const;
/**
* @brief check the blockchain against a set of checkpoints
*

View file

@ -377,7 +377,7 @@ namespace cryptonote
// folder might not be a directory, etc, etc
catch (...) { }
BlockchainDB* db = new_db(db_type);
std::unique_ptr<BlockchainDB> db(new_db(db_type));
if (db == NULL)
{
LOG_ERROR("Attempted to use non-existent database type");
@ -468,7 +468,7 @@ namespace cryptonote
m_blockchain_storage.set_user_options(blocks_threads,
blocks_per_sync, sync_mode, fast_sync);
r = m_blockchain_storage.init(db, m_testnet, m_offline, test_options);
r = m_blockchain_storage.init(db.release(), m_testnet, m_offline, test_options);
r = m_mempool.init();
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize memory pool");
@ -1052,21 +1052,6 @@ namespace cryptonote
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);

View file

@ -600,20 +600,6 @@ namespace cryptonote
*/
const Blockchain& get_blockchain_storage()const{return m_blockchain_storage;}
/**
* @copydoc Blockchain::print_blockchain
*
* @note see Blockchain::print_blockchain
*/
void print_blockchain(uint64_t start_index, uint64_t end_index) const;
/**
* @copydoc Blockchain::print_blockchain_index
*
* @note see Blockchain::print_blockchain_index
*/
void print_blockchain_index() const;
/**
* @copydoc tx_memory_pool::print_pool
*
@ -621,13 +607,6 @@ namespace cryptonote
*/
std::string print_pool(bool short_format) const;
/**
* @copydoc Blockchain::print_blockchain_outs
*
* @note see Blockchain::print_blockchain_outs
*/
void print_blockchain_outs(const std::string& file);
/**
* @copydoc miner::on_synchronized
*

View file

@ -190,6 +190,12 @@ namespace cryptonote
//---------------------------------------------------------------
bool construct_tx_with_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, bool rct, bool bulletproof, rct::multisig_out *msout)
{
if (sources.empty())
{
LOG_ERROR("Empty sources");
return false;
}
std::vector<rct::key> amount_keys;
tx.set_null();
amount_keys.clear();

View file

@ -62,6 +62,7 @@ void block_queue::add_blocks(uint64_t height, std::list<cryptonote::block_comple
void block_queue::add_blocks(uint64_t height, uint64_t nblocks, const boost::uuids::uuid &connection_id, boost::posix_time::ptime time)
{
CHECK_AND_ASSERT_THROW_MES(nblocks > 0, "Empty span");
boost::unique_lock<boost::recursive_mutex> lock(mutex);
blocks.insert(span(height, nblocks, connection_id, time));
}
@ -384,7 +385,7 @@ float block_queue::get_speed(const boost::uuids::uuid &connection_id) const
i->second = (i->second + span.rate) / 2;
}
float conn_rate = -1, best_rate = 0;
for (auto i: speeds)
for (const auto &i: speeds)
{
if (i.first == connection_id)
conn_rate = i.second;

View file

@ -266,13 +266,17 @@ namespace cryptonote
return true;
// from v6, if the peer advertises a top block version, reject if it's not what it should be (will only work if no voting)
const uint8_t version = m_core.get_ideal_hard_fork_version(hshd.current_height - 1);
if (version >= 6 && version != hshd.top_version)
if (hshd.current_height > 0)
{
if (version < hshd.top_version)
MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think - we may be forked from the network and a software upgrade may be needed");
LOG_DEBUG_CC(context, "Ignoring due to wrong top version for block " << (hshd.current_height - 1) << ": " << (unsigned)hshd.top_version << ", expected " << (unsigned)version);
return false;
const uint8_t version = m_core.get_ideal_hard_fork_version(hshd.current_height - 1);
if (version >= 6 && version != hshd.top_version)
{
if (version < hshd.top_version)
MCLOG_RED(el::Level::Warning, "global", context << " peer claims higher version that we think (" <<
(unsigned)hshd.top_version << " for " << (hshd.current_height - 1) << "instead of " << (unsigned)version <<
") - we may be forked from the network and a software upgrade may be needed");
return false;
}
}
context.m_remote_blockchain_height = hshd.current_height;
@ -999,6 +1003,11 @@ skip:
MDEBUG(context << " next span in the queue has blocks " << start_height << "-" << (start_height + blocks.size() - 1)
<< ", we need " << previous_height);
if (blocks.empty())
{
MERROR("Next span has no blocks");
break;
}
block new_block;
if (!parse_and_validate_block_from_blob(blocks.front().block, new_block))
@ -1494,6 +1503,7 @@ skip:
NOTIFY_REQUEST_CHAIN::request r = boost::value_initialized<NOTIFY_REQUEST_CHAIN::request>();
m_core.get_short_chain_history(r.block_ids);
CHECK_AND_ASSERT_MES(!r.block_ids.empty(), false, "Short chain history is empty");
if (!start_from_current_chain)
{
@ -1581,6 +1591,12 @@ skip:
drop_connection(context, true, false);
return 1;
}
if (arg.total_height < arg.m_block_ids.size() || arg.start_height > arg.total_height - arg.m_block_ids.size())
{
LOG_ERROR_CCONTEXT("sent invalid start/nblocks/height, dropping connection");
drop_connection(context, true, false);
return 1;
}
context.m_remote_blockchain_height = arg.total_height;
context.m_last_response_height = arg.start_height + arg.m_block_ids.size()-1;

View file

@ -173,7 +173,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
uint64_t height = boost::lexical_cast<uint64_t>(arg);
return m_executor.print_block_by_height(height);
}
catch (boost::bad_lexical_cast&)
catch (const boost::bad_lexical_cast&)
{
crypto::hash block_hash;
if (parse_hash256(arg, block_hash))
@ -420,7 +420,7 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
limit = std::stoi(args[0]);
}
catch(std::exception& ex) {
catch(const std::exception& ex) {
_erro("stoi exception");
return false;
}
@ -450,7 +450,7 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
try {
version = std::stoi(args[0]);
}
catch(std::exception& ex) {
catch(const std::exception& ex) {
return false;
}
if (version <= 0 || version > 255)

View file

@ -1611,7 +1611,7 @@ bool t_rpc_command_executor::alt_chain_info()
}
tools::msg_writer() << boost::lexical_cast<std::string>(res.chains.size()) << " alternate chains found:";
for (const auto chain: res.chains)
for (const auto &chain: res.chains)
{
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)

View file

@ -51,7 +51,7 @@ class size_logger
public:
~size_logger()
{
for (const auto i: types)
for (const auto &i: types)
std::cout << std::to_string(i.first) << "\t" << i.second << std::endl;
}
void add(const char *type, size_t size) { types.insert(std::make_pair(size, type)); }

View file

@ -205,6 +205,8 @@ namespace
*/
bool checksum_test(std::vector<std::string> seed, uint32_t unique_prefix_length)
{
if (seed.empty())
return false;
// The last word is the checksum.
std::string last_word = seed.back();
seed.pop_back();

View file

@ -1856,8 +1856,8 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::has_too_many_connections(const epee::net_utils::network_address &address)
{
const uint8_t max_connections = 1;
uint8_t count = 0;
const size_t max_connections = 1;
size_t count = 0;
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{

View file

@ -76,6 +76,7 @@ namespace rct {
//Generates a vector of secret key
//Mainly used in testing
keyV skvGen(size_t rows ) {
CHECK_AND_ASSERT_THROW_MES(rows > 0, "0 keys requested");
keyV rv(rows);
size_t i = 0;
crypto::rand(rows * sizeof(key), (uint8_t*)&rv[0]);
@ -351,6 +352,7 @@ namespace rct {
//This takes the outputs and commitments
//and hashes them into a 32 byte sized key
key cn_fast_hash(const ctkeyV &PC) {
if (PC.empty()) return rct::hash2rct(crypto::cn_fast_hash("", 0));
key rv;
cn_fast_hash(rv, &PC[0], 64*PC.size());
return rv;
@ -367,6 +369,7 @@ namespace rct {
//put them in the key vector and it concatenates them
//and then hashes them
key cn_fast_hash(const keyV &keys) {
if (keys.empty()) return rct::hash2rct(crypto::cn_fast_hash("", 0));
key rv;
cn_fast_hash(rv, &keys[0], keys.size() * sizeof(keys[0]));
//dp(rv);

View file

@ -492,6 +492,11 @@ namespace cryptonote
{
if (std::find(missed_txs.begin(), missed_txs.end(), h) == missed_txs.end())
{
if (txs.empty())
{
res.status = "Failed: internal error - txs is empty";
return true;
}
// core returns the ones it finds in the right order
if (get_transaction_hash(txs.front()) != h)
{
@ -1150,7 +1155,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.';
return false;
}
if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@ -1188,7 +1193,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by height. Height = " + boost::lexical_cast<std::string>(h) + ". Hash = " + epee::string_tools::pod_to_hex(block_hash) + '.';
return false;
}
if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@ -1274,7 +1279,7 @@ namespace cryptonote
error_resp.message = "Internal error: can't get block by hash. Hash = " + req.hash + '.';
return false;
}
if (blk.miner_tx.vin.front().type() != typeid(txin_gen))
if (blk.miner_tx.vin.size() != 1 || blk.miner_tx.vin.front().type() != typeid(txin_gen))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: coinbase transaction in the block has the wrong type";
@ -1436,19 +1441,25 @@ namespace cryptonote
{
failed = true;
}
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
txids.push_back(txid);
else
{
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
txids.push_back(txid);
}
}
}
if (!m_core.get_blockchain_storage().flush_txes_from_pool(txids))
{
res.status = "Failed to remove one more tx";
res.status = "Failed to remove one or more tx(es)";
return false;
}
if (failed)
{
res.status = "Failed to parse txid";
if (txids.empty())
res.status = "Failed to parse txid";
else
res.status = "Failed to parse some of the txids";
return false;
}
@ -1705,13 +1716,16 @@ namespace cryptonote
PERF_TIMER(on_relay_tx);
bool failed = false;
res.status = "";
for (const auto &str: req.txids)
{
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(str, txid_data))
{
res.status = std::string("Invalid transaction id: ") + str;
if (!res.status.empty()) res.status += ", ";
res.status += std::string("invalid transaction id: ") + str;
failed = true;
continue;
}
crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
@ -1727,8 +1741,10 @@ namespace cryptonote
}
else
{
res.status = std::string("Transaction not found in pool: ") + str;
if (!res.status.empty()) res.status += ", ";
res.status += std::string("transaction not found in pool: ") + str;
failed = true;
continue;
}
}

View file

@ -799,6 +799,10 @@ namespace rpc
}
header.hash = hash_in;
if (b.miner_tx.vin.size() != 1 || b.miner_tx.vin.front().type() != typeid(txin_gen))
{
return false;
}
header.height = boost::get<txin_gen>(b.miner_tx.vin.front()).height;
header.major_version = b.major_version;

View file

@ -111,7 +111,7 @@ FullMessage::FullMessage(Message* message)
FullMessage::FullMessage(const std::string& json_string, bool request)
{
doc.Parse(json_string.c_str());
if (doc.HasParseError())
if (doc.HasParseError() || !doc.IsObject())
{
throw cryptonote::json::PARSE_FAIL();
}

View file

@ -4321,9 +4321,9 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
fail_msg_writer() << tr("Multiple transactions are created, which is not supposed to happen");
return true;
}
if (ptx_vector[0].selected_transfers.size() > 1)
if (ptx_vector[0].selected_transfers.size() != 1)
{
fail_msg_writer() << tr("The transaction uses multiple inputs, which is not supposed to happen");
fail_msg_writer() << tr("The transaction uses multiple or no inputs, which is not supposed to happen");
return true;
}
@ -5175,7 +5175,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
min_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
catch (boost::bad_lexical_cast &) {
catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad min_height parameter:") << " " << local_args[0];
return true;
}
@ -5187,7 +5187,7 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
try {
max_height = boost::lexical_cast<uint64_t>(local_args[0]);
}
catch (boost::bad_lexical_cast &) {
catch (const boost::bad_lexical_cast &) {
fail_msg_writer() << tr("bad max_height parameter:") << " " << local_args[0];
return true;
}

View file

@ -293,6 +293,10 @@ std::vector<std::string> UnsignedTransactionImpl::recipientAddress() const
// TODO: return integrated address if short payment ID exists
std::vector<string> result;
for (const auto &utx: m_unsigned_tx_set.txes) {
if (utx.dests.empty()) {
MERROR("empty destinations, skipped");
continue;
}
result.push_back(cryptonote::get_account_address_as_str(m_wallet.m_wallet->testnet(), utx.dests[0].is_subaddress, utx.dests[0].addr));
}
return result;

View file

@ -540,6 +540,11 @@ crypto::hash8 get_short_payment_id(const tools::wallet2::pending_tx &ptx)
{
if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
if (ptx.dests.empty())
{
MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
return crypto::null_hash8;
}
decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key);
}
}
@ -4050,6 +4055,11 @@ crypto::hash wallet2::get_payment_id(const pending_tx &ptx) const
crypto::hash8 payment_id8 = null_hash8;
if(get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
if (ptx.dests.empty())
{
MWARNING("Encrypted payment id found, but no destinations public key, cannot decrypt");
return crypto::null_hash;
}
if (decrypt_payment_id(payment_id8, ptx.dests[0].addr.m_view_public_key, ptx.tx_key))
{
memcpy(payment_id.data, payment_id8.data, 8);
@ -4274,6 +4284,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, const std::string &signed_f
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
{
tools::wallet2::tx_construction_data &sd = exported_txs.txes[n];
THROW_WALLET_EXCEPTION_IF(sd.sources.empty(), error::wallet_internal_error, "Empty sources");
LOG_PRINT_L1(" " << (n+1) << ": " << sd.sources.size() << " inputs, ring size " << sd.sources[0].outputs.size());
signed_txes.ptx.push_back(pending_tx());
tools::wallet2::pending_tx &ptx = signed_txes.ptx.back();
@ -4950,6 +4961,7 @@ bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_out
if (global_index == real_index) // don't re-add real one
return false;
auto item = std::make_tuple(global_index, tx_public_key, mask);
CHECK_AND_ASSERT_MES(!outs.empty(), false, "internal error: outs is empty");
if (std::find(outs.back().begin(), outs.back().end(), item) != outs.back().end()) // don't add duplicates
return false;
outs.back().push_back(item);
@ -5114,7 +5126,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
// if there are just enough outputs to mix with, use all of them.
// Eventually this should become impossible.
uint64_t num_outs = 0, num_recent_outs = 0;
for (auto he: resp_t.result.histogram)
for (const auto &he: resp_t.result.histogram)
{
if (he.amount == amount)
{
@ -6223,7 +6235,8 @@ bool wallet2::light_wallet_parse_rct_str(const std::string& rct_string, const cr
if (decrypt) {
// Decrypt the mask
crypto::key_derivation derivation;
generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, derivation);
bool r = generate_key_derivation(tx_pub_key, get_account().get_keys().m_view_secret_key, derivation);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
crypto::secret_key scalar;
crypto::derivation_to_scalar(derivation, internal_output_index, scalar);
sc_sub(decrypted_mask.bytes,encrypted_mask.bytes,rct::hash_to_scalar(rct::sk2rct(scalar)).bytes);
@ -6635,7 +6648,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Made a " << ((txBlob.size() + 1023) / 1024) << " kB tx, with " << print_money(available_for_fee) << " available for fee (" <<
print_money(needed_fee) << " needed)");
if (needed_fee > available_for_fee && dsts[0].amount > 0)
if (needed_fee > available_for_fee && !dsts.empty() && dsts[0].amount > 0)
{
// we don't have enough for the fee, but we've only partially paid the current address,
// so we can take the fee from the paid amount, since we'll have to make another tx anyway
@ -7413,12 +7426,14 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
continue;
crypto::public_key derived_out_key;
derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
bool r = derive_public_key(derivation, n, address.m_spend_public_key, derived_out_key);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
bool found = out_key->key == derived_out_key;
crypto::key_derivation found_derivation = derivation;
if (!found && !additional_derivations.empty())
{
derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
r = derive_public_key(additional_derivations[n], n, address.m_spend_public_key, derived_out_key);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to derive public key");
found = out_key->key == derived_out_key;
found_derivation = additional_derivations[n];
}
@ -7883,13 +7898,15 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
bool r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
while (find_tx_extra_field_by_type(tx_extra_fields, pub_key_field, pk_index++)) {
const crypto::public_key tx_pub_key = pub_key_field.pub_key;
crypto::key_derivation derivation;
generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
for (size_t i = 0; i < td.m_tx.vout.size(); ++i)
{
@ -8176,13 +8193,15 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
const cryptonote::account_keys& keys = m_account.get_keys();
const crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(spent_tx);
crypto::key_derivation derivation;
generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
bool r = generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation);
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(spent_tx);
std::vector<crypto::key_derivation> additional_derivations;
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
additional_derivations.push_back({});
generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
r = generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back());
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key derivation");
}
size_t output_index = 0;
for (const cryptonote::tx_out& out : spent_tx.vout)
@ -8904,6 +8923,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
throw std::runtime_error(oss.str());
}
cryptonote::block blk_min, blk_mid, blk_max;
if (res.blocks.size() < 3) throw std::runtime_error("Not enough blocks returned from daemon");
if (!parse_and_validate_block_from_blob(res.blocks[0].block, blk_min)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_min));
if (!parse_and_validate_block_from_blob(res.blocks[1].block, blk_mid)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_mid));
if (!parse_and_validate_block_from_blob(res.blocks[2].block, blk_max)) throw std::runtime_error("failed to parse blob at height " + std::to_string(height_max));

View file

@ -497,7 +497,7 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er)
bool wallet_rpc_server::validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er)
{
crypto::hash8 integrated_payment_id = crypto::null_hash8;
std::string extra_nonce;
@ -552,6 +552,13 @@ namespace tools
}
}
if (at_least_one_destination && dsts.empty())
{
er.code = WALLET_RPC_ERROR_CODE_ZERO_DESTINATION;
er.message = "No destinations for this transfer";
return false;
}
if (!payment_id.empty())
{
@ -603,7 +610,7 @@ namespace tools
}
// validate the transfer requested and populate dsts & extra
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, true, er))
{
return false;
}
@ -613,6 +620,13 @@ namespace tools
uint64_t mixin = m_wallet->adjust_mixin(req.mixin);
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, req.priority, extra, req.account_index, req.subaddr_indices, m_trusted_daemon);
if (ptx_vector.empty())
{
er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
er.message = "No transaction created";
return false;
}
// reject proposed transactions if there are more than one. see on_transfer_split below.
if (ptx_vector.size() != 1)
{
@ -694,7 +708,7 @@ namespace tools
}
// validate the transfer requested and populate dsts & extra; RPC_TRANSFER::request and RPC_TRANSFER_SPLIT::request are identical types.
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, er))
if (!validate_transfer(req.destinations, req.payment_id, dsts, extra, true, er))
{
return false;
}
@ -891,7 +905,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
if (!validate_transfer(destination, req.payment_id, dsts, extra, er))
if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
}
@ -990,7 +1004,7 @@ namespace tools
destination.push_back(wallet_rpc::transfer_destination());
destination.back().amount = 0;
destination.back().address = req.address;
if (!validate_transfer(destination, req.payment_id, dsts, extra, er))
if (!validate_transfer(destination, req.payment_id, dsts, extra, true, er))
{
return false;
}

View file

@ -137,7 +137,7 @@ namespace tools
bool on_create_account(const wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_CREATE_ACCOUNT::response& res, epee::json_rpc::error& er);
bool on_label_account(const wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::request& req, wallet_rpc::COMMAND_RPC_LABEL_ACCOUNT::response& res, epee::json_rpc::error& er);
bool on_getheight(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res, epee::json_rpc::error& er);
bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, epee::json_rpc::error& er);
bool validate_transfer(const std::list<wallet_rpc::transfer_destination>& destinations, const std::string& payment_id, std::vector<cryptonote::tx_destination_entry>& dsts, std::vector<uint8_t>& extra, bool at_least_one_destination, epee::json_rpc::error& er);
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er);
bool on_transfer_split(const wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::request& req, wallet_rpc::COMMAND_RPC_TRANSFER_SPLIT::response& res, epee::json_rpc::error& er);
bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er);

View file

@ -81,7 +81,6 @@ static const struct {
{1,"x",1,"x",0},
{2,"x",1,"",1},
{1,"x",1,"",0},
{1,"x",2,"",0},
{1,"x",2,"x",0},
{2,"ax",2,"x",0},
{1,"xx",2,"xx",0},
@ -103,7 +102,7 @@ static const struct {
{8,"xxxxxxab",3,"xyz",0},
{8,"xxxxxxab",6,"abcdef",0},
{9,"\0xxxxxab",3,"ab",6},
{4,"\0\0a",3,"\0a",1},
{4,"\0\0a",3,"\0a",1}, //
};
TEST(slowmem,Success)
@ -122,7 +121,6 @@ TEST(slowmem,Success)
free(pat);
free(buf);
ASSERT_EQ(res,T[n].res);
ASSERT_EQ(1,1);
#ifdef VERBOSE
if (res!=T[n].res) printf("failed (got %zu, expected %zu)",res,T[n].res); else printf("ok");
printf("\n");