Merge commit 'f2f725d8db3535055d1c7e102c0bba75b22a3409' into LokiMergeUpstream

This commit is contained in:
Doyle 2019-04-12 15:23:01 +10:00
commit 2fe5ddb2ca
12 changed files with 169 additions and 86 deletions

View File

@ -233,13 +233,24 @@ public:
char *str;
};
static void add_anchors(ub_ctx *ctx)
{
const char * const *ds = ::get_builtin_ds();
while (*ds)
{
MINFO("adding trust anchor: " << *ds);
ub_ctx_add_ta(ctx, string_copy(*ds++));
}
}
DNSResolver::DNSResolver() : m_data(new DNSResolverData())
{
int use_dns_public = 0;
std::vector<std::string> dns_public_addr;
if (auto res = getenv("DNS_PUBLIC"))
const char *DNS_PUBLIC = getenv("DNS_PUBLIC");
if (DNS_PUBLIC)
{
dns_public_addr = tools::dns_utils::parse_dns_public(res);
dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC);
if (!dns_public_addr.empty())
{
MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)");
@ -267,11 +278,28 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData())
ub_ctx_hosts(m_data->m_ub_context, NULL);
}
const char * const *ds = ::get_builtin_ds();
while (*ds)
add_anchors(m_data->m_ub_context);
if (!DNS_PUBLIC)
{
MINFO("adding trust anchor: " << *ds);
ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++));
// if no DNS_PUBLIC specified, we try a lookup to what we know
// should be a valid DNSSEC record, and switch to known good
// DNSSEC resolvers if verification fails
bool available, valid;
static const char *probe_hostname = "updates.moneropulse.org";
auto records = get_txt_record(probe_hostname, available, valid);
if (!valid)
{
MINFO("Failed to verify DNSSEC record from " << probe_hostname << ", falling back to TCP with well known DNSSEC resolvers");
ub_ctx_delete(m_data->m_ub_context);
m_data->m_ub_context = ub_ctx_create();
add_anchors(m_data->m_ub_context);
dns_public_addr = tools::dns_utils::parse_dns_public(DNS_PUBLIC);
for (const auto &ip: dns_public_addr)
ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str()));
ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no"));
ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes"));
}
}
}

View File

