mirror of
https://github.com/monero-project/monero.git
synced 2024-11-18 10:01:02 +00:00
Merge pull request #1820
7a44f38a
Add support for the wallet to refresh pruned blocks (moneromooo-monero)da18898f
ringct: do not require range proof in decodeRct/decodeRctSimple (moneromooo-monero)b49c6ab4
rpc: add a default category for daemon rpc (moneromooo-monero)f113b92b
core: add functions to serialize base tx info (moneromooo-monero)6fd4b827
node_rpc_proxy: allow caching daemon RPC version (moneromooo-monero)b5c74e40
wallet: invalidate node proxy cache when reconnecting (moneromooo-monero)
This commit is contained in:
commit
78a99fe7da
12 changed files with 183 additions and 66 deletions
|
@ -250,6 +250,28 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
|
|
||||||
|
template<bool W, template <bool> class Archive>
|
||||||
|
bool serialize_base(Archive<W> &ar)
|
||||||
|
{
|
||||||
|
FIELDS(*static_cast<transaction_prefix *>(this))
|
||||||
|
|
||||||
|
if (version == 1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ar.tag("rct_signatures");
|
||||||
|
if (!vin.empty())
|
||||||
|
{
|
||||||
|
ar.begin_object();
|
||||||
|
bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
|
||||||
|
if (!r || !ar.stream().good()) return false;
|
||||||
|
ar.end_object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static size_t get_signature_size(const txin_v& tx_in);
|
static size_t get_signature_size(const txin_v& tx_in);
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,6 +93,16 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << tx_blob;
|
||||||
|
binary_archive<false> ba(ss);
|
||||||
|
bool r = tx.serialize_base(ba);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------
|
||||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
|
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace cryptonote
|
||||||
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
|
||||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
|
||||||
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||||
|
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx);
|
||||||
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||||
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
|
||||||
|
|
||||||
|
|
|
@ -873,8 +873,7 @@ namespace rct {
|
||||||
// must know the destination private key to find the correct amount, else will return a random number
|
// must know the destination private key to find the correct amount, else will return a random number
|
||||||
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
|
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeFull, false, "decodeRct called on non-full rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
|
@ -902,8 +901,7 @@ namespace rct {
|
||||||
|
|
||||||
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
|
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key &mask) {
|
||||||
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
|
CHECK_AND_ASSERT_MES(rv.type == RCTTypeSimple, false, "decodeRct called on non simple rctSig");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.p.rangeSigs.size() > 0, "Empty rv.p.rangeSigs");
|
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.ecdhInfo.size(), "Mismatched sizes of rv.outPk and rv.ecdhInfo");
|
||||||
CHECK_AND_ASSERT_THROW_MES(rv.outPk.size() == rv.p.rangeSigs.size(), "Mismatched sizes of rv.outPk and rv.p.rangeSigs");
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
CHECK_AND_ASSERT_THROW_MES(i < rv.ecdhInfo.size(), "Bad index");
|
||||||
|
|
||||||
//mask amount and mask
|
//mask amount and mask
|
||||||
|
|
|
@ -44,6 +44,9 @@ using namespace epee;
|
||||||
#include "rpc/rpc_args.h"
|
#include "rpc/rpc_args.h"
|
||||||
#include "core_rpc_server_error_codes.h"
|
#include "core_rpc_server_error_codes.h"
|
||||||
|
|
||||||
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||||
|
#define MONERO_DEFAULT_LOG_CATEGORY "daemon.rpc"
|
||||||
|
|
||||||
#define MAX_RESTRICTED_FAKE_OUTS_COUNT 40
|
#define MAX_RESTRICTED_FAKE_OUTS_COUNT 40
|
||||||
#define MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT 500
|
#define MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT 500
|
||||||
|
|
||||||
|
@ -151,6 +154,23 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobdata)
|
||||||
|
{
|
||||||
|
cryptonote::transaction tx;
|
||||||
|
|
||||||
|
if (!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx))
|
||||||
|
{
|
||||||
|
MERROR("Failed to parse and validate tx from blob");
|
||||||
|
return blobdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
binary_archive<true> ba(ss);
|
||||||
|
bool r = tx.serialize_base(ba);
|
||||||
|
CHECK_AND_ASSERT_MES(r, blobdata, "Failed to serialize rct signatures base");
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res)
|
bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res)
|
||||||
{
|
{
|
||||||
CHECK_CORE_BUSY();
|
CHECK_CORE_BUSY();
|
||||||
|
@ -162,10 +182,13 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t pruned_size = 0, unpruned_size = 0, ntxes = 0;
|
||||||
for(auto& bd: bs)
|
for(auto& bd: bs)
|
||||||
{
|
{
|
||||||
res.blocks.resize(res.blocks.size()+1);
|
res.blocks.resize(res.blocks.size()+1);
|
||||||
res.blocks.back().block = bd.first;
|
res.blocks.back().block = bd.first;
|
||||||
|
pruned_size += bd.first.size();
|
||||||
|
unpruned_size += bd.first.size();
|
||||||
res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices());
|
res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices());
|
||||||
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
|
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
|
||||||
block b;
|
block b;
|
||||||
|
@ -181,9 +204,15 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size_t txidx = 0;
|
size_t txidx = 0;
|
||||||
|
ntxes += bd.second.size();
|
||||||
for(const auto& t: bd.second)
|
for(const auto& t: bd.second)
|
||||||
{
|
{
|
||||||
res.blocks.back().txs.push_back(t);
|
if (req.prune)
|
||||||
|
res.blocks.back().txs.push_back(get_pruned_tx_blob(t));
|
||||||
|
else
|
||||||
|
res.blocks.back().txs.push_back(t);
|
||||||
|
pruned_size += res.blocks.back().txs.back().size();
|
||||||
|
unpruned_size += t.size();
|
||||||
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
|
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
|
||||||
bool r = m_core.get_tx_outputs_gindexs(b.tx_hashes[txidx++], res.output_indices.back().indices.back().indices);
|
bool r = m_core.get_tx_outputs_gindexs(b.tx_hashes[txidx++], res.output_indices.back().indices.back().indices);
|
||||||
if (!r)
|
if (!r)
|
||||||
|
@ -194,6 +223,7 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MDEBUG("on_get_blocks: " << bs.size() << " blocks, " << ntxes << " txes, pruned size " << pruned_size << ", unpruned size " << unpruned_size);
|
||||||
res.status = CORE_RPC_STATUS_OK;
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace cryptonote
|
||||||
// advance which version they will stop working with
|
// advance which version they will stop working with
|
||||||
// Don't go over 32767 for any of these
|
// Don't go over 32767 for any of these
|
||||||
#define CORE_RPC_VERSION_MAJOR 1
|
#define CORE_RPC_VERSION_MAJOR 1
|
||||||
#define CORE_RPC_VERSION_MINOR 6
|
#define CORE_RPC_VERSION_MINOR 7
|
||||||
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||||
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
|
||||||
|
|
||||||
|
@ -80,9 +80,11 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
std::list<crypto::hash> block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */
|
std::list<crypto::hash> block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */
|
||||||
uint64_t start_height;
|
uint64_t start_height;
|
||||||
|
bool prune;
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids)
|
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids)
|
||||||
KV_SERIALIZE(start_height)
|
KV_SERIALIZE(start_height)
|
||||||
|
KV_SERIALIZE(prune)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1638,11 +1638,11 @@ void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block
|
||||||
m_refresh_progress_reporter.update(height, false);
|
m_refresh_progress_reporter.update(height, false);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount)
|
void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount)
|
||||||
{
|
{
|
||||||
message_writer(console_color_green, false) << "\r" <<
|
message_writer(console_color_green, false) << "\r" <<
|
||||||
tr("Height ") << height << ", " <<
|
tr("Height ") << height << ", " <<
|
||||||
tr("transaction ") << get_transaction_hash(tx) << ", " <<
|
tr("transaction ") << txid << ", " <<
|
||||||
tr("received ") << print_money(amount);
|
tr("received ") << print_money(amount);
|
||||||
if (m_auto_refresh_refreshing)
|
if (m_auto_refresh_refreshing)
|
||||||
m_cmd_binder.print_prompt();
|
m_cmd_binder.print_prompt();
|
||||||
|
@ -1650,16 +1650,16 @@ void simple_wallet::on_money_received(uint64_t height, const cryptonote::transac
|
||||||
m_refresh_progress_reporter.update(height, true);
|
m_refresh_progress_reporter.update(height, true);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount)
|
void simple_wallet::on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount)
|
||||||
{
|
{
|
||||||
// Not implemented in CLI wallet
|
// Not implemented in CLI wallet
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx)
|
void simple_wallet::on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx)
|
||||||
{
|
{
|
||||||
message_writer(console_color_magenta, false) << "\r" <<
|
message_writer(console_color_magenta, false) << "\r" <<
|
||||||
tr("Height ") << height << ", " <<
|
tr("Height ") << height << ", " <<
|
||||||
tr("transaction ") << get_transaction_hash(spend_tx) << ", " <<
|
tr("transaction ") << txid << ", " <<
|
||||||
tr("spent ") << print_money(amount);
|
tr("spent ") << print_money(amount);
|
||||||
if (m_auto_refresh_refreshing)
|
if (m_auto_refresh_refreshing)
|
||||||
m_cmd_binder.print_prompt();
|
m_cmd_binder.print_prompt();
|
||||||
|
@ -1667,11 +1667,11 @@ void simple_wallet::on_money_spent(uint64_t height, const cryptonote::transactio
|
||||||
m_refresh_progress_reporter.update(height, true);
|
m_refresh_progress_reporter.update(height, true);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::on_skip_transaction(uint64_t height, const cryptonote::transaction& tx)
|
void simple_wallet::on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx)
|
||||||
{
|
{
|
||||||
message_writer(console_color_red, true) << "\r" <<
|
message_writer(console_color_red, true) << "\r" <<
|
||||||
tr("Height ") << height << ", " <<
|
tr("Height ") << height << ", " <<
|
||||||
tr("transaction ") << get_transaction_hash(tx) << ", " <<
|
tr("transaction ") << txid << ", " <<
|
||||||
tr("unsupported transaction format");
|
tr("unsupported transaction format");
|
||||||
if (m_auto_refresh_refreshing)
|
if (m_auto_refresh_refreshing)
|
||||||
m_cmd_binder.print_prompt();
|
m_cmd_binder.print_prompt();
|
||||||
|
|
|
@ -190,10 +190,10 @@ namespace cryptonote
|
||||||
|
|
||||||
//----------------- i_wallet2_callback ---------------------
|
//----------------- i_wallet2_callback ---------------------
|
||||||
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
|
virtual void on_new_block(uint64_t height, const cryptonote::block& block);
|
||||||
virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount);
|
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount);
|
||||||
virtual void on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount);
|
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount);
|
||||||
virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx);
|
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx);
|
||||||
virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx);
|
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx);
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
friend class refresh_progress_reporter_t;
|
friend class refresh_progress_reporter_t;
|
||||||
|
|
|
@ -45,8 +45,43 @@ NodeRPCProxy::NodeRPCProxy(epee::net_utils::http::http_simple_client &http_clien
|
||||||
, m_dynamic_per_kb_fee_estimate(0)
|
, m_dynamic_per_kb_fee_estimate(0)
|
||||||
, m_dynamic_per_kb_fee_estimate_cached_height(0)
|
, m_dynamic_per_kb_fee_estimate_cached_height(0)
|
||||||
, m_dynamic_per_kb_fee_estimate_grace_blocks(0)
|
, m_dynamic_per_kb_fee_estimate_grace_blocks(0)
|
||||||
|
, m_rpc_version(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
void NodeRPCProxy::invalidate()
|
||||||
|
{
|
||||||
|
m_height = 0;
|
||||||
|
m_height_time = 0;
|
||||||
|
for (size_t n = 0; n < 256; ++n)
|
||||||
|
m_earliest_height[n] = 0;
|
||||||
|
m_dynamic_per_kb_fee_estimate = 0;
|
||||||
|
m_dynamic_per_kb_fee_estimate_cached_height = 0;
|
||||||
|
m_dynamic_per_kb_fee_estimate_grace_blocks = 0;
|
||||||
|
m_rpc_version = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<std::string> NodeRPCProxy::get_rpc_version(uint32_t &rpc_version)
|
||||||
|
{
|
||||||
|
const time_t now = time(NULL);
|
||||||
|
if (m_rpc_version == 0)
|
||||||
|
{
|
||||||
|
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_VERSION::request> req_t = AUTO_VAL_INIT(req_t);
|
||||||
|
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_VERSION::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
|
||||||
|
req_t.jsonrpc = "2.0";
|
||||||
|
req_t.id = epee::serialization::storage_entry(0);
|
||||||
|
req_t.method = "get_version";
|
||||||
|
m_daemon_rpc_mutex.lock();
|
||||||
|
bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
|
||||||
|
m_daemon_rpc_mutex.unlock();
|
||||||
|
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
|
||||||
|
CHECK_AND_ASSERT_MES(resp_t.result.status != CORE_RPC_STATUS_BUSY, resp_t.result.status, "Failed to connect to daemon");
|
||||||
|
CHECK_AND_ASSERT_MES(resp_t.result.status == CORE_RPC_STATUS_OK, resp_t.result.status, "Failed to get daemon RPC version");
|
||||||
|
m_rpc_version = resp_t.result.version;
|
||||||
|
}
|
||||||
|
rpc_version = m_rpc_version;
|
||||||
|
return boost::optional<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
|
boost::optional<std::string> NodeRPCProxy::get_height(uint64_t &height)
|
||||||
{
|
{
|
||||||
const time_t now = time(NULL);
|
const time_t now = time(NULL);
|
||||||
|
|
|
@ -41,6 +41,9 @@ class NodeRPCProxy
|
||||||
public:
|
public:
|
||||||
NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex);
|
NodeRPCProxy(epee::net_utils::http::http_simple_client &http_client, boost::mutex &mutex);
|
||||||
|
|
||||||
|
void invalidate();
|
||||||
|
|
||||||
|
boost::optional<std::string> get_rpc_version(uint32_t &version);
|
||||||
boost::optional<std::string> get_height(uint64_t &height);
|
boost::optional<std::string> get_height(uint64_t &height);
|
||||||
void set_height(uint64_t h);
|
void set_height(uint64_t h);
|
||||||
boost::optional<std::string> get_earliest_height(uint8_t version, uint64_t &earliest_height);
|
boost::optional<std::string> get_earliest_height(uint8_t version, uint64_t &earliest_height);
|
||||||
|
@ -56,6 +59,7 @@ private:
|
||||||
uint64_t m_dynamic_per_kb_fee_estimate;
|
uint64_t m_dynamic_per_kb_fee_estimate;
|
||||||
uint64_t m_dynamic_per_kb_fee_estimate_cached_height;
|
uint64_t m_dynamic_per_kb_fee_estimate_cached_height;
|
||||||
uint64_t m_dynamic_per_kb_fee_estimate_grace_blocks;
|
uint64_t m_dynamic_per_kb_fee_estimate_grace_blocks;
|
||||||
|
uint32_t m_rpc_version;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -633,28 +633,13 @@ bool wallet2::wallet_generate_key_image_helper(const cryptonote::account_keys& a
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::process_new_transaction(const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool)
|
void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool)
|
||||||
{
|
{
|
||||||
class lazy_txid_getter
|
// In this function, tx (probably) only contains the base information
|
||||||
{
|
// (that is, the prunable stuff may or may not be included)
|
||||||
const cryptonote::transaction &tx;
|
|
||||||
crypto::hash lazy_txid;
|
|
||||||
bool computed;
|
|
||||||
public:
|
|
||||||
lazy_txid_getter(const transaction &tx): tx(tx), computed(false) {}
|
|
||||||
const crypto::hash &operator()()
|
|
||||||
{
|
|
||||||
if (!computed)
|
|
||||||
{
|
|
||||||
lazy_txid = cryptonote::get_transaction_hash(tx);
|
|
||||||
computed = true;
|
|
||||||
}
|
|
||||||
return lazy_txid;
|
|
||||||
}
|
|
||||||
} txid(tx);
|
|
||||||
|
|
||||||
if (!miner_tx)
|
if (!miner_tx)
|
||||||
process_unconfirmed(tx, height);
|
process_unconfirmed(txid, tx, height);
|
||||||
std::vector<size_t> outs;
|
std::vector<size_t> outs;
|
||||||
uint64_t tx_money_got_in_outs = 0;
|
uint64_t tx_money_got_in_outs = 0;
|
||||||
crypto::public_key tx_pub_key = null_pkey;
|
crypto::public_key tx_pub_key = null_pkey;
|
||||||
|
@ -663,7 +648,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
if(!parse_tx_extra(tx.extra, tx_extra_fields))
|
if(!parse_tx_extra(tx.extra, tx_extra_fields))
|
||||||
{
|
{
|
||||||
// Extra may only be partially parsed, it's OK if tx_extra_fields contains public key
|
// Extra may only be partially parsed, it's OK if tx_extra_fields contains public key
|
||||||
LOG_PRINT_L0("Transaction extra has unsupported format: " << txid());
|
LOG_PRINT_L0("Transaction extra has unsupported format: " << txid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't try to extract tx public key if tx has no ouputs
|
// Don't try to extract tx public key if tx has no ouputs
|
||||||
|
@ -677,9 +662,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
{
|
{
|
||||||
if (pk_index > 1)
|
if (pk_index > 1)
|
||||||
break;
|
break;
|
||||||
LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid());
|
LOG_PRINT_L0("Public key wasn't found in the transaction extra. Skipping transaction " << txid);
|
||||||
if(0 != m_callback)
|
if(0 != m_callback)
|
||||||
m_callback->on_skip_transaction(height, tx);
|
m_callback->on_skip_transaction(height, txid, tx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +864,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
td.m_internal_output_index = o;
|
td.m_internal_output_index = o;
|
||||||
td.m_global_output_index = o_indices[o];
|
td.m_global_output_index = o_indices[o];
|
||||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||||
td.m_txid = txid();
|
td.m_txid = txid;
|
||||||
td.m_key_image = ki[o];
|
td.m_key_image = ki[o];
|
||||||
td.m_key_image_known = !m_watch_only;
|
td.m_key_image_known = !m_watch_only;
|
||||||
td.m_amount = tx.vout[o].amount;
|
td.m_amount = tx.vout[o].amount;
|
||||||
|
@ -903,9 +888,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
set_unspent(m_transfers.size()-1);
|
set_unspent(m_transfers.size()-1);
|
||||||
m_key_images[td.m_key_image] = m_transfers.size()-1;
|
m_key_images[td.m_key_image] = m_transfers.size()-1;
|
||||||
m_pub_keys[in_ephemeral[o].pub] = m_transfers.size()-1;
|
m_pub_keys[in_ephemeral[o].pub] = m_transfers.size()-1;
|
||||||
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid());
|
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
|
||||||
if (0 != m_callback)
|
if (0 != m_callback)
|
||||||
m_callback->on_money_received(height, tx, td.m_amount);
|
m_callback->on_money_received(height, txid, tx, td.m_amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount)
|
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount)
|
||||||
|
@ -930,7 +915,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
td.m_internal_output_index = o;
|
td.m_internal_output_index = o;
|
||||||
td.m_global_output_index = o_indices[o];
|
td.m_global_output_index = o_indices[o];
|
||||||
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
td.m_tx = (const cryptonote::transaction_prefix&)tx;
|
||||||
td.m_txid = txid();
|
td.m_txid = txid;
|
||||||
td.m_amount = tx.vout[o].amount;
|
td.m_amount = tx.vout[o].amount;
|
||||||
td.m_pk_index = pk_index - 1;
|
td.m_pk_index = pk_index - 1;
|
||||||
if (td.m_amount == 0)
|
if (td.m_amount == 0)
|
||||||
|
@ -952,9 +937,9 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
THROW_WALLET_EXCEPTION_IF(td.get_public_key() != in_ephemeral[o].pub, error::wallet_internal_error, "Inconsistent public keys");
|
THROW_WALLET_EXCEPTION_IF(td.get_public_key() != in_ephemeral[o].pub, error::wallet_internal_error, "Inconsistent public keys");
|
||||||
THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status");
|
THROW_WALLET_EXCEPTION_IF(td.m_spent, error::wallet_internal_error, "Inconsistent spent status");
|
||||||
|
|
||||||
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid());
|
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
|
||||||
if (0 != m_callback)
|
if (0 != m_callback)
|
||||||
m_callback->on_money_received(height, tx, td.m_amount);
|
m_callback->on_money_received(height, txid, tx, td.m_amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -982,17 +967,17 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
tx_money_spent_in_ins += amount;
|
tx_money_spent_in_ins += amount;
|
||||||
if (!pool)
|
if (!pool)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid());
|
LOG_PRINT_L0("Spent money: " << print_money(amount) << ", with tx: " << txid);
|
||||||
set_spent(it->second, height);
|
set_spent(it->second, height);
|
||||||
if (0 != m_callback)
|
if (0 != m_callback)
|
||||||
m_callback->on_money_spent(height, tx, amount, tx);
|
m_callback->on_money_spent(height, txid, tx, amount, tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx_money_spent_in_ins > 0)
|
if (tx_money_spent_in_ins > 0)
|
||||||
{
|
{
|
||||||
process_outgoing(tx, height, ts, tx_money_spent_in_ins, tx_money_got_in_outs);
|
process_outgoing(txid, tx, height, ts, tx_money_spent_in_ins, tx_money_got_in_outs);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0;
|
uint64_t received = (tx_money_spent_in_ins < tx_money_got_in_outs) ? tx_money_got_in_outs - tx_money_spent_in_ins : 0;
|
||||||
|
@ -1038,7 +1023,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
}
|
}
|
||||||
|
|
||||||
payment_details payment;
|
payment_details payment;
|
||||||
payment.m_tx_hash = txid();
|
payment.m_tx_hash = txid;
|
||||||
payment.m_amount = received;
|
payment.m_amount = received;
|
||||||
payment.m_block_height = height;
|
payment.m_block_height = height;
|
||||||
payment.m_unlock_time = tx.unlock_time;
|
payment.m_unlock_time = tx.unlock_time;
|
||||||
|
@ -1046,7 +1031,7 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
if (pool) {
|
if (pool) {
|
||||||
m_unconfirmed_payments.emplace(payment_id, payment);
|
m_unconfirmed_payments.emplace(payment_id, payment);
|
||||||
if (0 != m_callback)
|
if (0 != m_callback)
|
||||||
m_callback->on_unconfirmed_money_received(height, tx, payment.m_amount);
|
m_callback->on_unconfirmed_money_received(height, txid, tx, payment.m_amount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_payments.emplace(payment_id, payment);
|
m_payments.emplace(payment_id, payment);
|
||||||
|
@ -1054,12 +1039,11 @@ void wallet2::process_new_transaction(const cryptonote::transaction& tx, const s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::process_unconfirmed(const cryptonote::transaction& tx, uint64_t height)
|
void wallet2::process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height)
|
||||||
{
|
{
|
||||||
if (m_unconfirmed_txs.empty())
|
if (m_unconfirmed_txs.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
crypto::hash txid = get_transaction_hash(tx);
|
|
||||||
auto unconf_it = m_unconfirmed_txs.find(txid);
|
auto unconf_it = m_unconfirmed_txs.find(txid);
|
||||||
if(unconf_it != m_unconfirmed_txs.end()) {
|
if(unconf_it != m_unconfirmed_txs.end()) {
|
||||||
if (store_tx_info()) {
|
if (store_tx_info()) {
|
||||||
|
@ -1075,9 +1059,8 @@ void wallet2::process_unconfirmed(const cryptonote::transaction& tx, uint64_t he
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::process_outgoing(const cryptonote::transaction &tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received)
|
void wallet2::process_outgoing(const crypto::hash &txid, const cryptonote::transaction &tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received)
|
||||||
{
|
{
|
||||||
crypto::hash txid = get_transaction_hash(tx);
|
|
||||||
std::pair<std::unordered_map<crypto::hash, confirmed_transfer_details>::iterator, bool> entry = m_confirmed_txs.insert(std::make_pair(txid, confirmed_transfer_details()));
|
std::pair<std::unordered_map<crypto::hash, confirmed_transfer_details>::iterator, bool> entry = m_confirmed_txs.insert(std::make_pair(txid, confirmed_transfer_details()));
|
||||||
// fill with the info we know, some info might already be there
|
// fill with the info we know, some info might already be there
|
||||||
if (entry.second)
|
if (entry.second)
|
||||||
|
@ -1120,16 +1103,19 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
|
||||||
if(b.timestamp + 60*60*24 > m_account.get_createtime() && height >= m_refresh_from_block_height)
|
if(b.timestamp + 60*60*24 > m_account.get_createtime() && height >= m_refresh_from_block_height)
|
||||||
{
|
{
|
||||||
TIME_MEASURE_START(miner_tx_handle_time);
|
TIME_MEASURE_START(miner_tx_handle_time);
|
||||||
process_new_transaction(b.miner_tx, o_indices.indices[txidx++].indices, height, b.timestamp, true, false);
|
process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, o_indices.indices[txidx++].indices, height, b.timestamp, true, false);
|
||||||
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
TIME_MEASURE_FINISH(miner_tx_handle_time);
|
||||||
|
|
||||||
TIME_MEASURE_START(txs_handle_time);
|
TIME_MEASURE_START(txs_handle_time);
|
||||||
for(auto& txblob: bche.txs)
|
THROW_WALLET_EXCEPTION_IF(bche.txs.size() != b.tx_hashes.size(), error::wallet_internal_error, "Wrong amount of transactions for block");
|
||||||
|
size_t idx = 0;
|
||||||
|
for (const auto& txblob: bche.txs)
|
||||||
{
|
{
|
||||||
cryptonote::transaction tx;
|
cryptonote::transaction tx;
|
||||||
bool r = parse_and_validate_tx_from_blob(txblob, tx);
|
bool r = parse_and_validate_tx_base_from_blob(txblob, tx);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::tx_parse_error, txblob);
|
THROW_WALLET_EXCEPTION_IF(!r, error::tx_parse_error, txblob);
|
||||||
process_new_transaction(tx, o_indices.indices[txidx++].indices, height, b.timestamp, false, false);
|
process_new_transaction(b.tx_hashes[idx], tx, o_indices.indices[txidx++].indices, height, b.timestamp, false, false);
|
||||||
|
++idx;
|
||||||
}
|
}
|
||||||
TIME_MEASURE_FINISH(txs_handle_time);
|
TIME_MEASURE_FINISH(txs_handle_time);
|
||||||
LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
|
LOG_PRINT_L2("Processed block: " << bl_id << ", height " << height << ", " << miner_tx_handle_time + txs_handle_time << "(" << miner_tx_handle_time << "/" << txs_handle_time <<")ms");
|
||||||
|
@ -1185,6 +1171,34 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height,
|
||||||
cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res);
|
cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res);
|
||||||
req.block_ids = short_chain_history;
|
req.block_ids = short_chain_history;
|
||||||
|
|
||||||
|
uint32_t rpc_version;
|
||||||
|
boost::optional<std::string> result = m_node_rpc_proxy.get_rpc_version(rpc_version);
|
||||||
|
// no error
|
||||||
|
if (!!result)
|
||||||
|
{
|
||||||
|
// empty string -> not connection
|
||||||
|
THROW_WALLET_EXCEPTION_IF(result->empty(), tools::error::no_connection_to_daemon, "getversion");
|
||||||
|
THROW_WALLET_EXCEPTION_IF(*result == CORE_RPC_STATUS_BUSY, tools::error::daemon_busy, "getversion");
|
||||||
|
if (*result != CORE_RPC_STATUS_OK)
|
||||||
|
{
|
||||||
|
MDEBUG("Cannot determined daemon RPC version, not asking for pruned blocks");
|
||||||
|
req.prune = false; // old daemon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rpc_version >= MAKE_CORE_RPC_VERSION(1, 7))
|
||||||
|
{
|
||||||
|
MDEBUG("Daemon is recent enough, asking for pruned blocks");
|
||||||
|
req.prune = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MDEBUG("Daemon is too old, not asking for pruned blocks");
|
||||||
|
req.prune = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.start_height = start_height;
|
req.start_height = start_height;
|
||||||
m_daemon_rpc_mutex.lock();
|
m_daemon_rpc_mutex.lock();
|
||||||
bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout);
|
bool r = net_utils::invoke_http_bin("/getblocks.bin", req, res, m_http_client, rpc_timeout);
|
||||||
|
@ -1497,7 +1511,7 @@ void wallet2::update_pool_state()
|
||||||
{
|
{
|
||||||
if (tx_hash == txid)
|
if (tx_hash == txid)
|
||||||
{
|
{
|
||||||
process_new_transaction(tx, std::vector<uint64_t>(), 0, time(NULL), false, true);
|
process_new_transaction(txid, tx, std::vector<uint64_t>(), 0, time(NULL), false, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2286,6 +2300,7 @@ bool wallet2::check_connection(uint32_t *version, uint32_t timeout)
|
||||||
|
|
||||||
if(!m_http_client.is_connected())
|
if(!m_http_client.is_connected())
|
||||||
{
|
{
|
||||||
|
m_node_rpc_proxy.invalidate();
|
||||||
if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
|
if (!m_http_client.connect(std::chrono::milliseconds(timeout)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,10 +70,10 @@ namespace tools
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void on_new_block(uint64_t height, const cryptonote::block& block) {}
|
virtual void on_new_block(uint64_t height, const cryptonote::block& block) {}
|
||||||
virtual void on_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) {}
|
virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) {}
|
||||||
virtual void on_unconfirmed_money_received(uint64_t height, const cryptonote::transaction& tx, uint64_t amount) {}
|
virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount) {}
|
||||||
virtual void on_money_spent(uint64_t height, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) {}
|
virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx) {}
|
||||||
virtual void on_skip_transaction(uint64_t height, const cryptonote::transaction& tx) {}
|
virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx) {}
|
||||||
virtual ~i_wallet2_callback() {}
|
virtual ~i_wallet2_callback() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ namespace tools
|
||||||
* \param password Password of wallet file
|
* \param password Password of wallet file
|
||||||
*/
|
*/
|
||||||
bool load_keys(const std::string& keys_file_name, const std::string& password);
|
bool load_keys(const std::string& keys_file_name, const std::string& password);
|
||||||
void process_new_transaction(const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool);
|
void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool);
|
||||||
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height, const cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices &o_indices);
|
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const crypto::hash& bl_id, uint64_t height, const cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices &o_indices);
|
||||||
void detach_blockchain(uint64_t height);
|
void detach_blockchain(uint64_t height);
|
||||||
void get_short_chain_history(std::list<crypto::hash>& ids) const;
|
void get_short_chain_history(std::list<crypto::hash>& ids) const;
|
||||||
|
@ -598,8 +598,8 @@ namespace tools
|
||||||
void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, const std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t& blocks_added);
|
void process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, const std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t& blocks_added);
|
||||||
uint64_t select_transfers(uint64_t needed_money, std::vector<size_t> unused_transfers_indices, std::list<size_t>& selected_transfers, bool trusted_daemon);
|
uint64_t select_transfers(uint64_t needed_money, std::vector<size_t> unused_transfers_indices, std::list<size_t>& selected_transfers, bool trusted_daemon);
|
||||||
bool prepare_file_names(const std::string& file_path);
|
bool prepare_file_names(const std::string& file_path);
|
||||||
void process_unconfirmed(const cryptonote::transaction& tx, uint64_t height);
|
void process_unconfirmed(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height);
|
||||||
void process_outgoing(const cryptonote::transaction& tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received);
|
void process_outgoing(const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t height, uint64_t ts, uint64_t spent, uint64_t received);
|
||||||
void add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amount_in, const std::vector<cryptonote::tx_destination_entry> &dests, const crypto::hash &payment_id, uint64_t change_amount);
|
void add_unconfirmed_tx(const cryptonote::transaction& tx, uint64_t amount_in, const std::vector<cryptonote::tx_destination_entry> &dests, const crypto::hash &payment_id, uint64_t change_amount);
|
||||||
void generate_genesis(cryptonote::block& b);
|
void generate_genesis(cryptonote::block& b);
|
||||||
void check_genesis(const crypto::hash& genesis_hash) const; //throws
|
void check_genesis(const crypto::hash& genesis_hash) const; //throws
|
||||||
|
|
Loading…
Reference in a new issue