aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_core/blockchain.cpp18
-rw-r--r--src/cryptonote_core/cryptonote_core.h2
-rw-r--r--src/cryptonote_core/i_core_events.h1
-rw-r--r--src/cryptonote_core/tx_pool.cpp5
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl2
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp63
-rw-r--r--src/cryptonote_protocol/levin_notify.h6
-rw-r--r--src/daemon/command_parser_executor.cpp300
-rw-r--r--src/daemon/command_server.cpp4
-rw-r--r--src/device/device_ledger.cpp43
-rw-r--r--src/device/device_ledger.hpp65
-rw-r--r--src/p2p/net_node.h25
-rw-r--r--src/p2p/net_node.inl124
-rw-r--r--src/p2p/net_node_common.h4
-rw-r--r--src/rpc/CMakeLists.txt2
-rw-r--r--src/rpc/core_rpc_server.cpp23
-rw-r--r--src/wallet/api/address_book.cpp19
-rw-r--r--src/wallet/api/address_book.h1
-rw-r--r--src/wallet/api/transaction_history.cpp17
-rw-r--r--src/wallet/api/transaction_history.h1
-rw-r--r--src/wallet/api/transaction_info.cpp11
-rw-r--r--src/wallet/api/transaction_info.h4
-rw-r--r--src/wallet/api/wallet.cpp5
-rw-r--r--src/wallet/api/wallet.h1
-rw-r--r--src/wallet/api/wallet2_api.h9
-rw-r--r--src/wallet/wallet2.cpp8
-rw-r--r--src/wallet/wallet2.h4
27 files changed, 495 insertions, 272 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 93e3ef3bc..f91b3d6c1 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -3068,9 +3068,21 @@ bool Blockchain::check_tx_outputs(const transaction& tx, tx_verification_context
if (tx.version >= 2) {
if (tx.rct_signatures.type <= rct::RCTTypeBulletproof2)
{
- MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1));
- tvc.m_invalid_output = true;
- return false;
+ // two MLSAG txes went in due to a bug with txes that went into the txpool before the fork, grandfather them in
+ static const char * grandfathered[2] = { "c5151944f0583097ba0c88cd0f43e7fabb3881278aa2f73b3b0a007c5d34e910", "6f2f117cde6fbcf8d4a6ef8974fcac744726574ac38cf25d3322c996b21edd4c" };
+ crypto::hash h0, h1;
+ epee::string_tools::hex_to_pod(grandfathered[0], h0);
+ epee::string_tools::hex_to_pod(grandfathered[1], h1);
+ if (cryptonote::get_transaction_hash(tx) == h0 || cryptonote::get_transaction_hash(tx) == h1)
+ {
+ MDEBUG("Grandfathering cryptonote::get_transaction_hash(tx) in");
+ }
+ else
+ {
+ MERROR_VER("Ringct type " << (unsigned)tx.rct_signatures.type << " is not allowed from v" << (HF_VERSION_CLSAG + 1));
+ tvc.m_invalid_output = true;
+ return false;
+ }
}
}
}
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index c9d26e0ed..7c578ac51 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -663,7 +663,7 @@ namespace cryptonote
*
* @param target_blockchain_height the target height
*/
- uint64_t get_target_blockchain_height() const;
+ virtual uint64_t get_target_blockchain_height() const override;
/**
* @brief returns the newest hardfork version known to the blockchain
diff --git a/src/cryptonote_core/i_core_events.h b/src/cryptonote_core/i_core_events.h
index 03394d785..addb659ab 100644
--- a/src/cryptonote_core/i_core_events.h
+++ b/src/cryptonote_core/i_core_events.h
@@ -39,6 +39,7 @@ namespace cryptonote
virtual ~i_core_events() noexcept
{}
+ virtual uint64_t get_target_blockchain_height() const = 0;
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, relay_method tx_relay) = 0;
};
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 85bcf2246..28721ee36 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -1391,7 +1391,10 @@ namespace cryptonote
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
{
- MERROR(" failed to find tx meta");
+ static bool warned = false;
+ if (!warned)
+ MERROR(" failed to find tx meta: " << sorted_it->second << " (will only print once)");
+ warned = true;
continue;
}
LOG_PRINT_L2("Considering " << sorted_it->second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current coinbase " << print_money(best_coinbase) << ", relay method " << (unsigned)meta.get_relay_method());
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 337885509..a8073e091 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -2538,7 +2538,7 @@ skip:
local mempool before doing the relay. The code was already updating the
DB twice on received transactions - it is difficult to workaround this
due to the internal design. */
- return m_p2p->send_txs(std::move(arg.txs), zone, source, m_core, tx_relay) != epee::net_utils::zone::invalid;
+ return m_p2p->send_txs(std::move(arg.txs), zone, source, tx_relay) != epee::net_utils::zone::invalid;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index 7c482156f..634750cab 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -105,8 +105,8 @@ namespace levin
return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())};
}
- //! \return All outgoing connections supporting fragments in `connections`.
- std::vector<boost::uuids::uuid> get_out_connections(connections& p2p)
+ //! \return Outgoing connections supporting fragments in `connections` filtered by remote blockchain height.
+ std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t min_blockchain_height)
{
std::vector<boost::uuids::uuid> outs;
outs.reserve(connection_id_reserve_size);
@@ -115,8 +115,8 @@ namespace levin
the reserve call so a strand is not used. Investigate if there is lots
of waiting in here. */
- p2p.foreach_connection([&outs] (detail::p2p_context& context) {
- if (!context.m_is_income)
+ p2p.foreach_connection([&outs, min_blockchain_height] (detail::p2p_context& context) {
+ if (!context.m_is_income && context.m_remote_blockchain_height >= min_blockchain_height)
outs.emplace_back(context.m_connection_id);
return true;
});
@@ -233,7 +233,7 @@ namespace levin
{
struct zone
{
- explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, bool is_public, bool pad_txs)
+ explicit zone(boost::asio::io_service& io_service, std::shared_ptr<connections> p2p, epee::byte_slice noise_in, epee::net_utils::zone zone, bool pad_txs)
: p2p(std::move(p2p)),
noise(std::move(noise_in)),
next_epoch(io_service),
@@ -243,7 +243,7 @@ namespace levin
channels(),
flush_time(std::chrono::steady_clock::time_point::max()),
connection_count(0),
- is_public(is_public),
+ nzone(zone),
pad_txs(pad_txs),
fluffing(false)
{
@@ -260,7 +260,7 @@ namespace levin
std::deque<noise_channel> channels; //!< Never touch after init; only update elements on `noise_channel.strand`
std::chrono::steady_clock::time_point flush_time; //!< Next expected Dandelion++ fluff flush
std::atomic<std::size_t> connection_count; //!< Only update in strand, can be read at any time
- const bool is_public; //!< Zone is public ipv4/ipv6 connections
+ const epee::net_utils::zone nzone; //!< Zone is public ipv4/ipv6 connections, or i2p or tor
const bool pad_txs; //!< Pad txs to the next boundary for privacy
bool fluffing; //!< Zone is in Dandelion++ fluff epoch
};
@@ -297,7 +297,8 @@ namespace levin
if (!channel.connection.is_nil())
channel.queue.push_back(std::move(message_));
else if (destination_ == 0 && zone_->connection_count == 0)
- MWARNING("Unable to send transaction(s) over anonymity network - no available outbound connections");
+ MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
+ " - no available outbound connections");
}
};
@@ -410,7 +411,7 @@ namespace levin
zone->p2p->foreach_connection([txs, now, &zone, &source, &in_duration, &out_duration, &next_flush, &available] (detail::p2p_context& context)
{
// When i2p/tor, only fluff to outbound connections
- if (source != context.m_connection_id && (zone->is_public || !context.m_is_income))
+ if (source != context.m_connection_id && (zone->nzone == epee::net_utils::zone::public_ || !context.m_is_income))
{
available = true;
if (context.fluff_txs.empty())
@@ -544,7 +545,7 @@ namespace levin
}
// connection list may be outdated, try again
- update_channels::run(zone_, get_out_connections(*zone_->p2p));
+ update_channels::run(zone_, get_out_connections(*zone_->p2p, core_->get_target_blockchain_height()));
}
MERROR("Unable to send transaction(s) via Dandelion++ stem");
@@ -577,7 +578,7 @@ namespace levin
assert(zone_->strand.running_in_this_thread());
- if (zone_->is_public)
+ if (zone_->nzone == epee::net_utils::zone::public_)
MDEBUG("Starting new Dandelion++ epoch: " << (fluffing_ ? "fluff" : "stem"));
zone_->map = std::move(map_);
@@ -591,8 +592,9 @@ namespace levin
{
std::shared_ptr<detail::zone> zone_;
const std::size_t channel_;
+ const i_core_events* core_;
- static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index)
+ static void wait(const std::chrono::steady_clock::time_point start, std::shared_ptr<detail::zone> zone, const std::size_t index, const i_core_events* core)
{
if (!zone)
return;
@@ -600,7 +602,7 @@ namespace levin
noise_channel& channel = zone->channels.at(index);
channel.next_noise.expires_at(start + noise_min_delay + random_duration(noise_delay_range));
channel.next_noise.async_wait(
- channel.strand.wrap(send_noise{std::move(zone), index})
+ channel.strand.wrap(send_noise{std::move(zone), index, core})
);
}
@@ -644,16 +646,18 @@ namespace levin
{
channel.active = nullptr;
channel.connection = boost::uuids::nil_uuid();
+ auto height = core_->get_target_blockchain_height();
- auto connections = get_out_connections(*zone_->p2p);
+ auto connections = get_out_connections(*zone_->p2p, height);
if (connections.empty())
- MWARNING("Lost all outbound connections to anonymity network - currently unable to send transaction(s)");
+ MWARNING("Unable to send transaction(s) to " << epee::net_utils::zone_to_string(zone_->nzone) <<
+ " - no suitable outbound connections at height " << height);
zone_->strand.post(update_channels{zone_, std::move(connections)});
}
}
- wait(start, std::move(zone_), channel_);
+ wait(start, std::move(zone_), channel_, core_);
}
};
@@ -665,6 +669,7 @@ namespace levin
std::chrono::seconds min_epoch_;
std::chrono::seconds epoch_range_;
std::size_t count_;
+ const i_core_events* core_;
//! \pre Should not be invoked within any strand to prevent blocking.
void operator()(const boost::system::error_code error = {})
@@ -677,8 +682,9 @@ namespace levin
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
const auto start = std::chrono::steady_clock::now();
+ auto connections = get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height());
zone_->strand.dispatch(
- change_channels{zone_, net::dandelionpp::connection_map{get_out_connections(*(zone_->p2p)), count_}, fluffing}
+ change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
);
detail::zone& alias = *zone_;
@@ -688,24 +694,25 @@ namespace levin
};
} // anonymous
- notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, const bool is_public, const bool pad_txs)
- : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), is_public, pad_txs))
+ notify::notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, const bool pad_txs, i_core_events& core)
+ : zone_(std::make_shared<detail::zone>(service, std::move(p2p), std::move(noise), zone, pad_txs))
+ , core_(std::addressof(core))
{
if (!zone_->p2p)
throw std::logic_error{"cryptonote::levin::notify cannot have nullptr p2p argument"};
const bool noise_enabled = !zone_->noise.empty();
- if (noise_enabled || is_public)
+ if (noise_enabled || zone == epee::net_utils::zone::public_)
{
const auto now = std::chrono::steady_clock::now();
const auto min_epoch = noise_enabled ? noise_min_epoch : dandelionpp_min_epoch;
const auto epoch_range = noise_enabled ? noise_epoch_range : dandelionpp_epoch_range;
const std::size_t out_count = noise_enabled ? CRYPTONOTE_NOISE_CHANNELS : CRYPTONOTE_DANDELIONPP_STEMS;
- start_epoch{zone_, min_epoch, epoch_range, out_count}();
+ start_epoch{zone_, min_epoch, epoch_range, out_count, core_}();
for (std::size_t channel = 0; channel < zone_->channels.size(); ++channel)
- send_noise::wait(now, zone_, channel);
+ send_noise::wait(now, zone_, channel, core_);
}
}
@@ -726,7 +733,7 @@ namespace levin
return;
zone_->strand.dispatch(
- update_channels{zone_, get_out_connections(*(zone_->p2p))}
+ update_channels{zone_, get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height())}
);
}
@@ -753,7 +760,7 @@ namespace levin
zone_->flush_txs.cancel();
}
- bool notify::send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, i_core_events& core, relay_method tx_relay)
+ bool notify::send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, relay_method tx_relay)
{
if (txs.empty())
return true;
@@ -785,7 +792,7 @@ namespace levin
tx_relay = relay_method::local; // do not put into stempool embargo (hopefully not there already!).
}
- core.on_transactions_relayed(epee::to_span(txs), tx_relay);
+ core_->on_transactions_relayed(epee::to_span(txs), tx_relay);
// Padding is not useful when using noise mode. Send as stem so receiver
// forwards in Dandelion++ mode.
@@ -817,11 +824,11 @@ namespace levin
case relay_method::stem:
case relay_method::forward:
case relay_method::local:
- if (zone_->is_public)
+ if (zone_->nzone == epee::net_utils::zone::public_)
{
// this will change a local/forward tx to stem or fluff ...
zone_->strand.dispatch(
- dandelionpp_notify{zone_, std::addressof(core), std::move(txs), source}
+ dandelionpp_notify{zone_, core_, std::move(txs), source}
);
break;
}
@@ -832,7 +839,7 @@ namespace levin
routine. A "fluff" over i2p/tor is not the same as a "fluff" over
ipv4/6. Marking it as "fluff" here will make the tx immediately
visible externally from this node, which is not desired. */
- core.on_transactions_relayed(epee::to_span(txs), tx_relay);
+ core_->on_transactions_relayed(epee::to_span(txs), tx_relay);
zone_->strand.dispatch(fluff_notify{zone_, std::move(txs), source});
break;
}
diff --git a/src/cryptonote_protocol/levin_notify.h b/src/cryptonote_protocol/levin_notify.h
index 957794b12..abbf9d461 100644
--- a/src/cryptonote_protocol/levin_notify.h
+++ b/src/cryptonote_protocol/levin_notify.h
@@ -69,6 +69,7 @@ namespace levin
class notify
{
std::shared_ptr<detail::zone> zone_;
+ i_core_events* core_;
public:
struct status
@@ -80,10 +81,11 @@ namespace levin
//! Construct an instance that cannot notify.
notify() noexcept
: zone_(nullptr)
+ , core_(nullptr)
{}
//! Construct an instance with available notification `zones`.
- explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, bool is_public, bool pad_txs);
+ explicit notify(boost::asio::io_service& service, std::shared_ptr<connections> p2p, epee::byte_slice noise, epee::net_utils::zone zone, bool pad_txs, i_core_events& core);
notify(const notify&) = delete;
notify(notify&&) = default;
@@ -123,7 +125,7 @@ namespace levin
particular stem.
\return True iff the notification is queued for sending. */
- bool send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, i_core_events& core, relay_method tx_relay);
+ bool send_txs(std::vector<blobdata> txs, const boost::uuids::uuid& source, relay_method tx_relay);
};
} // levin
} // net
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 504b104b0..aac891c4a 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -50,7 +50,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
{
if (args.size() > 3)
{
- std::cout << "use: print_pl [white] [gray] [<limit>] [pruned] [publicrpc]" << std::endl;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
return true;
}
@@ -79,7 +79,7 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
}
else if (!epee::string_tools::get_xtype_from_string(limit, args[i]))
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
@@ -90,56 +90,79 @@ bool t_command_parser_executor::print_peer_list(const std::vector<std::string>&
bool t_command_parser_executor::print_peer_list_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_peer_list_stats();
}
bool t_command_parser_executor::save_blockchain(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
-
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.save_blockchain();
}
bool t_command_parser_executor::show_hash_rate(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_hash_rate();
}
bool t_command_parser_executor::hide_hash_rate(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.hide_hash_rate();
}
bool t_command_parser_executor::show_difficulty(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_difficulty();
}
bool t_command_parser_executor::show_status(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.show_status();
}
bool t_command_parser_executor::print_connections(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_connections();
}
bool t_command_parser_executor::print_net_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_net_stats();
}
@@ -148,8 +171,8 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
{
if(!args.size())
{
- std::cout << "need block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
uint64_t start_index = 0;
uint64_t end_index = 0;
@@ -158,20 +181,20 @@ bool t_command_parser_executor::print_blockchain_info(const std::vector<std::str
int64_t nblocks;
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]))
{
- std::cout << "wrong number of blocks" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_info(nblocks, (uint64_t)-nblocks);
}
if(!epee::string_tools::get_xtype_from_string(start_index, args[0]))
{
- std::cout << "wrong starter block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong starter block index parameter. For more details, use the help command." << std::endl;
+ return true;
}
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(end_index, args[1]))
{
- std::cout << "wrong end block index parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong end block index parameter. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_info(start_index, end_index);
@@ -181,7 +204,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
{
if(args.size() > 1)
{
- std::cout << "use: set_log [<log_level_number_0-4> | <categories>]" << std::endl;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
return true;
}
@@ -195,7 +218,7 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
{
if(4 < l)
{
- std::cout << "wrong number range, use: set_log <log_level_number_0-4>" << std::endl;
+ std::cout << "Invalid syntax: Wrong number range, use: set_log <log_level_number_0-4>. For more details, use the help command." << std::endl;
return true;
}
return m_executor.set_log_level(l);
@@ -208,7 +231,10 @@ bool t_command_parser_executor::set_log_level(const std::vector<std::string>& ar
bool t_command_parser_executor::print_height(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_height();
}
@@ -223,14 +249,14 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
include_hex = true;
else
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
if (args.empty())
{
- std::cout << "expected: print_block (<block_hash> | <block_height>) [+hex]" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
const std::string& arg = args.front();
@@ -248,7 +274,7 @@ bool t_command_parser_executor::print_block(const std::vector<std::string>& args
}
}
- return false;
+ return true;
}
bool t_command_parser_executor::print_transaction(const std::vector<std::string>& args)
@@ -267,13 +293,13 @@ bool t_command_parser_executor::print_transaction(const std::vector<std::string>
include_json = true;
else
{
- std::cout << "unexpected argument: " << args[i] << std::endl;
+ std::cout << "Invalid syntax: Unexpected parameter: " << args[i] << ". For more details, use the help command." << std::endl;
return true;
}
}
if (args.empty())
{
- std::cout << "expected: print_tx <transaction_hash> [+meta] [+hex] [+json]" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -291,7 +317,7 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
{
if (args.empty())
{
- std::cout << "expected: is_key_image_spent <key_image>" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -309,21 +335,30 @@ bool t_command_parser_executor::is_key_image_spent(const std::vector<std::string
bool t_command_parser_executor::print_transaction_pool_long(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_long();
}
bool t_command_parser_executor::print_transaction_pool_short(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_short();
}
bool t_command_parser_executor::print_transaction_pool_stats(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_transaction_pool_stats();
}
@@ -332,7 +367,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
{
if(!args.size())
{
- std::cout << "Please specify a wallet address to mine for: start_mining <addr> [<threads>|auto]" << std::endl;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
return true;
}
@@ -353,7 +388,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
{
if(!cryptonote::get_account_address_from_str(info, cryptonote::STAGENET, address_str))
{
- std::cout << "target account address has wrong format" << std::endl;
+ std::cout << "Invalid syntax: Target account address has wrong format. For more details, use the help command." << std::endl;
return true;
}
else
@@ -389,9 +424,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
bool ignore_battery = false;
if(args.size() > 4)
{
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
-
+
if(args.size() == 4)
{
if(args[3] == "true" || command_line::is_yes(args[3]) || args[3] == "1")
@@ -400,10 +436,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
else if(args[3] != "false" && !command_line::is_no(args[3]) && args[3] != "0")
{
- return false;
+ std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
+ return true;
}
- }
-
+ }
+
if(args.size() >= 3)
{
if(args[2] == "true" || command_line::is_yes(args[2]) || args[2] == "1")
@@ -412,10 +449,11 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
else if(args[2] != "false" && !command_line::is_no(args[2]) && args[2] != "0")
{
- return false;
+ std::cout << "Invalid syntax: Invalid combination of parameters. For more details, use the help command." << std::endl;
+ return true;
}
}
-
+
if(args.size() >= 2)
{
if (args[1] == "auto" || args[1] == "autodetect")
@@ -436,7 +474,10 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
bool t_command_parser_executor::stop_mining(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.stop_mining();
}
@@ -448,21 +489,31 @@ bool t_command_parser_executor::mining_status(const std::vector<std::string>& ar
bool t_command_parser_executor::stop_daemon(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.stop_daemon();
}
bool t_command_parser_executor::print_status(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.print_status();
}
bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit();
}
@@ -471,8 +522,8 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(limit, limit);
@@ -480,7 +531,11 @@ bool t_command_parser_executor::set_limit(const std::vector<std::string>& args)
bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit_up();
}
@@ -489,8 +544,8 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(0, limit);
@@ -498,7 +553,11 @@ bool t_command_parser_executor::set_limit_up(const std::vector<std::string>& arg
bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& args)
{
- if(args.size()>1) return false;
+ if(args.size()>1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
+
if(args.size()==0) {
return m_executor.get_limit_down();
}
@@ -507,8 +566,8 @@ bool t_command_parser_executor::set_limit_down(const std::vector<std::string>& a
limit = std::stoll(args[0]);
}
catch(const std::exception& ex) {
- std::cout << "failed to parse argument" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Failed to parse limit. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_limit(limit, 0);
@@ -525,12 +584,13 @@ bool t_command_parser_executor::out_peers(const std::vector<std::string>& args)
set = true;
}
}
-
+
catch(const std::exception& ex) {
_erro("stoi exception");
- return false;
+ std::cout << "Invalid syntax: Failed to parse number. For more details, use the help command." << std::endl;
+ return true;
}
-
+
return m_executor.out_peers(set, limit);
}
@@ -548,7 +608,8 @@ bool t_command_parser_executor::in_peers(const std::vector<std::string>& args)
catch(const std::exception& ex) {
_erro("stoi exception");
- return false;
+ std::cout << "Invalid syntax: Failed to parse number." << std::endl;
+ return true;
}
return m_executor.in_peers(set, limit);
@@ -565,26 +626,37 @@ bool t_command_parser_executor::hard_fork_info(const std::vector<std::string>& a
version = std::stoi(args[0]);
}
catch(const std::exception& ex) {
- return false;
+ std::cout << "Invalid syntax: Failed to parse version number. For more details, use the help command." << std::endl;
+ return true;
+ }
+ if (version <= 0 || version > 255) {
+ std::cout << "Invalid syntax: Unknown version number. Must be between 0 and 255. For more details, use the help command." << std::endl;
+ return true;
}
- if (version <= 0 || version > 255)
- return false;
}
else {
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.hard_fork_info(version);
}
bool t_command_parser_executor::show_bans(const std::vector<std::string>& args)
{
- if (!args.empty()) return false;
+ if (!args.empty()) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
+
return m_executor.print_bans();
}
bool t_command_parser_executor::ban(const std::vector<std::string>& args)
{
- if (args.size() != 1 && args.size() != 2) return false;
+ if (args.size() != 1 && args.size() != 2) {
+ std::cout << "Invalid syntax: Expects one or two parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string ip = args[0];
time_t seconds = P2P_IP_BLOCKTIME;
if (args.size() > 1)
@@ -595,11 +667,13 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
}
catch (const std::exception &e)
{
- return false;
+ std::cout << "Invalid syntax: Failed to parse seconds. For more details, use the help command." << std::endl;
+ return true;
}
if (seconds == 0)
{
- return false;
+ std::cout << "Seconds must be greater than 0." << std::endl;
+ return true;
}
}
return m_executor.ban(ip, seconds);
@@ -607,21 +681,31 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
bool t_command_parser_executor::unban(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1) {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
+
std::string ip = args[0];
return m_executor.unban(ip);
}
bool t_command_parser_executor::banned(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1) {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string address = args[0];
return m_executor.banned(address);
}
bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& args)
{
- if (args.size() > 1) return false;
+ if (args.size() > 1) {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string txid;
if (args.size() == 1)
@@ -629,7 +713,7 @@ bool t_command_parser_executor::flush_txpool(const std::vector<std::string>& arg
crypto::hash hash;
if (!parse_hash256(args[0], hash))
{
- std::cout << "failed to parse tx id" << std::endl;
+ std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
return true;
}
txid = args[0];
@@ -662,7 +746,7 @@ bool t_command_parser_executor::output_histogram(const std::vector<std::string>&
}
else
{
- std::cout << "Invalid syntax: more than two non-amount parameters" << std::endl;
+ std::cout << "Invalid syntax: More than two non-amount parameters. For more details, use the help command." << std::endl;
return true;
}
}
@@ -673,20 +757,21 @@ bool t_command_parser_executor::print_coinbase_tx_sum(const std::vector<std::str
{
if(!args.size())
{
- std::cout << "need block height parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: At least one parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
+
uint64_t height = 0;
uint64_t count = 0;
if(!epee::string_tools::get_xtype_from_string(height, args[0]))
{
- std::cout << "wrong starter block height parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong starter block height parameter. For more details, use the help command." << std::endl;
+ return true;
}
if(args.size() >1 && !epee::string_tools::get_xtype_from_string(count, args[1]))
{
std::cout << "wrong count parameter" << std::endl;
- return false;
+ return true;
}
return m_executor.print_coinbase_tx_sum(height, count);
@@ -696,8 +781,8 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
{
if(args.size() > 1)
{
- std::cout << "usage: alt_chain_info [block_hash|>N|-N]" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
}
std::string tip;
@@ -709,16 +794,16 @@ bool t_command_parser_executor::alt_chain_info(const std::vector<std::string>& a
{
if (!epee::string_tools::get_xtype_from_string(above, args[0].c_str() + 1))
{
- std::cout << "invalid above parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Invalid above parameter. For more details, use the help command." << std::endl;
+ return true;
}
}
else if (args[0].size() > 0 && args[0][0] == '-')
{
if (!epee::string_tools::get_xtype_from_string(last_blocks, args[0].c_str() + 1))
{
- std::cout << "invalid last_blocks parameter" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Invalid last_blocks parameter. For more details, use the help command." << std::endl;
+ return true;
}
}
else
@@ -734,15 +819,15 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
{
if(args.size() != 1)
{
- std::cout << "Exactly one parameter is needed" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
uint64_t nblocks = 0;
if(!epee::string_tools::get_xtype_from_string(nblocks, args[0]) || nblocks == 0)
{
- std::cout << "wrong number of blocks" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Wrong number of blocks. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.print_blockchain_dynamic_stats(nblocks);
@@ -750,10 +835,10 @@ bool t_command_parser_executor::print_blockchain_dynamic_stats(const std::vector
bool t_command_parser_executor::update(const std::vector<std::string>& args)
{
- if(args.size() != 1)
+ if (args.size() != 1)
{
- std::cout << "Exactly one parameter is needed: check, download, or update" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.update(args.front());
@@ -761,13 +846,17 @@ bool t_command_parser_executor::update(const std::vector<std::string>& args)
bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
{
- if (args.size() != 1) return false;
+ if (args.size() != 1)
+ {
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
+ }
std::string txid;
crypto::hash hash;
if (!parse_hash256(args[0], hash))
{
- std::cout << "failed to parse tx id" << std::endl;
+ std::cout << "Invalid syntax: Failed to parse tx id. For more details, use the help command." << std::endl;
return true;
}
txid = args[0];
@@ -776,7 +865,10 @@ bool t_command_parser_executor::relay_tx(const std::vector<std::string>& args)
bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
{
- if (args.size() != 0) return false;
+ if (args.size() != 0) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.sync_info();
}
@@ -785,8 +877,8 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
{
if (args.size() != 1)
{
- std::cout << "Exactly one parameter is needed" << std::endl;
- return false;
+ std::cout << "Invalid syntax: One parameter expected. For more details, use the help command." << std::endl;
+ return true;
}
try
@@ -794,21 +886,24 @@ bool t_command_parser_executor::pop_blocks(const std::vector<std::string>& args)
uint64_t nblocks = boost::lexical_cast<uint64_t>(args[0]);
if (nblocks < 1)
{
- std::cout << "number of blocks must be greater than 0" << std::endl;
- return false;
+ std::cout << "Invalid syntax: Number of blocks must be greater than 0. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.pop_blocks(nblocks);
}
catch (const boost::bad_lexical_cast&)
{
- std::cout << "number of blocks must be a number greater than 0" << std::endl;
+ std::cout << "Invalid syntax: Number of blocks must be a number greater than 0. For more details, use the help command." << std::endl;
}
- return false;
+ return true;
}
bool t_command_parser_executor::rpc_payments(const std::vector<std::string>& args)
{
- if (args.size() != 0) return false;
+ if (args.size() != 0) {
+ std::cout << "Invalid syntax: No parameters expected. For more details, use the help command." << std::endl;
+ return true;
+ }
return m_executor.rpc_payments();
}
@@ -820,7 +915,11 @@ bool t_command_parser_executor::version(const std::vector<std::string>& args)
bool t_command_parser_executor::prune_blockchain(const std::vector<std::string>& args)
{
- if (args.size() > 1) return false;
+ if (args.size() > 1)
+ {
+ std::cout << "Invalid syntax: Too many parameters. For more details, use the help command." << std::endl;
+ return true;
+ }
if (args.empty() || args[0] != "confirm")
{
@@ -846,7 +945,8 @@ bool t_command_parser_executor::set_bootstrap_daemon(const std::vector<std::stri
const size_t args_count = args.size();
if (args_count < 1 || args_count > 3)
{
- return false;
+ std::cout << "Invalid syntax: Wrong number of parameters. For more details, use the help command." << std::endl;
+ return true;
}
return m_executor.set_bootstrap_daemon(
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index ac4c30726..dd5f76188 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -223,7 +223,8 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"hard_fork_info"
, std::bind(&t_command_parser_executor::hard_fork_info, &m_parser, p::_1)
- , "Print the hard fork voting information."
+ , "hard_fork_info <version>"
+ , "Print the hard fork voting information. If given a version, prints whether is this version enabled."
);
m_command_lookup.set_handler(
"bans"
@@ -314,6 +315,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"prune_blockchain"
, std::bind(&t_command_parser_executor::prune_blockchain, &m_parser, p::_1)
+ , "prune_blockchain [confirm]"
, "Prune the blockchain."
);
m_command_lookup.set_handler(
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
index 3e0afeb65..384b776ee 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -83,44 +83,33 @@ namespace hw {
// Must be sorted in ascending order by the code
#define LEDGER_STATUS(status) {status, #status}
constexpr Status status_codes[] = {
- LEDGER_STATUS(SW_BYTES_REMAINING_00),
- LEDGER_STATUS(SW_WARNING_STATE_UNCHANGED),
- LEDGER_STATUS(SW_STATE_TERMINATED),
- LEDGER_STATUS(SW_MORE_DATA_AVAILABLE),
+ LEDGER_STATUS(SW_OK),
LEDGER_STATUS(SW_WRONG_LENGTH),
- LEDGER_STATUS(SW_LOGICAL_CHANNEL_NOT_SUPPORTED),
- LEDGER_STATUS(SW_SECURE_MESSAGING_NOT_SUPPORTED),
- LEDGER_STATUS(SW_LAST_COMMAND_EXPECTED),
- LEDGER_STATUS(SW_COMMAND_CHAINING_NOT_SUPPORTED),
+ LEDGER_STATUS(SW_SECURITY_PIN_LOCKED),
LEDGER_STATUS(SW_SECURITY_LOAD_KEY),
LEDGER_STATUS(SW_SECURITY_COMMITMENT_CONTROL),
LEDGER_STATUS(SW_SECURITY_AMOUNT_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_COMMITMENT_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_OUTKEYS_CHAIN_CONTROL),
LEDGER_STATUS(SW_SECURITY_MAXOUTPUT_REACHED),
- LEDGER_STATUS(SW_SECURITY_TRUSTED_INPUT),
- LEDGER_STATUS(SW_CLIENT_NOT_SUPPORTED),
- LEDGER_STATUS(SW_SECURITY_STATUS_NOT_SATISFIED),
- LEDGER_STATUS(SW_FILE_INVALID),
- LEDGER_STATUS(SW_PIN_BLOCKED),
- LEDGER_STATUS(SW_DATA_INVALID),
- LEDGER_STATUS(SW_CONDITIONS_NOT_SATISFIED),
+ LEDGER_STATUS(SW_SECURITY_HMAC),
+ LEDGER_STATUS(SW_SECURITY_RANGE_VALUE),
+ LEDGER_STATUS(SW_SECURITY_INTERNAL),
+ LEDGER_STATUS(SW_SECURITY_MAX_SIGNATURE_REACHED),
+ LEDGER_STATUS(SW_SECURITY_PREFIX_HASH),
+ LEDGER_STATUS(SW_SECURITY_LOCKED),
LEDGER_STATUS(SW_COMMAND_NOT_ALLOWED),
- LEDGER_STATUS(SW_APPLET_SELECT_FAILED),
+ LEDGER_STATUS(SW_SUBCOMMAND_NOT_ALLOWED),
+ LEDGER_STATUS(SW_DENY),
+ LEDGER_STATUS(SW_KEY_NOT_SET),
LEDGER_STATUS(SW_WRONG_DATA),
- LEDGER_STATUS(SW_FUNC_NOT_SUPPORTED),
- LEDGER_STATUS(SW_FILE_NOT_FOUND),
- LEDGER_STATUS(SW_RECORD_NOT_FOUND),
- LEDGER_STATUS(SW_FILE_FULL),
- LEDGER_STATUS(SW_INCORRECT_P1P2),
- LEDGER_STATUS(SW_REFERENCED_DATA_NOT_FOUND),
+ LEDGER_STATUS(SW_WRONG_DATA_RANGE),
+ LEDGER_STATUS(SW_IO_FULL),
+ LEDGER_STATUS(SW_CLIENT_NOT_SUPPORTED),
LEDGER_STATUS(SW_WRONG_P1P2),
- LEDGER_STATUS(SW_CORRECT_LENGTH_00),
LEDGER_STATUS(SW_INS_NOT_SUPPORTED),
- LEDGER_STATUS(SW_CLA_NOT_SUPPORTED),
- LEDGER_STATUS(SW_UNKNOWN),
- LEDGER_STATUS(SW_OK),
- LEDGER_STATUS(SW_ALGORITHM_UNSUPPORTED)
+ LEDGER_STATUS(SW_PROTOCOL_NOT_SUPPORTED),
+ LEDGER_STATUS(SW_UNKNOWN)
};
const char *Status::to_string(unsigned int code)
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
index 5cb834e02..00ff05ec5 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -59,44 +59,33 @@ namespace hw {
#ifdef WITH_DEVICE_LEDGER
// Origin: https://github.com/LedgerHQ/ledger-app-monero/blob/master/src/monero_types.h
- #define SW_BYTES_REMAINING_00 0x6100
- #define SW_WARNING_STATE_UNCHANGED 0x6200
- #define SW_STATE_TERMINATED 0x6285
- #define SW_MORE_DATA_AVAILABLE 0x6310
- #define SW_WRONG_LENGTH 0x6700
- #define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881
- #define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882
- #define SW_LAST_COMMAND_EXPECTED 0x6883
- #define SW_COMMAND_CHAINING_NOT_SUPPORTED 0x6884
- #define SW_SECURITY_LOAD_KEY 0x6900
- #define SW_SECURITY_COMMITMENT_CONTROL 0x6911
- #define SW_SECURITY_AMOUNT_CHAIN_CONTROL 0x6912
- #define SW_SECURITY_COMMITMENT_CHAIN_CONTROL 0x6913
- #define SW_SECURITY_OUTKEYS_CHAIN_CONTROL 0x6914
- #define SW_SECURITY_MAXOUTPUT_REACHED 0x6915
- #define SW_SECURITY_TRUSTED_INPUT 0x6916
- #define SW_CLIENT_NOT_SUPPORTED 0x6930
- #define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982
- #define SW_FILE_INVALID 0x6983
- #define SW_PIN_BLOCKED 0x6983
- #define SW_DATA_INVALID 0x6984
- #define SW_CONDITIONS_NOT_SATISFIED 0x6985
- #define SW_COMMAND_NOT_ALLOWED 0x6986
- #define SW_APPLET_SELECT_FAILED 0x6999
- #define SW_WRONG_DATA 0x6a80
- #define SW_FUNC_NOT_SUPPORTED 0x6a81
- #define SW_FILE_NOT_FOUND 0x6a82
- #define SW_RECORD_NOT_FOUND 0x6a83
- #define SW_FILE_FULL 0x6a84
- #define SW_INCORRECT_P1P2 0x6a86
- #define SW_REFERENCED_DATA_NOT_FOUND 0x6a88
- #define SW_WRONG_P1P2 0x6b00
- #define SW_CORRECT_LENGTH_00 0x6c00
- #define SW_INS_NOT_SUPPORTED 0x6d00
- #define SW_CLA_NOT_SUPPORTED 0x6e00
- #define SW_UNKNOWN 0x6f00
- #define SW_OK 0x9000
- #define SW_ALGORITHM_UNSUPPORTED 0x9484
+ #define SW_OK 0x9000
+ #define SW_WRONG_LENGTH 0x6700
+ #define SW_SECURITY_PIN_LOCKED 0x6910
+ #define SW_SECURITY_LOAD_KEY 0x6911
+ #define SW_SECURITY_COMMITMENT_CONTROL 0x6912
+ #define SW_SECURITY_AMOUNT_CHAIN_CONTROL 0x6913
+ #define SW_SECURITY_COMMITMENT_CHAIN_CONTROL 0x6914
+ #define SW_SECURITY_OUTKEYS_CHAIN_CONTROL 0x6915
+ #define SW_SECURITY_MAXOUTPUT_REACHED 0x6916
+ #define SW_SECURITY_HMAC 0x6917
+ #define SW_SECURITY_RANGE_VALUE 0x6918
+ #define SW_SECURITY_INTERNAL 0x6919
+ #define SW_SECURITY_MAX_SIGNATURE_REACHED 0x691A
+ #define SW_SECURITY_PREFIX_HASH 0x691B
+ #define SW_SECURITY_LOCKED 0x69EE
+ #define SW_COMMAND_NOT_ALLOWED 0x6980
+ #define SW_SUBCOMMAND_NOT_ALLOWED 0x6981
+ #define SW_DENY 0x6982
+ #define SW_KEY_NOT_SET 0x6983
+ #define SW_WRONG_DATA 0x6984
+ #define SW_WRONG_DATA_RANGE 0x6985
+ #define SW_IO_FULL 0x6986
+ #define SW_CLIENT_NOT_SUPPORTED 0x6A30
+ #define SW_WRONG_P1P2 0x6b00
+ #define SW_INS_NOT_SUPPORTED 0x6d00
+ #define SW_PROTOCOL_NOT_SUPPORTED 0x6e00
+ #define SW_UNKNOWN 0x6f00
namespace {
bool apdu_verbose =true;
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index e81371783..d7c3e6096 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -164,6 +164,7 @@ namespace nodetool
network_zone()
: m_connect(nullptr),
m_net_server(epee::net_utils::e_connection_type_P2P),
+ m_seed_nodes(),
m_bind_ip(),
m_bind_ipv6_address(),
m_port(),
@@ -175,7 +176,9 @@ namespace nodetool
m_proxy_address(),
m_current_number_of_out_peers(0),
m_current_number_of_in_peers(0),
- m_can_pingback(false)
+ m_seed_nodes_lock(),
+ m_can_pingback(false),
+ m_seed_nodes_initialized(false)
{
set_config_defaults();
}
@@ -183,6 +186,7 @@ namespace nodetool
network_zone(boost::asio::io_service& public_service)
: m_connect(nullptr),
m_net_server(public_service, epee::net_utils::e_connection_type_P2P),
+ m_seed_nodes(),
m_bind_ip(),
m_bind_ipv6_address(),
m_port(),
@@ -194,13 +198,16 @@ namespace nodetool
m_proxy_address(),
m_current_number_of_out_peers(0),
m_current_number_of_in_peers(0),
- m_can_pingback(false)
+ m_seed_nodes_lock(),
+ m_can_pingback(false),
+ m_seed_nodes_initialized(false)
{
set_config_defaults();
}
connect_func* m_connect;
net_server m_net_server;
+ std::vector<epee::net_utils::network_address> m_seed_nodes;
std::string m_bind_ip;
std::string m_bind_ipv6_address;
std::string m_port;
@@ -212,7 +219,9 @@ namespace nodetool
boost::asio::ip::tcp::endpoint m_proxy_address;
std::atomic<unsigned int> m_current_number_of_out_peers;
std::atomic<unsigned int> m_current_number_of_in_peers;
+ boost::shared_mutex m_seed_nodes_lock;
bool m_can_pingback;
+ bool m_seed_nodes_initialized;
private:
void set_config_defaults() noexcept
@@ -334,7 +343,7 @@ namespace nodetool
virtual void callback(p2p_connection_context& context);
//----------------- i_p2p_endpoint -------------------------------------------------------------
virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections);
- virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay);
+ virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay);
virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context);
virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context);
virtual bool drop_connection(const epee::net_utils::connection_context_base& context);
@@ -383,9 +392,10 @@ namespace nodetool
void record_addr_failed(const epee::net_utils::network_address& addr);
bool is_addr_recently_failed(const epee::net_utils::network_address& addr);
bool is_priority_node(const epee::net_utils::network_address& na);
- std::set<std::string> get_seed_nodes(cryptonote::network_type nettype) const;
- std::set<std::string> get_seed_nodes();
- bool connect_to_seed();
+ std::set<std::string> get_ip_seed_nodes() const;
+ std::set<std::string> get_dns_seed_nodes();
+ std::set<std::string> get_seed_nodes(epee::net_utils::zone);
+ bool connect_to_seed(epee::net_utils::zone);
template <class Container>
bool connect_to_peerlist(const Container& peers);
@@ -467,9 +477,6 @@ namespace nodetool
std::list<epee::net_utils::network_address> m_priority_peers;
std::vector<epee::net_utils::network_address> m_exclusive_peers;
- std::vector<epee::net_utils::network_address> m_seed_nodes;
- bool m_seed_nodes_initialized = false;
- boost::shared_mutex m_seed_nodes_lock;
std::atomic_flag m_fallback_seed_nodes_added;
std::vector<nodetool::peerlist_entry> m_command_line_peers;
uint64_t m_peer_livetime;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 175741146..c50617965 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -386,7 +386,7 @@ namespace nodetool
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
public_zone.m_notifier = cryptonote::levin::notify{
- public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true, pad_txs
+ public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, epee::net_utils::zone::public_, pad_txs, m_payload_handler.get_core()
};
if (command_line::has_arg(vm, arg_p2p_add_peer))
@@ -435,9 +435,9 @@ namespace nodetool
if (command_line::has_arg(vm, arg_p2p_seed_node))
{
- boost::unique_lock<boost::shared_mutex> lock(m_seed_nodes_lock);
+ boost::unique_lock<boost::shared_mutex> lock(public_zone.m_seed_nodes_lock);
- if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, m_seed_nodes))
+ if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, public_zone.m_seed_nodes))
return false;
}
@@ -499,7 +499,7 @@ namespace nodetool
}
zone.m_notifier = cryptonote::levin::notify{
- zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), false, pad_txs
+ zone.m_net_server.get_io_service(), zone.m_net_server.get_config_shared(), std::move(this_noise), proxy.zone, pad_txs, m_payload_handler.get_core()
};
}
@@ -598,21 +598,21 @@ namespace nodetool
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(cryptonote::network_type nettype) const
+ std::set<std::string> node_server<t_payload_net_handler>::get_ip_seed_nodes() const
{
std::set<std::string> full_addrs;
- if (nettype == cryptonote::TESTNET)
+ if (m_nettype == cryptonote::TESTNET)
{
full_addrs.insert("212.83.175.67:28080");
full_addrs.insert("212.83.172.165:28080");
full_addrs.insert("192.110.160.146:28080");
}
- else if (nettype == cryptonote::STAGENET)
+ else if (m_nettype == cryptonote::STAGENET)
{
full_addrs.insert("162.210.173.150:38080");
full_addrs.insert("192.110.160.146:38080");
}
- else if (nettype == cryptonote::FAKECHAIN)
+ else if (m_nettype == cryptonote::FAKECHAIN)
{
}
else
@@ -630,7 +630,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes()
+ std::set<std::string> node_server<t_payload_net_handler>::get_dns_seed_nodes()
{
if (!m_exclusive_peers.empty() || m_offline)
{
@@ -638,11 +638,11 @@ namespace nodetool
}
if (m_nettype == cryptonote::TESTNET)
{
- return get_seed_nodes(cryptonote::TESTNET);
+ return get_ip_seed_nodes();
}
if (m_nettype == cryptonote::STAGENET)
{
- return get_seed_nodes(cryptonote::STAGENET);
+ return get_ip_seed_nodes();
}
std::set<std::string> full_addrs;
@@ -730,7 +730,7 @@ namespace nodetool
else
MINFO("Not enough DNS seed nodes found, using fallback defaults too");
- for (const auto &peer: get_seed_nodes(cryptonote::MAINNET))
+ for (const auto &peer: get_ip_seed_nodes())
full_addrs.insert(peer);
m_fallback_seed_nodes_added.test_and_set();
}
@@ -739,6 +739,23 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
+ std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(epee::net_utils::zone zone)
+ {
+ switch (zone)
+ {
+ case epee::net_utils::zone::public_:
+ return get_dns_seed_nodes();
+ case epee::net_utils::zone::tor:
+ return {};
+ case epee::net_utils::zone::i2p:
+ return {};
+ default:
+ break;
+ }
+ throw std::logic_error{"Bad zone given to get_seed_nodes"};
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
typename node_server<t_payload_net_handler>::network_zone& node_server<t_payload_net_handler>::add_zone(const epee::net_utils::zone zone)
{
const auto zone_ = m_network_zones.lower_bound(zone);
@@ -1541,56 +1558,59 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::connect_to_seed()
+ bool node_server<t_payload_net_handler>::connect_to_seed(epee::net_utils::zone zone)
{
- boost::upgrade_lock<boost::shared_mutex> seed_nodes_upgrade_lock(m_seed_nodes_lock);
+ network_zone& server = m_network_zones.at(zone);
+ boost::upgrade_lock<boost::shared_mutex> seed_nodes_upgrade_lock(server.m_seed_nodes_lock);
- if (!m_seed_nodes_initialized)
+ if (!server.m_seed_nodes_initialized)
{
+ const std::uint16_t default_port = cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT;
boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
- m_seed_nodes_initialized = true;
- for (const auto& full_addr : get_seed_nodes())
+ server.m_seed_nodes_initialized = true;
+ for (const auto& full_addr : get_seed_nodes(zone))
{
+ // seeds should have hostname converted to IP already
MDEBUG("Seed node: " << full_addr);
- append_net_address(m_seed_nodes, full_addr, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
+ server.m_seed_nodes.push_back(MONERO_UNWRAP(net::get_network_address(full_addr, default_port)));
}
- MDEBUG("Number of seed nodes: " << m_seed_nodes.size());
+ MDEBUG("Number of seed nodes: " << server.m_seed_nodes.size());
}
- if (m_seed_nodes.empty() || m_offline || !m_exclusive_peers.empty())
+ if (server.m_seed_nodes.empty() || m_offline || !m_exclusive_peers.empty())
return true;
size_t try_count = 0;
bool is_connected_to_at_least_one_seed_node = false;
- size_t current_index = crypto::rand_idx(m_seed_nodes.size());
- const net_server& server = m_network_zones.at(epee::net_utils::zone::public_).m_net_server;
+ size_t current_index = crypto::rand_idx(server.m_seed_nodes.size());
while(true)
{
- if(server.is_stop_signal_sent())
+ if(server.m_net_server.is_stop_signal_sent())
return false;
peerlist_entry pe_seed{};
- pe_seed.adr = m_seed_nodes[current_index];
+ pe_seed.adr = server.m_seed_nodes[current_index];
if (is_peer_used(pe_seed))
is_connected_to_at_least_one_seed_node = true;
- else if (try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true))
+ else if (try_to_connect_and_handshake_with_new_peer(server.m_seed_nodes[current_index], true))
break;
- if(++try_count > m_seed_nodes.size())
+ if(++try_count > server.m_seed_nodes.size())
{
- if (!m_fallback_seed_nodes_added.test_and_set())
+ // only IP zone has fallback (to direct IP) seeds
+ if (zone == epee::net_utils::zone::public_ && !m_fallback_seed_nodes_added.test_and_set())
{
MWARNING("Failed to connect to any of seed peers, trying fallback seeds");
- current_index = m_seed_nodes.size() - 1;
+ current_index = server.m_seed_nodes.size() - 1;
{
boost::upgrade_to_unique_lock<boost::shared_mutex> seed_nodes_lock(seed_nodes_upgrade_lock);
- for (const auto &peer: get_seed_nodes(m_nettype))
+ for (const auto &peer: get_ip_seed_nodes())
{
MDEBUG("Fallback seed node: " << peer);
- append_net_address(m_seed_nodes, peer, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
+ append_net_address(server.m_seed_nodes, peer, cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT);
}
}
- if (current_index == m_seed_nodes.size() - 1)
+ if (current_index == server.m_seed_nodes.size() - 1)
{
MWARNING("No fallback seeds, continuing without seeds");
break;
@@ -1604,7 +1624,7 @@ namespace nodetool
break;
}
}
- if(++current_index >= m_seed_nodes.size())
+ if(++current_index >= server.m_seed_nodes.size())
current_index = 0;
}
return true;
@@ -1620,20 +1640,21 @@ namespace nodetool
if (!m_exclusive_peers.empty()) return true;
- // Only have seeds in the public zone right now.
-
- size_t start_conn_count = get_public_outgoing_connections_count();
- if(!get_public_white_peers_count() && !connect_to_seed())
+ bool one_succeeded = false;
+ for(auto& zone : m_network_zones)
{
- return false;
- }
+ size_t start_conn_count = get_outgoing_connections_count(zone.second);
+ if(!zone.second.m_peerlist.get_white_peers_count() && !connect_to_seed(zone.first))
+ {
+ continue;
+ }
- if (!connect_to_peerlist(m_priority_peers)) return false;
+ if (zone.first == zone_type::public_ && !connect_to_peerlist(m_priority_peers)) continue;
- for(auto& zone : m_network_zones)
- {
size_t base_expected_white_connections = (zone.second.m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
+ // carefully avoid `continue` in nested loop
+
size_t conn_count = get_outgoing_connections_count(zone.second);
while(conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
{
@@ -1670,16 +1691,17 @@ namespace nodetool
}
conn_count = new_conn_count;
}
- }
- if (start_conn_count == get_public_outgoing_connections_count() && start_conn_count < m_network_zones.at(zone_type::public_).m_config.m_net_config.max_out_connection_count)
- {
- MINFO("Failed to connect to any, trying seeds");
- if (!connect_to_seed())
- return false;
+ if (start_conn_count == get_outgoing_connections_count(zone.second) && start_conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
+ {
+ MINFO("Failed to connect to any, trying seeds");
+ if (!connect_to_seed(zone.first))
+ continue;
+ }
+ one_succeeded = true;
}
- return true;
+ return one_succeeded;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -1994,13 +2016,13 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- epee::net_utils::zone node_server<t_payload_net_handler>::send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, const cryptonote::relay_method tx_relay)
+ epee::net_utils::zone node_server<t_payload_net_handler>::send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, const cryptonote::relay_method tx_relay)
{
namespace enet = epee::net_utils;
- const auto send = [&txs, &source, &core, tx_relay] (std::pair<const enet::zone, network_zone>& network)
+ const auto send = [&txs, &source, tx_relay] (std::pair<const enet::zone, network_zone>& network)
{
- if (network.second.m_notifier.send_txs(std::move(txs), source, core, tx_relay))
+ if (network.second.m_notifier.send_txs(std::move(txs), source, tx_relay))
return network.first;
return enet::zone::invalid;
};
diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h
index 393d38e0a..2ace5987f 100644
--- a/src/p2p/net_node_common.h
+++ b/src/p2p/net_node_common.h
@@ -50,7 +50,7 @@ namespace nodetool
struct i_p2p_endpoint
{
virtual bool relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)=0;
- virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay)=0;
+ virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay)=0;
virtual bool invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)=0;
virtual bool invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)=0;
virtual bool drop_connection(const epee::net_utils::connection_context_base& context)=0;
@@ -75,7 +75,7 @@ namespace nodetool
{
return false;
}
- virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::i_core_events& core, cryptonote::relay_method tx_relay)
+ virtual epee::net_utils::zone send_txs(std::vector<cryptonote::blobdata> txs, const epee::net_utils::zone origin, const boost::uuids::uuid& source, cryptonote::relay_method tx_relay)
{
return epee::net_utils::zone::invalid;
}
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index 19298c969..aa4102481 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -66,7 +66,7 @@ set(rpc_pub_headers zmq_pub.h)
set(daemon_rpc_server_headers)
-set(rpc_daemon_private_headers
+set(rpc_private_headers
bootstrap_daemon.h
core_rpc_server.h
rpc_payment.h
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index a50c70418..e72f60d05 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -521,9 +521,17 @@ namespace cryptonote
bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, const connection_context *ctx)
{
RPC_TRACKER(get_blocks);
- bool r;
- if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r))
- return r;
+
+ bool use_bootstrap_daemon;
+ {
+ boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
+ use_bootstrap_daemon = m_should_use_bootstrap_daemon;
+ }
+ if (use_bootstrap_daemon)
+ {
+ bool r;
+ return use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r);
+ }
CHECK_PAYMENT(req, res, 1);
@@ -1129,7 +1137,7 @@ namespace cryptonote
if (!restricted)
{
boost::shared_lock<boost::shared_mutex> lock(m_bootstrap_daemon_mutex);
- if (m_bootstrap_daemon.get() != nullptr)
+ if (m_should_use_bootstrap_daemon)
{
skip_validation = !check_core_ready();
}
@@ -1661,6 +1669,13 @@ namespace cryptonote
return false;
}
+ uint64_t next_height;
+ crypto::rx_seedheights(height, &seed_height, &next_height);
+ if (next_height != seed_height)
+ next_seed_hash = m_core.get_block_id_by_height(next_height);
+ else
+ next_seed_hash = seed_hash;
+
if (extra_nonce.empty())
{
reserved_offset = 0;
diff --git a/src/wallet/api/address_book.cpp b/src/wallet/api/address_book.cpp
index f69a69ca3..96090d9f5 100644
--- a/src/wallet/api/address_book.cpp
+++ b/src/wallet/api/address_book.cpp
@@ -70,6 +70,25 @@ bool AddressBookImpl::addRow(const std::string &dst_addr , const std::string &pa
return r;
}
+bool AddressBookImpl::setDescription(std::size_t index, const std::string &description)
+{
+ clearStatus();
+
+ const auto ab = m_wallet->m_wallet->get_address_book();
+ if (index >= ab.size()){
+ return false;
+ }
+
+ tools::wallet2::address_book_row entry = ab[index];
+ entry.m_description = description;
+ bool r = m_wallet->m_wallet->set_address_book_row(index, entry.m_address, NULL, entry.m_description, entry.m_is_subaddress);
+ if (r)
+ refresh();
+ else
+ m_errorCode = General_Error;
+ return r;
+}
+
void AddressBookImpl::refresh()
{
LOG_PRINT_L2("Refreshing addressbook");
diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h
index f287969f3..e22f474fb 100644
--- a/src/wallet/api/address_book.h
+++ b/src/wallet/api/address_book.h
@@ -45,6 +45,7 @@ public:
void refresh() override;
std::vector<AddressBookRow*> getAll() const override;
bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) override;
+ bool setDescription(std::size_t index, const std::string &description) override;
bool deleteRow(std::size_t rowId) override;
// Error codes. See AddressBook:ErrorCode enum in wallet2_api.h
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index bcb300889..3a8532db8 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -92,6 +92,17 @@ std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
return m_history;
}
+void TransactionHistoryImpl::setTxNote(const std::string &txid, const std::string &note)
+{
+ cryptonote::blobdata txid_data;
+ if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
+ return;
+ const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
+
+ m_wallet->m_wallet->set_tx_note(htxid, note);
+ refresh();
+}
+
void TransactionHistoryImpl::refresh()
{
// multithreaded access:
@@ -126,10 +137,12 @@ void TransactionHistoryImpl::refresh()
payment_id = payment_id.substr(0,16);
TransactionInfoImpl * ti = new TransactionInfoImpl();
ti->m_paymentid = payment_id;
+ ti->m_coinbase = pd.m_coinbase;
ti->m_amount = pd.m_amount;
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
@@ -173,6 +186,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_Out;
ti->m_hash = string_tools::pod_to_hex(hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
@@ -183,6 +197,7 @@ void TransactionHistoryImpl::refresh()
for (const auto &d: pd.m_dests) {
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
}
+
m_history.push_back(ti);
}
@@ -207,6 +222,7 @@ void TransactionHistoryImpl::refresh()
ti->m_failed = is_failed;
ti->m_pending = true;
ti->m_hash = string_tools::pod_to_hex(hash);
+ ti->m_description = m_wallet->m_wallet->get_tx_note(hash);
ti->m_subaddrIndex = pd.m_subaddr_indices;
ti->m_subaddrAccount = pd.m_subaddr_account;
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
@@ -230,6 +246,7 @@ void TransactionHistoryImpl::refresh()
ti->m_direction = TransactionInfo::Direction_In;
ti->m_hash = string_tools::pod_to_hex(pd.m_tx_hash);
ti->m_blockheight = pd.m_block_height;
+ ti->m_description = m_wallet->m_wallet->get_tx_note(pd.m_tx_hash);
ti->m_pending = true;
ti->m_subaddrIndex = { pd.m_subaddr_index.minor };
ti->m_subaddrAccount = pd.m_subaddr_index.major;
diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h
index 8f3805788..60f12d771 100644
--- a/src/wallet/api/transaction_history.h
+++ b/src/wallet/api/transaction_history.h
@@ -45,6 +45,7 @@ public:
virtual TransactionInfo * transaction(const std::string &id) const;
virtual std::vector<TransactionInfo*> getAll() const;
virtual void refresh();
+ virtual void setTxNote(const std::string &txid, const std::string &note);
private:
diff --git a/src/wallet/api/transaction_info.cpp b/src/wallet/api/transaction_info.cpp
index 5ae3a6937..33e7856db 100644
--- a/src/wallet/api/transaction_info.cpp
+++ b/src/wallet/api/transaction_info.cpp
@@ -45,6 +45,7 @@ TransactionInfoImpl::TransactionInfoImpl()
: m_direction(Direction_Out)
, m_pending(false)
, m_failed(false)
+ , m_coinbase(false)
, m_amount(0)
, m_fee(0)
, m_blockheight(0)
@@ -77,6 +78,11 @@ bool TransactionInfoImpl::isFailed() const
return m_failed;
}
+bool TransactionInfoImpl::isCoinbase() const
+{
+ return m_coinbase;
+}
+
uint64_t TransactionInfoImpl::amount() const
{
return m_amount;
@@ -92,6 +98,11 @@ uint64_t TransactionInfoImpl::blockHeight() const
return m_blockheight;
}
+std::string TransactionInfoImpl::description() const
+{
+ return m_description;
+}
+
std::set<uint32_t> TransactionInfoImpl::subaddrIndex() const
{
return m_subaddrIndex;
diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h
index 73bb7689d..8bc36a8e9 100644
--- a/src/wallet/api/transaction_info.h
+++ b/src/wallet/api/transaction_info.h
@@ -46,10 +46,12 @@ public:
//! true if hold
virtual bool isPending() const override;
virtual bool isFailed() const override;
+ virtual bool isCoinbase() const override;
virtual uint64_t amount() const override;
//! always 0 for incoming txes
virtual uint64_t fee() const override;
virtual uint64_t blockHeight() const override;
+ virtual std::string description() const override;
virtual std::set<uint32_t> subaddrIndex() const override;
virtual uint32_t subaddrAccount() const override;
virtual std::string label() const override;
@@ -65,9 +67,11 @@ private:
int m_direction;
bool m_pending;
bool m_failed;
+ bool m_coinbase;
uint64_t m_amount;
uint64_t m_fee;
uint64_t m_blockheight;
+ std::string m_description;
std::set<uint32_t> m_subaddrIndex; // always unique index for incoming transfers; can be multiple indices for outgoing transfers
uint32_t m_subaddrAccount;
std::string m_label;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 152a7dcd7..9acc8484c 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -910,6 +910,11 @@ std::string WalletImpl::path() const
return m_wallet->path();
}
+void WalletImpl::stop()
+{
+ m_wallet->stop();
+}
+
bool WalletImpl::store(const std::string &path)
{
clearStatus();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index caf1e9ed4..3bf3e759b 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -99,6 +99,7 @@ public:
std::string publicSpendKey() const override;
std::string publicMultisigSignerKey() const override;
std::string path() const override;
+ void stop() override;
bool store(const std::string &path) override;
std::string filename() const override;
std::string keysFilename() const override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
index 50df7e5dd..44928a422 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -182,9 +182,11 @@ struct TransactionInfo
virtual int direction() const = 0;
virtual bool isPending() const = 0;
virtual bool isFailed() const = 0;
+ virtual bool isCoinbase() const = 0;
virtual uint64_t amount() const = 0;
virtual uint64_t fee() const = 0;
virtual uint64_t blockHeight() const = 0;
+ virtual std::string description() const = 0;
virtual std::set<uint32_t> subaddrIndex() const = 0;
virtual uint32_t subaddrAccount() const = 0;
virtual std::string label() const = 0;
@@ -208,6 +210,7 @@ struct TransactionHistory
virtual TransactionInfo * transaction(const std::string &id) const = 0;
virtual std::vector<TransactionInfo*> getAll() const = 0;
virtual void refresh() = 0;
+ virtual void setTxNote(const std::string &txid, const std::string &note) = 0;
};
/**
@@ -250,6 +253,7 @@ struct AddressBook
virtual std::vector<AddressBookRow*> getAll() const = 0;
virtual bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) = 0;
virtual bool deleteRow(std::size_t rowId) = 0;
+ virtual bool setDescription(std::size_t index, const std::string &description) = 0;
virtual void refresh() = 0;
virtual std::string errorString() const = 0;
virtual int errorCode() const = 0;
@@ -507,6 +511,11 @@ struct Wallet
virtual std::string publicMultisigSignerKey() const = 0;
/*!
+ * \brief stop - interrupts wallet refresh() loop once (doesn't stop background refresh thread)
+ */
+ virtual void stop() = 0;
+
+ /*!
* \brief store - stores wallet to file.
* \param path - main filename to store wallet to. additionally stores address file and keys file.
* to store to the same file - just pass empty string;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index a3755ff08..7cbb4a910 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2961,6 +2961,8 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
MTRACE("update_pool_state got pool");
// remove any pending tx that's not in the pool
+ constexpr const std::chrono::seconds tx_propagation_timeout{CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE * 3 / 2};
+ const auto now = std::chrono::system_clock::now();
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
while (it != m_unconfirmed_txs.end())
{
@@ -2988,9 +2990,11 @@ void wallet2::update_pool_state(std::vector<std::tuple<cryptonote::transaction,
LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as not in pool");
pit->second.m_state = wallet2::unconfirmed_transfer_details::pending_not_in_pool;
}
- else if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending_not_in_pool && refreshed)
+ else if (pit->second.m_state == wallet2::unconfirmed_transfer_details::pending_not_in_pool && refreshed &&
+ now > std::chrono::system_clock::from_time_t(pit->second.m_sent_time) + tx_propagation_timeout)
{
- LOG_PRINT_L1("Pending txid " << txid << " not in pool, marking as failed");
+ LOG_PRINT_L1("Pending txid " << txid << " not in pool after " << tx_propagation_timeout.count() <<
+ " seconds, marking as failed");
pit->second.m_state = wallet2::unconfirmed_transfer_details::failed;
// the inputs aren't spent anymore, since the tx failed
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index eac99185c..fed7d745c 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -434,7 +434,7 @@ private:
std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> m_rings; // relative
BEGIN_SERIALIZE_OBJECT()
- VERSION_FIELD(0)
+ VERSION_FIELD(1)
FIELD(m_tx)
VARINT_FIELD(m_amount_in)
VARINT_FIELD(m_amount_out)
@@ -442,6 +442,8 @@ private:
VARINT_FIELD(m_sent_time)
FIELD(m_dests)
FIELD(m_payment_id)
+ if (version >= 1)
+ VARINT_FIELD(m_state)
VARINT_FIELD(m_timestamp)
VARINT_FIELD(m_subaddr_account)
FIELD(m_subaddr_indices)