@ -139,6 +139,7 @@ static_assert(STAKING_PORTIONS % 3 == 0, "Use a multiple of three, so that it di
#define P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT 5000 //5 seconds
#define P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT 70
#define P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT 2
#define P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT 2
#define P2P_DEFAULT_LIMIT_RATE_UP 2048 // kB/s
#define P2P_DEFAULT_LIMIT_RATE_DOWN 8192 // kB/s

View File

@ -114,6 +114,7 @@ namespace cryptonote
void stop();
void on_connection_close(cryptonote_connection_context &context);
void set_max_out_peers(unsigned int max) { m_max_out_peers = max; }
void set_no_sync(bool value) { m_no_sync = value; }
std::string get_peers_overview() const;
std::pair<uint32_t, uint32_t> get_next_needed_pruning_stripe() const;
bool needs_new_sync_connections() const;
@ -146,6 +147,7 @@ namespace cryptonote
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
bool kick_idle_peers();
bool check_standby_peers();
bool update_sync_search();
int try_add_next_blocks(cryptonote_connection_context &context);
void notify_new_stripe(cryptonote_connection_context &context, uint32_t stripe);
void skip_unneeded_hashes(cryptonote_connection_context& context, bool check_block_queue) const;
@ -157,10 +159,12 @@ namespace cryptonote
std::atomic<uint32_t> m_syncronized_connections_count;
std::atomic<bool> m_synchronized;
std::atomic<bool> m_stopping;
std::atomic<bool> m_no_sync;
boost::mutex m_sync_lock;
block_queue m_block_queue;
epee::math_helper::once_a_time_seconds<30> m_idle_peer_kicker;
epee::math_helper::once_a_time_milliseconds<100> m_standby_checker;
epee::math_helper::once_a_time_seconds<101> m_sync_search_checker;
std::atomic<unsigned int> m_max_out_peers;
tools::PerformanceTimer m_sync_timer, m_add_timer;
uint64_t m_last_add_end_time;

View File

@ -73,7 +73,8 @@ namespace cryptonote
m_p2p(p_net_layout),
m_syncronized_connections_count(0),
m_synchronized(offline),
m_stopping(false)
m_stopping(false),
m_no_sync(false)
{
if(!m_p2p)
@ -375,6 +376,13 @@ namespace cryptonote
m_core.set_target_blockchain_height((hshd.current_height));
}
MINFO(context << "Remote blockchain height: " << hshd.current_height << ", id: " << hshd.top_id);
if (m_no_sync)
{
context.m_state = cryptonote_connection_context::state_normal;
return true;
}
context.m_state = cryptonote_connection_context::state_synchronizing;
//let the socket to send response to handshake, but request callback, to let send request data after response
LOG_PRINT_CCONTEXT_L2("requesting callback");
@ -1452,6 +1460,7 @@ skip:
{
m_idle_peer_kicker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::kick_idle_peers, this));
m_standby_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::check_standby_peers, this));
m_sync_search_checker.do_call(boost::bind(&t_cryptonote_protocol_handler<t_core>::update_sync_search, this));
return m_core.on_idle();
}
//------------------------------------------------------------------------------------------------------------------------
@ -1481,6 +1490,47 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::update_sync_search()
{
const uint64_t target = m_core.get_target_blockchain_height();
const uint64_t height = m_core.get_current_blockchain_height();
if (target > height) // if we're not synced yet, don't do it
return true;
MTRACE("Checking for outgoing syncing peers...");
unsigned n_syncing = 0, n_synced = 0;
boost::uuids::uuid last_synced_peer_id(boost::uuids::nil_uuid());
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool
{
if (!peer_id || context.m_is_income) // only consider connected outgoing peers
return true;
if (context.m_state == cryptonote_connection_context::state_synchronizing)
++n_syncing;
if (context.m_state == cryptonote_connection_context::state_normal)
{
++n_synced;
if (!context.m_anchor)
last_synced_peer_id = context.m_connection_id;
}
return true;
});
MTRACE(n_syncing << " syncing, " << n_synced << " synced");
// if we're at max out peers, and not enough are syncing
if (n_synced + n_syncing >= m_max_out_peers && n_syncing < P2P_DEFAULT_SYNC_SEARCH_CONNECTIONS_COUNT && last_synced_peer_id != boost::uuids::nil_uuid())
{
if (!m_p2p->for_connection(last_synced_peer_id, [&](cryptonote_connection_context& ctx, nodetool::peerid_type peer_id, uint32_t f)->bool{
MINFO(ctx << "dropping synced peer, " << n_syncing << " syncing, " << n_synced << " synced");
drop_connection(ctx, false, false);
return true;
}))
MDEBUG("Failed to find peer we wanted to drop");
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::check_standby_peers()
{
m_p2p->for_each_connection([&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t support_flags)->bool

View File

@ -81,11 +81,9 @@ int main(int argc, char* argv[])
po::options_description desc_cmd_only("Command line options");
po::options_description desc_cmd_sett("Command line options and settings options");
const command_line::arg_descriptor<std::string> arg_output_file = {"output-file", "Specify output file", "", true};
const command_line::arg_descriptor<uint32_t> arg_log_level = {"log-level", "", log_level};
const command_line::arg_descriptor<std::string> arg_input = {"input", "Specify input has a hexadecimal string", ""};
command_line::add_arg(desc_cmd_sett, arg_output_file);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_input);
@ -121,52 +119,10 @@ int main(int argc, char* argv[])
mlog_configure("", true);
std::string m_config_folder;
std::ostream *output;
std::ofstream *raw_data_file = NULL;
if (command_line::has_arg(vm, arg_output_file))
{
output_file_path = boost::filesystem::path(command_line::get_arg(vm, arg_output_file));
const boost::filesystem::path dir_path = output_file_path.parent_path();
if (!dir_path.empty())
{
if (boost::filesystem::exists(dir_path))
{
if (!boost::filesystem::is_directory(dir_path))
{
std::cerr << "output directory path is a file: " << dir_path << std::endl;
return 1;
}
}
else
{
if (!boost::filesystem::create_directory(dir_path))
{
std::cerr << "Failed to create directory " << dir_path << std::endl;
return 1;
}
}
}
raw_data_file = new std::ofstream();
raw_data_file->open(output_file_path.string(), std::ios_base::out | std::ios::trunc);
if (raw_data_file->fail())
return 1;
output = raw_data_file;
}
else
{
output_file_path = "";
output = &std::cout;
}
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(input, blob))
{
std::cerr << "Invalid hex input" << std::endl;
std::cerr << "Invalid hex input: " << input << std::endl;
return 1;
}
@ -213,11 +169,5 @@ int main(int argc, char* argv[])
if (output->fail())
return 1;
output->flush();
if (raw_data_file)
delete raw_data_file;
return 0;
}

