Merge pull request 'upstream' (#494) from wowario/wownero:upstream into master

Reviewed-on: https://codeberg.org/wownero/wownero/pulls/494
This commit is contained in:
wowario
2024-12-15 21:38:34 +00:00
22 changed files with 268 additions and 36 deletions

View File

@@ -1201,6 +1201,7 @@ endif()
if(NOT ZMQ_LIB)
message(FATAL_ERROR "Could not find required libzmq")
endif()
include_directories(${ZMQ_INCLUDE_PATH})
if(PGM_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PGM_LIBRARY}")
endif()
@@ -1214,7 +1215,15 @@ if(PROTOLIB_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${PROTOLIB_LIBRARY}")
endif()
if(SODIUM_LIBRARY)
message(STATUS "ZMQ_LIB: ${ZMQ_LIB};${SODIUM_LIBRARY}")
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
find_path(SODIUM_INCLUDE_PATH sodium/crypto_verify_32.h)
if (SODIUM_INCLUDE_PATH)
message(STATUS "SODIUM_INCLUDE_PATH: ${SODIUM_INCLUDE_PATH}")
include_directories(${SODIUM_INCLUDE_PATH})
else()
message(FATAL_ERROR "Could not find required sodium/crypto_verify_32.h")
endif()
endif()
if(BSD_LIBRARY)
set(ZMQ_LIB "${ZMQ_LIB};${BSD_LIBRARY}")

View File

@@ -74,6 +74,7 @@ namespace epee
public:
using char_type = std::uint8_t;
using Ch = char_type;
using value_type = char_type;
//! Increase internal buffer by at least `byte_stream_increase` bytes.
byte_stream() noexcept
@@ -86,6 +87,7 @@ namespace epee
~byte_stream() noexcept = default;
byte_stream& operator=(byte_stream&& rhs) noexcept;
std::uint8_t* data() noexcept { return buffer_.get(); }
const std::uint8_t* data() const noexcept { return buffer_.get(); }
std::uint8_t* tellp() const noexcept { return next_write_; }
std::size_t available() const noexcept { return end_ - next_write_; }

View File

@@ -171,6 +171,13 @@
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
return true; \
} \
epee::serialization::storage_entry params_; \
params_ = epee::serialization::storage_entry(epee::serialization::section()); \
if(!ps.get_value("params", params_, nullptr)) \
{ \
epee::serialization::section params_section; \
ps.set_value("params", std::move(params_section), nullptr); \
} \
if(false) return true; //just a stub to have "else if"

View File

@@ -71,8 +71,6 @@ namespace string_tools
std::string get_current_module_path();
#endif
void set_module_name_and_folder(const std::string& path_to_process_);
void trim_left(std::string& str);
void trim_right(std::string& str);
//----------------------------------------------------------------------------
inline std::string& trim(std::string& str)
{

View File

@@ -152,7 +152,11 @@ namespace epee
{
std::size_t space_needed = 0;
for (const auto& source : sources)
{
if (std::numeric_limits<std::size_t>::max() - space_needed < source.size())
throw std::bad_alloc{};
space_needed += source.size();
}
if (space_needed)
{
@@ -162,9 +166,9 @@ namespace epee
for (const auto& source : sources)
{
assert(source.size() <= out.size()); // see check above
std::memcpy(out.data(), source.data(), source.size());
if (out.remove_prefix(source.size()) < source.size())
throw std::bad_alloc{}; // size_t overflow on space_needed
out.remove_prefix(source.size());
}
storage_ = std::move(storage);
}

View File

@@ -1,5 +1,4 @@
#include "readline_buffer.h"
#include "string_tools.h"
#include <readline/readline.h>
#include <readline/history.h>
#include <iostream>
@@ -174,7 +173,7 @@ static void handle_line(char* line)
line_stat = rdln::full;
the_line = line;
std::string test_line = line;
epee::string_tools::trim_right(test_line);
boost::trim_right(test_line);
if(!test_line.empty())
{
if (!same_as_last_line(test_line))

View File

@@ -174,19 +174,6 @@ namespace string_tools
}
//----------------------------------------------------------------------------
void trim_left(std::string& str)
{
boost::trim_left(str);
return;
}
//----------------------------------------------------------------------------
void trim_right(std::string& str)
{
boost::trim_right(str);
return;
}
std::string pad_string(std::string s, size_t n, char c, bool prepend)
{
if (s.size() < n)

View File

@@ -1242,12 +1242,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
// just the latter (because the rollback was done above).
rollback_blockchain_switching(disconnected_chain, split_height);
// FIXME: Why do we keep invalid blocks around? Possibly in case we hear
// about them again so we can immediately dismiss them, but needs some
// looking into.
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
add_block_as_invalid(bei, blkid);
MERROR("The block was inserted as invalid while connecting new alternative chain, block_id: " << blkid);
m_db->remove_alt_block(blkid);
alt_ch_iter++;
@@ -1255,7 +1250,6 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
{
const auto &bei = *alt_ch_to_orph_iter++;
const crypto::hash blkid = cryptonote::get_block_hash(bei.bl);
add_block_as_invalid(bei, blkid);
m_db->remove_alt_block(blkid);
}
return false;

View File

@@ -696,6 +696,16 @@ bool t_command_parser_executor::ban(const std::vector<std::string>& args)
std::ifstream ifs(ban_list_path.string());
for (std::string line; std::getline(ifs, line); )
{
// ignore comments after '#' character
const size_t pound_idx = line.find('#');
if (pound_idx != std::string::npos)
line.resize(pound_idx);
// trim whitespace and ignore empty lines
boost::trim(line);
if (line.empty())
continue;
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{

View File

@@ -133,6 +133,7 @@ namespace lmdb
//! \pre `!is_end()` \return Current key
K get_key() const noexcept
{
static_assert(std::is_trivially_copyable<K>(), "key is not memcpy safe");
assert(!is_end());
K out;
std::memcpy(std::addressof(out), key.data(), sizeof(out));

View File

@@ -55,7 +55,7 @@ namespace lmdb
static expect<F> get_value(MDB_val value) noexcept
{
static_assert(std::is_same<U, V>(), "bad MONERO_FIELD?");
static_assert(std::is_pod<F>(), "F must be POD");
static_assert(std::is_trivially_copyable<F>(), "F must be memcpy safe");
static_assert(sizeof(F) + offset <= sizeof(U), "bad field type and/or offset");
if (value.mv_size != sizeof(U))

View File

@@ -111,6 +111,7 @@ namespace lmdb
template<typename T, std::size_t offset = 0>
inline int less(MDB_val const* left, MDB_val const* right) noexcept
{
static_assert(std::is_trivially_copyable<T>(), "memcpy will not work");
if (!left || !right || left->mv_size < sizeof(T) + offset || right->mv_size < sizeof(T) + offset)
{
assert("invalid use of custom comparison" == 0);

View File

@@ -162,8 +162,8 @@ namespace lmdb
G get_value() const noexcept
{
static_assert(std::is_same<U, T>(), "bad MONERO_FIELD usage?");
static_assert(std::is_pod<U>(), "value type must be pod");
static_assert(std::is_pod<G>(), "field type must be pod");
static_assert(std::is_trivially_copyable<U>(), "value type must be memcpy safe");
static_assert(std::is_trivially_copyable<G>(), "field type must be memcpy safe");
static_assert(sizeof(G) + uoffset <= sizeof(U), "bad field and/or offset");
assert(sizeof(G) + uoffset <= values.size());
assert(!is_end());

View File

@@ -531,6 +531,16 @@ namespace nodetool
std::istringstream iss(banned_ips);
for (std::string line; std::getline(iss, line); )
{
// ignore comments after '#' character
const size_t pound_idx = line.find('#');
if (pound_idx != std::string::npos)
line.resize(pound_idx);
// trim whitespace and ignore empty lines
boost::trim(line);
if (line.empty())
continue;
auto subnet = net::get_ipv4_subnet_address(line);
if (subnet)
{

View File

@@ -8886,6 +8886,22 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
PAUSE_READLINE();
auto formatter = boost::format("%8.8s %6.6s %8.8s %25.25s %20.20s %64.64s %15.15s %14.14s %s %s - %s");
message_writer(console_color_default, false) << formatter
% "Block"
% "In/Out"
% "Locked?"
% "Timestamp"
% "Amount"
% "Tx Hash"
% "Tx Payment ID"
% "Tx Fee"
% "Destination(s)"
% "Index"
% "Tx Note";
formatter = boost::format("%8.8llu %6.6s %8.8s %25.25s %20.20s %64.64s %15.15s %14.14s %s %s - %s");
for (const auto& transfer : all_transfers)
{
const auto color = transfer.type == "failed" ? console_color_red : transfer.confirmed ? ((transfer.direction == "in" || transfer.direction == "block") ? console_color_green : console_color_magenta) : console_color_default;
@@ -8902,8 +8918,6 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_)
}
}
auto formatter = boost::format("%8.8llu %6.6s %8.8s %25.25s %20.20s %s %s %14.14s %s %s - %s");
message_writer(color, false) << formatter
% transfer.block
% transfer.direction

View File

@@ -1280,6 +1280,11 @@ bool wallet2::has_stagenet_option(const boost::program_options::variables_map& v
return command_line::get_arg(vm, options().stagenet);
}
bool wallet2::has_proxy_option() const
{
return !m_proxy.empty();
}
std::string wallet2::device_name_option(const boost::program_options::variables_map& vm)
{
return command_line::get_arg(vm, options().hw_device);
@@ -1364,12 +1369,15 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
}
//----------------------------------------------------------------------------------------------------
bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options, const std::string& proxy)
{
boost::lock_guard<boost::recursive_mutex> lock(m_daemon_rpc_mutex);
if(m_http_client->is_connected())
m_http_client->disconnect();
CHECK_AND_ASSERT_MES2(m_proxy.empty() || proxy.empty() , "It is not possible to set global proxy (--proxy) and daemon specific proxy together.");
if(m_proxy.empty())
CHECK_AND_ASSERT_MES(set_proxy(proxy), false, "failed to set proxy address");
const bool changed = m_daemon_address != daemon_address;
m_daemon_address = std::move(daemon_address);
m_daemon_login = std::move(daemon_login);
@@ -1404,7 +1412,8 @@ bool wallet2::set_proxy(const std::string &address)
//----------------------------------------------------------------------------------------------------
bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, const std::string &proxy_address, uint64_t upper_transaction_weight_limit, bool trusted_daemon, epee::net_utils::ssl_options_t ssl_options)
{
CHECK_AND_ASSERT_MES(set_proxy(proxy_address), false, "failed to set proxy address");
m_proxy = proxy_address;
CHECK_AND_ASSERT_MES(set_proxy(m_proxy), false, "failed to set proxy address");
m_checkpoints.init_default_checkpoints(m_nettype);
m_is_initialized = true;
m_upper_transaction_weight_limit = upper_transaction_weight_limit;
@@ -6143,7 +6152,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
bool r = true;
if (use_fs)
{
load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::max());
r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::max());
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file);
}

View File

@@ -971,6 +971,12 @@ private:
std::string path() const;
/*!
* \brief has_proxy_option Check the global proxy (--proxy) has been defined or not.
* \return returns bool representing the global proxy (--proxy).
*/
bool has_proxy_option() const;
/*!
* \brief verifies given password is correct for default wallet keys file
*/
@@ -1001,7 +1007,8 @@ private:
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
bool set_daemon(std::string daemon_address = "http://localhost:8080",
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true,
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect,
const std::string &proxy = "");
bool set_proxy(const std::string &address);
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
@@ -1834,6 +1841,7 @@ private:
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
std::string m_daemon_address;
std::string m_proxy;
std::string m_wallet_file;
std::string m_keys_file;
std::string m_mms_file;

View File

@@ -3465,7 +3465,7 @@ namespace tools
if (!wal)
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
er.message = "Failed to open wallet";
er.message = "Failed to open wallet : " + (!er.message.empty() ? er.message : "Unknown.");
return false;
}
@@ -4438,6 +4438,13 @@ namespace tools
return false;
}
if (m_wallet->has_proxy_option() && !req.proxy.empty())
{
er.code = WALLET_RPC_ERROR_CODE_PROXY_ALREADY_DEFINED;
er.message = "It is not possible to set daemon specific proxy when --proxy is defined.";
return false;
}
std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints;
ssl_allowed_fingerprints.reserve(req.ssl_allowed_fingerprints.size());
for (const std::string &fp: req.ssl_allowed_fingerprints)
@@ -4480,7 +4487,7 @@ namespace tools
if (!req.username.empty() || !req.password.empty())
daemon_login.emplace(req.username, req.password);
if (!m_wallet->set_daemon(req.address, daemon_login, req.trusted, std::move(ssl_options)))
if (!m_wallet->set_daemon(req.address, daemon_login, req.trusted, std::move(ssl_options), req.proxy))
{
er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
er.message = std::string("Unable to set daemon");

View File

@@ -2598,6 +2598,7 @@ namespace wallet_rpc
std::string ssl_ca_file;
std::vector<std::string> ssl_allowed_fingerprints;
bool ssl_allow_any_cert;
std::string proxy;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
@@ -2610,6 +2611,7 @@ namespace wallet_rpc
KV_SERIALIZE(ssl_ca_file)
KV_SERIALIZE(ssl_allowed_fingerprints)
KV_SERIALIZE_OPT(ssl_allow_any_cert, false)
KV_SERIALIZE_OPT(proxy, (std::string)"")
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;

View File

@@ -0,0 +1,17 @@
# magicfolk
255.255.255.0 # Saruman the White
128.128.128.0 # Gandalf the Gray
150.75.0.0 # Radagast the Brown
99.98.0.0/16 # All of Misty Mountain
# personal enemies
1.2.3.4 # this woman used to give me swirlies
6.7.8.9 # I just don't like the cut of his jib
1.0.0.7#Literally James Bond, he wrecked my aston martin
100.98.1.13 # Earl from HOA
100.98.1.0/24 #The rest of the HOA for good measure
#
#7.7.7.7
#^^^We're chill now, she's truly an angel

View File

@@ -29,8 +29,11 @@
#include <cstdint>
#include <gtest/gtest.h>
#include <vector>
#include "serialization/keyvalue_serialization.h"
#include "storages/portable_storage.h"
#include "storages/portable_storage_template_helper.h"
#include "span.h"
TEST(epee_binary, two_keys)
@@ -54,3 +57,68 @@ TEST(epee_binary, duplicate_key)
epee::serialization::portable_storage storage{};
EXPECT_FALSE(storage.load_from_binary(data));
}
namespace
{
template<typename t_param>
struct ParentObjWithOptChild
{
t_param params;
ParentObjWithOptChild(): params{} {}
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(params)
END_KV_SERIALIZE_MAP()
};
struct ObjWithOptChild
{
bool test_value;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(test_value, true);
END_KV_SERIALIZE_MAP()
};
}
TEST(epee_binary, serialize_deserialize)
{
ParentObjWithOptChild<ObjWithOptChild> o;
std::string o_json;
o.params.test_value = true;
EXPECT_TRUE(epee::serialization::store_t_to_json(o, o_json));
EXPECT_TRUE(o.params.test_value);
EXPECT_TRUE(epee::serialization::load_t_from_json(o, o_json));
EXPECT_TRUE(o.params.test_value);
ParentObjWithOptChild<ObjWithOptChild> o2;
std::string o2_json;
o.params.test_value = false;
EXPECT_TRUE(epee::serialization::store_t_to_json(o2, o2_json));
EXPECT_FALSE(o2.params.test_value);
EXPECT_TRUE(epee::serialization::load_t_from_json(o2, o2_json));
EXPECT_FALSE(o2.params.test_value);
// compiler sets default value of test_value to false
ParentObjWithOptChild<ObjWithOptChild> o3;
std::string o3_json;
EXPECT_TRUE(epee::serialization::store_t_to_json(o3, o3_json));
EXPECT_FALSE(o3.params.test_value);
EXPECT_TRUE(epee::serialization::load_t_from_json(o3, o3_json));
EXPECT_FALSE(o3.params.test_value);
// test optional field default initialization.
ParentObjWithOptChild<ObjWithOptChild> o4;
std::string o4_json = "{\"params\": {}}";
EXPECT_TRUE(epee::serialization::load_t_from_json(o4, o4_json));
EXPECT_TRUE(o4.params.test_value);
}

View File

@@ -35,6 +35,7 @@
#include "cryptonote_core/i_core_events.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.inl"
#include "unit_tests_utils.h"
#include <condition_variable>
#define MAKE_IPV4_ADDRESS(a,b,c,d) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),0}
@@ -114,6 +115,18 @@ static bool is_blocked(Server &server, const epee::net_utils::network_address &a
return true;
}
}
if (address.get_type_id() != epee::net_utils::address_type::ipv4)
return false;
const epee::net_utils::ipv4_network_address ipv4_address = address.as<epee::net_utils::ipv4_network_address>();
// check if in a blocked ipv4 subnet
const std::map<epee::net_utils::ipv4_network_subnet, time_t> subnets = server.get_blocked_subnets();
for (const auto &subnet : subnets)
if (subnet.first.matches(ipv4_address))
return true;
return false;
}
@@ -266,6 +279,78 @@ TEST(ban, ignores_port)
ASSERT_FALSE(is_blocked(server,MAKE_IPV4_ADDRESS_PORT(1,2,3,4,6)));
}
TEST(ban, file_banlist)
{
test_core pr_core;
cryptonote::t_cryptonote_protocol_handler<test_core> cprotocol(pr_core, NULL);
Server server(cprotocol);
cprotocol.set_p2p_endpoint(&server);
auto create_node_dir = [](){
boost::system::error_code ec;
auto path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("daemon-%%%%%%%%%%%%%%%%", ec);
if (ec)
return boost::filesystem::path{};
auto success = boost::filesystem::create_directory(path, ec);
if (!ec && success)
return path;
return boost::filesystem::path{};
};
const auto node_dir = create_node_dir();
ASSERT_TRUE(!node_dir.empty());
auto auto_remove_node_dir = epee::misc_utils::create_scope_leave_handler([&node_dir](){
boost::filesystem::remove_all(node_dir);
});
boost::program_options::variables_map vm;
boost::program_options::store(
boost::program_options::command_line_parser({
"--data-dir",
node_dir.string(),
"--ban-list",
(unit_test::data_dir / "node" / "banlist_1.txt").string()
}).options([]{
boost::program_options::options_description options_description{};
cryptonote::core::init_options(options_description);
Server::init_options(options_description);
return options_description;
}()).run(),
vm
);
ASSERT_TRUE(server.init(vm));
// Test cases (look in the banlist_1.txt file)
// magicfolk
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(255,255,255,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(128,128,128,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(150,75,0,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,0,255,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,1,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,98,255,255,9999)) );
EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(99,99,0,0,9999)) );
// personal enemies
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,2,3,4,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(6,7,8,9,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(1,0,0,7,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,13,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,0,9999)) );
EXPECT_TRUE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,1,255,9999)) );
EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,2,0,9999)) );
EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(100,98,0,255,9999)) );
// angel
EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(007,007,007,007,9999)) );
// random IP
EXPECT_FALSE( is_blocked(server, MAKE_IPV4_ADDRESS_PORT(145,036,205,235,9999)) );
}
TEST(node_server, bind_same_p2p_port)
{
struct test_data_t