54 std::vector<std::pair<std::pair<blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, blobdata> > > >
blocks;
59 res.error_details =
"core::find_blockchain_supplement() returned false";
76 res.output_indices.clear();
78 res.error_details =
"failed retrieving a requested block";
85 res.output_indices.clear();
87 res.error_details =
"incorrect number of transactions retrieved for block";
99 res.error_details =
"core::get_tx_outputs_gindexs() returned false";
102 indices.push_back(
std::move(tx_indices));
107 for (
const auto& blob : it->second)
113 res.output_indices.clear();
115 res.error_details =
"failed retrieving a requested transaction";
123 res.error_details =
"core::get_tx_outputs_gindexs() returned false";
127 indices.push_back(
std::move(tx_indices));
140 res.start_height = req.start_height;
144 if (!chain.find_blockchain_supplement(req.known_hashes,
res.hashes,
res.start_height,
res.current_height,
false))
147 res.error_details =
"Blockchain::find_blockchain_supplement() returned false";
156 std::vector<cryptonote::transaction> found_txs_vec;
157 std::vector<crypto::hash> missed_vec;
165 res.error_details =
"core::get_transactions() returned false (exception caught there)";
169 size_t num_found = found_txs_vec.size();
171 std::vector<uint64_t> heights(num_found);
172 std::vector<bool> in_pool(num_found,
false);
173 std::vector<crypto::hash> found_hashes(num_found);
175 for (
size_t i=0; i < num_found; i++)
182 if (!missed_vec.empty())
184 std::vector<cryptonote::transaction> pool_txs;
188 for (
const auto& tx : pool_txs)
192 auto itr = std::find(missed_vec.begin(), missed_vec.end(), h);
194 if (itr != missed_vec.end())
196 found_hashes.push_back(h);
197 found_txs_vec.push_back(tx);
198 heights.push_back(std::numeric_limits<uint64_t>::max());
199 in_pool.push_back(
true);
200 missed_vec.erase(itr);
205 for (
size_t i=0; i < found_hashes.size(); i++)
208 info.height = heights[i];
209 info.in_pool = in_pool[i];
223 std::vector<bool> chain_spent_status;
224 std::vector<bool> pool_spent_status;
229 if ((chain_spent_status.size() != req.key_images.size()) || (pool_spent_status.size() != req.key_images.size()))
232 res.error_details =
"tx_pool::have_key_images_as_spent() gave vectors of wrong size(s).";
236 for(
size_t i=0; i < req.key_images.size(); i++)
238 if ( chain_spent_status[i] )
242 else if ( pool_spent_status[i] )
256 res.error_details =
"core::get_tx_outputs_gindexs() returned false";
274 MERROR(
"[SendRawTxHex]: Failed to parse tx from hexbuff: " << req.tx_as_hex);
276 res.error_details =
"Invalid hex";
279 handleTxBlob(tx_blob, req.relay,
res);
284 if (!m_p2p.get_payload_object().is_synchronized())
287 res.error_details =
"Not ready to accept transactions; try again later";
298 MERROR(
"[SendRawTx]: tx verification failed");
302 MERROR(
"[SendRawTx]: Failed to process tx");
305 res.error_details =
"";
309 res.error_details =
"mixin too low";
313 if (!
res.error_details.empty())
res.error_details +=
" and ";
314 res.error_details =
"double spend";
318 if (!
res.error_details.empty())
res.error_details +=
" and ";
319 res.error_details =
"utxo is already spent or is nonexistent";
323 if (!
res.error_details.empty())
res.error_details +=
" and ";
324 res.error_details =
"invalid input";
328 if (!
res.error_details.empty())
res.error_details +=
" and ";
329 res.error_details =
"invalid output";
333 if (!
res.error_details.empty())
res.error_details +=
" and ";
334 res.error_details =
"too big";
338 if (!
res.error_details.empty())
res.error_details +=
" and ";
339 res.error_details =
"overspend";
343 if (!
res.error_details.empty())
res.error_details +=
" and ";
344 res.error_details =
"fee too low";
348 if (!
res.error_details.empty())
res.error_details +=
" and ";
349 res.error_details =
"tx is not ringct";
351 if (
res.error_details.empty())
353 res.error_details =
"an unknown issue was found with the transaction";
361 MERROR(
"[SendRawTx]: tx accepted, but not relayed");
362 res.error_details =
"Not relayed";
370 r.txs.push_back(tx_blob);
385 res.error_details =
"Failed, wrong address";
390 if (
info.is_subaddress)
392 res.error_details =
"Failed, mining to subaddress isn't supported yet";
398 unsigned int concurrency_count = boost::thread::hardware_concurrency() * 4;
401 if(concurrency_count == 0)
403 concurrency_count = 257;
408 if(req.threads_count > concurrency_count)
410 res.error_details =
"Failed, too many threads relative to CPU cores.";
416 if(!m_core.
get_miner().
start(
info.address,
static_cast<size_t>(req.threads_count), req.do_background_mining, req.ignore_battery))
418 res.error_details =
"Failed, mining not started";
424 res.error_details =
"";
434 if (
res.info.height >
res.info.target_height)
436 res.info.target_height =
res.info.height;
441 res.info.wide_difficulty = chain.get_difficulty_for_next_block();
442 res.info.difficulty = (
res.info.wide_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
444 res.info.target = chain.get_difficulty_target();
446 res.info.tx_count = chain.get_total_transactions() -
res.info.height;
450 res.info.alt_blocks_count = chain.get_alternative_blocks_count();
452 uint64_t total_conn = m_p2p.get_public_connections_count();
453 res.info.outgoing_connections_count = m_p2p.get_public_outgoing_connections_count();
454 res.info.incoming_connections_count = total_conn -
res.info.outgoing_connections_count;
456 res.info.white_peerlist_size = m_p2p.get_public_white_peers_count();
458 res.info.grey_peerlist_size = m_p2p.get_public_gray_peers_count();
464 res.info.cumulative_difficulty = (
res.info.wide_cumulative_difficulty & 0xffffffffffffffff).convert_to<uint64_t>();
471 res.error_details =
"";
478 res.error_details =
"Failed, mining not stopped";
485 res.error_details =
"";
502 res.error_details =
"";
510 res.error_details =
"Error storing the blockchain";
522 res.hash = crypto::null_hash;
524 res.error_details =
"height given is higher than current chain height";
536 res.error_details =
"RPC method not yet implemented.";
542 res.error_details =
"RPC method not yet implemented.";
549 if (!getBlockHeaderByHash(block_hash,
res.header))
552 res.error_details =
"Requested block does not exist";
561 if (!getBlockHeaderByHash(req.hash,
res.header))
564 res.error_details =
"Requested block does not exist";
575 if (!getBlockHeaderByHash(block_hash,
res.header))
578 res.error_details =
"Requested block does not exist";
587 res.headers.resize(req.heights.size());
589 for (
size_t i=0; i < req.heights.size(); i++)
593 if (!getBlockHeaderByHash(block_hash,
res.headers[i]))
596 res.error_details =
"A requested block does not exist";
607 res.error_details =
"RPC method not yet implemented.";
613 res.error_details =
"RPC method not yet implemented.";
619 res.error_details =
"RPC method not yet implemented.";
624 if (req.level < 0 || req.level > 4)
627 res.error_details =
"Error: log level not valid";
647 res.error_details =
"RPC method not yet implemented.";
653 res.error_details =
"RPC method not yet implemented.";
659 res.error_details =
"RPC method not yet implemented.";
665 res.error_details =
"RPC method not yet implemented.";
671 res.error_details =
"RPC method not yet implemented.";
687 res.error_details =
"RPC method not yet implemented.";
693 res.error_details =
"RPC method not yet implemented.";
699 res.error_details =
"RPC method not yet implemented.";
704 std::map<uint64_t, std::tuple<uint64_t, uint64_t, uint64_t> > histogram;
709 catch (
const std::exception &e)
712 res.error_details = e.what();
716 res.histogram.clear();
717 res.histogram.reserve(histogram.size());
718 for (
const auto &i: histogram)
720 if (std::get<0>(i.second) >= req.min_count && (std::get<0>(i.second) <= req.max_count || req.max_count == 0))
721 res.histogram.emplace_back(
output_amount_count{i.first, std::get<0>(i.second), std::get<1>(i.second), std::get<2>(i.second)});
731 for (
const auto& i : req.outputs)
740 catch (
const std::exception& e)
743 res.error_details = e.what();
752 res.version = DAEMON_RPC_VERSION_ZMQ;
763 res.size_scale = 1024;
778 res.distributions.reserve(req.amounts.size());
783 auto data =
rpc::RpcHandler::get_output_distribution([
this](
uint64_t amount,
uint64_t from,
uint64_t to,
uint64_t &start_height, std::vector<uint64_t> &distribution,
uint64_t &base) {
return m_core.
get_output_distribution(amount, from, to, start_height, distribution, base); }, amount, req.from_height, req_to_height, [
this](
uint64_t height) {
return m_core.
get_blockchain_storage().
get_db().
get_block_hash_from_height(
height); }, req.cumulative, m_core.
get_current_blockchain_height());
786 res.distributions.clear();
788 res.error_details =
"Failed to get output distribution";
795 catch (
const std::exception& e)
797 res.distributions.clear();
799 res.error_details = e.what();
812 header.
hash = hash_in;
830 header.
reward += out.amount;
841 MDEBUG(
"Handling RPC request: " << request);
883 if (resp_message == NULL)
898 catch (
const std::exception& e)
virtual uint64_t get_tx_block_height(const crypto::hash &h) const =0
fetches the height of a transaction's block
virtual difficulty_type get_block_cumulative_difficulty(const uint64_t &height) const =0
fetch a block's cumulative difficulty
virtual crypto::hash get_block_hash_from_height(const uint64_t &height) const =0
fetch a block's hash
uint8_t get_current_hard_fork_version() const
gets the current hardfork version in use/voted for
uint64_t get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
get dynamic per kB or byte fee estimate for the next few blocks
HardFork::State get_hard_fork_state() const
gets the hardfork voting state object
uint64_t get_current_cumulative_block_weight_median() const
gets the block weight median based on recent blocks (same window as for the limit)
difficulty_type block_difficulty(uint64_t i) const
gets the difficulty of the block with a given height
uint64_t get_current_cumulative_block_weight_limit() const
gets the block weight limit based on recent blocks
bool store_blockchain()
stores the blockchain
static uint64_t get_fee_quantization_mask()
get fee quantization mask
const BlockchainDB & get_db() const
get a reference to the BlockchainDB in use by Blockchain
uint8_t get_ideal_hard_fork_version() const
returns the newest hardfork version known to the blockchain
std::map< uint64_t, std::tuple< uint64_t, uint64_t, uint64_t > > get_output_histogram(const std::vector< uint64_t > &amounts, bool unlocked, uint64_t recent_cutoff, uint64_t min_count=0) const
return a histogram of outputs on the blockchain
void get_output_key_mask_unlocked(const uint64_t &amount, const uint64_t &index, crypto::public_key &key, rct::key &mask, bool &unlocked) const
gets an output's key and unlocked state
bool get_hard_fork_voting_info(uint8_t version, uint32_t &window, uint32_t &votes, uint32_t &threshold, uint64_t &earliest_height, uint8_t &voting) const
get information about hardfork voting for a version
size_t get_pool_transactions_count() const
get the total number of transactions in the pool
bool get_transactions(const std::vector< crypto::hash > &txs_ids, std::vector< cryptonote::blobdata > &txs, std::vector< crypto::hash > &missed_txs) const
bool get_output_distribution(uint64_t amount, uint64_t from_height, uint64_t to_height, uint64_t &start_height, std::vector< uint64_t > &distribution, uint64_t &base) const
gets per block distribution of outputs of a given amount
bool are_key_images_spent_in_pool(const std::vector< crypto::key_image > &key_im, std::vector< bool > &spent) const
check if multiple key images are spent in the transaction pool
uint64_t get_current_blockchain_height() const
get the current height of the blockchain
Blockchain & get_blockchain_storage()
gets the Blockchain instance
crypto::hash get_tail_id() const
get the hash of the most recent block on the blockchain
network_type get_nettype() const
get the network type we're on
std::time_t get_start_time() const
gets start_time
crypto::hash get_block_id_by_height(uint64_t height) const
gets a block's hash given a height
i_cryptonote_protocol * get_protocol()
get the cryptonote protocol instance
uint64_t get_target_blockchain_height() const
gets the target blockchain height
bool get_pool_for_rpc(std::vector< cryptonote::rpc::tx_in_pool > &tx_infos, cryptonote::rpc::key_images_with_tx_hashes &key_image_infos) const
get information about all transactions and key images in the pool
miner & get_miner()
gets the miner instance
bool find_blockchain_supplement(const std::list< crypto::hash > &qblock_ids, NOTIFY_RESPONSE_CHAIN_ENTRY::request &resp) const
get recent block hashes for a foreign chain
bool get_block_by_hash(const crypto::hash &h, block &blk, bool *orphan=NULL) const
gets the block with a given hash
bool are_key_images_spent(const std::vector< crypto::key_image > &key_im, std::vector< bool > &spent) const
check if multiple key images are spent
bool handle_incoming_tx(const blobdata &tx_blob, tx_verification_context &tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
handles an incoming transaction
bool get_pool_transactions(std::vector< transaction > &txs, bool include_unrelayed_txes=true) const
get a list of all transactions in the pool
bool get_tx_outputs_gindexs(const crypto::hash &tx_id, std::vector< uint64_t > &indexs) const
gets the global indices for outputs from a given transaction
const account_public_address & get_mining_address() const
uint64_t get_speed() const
uint32_t get_threads_count() const
bool get_is_background_mining_enabled() const
bool start(const account_public_address &adr, size_t threads_count, bool do_background=false, bool ignore_battery=false)
void handle(const GetHeight::Request &req, GetHeight::Response &res)
rapidjson::Value & getID()
rapidjson::Value & getMessage()
static FullMessage responseMessage(Message *message)
std::string getRequestType() const
static const char * STATUS_FAILED
static const char * STATUS_OK
static boost::optional< output_distribution_data > get_output_distribution(const std::function< bool(uint64_t, uint64_t, uint64_t, uint64_t &, std::vector< uint64_t > &, uint64_t &)> &f, uint64_t amount, uint64_t from_height, uint64_t to_height, const std::function< crypto::hash(uint64_t)> &get_hash, bool cumulative, uint64_t blockchain_height)
std::vector< txin_v > vin
std::vector< tx_out > vout
#define HF_VERSION_PER_BYTE_FEE
#define COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
#define REQ_RESP_TYPES_MACRO(runtime_str, type, reqjson, resp_message_ptr, handler)
void mlog_set_log_level(int level)
SendRawTx::Response Response
std::string BAD_REQUEST(const std::string &request)
std::string BAD_JSON(const std::string &error_details)
std::vector< tx_output_indices > block_output_indices
std::vector< uint64_t > tx_output_indices
Holds cryptonote related classes and helpers.
bool get_account_address_from_str(address_parse_info &info, network_type nettype, std::string const &str)
bool parse_and_validate_block_from_blob(const blobdata &b_blob, block &b, crypto::hash *block_hash)
std::string get_account_address_as_str(network_type nettype, bool subaddress, account_public_address const &adr)
crypto::hash get_transaction_hash(const transaction &t)
blobdata tx_to_blob(const transaction &tx)
bool parse_and_validate_tx_from_blob(const blobdata &tx_blob, transaction &tx)
epee::misc_utils::struct_init< response_t > response
version
Supported socks variants.
const T & move(const T &t)
unsigned __int64 uint64_t
epee::misc_utils::struct_init< request_t > request
std::vector< crypto::hash > tx_hashes
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request &arg, cryptonote_connection_context &exclude_context)=0
std::vector< cryptonote::transaction > transactions
bool m_verification_failed
const char *const ELECTRONEUM_VERSION