View File

@ -133,6 +133,7 @@ namespace nodetool
const command_line::arg_descriptor<std::vector<std::string> > arg_proxy = {"proxy", "<network-type>,<socks-ip:port>[,max_connections] i.e. \"tor,127.0.0.1:9050,100\""};
const command_line::arg_descriptor<std::vector<std::string> > arg_anonymous_inbound = {"anonymous-inbound", "<hidden-service-address>,<[bind-ip:]port>[,max_connections] i.e. \"x.onion,127.0.0.1:18083,100\""};
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
const command_line::arg_descriptor<bool> arg_no_sync = {"no-sync", "Don't synchronize the blockchain with other peers", false};
const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max number of out peers", -1};

View File

@ -487,6 +487,7 @@ namespace nodetool
extern const command_line::arg_descriptor<std::vector<std::string> > arg_proxy;
extern const command_line::arg_descriptor<std::vector<std::string> > arg_anonymous_inbound;
extern const command_line::arg_descriptor<bool> arg_p2p_hide_my_port;
extern const command_line::arg_descriptor<bool> arg_no_sync;
extern const command_line::arg_descriptor<bool> arg_no_igd;
extern const command_line::arg_descriptor<bool> arg_offline;

View File

@ -104,6 +104,7 @@ namespace nodetool
command_line::add_arg(desc, arg_proxy);
command_line::add_arg(desc, arg_anonymous_inbound);
command_line::add_arg(desc, arg_p2p_hide_my_port);
command_line::add_arg(desc, arg_no_sync);
command_line::add_arg(desc, arg_no_igd);
command_line::add_arg(desc, arg_out_peers);
command_line::add_arg(desc, arg_in_peers);
@ -311,6 +312,9 @@ namespace nodetool
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
m_hide_my_port = true;
if (command_line::has_arg(vm, arg_no_sync))
m_payload_handler.set_no_sync(true);
if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) )
return false;
else

View File

@ -6522,17 +6522,17 @@ bool wallet2::save_multisig_tx(const std::vector<pending_tx>& ptx_vector, const
return epee::file_io_utils::save_string_to_file(filename, ciphertext);
}
//----------------------------------------------------------------------------------------------------
bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func)
bool wallet2::parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const
{
const size_t magiclen = strlen(MULTISIG_UNSIGNED_TX_PREFIX);
if (strncmp(s.c_str(), MULTISIG_UNSIGNED_TX_PREFIX, magiclen))
if (strncmp(multisig_tx_st.c_str(), MULTISIG_UNSIGNED_TX_PREFIX, magiclen))
{
LOG_PRINT_L0("Bad magic from multisig tx data");
return false;
}
try
{
s = decrypt_with_view_secret_key(std::string(s, magiclen));
multisig_tx_st = decrypt_with_view_secret_key(std::string(multisig_tx_st, magiclen));
}
catch (const std::exception &e)
{
@ -6541,7 +6541,7 @@ bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported
}
try
{
std::istringstream iss(s);
std::istringstream iss(multisig_tx_st);
boost::archive::portable_binary_iarchive ar(iss);
ar >> exported_txs;
}
@ -6563,6 +6563,17 @@ bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported
CHECK_AND_ASSERT_MES(ptx.construction_data.sources.size() == ptx.tx.vin.size(), false, "Mismatched sources/vin sizes");
}
return true;
}
//----------------------------------------------------------------------------------------------------
bool wallet2::load_multisig_tx(cryptonote::blobdata s, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func)
{
if(!parse_multisig_tx_from_str(s, exported_txs))
{
LOG_PRINT_L0("Failed to parse multisig transaction from string");
return false;
}
LOG_PRINT_L1("Loaded multisig tx unsigned data from binary: " << exported_txs.m_ptx.size() << " transactions");
for (auto &ptx: exported_txs.m_ptx) LOG_PRINT_L0(cryptonote::obj_to_json_str(ptx.tx));

View File

@ -855,6 +855,7 @@ namespace tools
void cold_tx_aux_import(const std::vector<pending_tx>& ptx, const std::vector<std::string>& tx_device_aux);
void cold_sign_tx(const std::vector<pending_tx>& ptx_vector, signed_tx_set &exported_txs, std::vector<cryptonote::address_parse_info> &dsts_info, std::vector<std::string> & tx_device_aux);
uint64_t cold_key_image_sync(uint64_t &spent, uint64_t &unspent);
bool parse_multisig_tx_from_str(std::string multisig_tx_st, multisig_tx_set &exported_txs) const;
bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function<bool(const multisig_tx_set&)> accept_func = NULL);
bool sign_multisig_tx_from_file(const std::string &filename, std::vector<crypto::hash> &txids, std::function<bool(const multisig_tx_set&)> accept_func);

