dns_utils: factor TXT record loading code from checkpoint code
This commit is contained in:
parent
5892f653c7
commit
e8a7525ceb
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
|
#include <random>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
using namespace epee;
|
using namespace epee;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
|
@ -451,6 +452,108 @@ std::string get_account_address_as_str_from_url(const std::string& url, bool& dn
|
||||||
return addresses[0];
|
return addresses[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
|
||||||
|
{
|
||||||
|
if (a.size() != b.size()) return false;
|
||||||
|
|
||||||
|
for (const auto& record_in_a : a)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
for (const auto& record_in_b : b)
|
||||||
|
{
|
||||||
|
if (record_in_a == record_in_b)
|
||||||
|
{
|
||||||
|
ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_txt_records_from_dns(std::vector<std::string> &good_records, const std::vector<std::string> &dns_urls)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<std::string> > records;
|
||||||
|
records.resize(dns_urls.size());
|
||||||
|
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
|
||||||
|
size_t first_index = dis(gen);
|
||||||
|
|
||||||
|
bool avail, valid;
|
||||||
|
size_t cur_index = first_index;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::string url = dns_urls[cur_index];
|
||||||
|
|
||||||
|
records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
|
||||||
|
if (!avail)
|
||||||
|
{
|
||||||
|
records[cur_index].clear();
|
||||||
|
LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
|
||||||
|
}
|
||||||
|
if (!valid)
|
||||||
|
{
|
||||||
|
records[cur_index].clear();
|
||||||
|
LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_index++;
|
||||||
|
if (cur_index == dns_urls.size())
|
||||||
|
{
|
||||||
|
cur_index = 0;
|
||||||
|
}
|
||||||
|
records[cur_index].clear();
|
||||||
|
} while (cur_index != first_index);
|
||||||
|
|
||||||
|
size_t num_valid_records = 0;
|
||||||
|
|
||||||
|
for( const auto& record_set : records)
|
||||||
|
{
|
||||||
|
if (record_set.size() != 0)
|
||||||
|
{
|
||||||
|
num_valid_records++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_valid_records < 2)
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int good_records_index = -1;
|
||||||
|
for (size_t i = 0; i < records.size() - 1; ++i)
|
||||||
|
{
|
||||||
|
if (records[i].size() == 0) continue;
|
||||||
|
|
||||||
|
for (size_t j = i + 1; j < records.size(); ++j)
|
||||||
|
{
|
||||||
|
if (dns_records_match(records[i], records[j]))
|
||||||
|
{
|
||||||
|
good_records_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (good_records_index >= 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (good_records_index < 0)
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
good_records = records[good_records_index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tools::dns_utils
|
} // namespace tools::dns_utils
|
||||||
|
|
||||||
} // namespace tools
|
} // namespace tools
|
||||||
|
|
|
@ -165,6 +165,8 @@ std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec
|
||||||
|
|
||||||
std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid);
|
std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid);
|
||||||
|
|
||||||
|
bool load_txt_records_from_dns(std::vector<std::string> &records, const std::vector<std::string> &dns_urls);
|
||||||
|
|
||||||
} // namespace tools::dns_utils
|
} // namespace tools::dns_utils
|
||||||
|
|
||||||
} // namespace tools
|
} // namespace tools
|
||||||
|
|
|
@ -42,30 +42,6 @@ using namespace epee;
|
||||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||||
#define MONERO_DEFAULT_LOG_CATEGORY "checkpoints"
|
#define MONERO_DEFAULT_LOG_CATEGORY "checkpoints"
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
|
|
||||||
{
|
|
||||||
if (a.size() != b.size()) return false;
|
|
||||||
|
|
||||||
for (const auto& record_in_a : a)
|
|
||||||
{
|
|
||||||
bool ok = false;
|
|
||||||
for (const auto& record_in_b : b)
|
|
||||||
{
|
|
||||||
if (record_in_a == record_in_b)
|
|
||||||
{
|
|
||||||
ok = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ok) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
namespace cryptonote
|
namespace cryptonote
|
||||||
{
|
{
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -230,6 +206,8 @@ namespace cryptonote
|
||||||
|
|
||||||
bool checkpoints::load_checkpoints_from_dns(bool testnet)
|
bool checkpoints::load_checkpoints_from_dns(bool testnet)
|
||||||
{
|
{
|
||||||
|
std::vector<std::string> records;
|
||||||
|
|
||||||
// All four MoneroPulse domains have DNSSEC on and valid
|
// All four MoneroPulse domains have DNSSEC on and valid
|
||||||
static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
|
static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
|
||||||
, "checkpoints.moneropulse.org"
|
, "checkpoints.moneropulse.org"
|
||||||
|
@ -243,87 +221,10 @@ namespace cryptonote
|
||||||
, "testpoints.moneropulse.co"
|
, "testpoints.moneropulse.co"
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::vector<std::string> > records;
|
if (!tools::dns_utils::load_txt_records_from_dns(records, testnet ? testnet_dns_urls : dns_urls))
|
||||||
records.resize(dns_urls.size());
|
return true; // why true ?
|
||||||
|
|
||||||
std::random_device rd;
|
for (const auto& record : records)
|
||||||
std::mt19937 gen(rd());
|
|
||||||
std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
|
|
||||||
size_t first_index = dis(gen);
|
|
||||||
|
|
||||||
bool avail, valid;
|
|
||||||
size_t cur_index = first_index;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
std::string url;
|
|
||||||
if (testnet)
|
|
||||||
{
|
|
||||||
url = testnet_dns_urls[cur_index];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
url = dns_urls[cur_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
|
|
||||||
if (!avail)
|
|
||||||
{
|
|
||||||
records[cur_index].clear();
|
|
||||||
LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
|
|
||||||
}
|
|
||||||
if (!valid)
|
|
||||||
{
|
|
||||||
records[cur_index].clear();
|
|
||||||
LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_index++;
|
|
||||||
if (cur_index == dns_urls.size())
|
|
||||||
{
|
|
||||||
cur_index = 0;
|
|
||||||
}
|
|
||||||
records[cur_index].clear();
|
|
||||||
} while (cur_index != first_index);
|
|
||||||
|
|
||||||
size_t num_valid_records = 0;
|
|
||||||
|
|
||||||
for( const auto& record_set : records)
|
|
||||||
{
|
|
||||||
if (record_set.size() != 0)
|
|
||||||
{
|
|
||||||
num_valid_records++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_valid_records < 2)
|
|
||||||
{
|
|
||||||
LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int good_records_index = -1;
|
|
||||||
for (size_t i = 0; i < records.size() - 1; ++i)
|
|
||||||
{
|
|
||||||
if (records[i].size() == 0) continue;
|
|
||||||
|
|
||||||
for (size_t j = i + 1; j < records.size(); ++j)
|
|
||||||
{
|
|
||||||
if (dns_records_match(records[i], records[j]))
|
|
||||||
{
|
|
||||||
good_records_index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (good_records_index >= 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (good_records_index < 0)
|
|
||||||
{
|
|
||||||
LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& record : records[good_records_index])
|
|
||||||
{
|
{
|
||||||
auto pos = record.find(":");
|
auto pos = record.find(":");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
|
|
Loading…
Reference in New Issue