View File

@ -1074,40 +1074,70 @@ namespace tools
er.message = "command not supported by watch-only wallet";
return false;
}
tools::wallet2::unsigned_tx_set exported_txs;
try
if(req.unsigned_txset.empty() && req.multisig_txset.empty())
{
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
{
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
er.message = "Failed to parse hex.";
return false;
}
if(!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs))
{
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
er.message = "cannot load unsigned_txset";
return false;
}
}
catch (const std::exception &e)
{
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
er.message = "failed to parse unsigned transfers: " + std::string(e.what());
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "no txset provided";
return false;
}
std::vector <wallet2::tx_construction_data> tx_constructions;
if (!req.unsigned_txset.empty()) {
try {
tools::wallet2::unsigned_tx_set exported_txs;
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob)) {
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
er.message = "Failed to parse hex.";
return false;
}
if (!m_wallet->parse_unsigned_tx_from_str(blob, exported_txs)) {
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
er.message = "cannot load unsigned_txset";
return false;
}
tx_constructions = exported_txs.txes;
}
catch (const std::exception &e) {
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
er.message = "failed to parse unsigned transfers: " + std::string(e.what());
return false;
}
} else if (!req.multisig_txset.empty()) {
try {
tools::wallet2::multisig_tx_set exported_txs;
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(req.multisig_txset, blob)) {
er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
er.message = "Failed to parse hex.";
return false;
}
if (!m_wallet->parse_multisig_tx_from_str(blob, exported_txs)) {
er.code = WALLET_RPC_ERROR_CODE_BAD_MULTISIG_TX_DATA;
er.message = "cannot load multisig_txset";
return false;
}
for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n) {
tx_constructions.push_back(exported_txs.m_ptx[n].construction_data);
}
}
catch (const std::exception &e) {
er.code = WALLET_RPC_ERROR_CODE_BAD_MULTISIG_TX_DATA;
er.message = "failed to parse multisig transfers: " + std::string(e.what());
return false;
}
}
std::vector<tools::wallet2::pending_tx> ptx;
try
{
// gather info to ask the user
std::unordered_map<cryptonote::account_public_address, std::pair<std::string, uint64_t>> dests;
int first_known_non_zero_change_index = -1;
for (size_t n = 0; n < exported_txs.txes.size(); ++n)
for (size_t n = 0; n < tx_constructions.size(); ++n)
{
const tools::wallet2::tx_construction_data &cd = exported_txs.txes[n];
const tools::wallet2::tx_construction_data &cd = tx_constructions[n];
res.desc.push_back({0, 0, std::numeric_limits<uint32_t>::max(), 0, {}, "", 0, "", 0, 0, ""});
wallet_rpc::COMMAND_RPC_DESCRIBE_TRANSFER::transfer_description &desc = res.desc.back();
@ -1171,7 +1201,7 @@ namespace tools
{
if (first_known_non_zero_change_index == -1)
first_known_non_zero_change_index = n;
const tools::wallet2::tx_construction_data &cdn = exported_txs.txes[first_known_non_zero_change_index];
const tools::wallet2::tx_construction_data &cdn = tx_constructions[first_known_non_zero_change_index];
if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr)))
{
er.code = WALLET_RPC_ERROR_CODE_BAD_UNSIGNED_TX_DATA;
@ -1199,7 +1229,7 @@ namespace tools
if (desc.change_amount > 0)
{
const tools::wallet2::tx_construction_data &cd0 = exported_txs.txes[0];
const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0];
desc.change_address = get_account_address_as_str(m_wallet->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr);
}

View File

@ -653,9 +653,11 @@ namespace wallet_rpc
struct request_t
{
std::string unsigned_txset; // Set of unsigned tx returned by "transfer" or "transfer_split" methods.
std::string multisig_txset; // Set of unsigned multisig txes returned by "transfer" or "transfer_split" methods
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(unsigned_txset)
KV_SERIALIZE(multisig_txset)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;