Eliminate most << output operators

Replace (nearly) everything with fmt formatting.  Some crap in wallet2
remains that I'm not going to bother with.
This commit is contained in:
Jason Rhinelander 2022-10-07 23:30:29 -03:00
parent c4f4bfc87e
commit 463590ad5c
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262
58 changed files with 804 additions and 827 deletions

View File

@ -215,18 +215,6 @@ POP_WARNINGS
trim(str);
return str;
}
//----------------------------------------------------------------------------
inline std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false)
{
if (s.size() < n)
{
if (prepend)
s = std::string(n - s.size(), c) + s;
else
s.append(n - s.size(), c);
}
return s;
}
}
}
#endif //_STRING_TOOLS_H_

View File

@ -41,6 +41,7 @@
#include "cryptonote_basic/hardfork.h"
#include "epee/string_tools.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/pruning.h"
#include "common/hex.h"
#include "common/median.h"

View File

@ -31,7 +31,6 @@
#include <sodium.h>
#include <fmt/core.h>
#include <iostream>
#include <cassert>
#include "cryptonote_config.h"

View File

@ -39,7 +39,7 @@
#include "common/command_line.h"
#include "common/varint.h"
#include "common/signal_handler.h"
#include "common/fs.h"
#include "common/fs-format.h"
#include "serialization/boost_std_variant.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_core/cryptonote_core.h"

View File

@ -36,6 +36,7 @@
#include "common/string_util.h"
#include "common/varint.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/signal_handler.h"
#include "common/hex.h"
#include "serialization/crypto.h"

View File

@ -29,6 +29,7 @@
#include "common/command_line.h"
#include "common/varint.h"
#include "common/median.h"
#include "common/fs-format.h"
#include "cryptonote_core/cryptonote_core.h"
#include "blockchain_objects.h"
#include "blockchain_db/blockchain_db.h"

View File

@ -30,6 +30,7 @@
#include "bootstrap_file.h"
#include "blocksdat_file.h"
#include "common/command_line.h"
#include "common/fs-format.h"
#include "cryptonote_core/cryptonote_core.h"
#include "blockchain_objects.h"
#include "version.h"

View File

@ -45,6 +45,7 @@
#include "cryptonote_core/uptime_proof.h"
#include "cryptonote_core/cryptonote_core.h"
#include "common/hex.h"
#include "common/fs-format.h"
#include <fmt/color.h>
namespace

View File

@ -31,6 +31,7 @@
#include "common/command_line.h"
#include "common/varint.h"
#include "common/signal_handler.h"
#include "common/fs-format.h"
#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_core/cryptonote_core.h"
#include "blockchain_objects.h"

View File

@ -29,6 +29,7 @@
#include "common/command_line.h"
#include "common/varint.h"
#include "common/fs-format.h"
#include "cryptonote_core/cryptonote_core.h"
#include "blockchain_objects.h"
#include "blockchain_db/blockchain_db.h"

View File

@ -28,6 +28,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "blocksdat_file.h"
#include "common/fs-format.h"
using namespace cryptonote;

View File

@ -32,7 +32,7 @@
#include "bootstrap_file.h"
namespace po = boost::program_options;
#include "common/fs-format.h"
using namespace cryptonote;

View File

@ -41,6 +41,7 @@
#include "common/oxen.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/hex.h"
namespace cryptonote

View File

@ -64,6 +64,7 @@ target_link_libraries(common
cncrypto
oxenmq::oxenmq
filesystem
oxen::logging
fmt::fmt
date::date
PRIVATE

View File

@ -31,7 +31,6 @@
#pragma once
#include <functional>
#include <sstream>
#include <array>
#include <type_traits>

View File

@ -30,6 +30,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
//
#include "file.h"
#include "fs-format.h"
#include "logging/oxen_logger.h"
#include <unistd.h>
#include <cstdio>

View File

@ -1,3 +1,5 @@
#pragma once
#include <fmt/format.h>
#include <string_view>
#include <type_traits>
@ -31,6 +33,11 @@ namespace formattable {
template <typename T, typename SFINAE = void>
constexpr bool via_to_string = false;
// Same as above, but looks for a to_hex_string() instead of to_string(), for types that get
// dumped as hex.
template <typename T, typename SFINAE = void>
constexpr bool via_to_hex_string = false;
// Scoped enums can alternatively be formatted as their underlying integer value by specializing
// this function to true:
template <typename T, typename SFINAE = void>
@ -40,12 +47,19 @@ namespace formattable {
template <typename T, typename SFINAE = void>
constexpr bool has_to_string_method = false;
template <typename T, typename SFINAE = void>
constexpr bool has_to_hex_string_method = false;
template <typename T>
inline constexpr bool has_to_string_method<T,
std::void_t<decltype(std::declval<const T&>().to_string())>
> = true;
template <typename T>
inline constexpr bool has_to_hex_string_method<T,
std::void_t<decltype(std::declval<const T&>().to_hex_string())>
> = true;
} // namespace detail
} // namespace formattable
@ -70,6 +84,22 @@ namespace fmt {
}
}
};
template <typename T, typename Char>
struct formatter<T, Char, std::enable_if_t<::formattable::via_to_hex_string<T>>>
: formatter<std::string_view>
{
template <typename FormatContext>
auto format(const T& val, FormatContext& ctx) const {
if constexpr (::formattable::detail::has_to_hex_string_method<T>)
return formatter<std::string_view>::format(val.to_hex_string(), ctx);
else {
using namespace formattable;
return formatter<std::string_view>::format(to_hex_string(val), ctx);
}
}
};
template <typename T, typename Char>
struct formatter<T, Char, std::enable_if_t<::formattable::via_underlying<T>>>

View File

@ -20,16 +20,7 @@ namespace fs {
#else
#include <ghc/filesystem.hpp>
#include "formattable.h"
namespace fs = ghc::filesystem;
namespace formattable {
template <> inline constexpr bool via_to_string<ghc::filesystem::path> = true;
inline std::string to_string(const ghc::filesystem::path& path) {
return path.string();
}
}
#endif

View File

@ -5,18 +5,26 @@ namespace tools {
static auto logcat = log::Cat("msgwriter");
scoped_message_writer& scoped_message_writer::flush()
{
if (!m_content.empty())
{
logcat->log(m_log_level, "{}{}", m_prefix, m_content);
if (m_color) {
rdln::suspend_readline pause_readline;
fmt::print(fg(*m_color), "{}{}\n", m_prefix, m_content);
}
else
fmt::print("{}{}\n", m_prefix, m_content);
m_content.clear();
}
return *this;
}
scoped_message_writer::~scoped_message_writer()
{
if (m_flush)
{
m_flush = false;
if (fmt::terminal_color::white == m_color)
logcat->log(m_log_level, m_oss.str());
else
logcat->log(m_log_level, "{}",
log::detail::text_style_wrapper{fg(m_color), "{}", m_oss.str()});
std::cout << std::endl;
}
flush();
}
}

View File

@ -43,59 +43,116 @@ namespace tools
class scoped_message_writer
{
private:
bool m_flush;
std::ostringstream m_oss;
fmt::terminal_color m_color;
std::string m_prefix;
std::string m_content;
std::optional<fmt::terminal_color> m_color;
oxen::log::Level m_log_level;
public:
scoped_message_writer(
fmt::terminal_color color = fmt::terminal_color::white
, std::string prefix = {}
, spdlog::level::level_enum log_level = spdlog::level::info
)
: m_flush(true)
, m_color(color)
, m_log_level(log_level)
explicit scoped_message_writer(
std::optional<fmt::terminal_color> color = std::nullopt,
std::string prefix = "",
log::Level log_level = log::Level::info
)
: m_color{color}, m_log_level{log_level}, m_prefix{std::move(prefix)}
{}
scoped_message_writer(scoped_message_writer&& o)
: m_prefix{std::move(o.m_prefix)},
m_content{std::move(o.m_content)},
m_color{o.m_color},
m_log_level{o.m_log_level}
{
m_oss << prefix;
o.m_content.clear();
}
scoped_message_writer(scoped_message_writer&& rhs)
: m_flush(std::move(rhs.m_flush))
, m_oss(std::move(rhs.m_oss))
, m_color(std::move(rhs.m_color))
, m_log_level(std::move(rhs.m_log_level))
{
rhs.m_flush = false;
}
scoped_message_writer(scoped_message_writer& rhs) = delete;
scoped_message_writer& operator=(scoped_message_writer& rhs) = delete;
scoped_message_writer(const scoped_message_writer& rhs) = delete;
scoped_message_writer& operator=(const scoped_message_writer& rhs) = delete;
scoped_message_writer& operator=(scoped_message_writer&& rhs) = delete;
template<typename T>
std::ostream& operator<<(const T& val)
/// Appends a message and returns *this (so that it can be chained). If called with more than 1
/// argument then the first argument is fmt::format'ed with the remaining arguments.
template <typename... T>
scoped_message_writer& append(std::string_view msg, T&&... args)
{
m_oss << val;
return m_oss;
if constexpr (sizeof...(T))
fmt::format_to(std::back_inserter(m_content), msg, std::forward<T>(args)...);
else
m_content.append(msg);
return *this;
}
/// Same as .append(msg). (Doesn't format, just like the single-argument .append(msg)).
scoped_message_writer& operator+=(std::string_view msg) { return append(msg); }
/// Essentially the same as +=, but can only be used on an rvalue instance of the object, so that
/// you can do things like: `scoped_message_writer{} + "abc"`, which feels more natural than
/// `scoped_message_writer{} += "abc"`.
scoped_message_writer&& operator+(std::string_view msg) && { append(msg); return std::move(*this); }
/// Flushes the current message to output and resets it. This is normally not called explicitly
/// but rather implicitly when the object is destroyed.
scoped_message_writer& flush();
/// Prints the complete message on destruction.
~scoped_message_writer();
};
inline scoped_message_writer success_msg_writer(bool color = true)
template <typename... T>
scoped_message_writer msg_writer(std::optional<fmt::terminal_color> color = std::nullopt, T&&... args)
{
return scoped_message_writer(color ? fmt::terminal_color::green : fmt::terminal_color::white, std::string(), spdlog::level::info);
scoped_message_writer writer{color};
if constexpr (sizeof...(T))
writer.append(std::forward<T>(args)...);
return writer;
}
inline scoped_message_writer msg_writer(fmt::terminal_color color = fmt::terminal_color::white)
template <typename... T>
scoped_message_writer msg_writer(std::string_view msg, T&&... args)
{
return scoped_message_writer(color, std::string(), spdlog::level::info);
return msg_writer(std::nullopt, msg, std::forward<T>(args)...);
}
inline scoped_message_writer fail_msg_writer()
constexpr std::optional<fmt::terminal_color> success_color{fmt::terminal_color::green};
constexpr std::optional<fmt::terminal_color> fail_color{fmt::terminal_color::red};
/// Constructs and returns a scoped_message_writer for a typical success message, with or without
/// color, as specified by the first argument. If additional arguments are provided they will be
/// passed to append(...) to set a message (or formatted message, if multiple arguments are given).
///
/// (We deduce the Bool argument here to avoid implicit conversion to bool from non-bool values).
template <typename Bool, typename... T, std::enable_if_t<std::is_same_v<Bool, bool>, int> = 0>
scoped_message_writer success_msg_writer(Bool color, T&&... args)
{
return scoped_message_writer(fmt::terminal_color::red, "Error: ", spdlog::level::err);
auto writer = msg_writer(color ? success_color : std::nullopt);
if constexpr (sizeof...(T))
writer.append(std::forward<T>(args)...);
return writer;
}
inline scoped_message_writer success_msg_writer()
{
return success_msg_writer(true);
}
/// Same as above, but for calling without just a message (with a bool). Color will be true.
template <typename... T>
scoped_message_writer success_msg_writer(std::string_view msg, T&&... args)
{
return success_msg_writer(true, msg, std::forward<T>(args)...);
}
/// Constructs and returns a scoped_message_writer for a typical error message. Color will be
/// enabled and the message will be prefixed with "Error: ". Given arguments, if any, are passed to
/// .append() and so can specify either a single unformatted string, or a format string + format
/// arguments.
template <typename... T>
scoped_message_writer fail_msg_writer(T&&... args)
{
scoped_message_writer writer{fail_color, "Error: ", spdlog::level::err};
if constexpr (sizeof...(T))
writer.append(std::forward<T>(args)...);
return writer;
}
} // namespace tools

View File

@ -1,7 +1,6 @@
#include "string_util.h"
#include <fmt/core.h>
#include <cassert>
#include <iomanip>
#include <sstream>
namespace tools {
@ -80,66 +79,39 @@ std::string lowercase_ascii_string(std::string_view src)
}
std::string friendly_duration(std::chrono::nanoseconds dur) {
std::ostringstream os;
std::string friendly;
auto append = std::back_inserter(friendly);
bool some = false;
if (dur >= 24h) {
os << dur / 24h << 'd';
fmt::format_to(append, "{}d", dur / 24h);
dur %= 24h;
some = true;
}
if (dur >= 1h || some) {
os << dur / 1h << 'h';
fmt::format_to(append, "{}h", dur / 1h);
dur %= 1h;
some = true;
}
if (dur >= 1min || some) {
os << dur / 1min << 'm';
fmt::format_to(append, "{}m", dur / 1min);
dur %= 1min;
some = true;
}
if (some || dur == 0s) {
// If we have >= minutes or its exactly 0 seconds then don't bother with fractional seconds
os << dur / 1s << 's';
fmt::format_to(append, "{}s", dur / 1s);
} else {
double seconds = std::chrono::duration<double>(dur).count();
os.precision(3);
if (dur >= 1s)
os << seconds << "s";
fmt::format_to(append, "{:.3f}s", seconds);
else if (dur >= 1ms)
os << seconds * 1000 << "ms";
fmt::format_to(append, "{:.3f}ms", seconds * 1000);
else if (dur >= 1us)
os << seconds * 1'000'000 << u8"µs";
fmt::format_to(append, "{:.3f}µs", seconds * 1'000'000);
else
os << seconds * 1'000'000'000 << "ns";
fmt::format_to(append, "{:.0f}ns", seconds * 1'000'000'000);
}
return os.str();
return friendly;
}
std::string short_duration(std::chrono::duration<double> dur) {
std::ostringstream os;
os << std::fixed << std::setprecision(1);
if (dur >= 36h)
os << dur / 24h;
else if (dur >= 90min)
os << dur / 1h;
else if (dur >= 90s)
os << dur / 1min;
else if (dur >= 1s)
os << dur / 1s;
else if (dur >= 100ms)
os << std::setprecision(0) << dur / 1ms;
else if (dur >= 1ms)
os << dur / 1ms;
else if (dur >= 100us)
os << std::setprecision(0) << dur / 1us;
else if (dur >= 1us)
os << dur / 1us;
else if (dur >= 1ns)
os << std::setprecision(0) << dur / 1ns;
else
os << "0s";
return os.str();
}
}

View File

@ -4,9 +4,9 @@
#include <cstring>
#include <iterator>
#include <charconv>
#include <sstream>
#include <chrono>
#include <cassert>
#include <fmt/format.h>
#include "epee/span.h" // epee
namespace tools {
@ -60,30 +60,28 @@ std::vector<std::string_view> split(std::string_view str, std::string_view delim
std::vector<std::string_view> split_any(std::string_view str, std::string_view delims, bool trim = false);
/// Joins [begin, end) with a delimiter and returns the resulting string. Elements can be anything
/// that can be sent to an ostream via `<<`.
/// that can be formatted. Semi-deprecated: this just uses fmt to join.
template <typename It>
std::string join(std::string_view delimiter, It begin, It end) {
std::ostringstream o;
if (begin != end)
o << *begin++;
while (begin != end)
o << delimiter << *begin++;
return o.str();
return fmt::format("{}", fmt::join(begin, end, delimiter));
}
/// Wrapper around the above that takes a container and passes c.begin(), c.end() to the above.
/// Same as the above, but works on a container. Just use fmt::join.
template <typename Container>
std::string join(std::string_view delimiter, const Container& c) { return join(delimiter, c.begin(), c.end()); }
std::string join(std::string_view delimiter, const Container& c) {
return fmt::format("{}", fmt::join(c, delimiter));
}
/// Similar to join(), but first applies a transformation to each element.
template <typename It, typename UnaryOperation>
std::string join_transform(std::string_view delimiter, It begin, It end, UnaryOperation transform) {
std::ostringstream o;
std::string result;
auto append = std::back_inserter(result);
if (begin != end)
o << transform(*begin++);
result = fmt::format("{}", transform(*begin++));
while (begin != end)
o << delimiter << transform(*begin++);
return o.str();
fmt::format_to(append, "{}{}", delimiter, transform(*begin++));
return result;
}
/// Wrapper around the above that takes a container and passes c.begin(), c.end().
@ -92,22 +90,23 @@ std::string join_transform(std::string_view delimiter, const Container& c, Unary
return join_transform(delimiter, c.begin(), c.end(), std::forward<UnaryOperation>(transform));
}
/// Concatenates a bunch of random values together with delim as a separator via << operator.
/// Concatenates a bunch of random values together with delim as a separator via fmt::format.
/// Returns the result as a string.
template <typename T, typename... Ts>
std::string join_stuff(std::string_view delim, T&& first, Ts&&... stuff) {
std::ostringstream o;
o << std::forward<T>(first);
((o << delim << std::forward<Ts>(stuff)), ...);
return o.str();
std::string result = fmt::format(std::forward<T>(first));
auto append = std::back_inserter(result);
(fmt::format_to(append, "{}{}", delim, std::forward<Ts>(stuff)), ...);
return result;
}
/// Concatenates arguments via << operator, returns as a string.
/// Concatenates arguments via fmt::format operator, returns as a string.
template <typename... T>
std::string concat(T&&... stuff) {
std::ostringstream o;
(o << ... << std::forward<T>(stuff));
return o.str();
std::string result;
auto append = std::back_inserter(result);
(fmt::format_to(append, "{}", std::forward<T>(stuff)), ...);
return result;
}
/// Simple version of whitespace trimming: mutates the given string view to remove leading

View File

@ -41,6 +41,8 @@
#include "epee/mlocker.h"
#include "generic-ops.h"
#include "common/hex.h"
#include "common/format.h"
#include "common/formattable.h"
#include "hash.h"
namespace crypto {
@ -284,27 +286,11 @@ namespace crypto {
const public_key& pub,
const signature& sig);
inline std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::secret_key &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::key_derivation &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::key_image &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::signature &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::ed25519_public_key &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::x25519_public_key &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::string to_string(const ec_point& P) { return "<{}>"_format(tools::type_to_hex(P)); }
inline std::string to_string(const signature& s) { return "<{}>"_format(tools::type_to_hex(s)); }
inline std::string to_string(const ed25519_public_key& P) { return "<{}>"_format(tools::type_to_hex(P)); }
inline std::string to_string(const x25519_public_key& P) { return "<{}>"_format(tools::type_to_hex(P)); }
constexpr inline crypto::public_key null_pkey{};
const inline crypto::secret_key null_skey{};
}
@ -315,3 +301,8 @@ CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_HASHABLE(signature)
CRYPTO_MAKE_HASHABLE(ed25519_public_key)
CRYPTO_MAKE_HASHABLE(x25519_public_key)
template <> inline constexpr bool formattable::via_to_string<crypto::ec_point> = true;
template <> inline constexpr bool formattable::via_to_string<crypto::signature> = true;
template <> inline constexpr bool formattable::via_to_string<crypto::ed25519_public_key> = true;
template <> inline constexpr bool formattable::via_to_string<crypto::x25519_public_key> = true;

View File

@ -1,38 +0,0 @@
#pragma once
#include <fmt/format.h>
#include "common/format.h"
#include "crypto.h"
#include "hash.h"
namespace crypto {
template <typename T, typename SFINAE = void>
constexpr bool is_hex_printable = false;
template <typename T>
constexpr bool is_hex_printable<T, std::enable_if_t<std::is_base_of_v<ec_point, T> && sizeof(T) == sizeof(ec_point)>> = true;
template <> inline constexpr bool is_hex_printable<signature> = true;
template <> inline constexpr bool is_hex_printable<ed25519_public_key> = true;
template <> inline constexpr bool is_hex_printable<x25519_public_key> = true;
template <> inline constexpr bool is_hex_printable<hash> = true;
template <> inline constexpr bool is_hex_printable<hash8> = true;
template <typename T> inline constexpr bool is_hex_printable<T&> = is_hex_printable<T>;
template <typename T> inline constexpr bool is_hex_printable<T&&> = is_hex_printable<T>;
template <typename T> inline constexpr bool is_hex_printable<const T> = is_hex_printable<T>;
// Helper for when you are really sure you want to print a secret key (which is not printable by
// default so that you have to be explicit and can't accidentally expose one in a log
// statement).
inline std::string expose_secret(const ec_scalar& secret) {
return "<{}>"_format(tools::type_to_hex(secret));
}
}
template <typename T, typename Char>
struct fmt::formatter<T, Char, std::enable_if_t<crypto::is_hex_printable<T>>> : fmt::formatter<std::string> {
auto format(const T& v, format_context& ctx) {
return formatter<std::string>::format("<{}>"_format(tools::type_to_hex(v)), ctx);
}
};

View File

@ -35,6 +35,8 @@
#include "generic-ops.h"
#include "common/hex.h"
#include "common/formattable.h"
#include "common/format.h"
#include "crypto/cn_heavy_hash.hpp"
namespace crypto {
@ -156,12 +158,9 @@ namespace crypto {
return c;
}
inline std::ostream &operator <<(std::ostream &o, const crypto::hash &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::ostream &operator <<(std::ostream &o, const crypto::hash8 &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
inline std::string to_hex_string(const crypto::hash& h) { return "<{}>"_format(tools::type_to_hex(h)); }
inline std::string to_hex_string(const crypto::hash8& h) { return "<{}>"_format(tools::type_to_hex(h)); }
constexpr inline crypto::hash null_hash = {};
constexpr inline crypto::hash8 null_hash8 = {};
@ -169,3 +168,6 @@ namespace crypto {
CRYPTO_MAKE_HASHABLE(hash)
CRYPTO_MAKE_COMPARABLE(hash8)
template <> inline constexpr bool formattable::via_to_hex_string<crypto::hash> = true;
template <> inline constexpr bool formattable::via_to_hex_string<crypto::hash8> = true;

View File

@ -31,7 +31,6 @@
#pragma once
#include <vector>
#include <sstream>
#include <atomic>
#include "serialization/variant.h"
#include "serialization/vector.h"
@ -176,9 +175,6 @@ namespace cryptonote
{
public:
static char const* version_to_string(txversion v);
static char const* type_to_string(txtype type);
static constexpr txversion get_min_version_for_hf(hf hf_version);
static txversion get_max_version_for_hf(hf hf_version);
static constexpr txtype get_max_type_for_hf (hf hf_version);
@ -560,42 +556,6 @@ namespace cryptonote
return result;
}
inline const char* transaction_prefix::version_to_string(txversion v)
{
switch(v)
{
case txversion::v1: return "1";
case txversion::v2_ringct: return "2_ringct";
case txversion::v3_per_output_unlock_times: return "3_per_output_unlock_times";
case txversion::v4_tx_types: return "4_tx_types";
default: assert(false); return "xx_unhandled_version";
}
}
inline const char* transaction_prefix::type_to_string(txtype type)
{
switch(type)
{
case txtype::standard: return "standard";
case txtype::state_change: return "state_change";
case txtype::key_image_unlock: return "key_image_unlock";
case txtype::stake: return "stake";
case txtype::oxen_name_system: return "oxen_name_system";
default: assert(false); return "xx_unhandled_type";
}
}
inline std::ostream& operator<<(std::ostream& os, txtype t) {
return os << transaction::type_to_string(t);
}
inline std::ostream& operator<<(std::ostream& os, txversion v) {
return os << transaction::version_to_string(v);
}
inline std::ostream& operator<<(std::ostream& os, hf v) = delete;/*{
return os << "HF" << static_cast<int>(v);
}*/
// Serialization for the `hf` type; this is simply writing/reading the underlying uint8_t value
template <class Archive>
void serialize_value(Archive& ar, hf& x) {
@ -606,21 +566,6 @@ namespace cryptonote
}
}
template <>
struct fmt::formatter<cryptonote::txtype> : fmt::formatter<std::string_view> {
auto format(cryptonote::txtype t, format_context& ctx) {
return formatter<std::string_view>::format(
cryptonote::transaction::type_to_string(t), ctx);
}
};
template <>
struct fmt::formatter<cryptonote::txversion> : fmt::formatter<std::string_view> {
auto format(cryptonote::txversion v, format_context& ctx) {
return formatter<std::string_view>::format(
cryptonote::transaction::version_to_string(v), ctx);
}
};
namespace std {
template <>
struct hash<cryptonote::account_public_address>
@ -648,3 +593,5 @@ VARIANT_TAG(cryptonote::txout_to_scripthash, "scripthash", 0x1);
VARIANT_TAG(cryptonote::txout_to_key, "key", 0x2);
VARIANT_TAG(cryptonote::transaction, "tx", 0xcc);
VARIANT_TAG(cryptonote::block, "block", 0xbb);
template <> inline constexpr bool formattable::via_to_string<cryptonote::transaction> = true;

View File

@ -46,7 +46,6 @@
#include "cryptonote_config.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "crypto/fmt.h"
#include "ringct/rctSigs.h"
#include "cryptonote_basic/verification_context.h"
#include "cryptonote_core/service_node_voting.h"
@ -269,7 +268,7 @@ namespace cryptonote
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
if (!r)
{
log::warning(logcat, "key image helper: failed to generate_key_derivation({}, <{}>)", tx_public_key, expose_secret(ack.m_view_secret_key));
log::warning(logcat, "key image helper: failed to generate_key_derivation({}, <{}>)", tx_public_key, tools::type_to_hex(ack.m_view_secret_key));
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
}
@ -280,7 +279,7 @@ namespace cryptonote
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
if (!r)
{
log::warning(logcat, "key image helper: failed to generate_key_derivation({}, {})", additional_tx_public_keys[i], expose_secret(ack.m_view_secret_key));
log::warning(logcat, "key image helper: failed to generate_key_derivation({}, {})", additional_tx_public_keys[i], tools::type_to_hex(ack.m_view_secret_key));
}
else
{
@ -902,13 +901,13 @@ namespace cryptonote
{
if (!tx.is_transfer() && tx.vout.size() != 0)
{
log::warning(logcat, "tx type: {} must have 0 outputs, received: {}, id={}", transaction::type_to_string(tx.type), tx.vout.size(), get_transaction_hash(tx));
log::warning(logcat, "tx type: {} must have 0 outputs, received: {}, id={}", tx.type, tx.vout.size(), get_transaction_hash(tx));
return false;
}
if (tx.version >= txversion::v3_per_output_unlock_times && tx.vout.size() != tx.output_unlock_times.size())
{
log::warning(logcat, "tx version: {} must have equal number of output unlock times and outputs", transaction::version_to_string(tx.version));
log::warning(logcat, "tx version: {} must have equal number of output unlock times and outputs", tx.version);
return false;
}
@ -1104,7 +1103,7 @@ namespace cryptonote
if (tvc.m_key_image_blacklisted) os << "Key image is blacklisted on the service node network, ";
if (tx)
os << "TX Version: " << tx->version << ", Type: " << tx->type;
os << "TX Version: {}, Type: {}"_format(tx->version, tx->type);
std::string buf = os.str();
if (buf.size() >= 2 && buf[buf.size() - 2] == ',')

View File

@ -248,12 +248,10 @@ namespace cryptonote
bool is_valid_address(const std::string address, cryptonote::network_type nettype, bool allow_subaddress = true, bool allow_integrated = true);
inline std::ostream &operator<<(std::ostream &stream, transaction const &tx)
inline std::string to_string(const transaction& tx)
{
stream << "tx={version=" << tx.version << ", type=" << tx.type << ", hash=" << get_transaction_hash(tx) << "}";
return stream;
return "tx={{version={}, type={}, hash={}}}"_format(tx.version, tx.type, get_transaction_hash(tx));
}
//---------------------------------------------------------------
template <typename T>
bool t_serializable_object_from_blob(T& to, const std::string& blob)

View File

@ -34,6 +34,8 @@
#include <ostream>
#include "common/oxen.h"
#include "common/formattable.h"
#include "common/format.h"
namespace cryptonote
{
@ -48,7 +50,7 @@ namespace cryptonote
std::string to_string() const
{
return std::to_string(major) + '/' + std::to_string(minor);
return "{}/{}"_format(major, minor);
}
BEGIN_KV_SERIALIZE_MAP()
@ -62,14 +64,10 @@ namespace cryptonote
field(ar, "major", x.major);
field(ar, "minor", x.minor);
}
inline std::ostream& operator<<(std::ostream& out, const cryptonote::subaddress_index& subaddr_index)
{
return out << subaddr_index.major << '/' << subaddr_index.minor;
}
}
template <> inline constexpr bool formattable::via_to_string<cryptonote::subaddress_index> = true;
namespace std
{
template <>

View File

@ -113,6 +113,7 @@ struct alignas(size_t) generic_owner
std::string to_string(cryptonote::network_type nettype) const;
explicit operator bool() const { return (type == generic_owner_sig_type::monero) ? wallet.address != cryptonote::null_address : ed25519; }
bool operator==(generic_owner const &other) const;
bool operator!=(generic_owner const &other) const { return !(*this == other); }
BEGIN_SERIALIZE()
ENUM_FIELD(type, type < generic_owner_sig_type::_count)
@ -149,9 +150,6 @@ struct generic_signature
};
static_assert(sizeof(crypto::ed25519_signature) == sizeof(crypto::signature), "ONS allows storing either ed25519 or monero style signatures, we store all signatures into crypto::signature in ONS");
inline std::ostream &operator<<(std::ostream &o, const generic_signature &v) {
return o << '<' << tools::type_to_hex(v.data) << '>';
}
} // namespace ons

View File

@ -1,10 +1,15 @@
#pragma once
#include <cstdint>
#include <string_view>
#include <cassert>
#include "common/formattable.h"
namespace cryptonote {
enum class txversion : uint16_t {
using namespace std::literals;
enum class txversion : uint16_t {
v0 = 0,
v1,
v2_ringct,
@ -21,4 +26,31 @@ enum class txversion : uint16_t {
_count
};
inline constexpr std::string_view to_string(txversion v) {
switch(v)
{
case txversion::v1: return "1"sv;
case txversion::v2_ringct: return "2_ringct"sv;
case txversion::v3_per_output_unlock_times: return "3_per_output_unlock_times"sv;
case txversion::v4_tx_types: return "4_tx_types"sv;
default: assert(false); return "xx_unhandled_version"sv;
}
}
inline constexpr std::string_view to_string(txtype type)
{
switch(type)
{
case txtype::standard: return "standard"sv;
case txtype::state_change: return "state_change"sv;
case txtype::key_image_unlock: return "key_image_unlock"sv;
case txtype::stake: return "stake"sv;
case txtype::oxen_name_system: return "oxen_name_system"sv;
default: assert(false); return "xx_unhandled_type"sv;
}
}
}
template <> inline constexpr bool formattable::via_to_string<cryptonote::txversion> = true;
template <> inline constexpr bool formattable::via_to_string<cryptonote::txtype> = true;

View File

@ -41,6 +41,7 @@
#include "common/hex.h"
#include "common/string_util.h"
#include "common/median.h"
#include "common/fs-format.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "cryptonote_basic/hardfork.h"

View File

@ -34,7 +34,6 @@
#include "epee/string_tools.h"
#include <unordered_set>
#include <sstream>
#include <iomanip>
#include <oxenc/base32z.h>
@ -50,6 +49,7 @@ extern "C" {
#include "cryptonote_core.h"
#include "uptime_proof.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/sha256sum.h"
#include "common/threadpool.h"
#include "common/command_line.h"
@ -1488,11 +1488,11 @@ namespace cryptonote
}
else
{
std::ostringstream os;
os << "Blink validation failed:";
std::string blink_error = "Blink validation failed:";
auto append = std::back_inserter(blink_error);
for (auto &f : failures)
os << " [" << int(bdata.quorum[f.first]) << ":" << int(bdata.position[f.first]) << "]: " << f.second;
log::info(logcat, "Invalid blink tx {}: {}", bdata.tx_hash, os.str());
fmt::format_to(append, " [{}:{}]: {}", int(bdata.quorum[f.first]), int(bdata.position[f.first]), f.second);
log::info(logcat, "Invalid blink tx {}: {}", bdata.tx_hash, blink_error);
}
}

View File

@ -41,7 +41,6 @@
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "crypto/fmt.h"
#include "ringct/rctSigs.h"
#include "multisig/multisig.h"
#include "epee/int-util.h"

View File

@ -9,6 +9,7 @@
#include "common/oxen.h"
#include "common/string_util.h"
#include "common/fs-format.h"
#include "crypto/hash.h"
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/cryptonote_basic_impl.h"
@ -132,20 +133,18 @@ namespace {
std::string ons_extra_string(cryptonote::network_type nettype, cryptonote::tx_extra_oxen_name_system const &data)
{
std::stringstream stream;
stream << "ONS Extra={";
std::string extra = "ONS Extra={";
auto append = std::back_inserter(extra);
if (data.is_buying())
{
stream << "owner=" << data.owner.to_string(nettype);
stream << ", backup_owner=" << (data.backup_owner ? data.backup_owner.to_string(nettype) : "(none)");
}
fmt::format_to(append, "owner={}, backup_owner={}",
data.owner.to_string(nettype), (data.backup_owner ? data.backup_owner.to_string(nettype) : "(none)"));
else if (data.is_renewing())
stream << "renewal";
extra += "renewal";
else
stream << "signature=" << tools::type_to_hex(data.signature.data);
fmt::format_to(append, "signature={}", tools::type_to_hex(data.signature.data));
stream << ", type=" << data.type << ", name_hash=" << data.name_hash << "}";
return stream.str();
fmt::format_to(append, ", type={}, name_hash={}}}", data.type, data.name_hash);
return extra;
}
/// Clears any existing bindings
@ -742,13 +741,9 @@ static constexpr bool char_is_alphanum_or(char c)
static constexpr bool char_is_alphanum(char c) { return char_is_alphanum_or<>(c); }
template <typename... T>
static bool check_condition(bool condition, std::string* reason, T&&... args) {
static bool check_condition(bool condition, std::string* reason, std::string_view format, T&&... args) {
if (condition && reason)
{
std::ostringstream os;
(os << ... << std::forward<T>(args));
*reason = os.str();
}
*reason = fmt::format(format, std::forward<T>(args)...);
return condition;
}
@ -766,17 +761,15 @@ bool validate_ons_name(mapping_type type, std::string name, std::string *reason)
else
{
if (reason)
{
std::stringstream err_stream;
err_stream << "ONS type=" << mapping_type_str(type) << ", specifies unhandled mapping type in name validation";
*reason = err_stream.str();
}
*reason = "ONS type={} specifies unhandled mapping type in name validation"_format(type);
return false;
}
// NOTE: Validate name length
name = tools::lowercase_ascii_string(name);
if (check_condition((name.empty() || name.size() > max_name_len), reason, "ONS type=", type, ", specifies mapping from name->value where the name's length=", name.size(), " is 0 or exceeds the maximum length=", max_name_len, ", given name=", name))
if (check_condition((name.empty() || name.size() > max_name_len), reason,
"ONS type={} specifies mapping from name->value where the name's length={} is 0 or exceeds the maximum length={}, given name={}",
type, name.size(), max_name_len, name))
return false;
std::string_view name_view{name}; // Will chop this down as we validate each part
@ -796,41 +789,46 @@ bool validate_ons_name(mapping_type type, std::string name, std::string *reason)
// domains (in which case the user looking up "foo.loki" would try end up trying to resolve
// "foo.loki.loki").
for (auto& reserved : {"localhost.loki"sv, "loki.loki"sv, "snode.loki"sv})
if (check_condition(name == reserved, reason, "ONS type=", type, ", specifies mapping from name->value using protocol reserved name=", name))
if (check_condition(name == reserved, reason,
"ONS type={} specifies mapping from name->value using protocol reserved name={}", type, name))
return false;
auto constexpr SHORTEST_DOMAIN = "a.loki"sv;
if (check_condition(name.size() < SHORTEST_DOMAIN.size(), reason, "ONS type=", type, ", specifies mapping from name->value where the name is shorter than the shortest possible name=", SHORTEST_DOMAIN, ", given name=", name))
if (check_condition(name.size() < SHORTEST_DOMAIN.size(), reason,
"ONS type={} specifies mapping from name->value where the name is shorter than the shortest possible name={}, given name={}", type, SHORTEST_DOMAIN, name))
return false;
// Must end with .loki
auto constexpr SUFFIX = ".loki"sv;
if (check_condition(!tools::ends_with(name_view, SUFFIX), reason, "ONS type=", type, ", specifies mapping from name->value where the name does not end with the domain .loki, name=", name))
if (check_condition(!tools::ends_with(name_view, SUFFIX), reason,
"ONS type={} specifies mapping from name->value where the name does not end with the domain .loki, name={}", type, name))
return false;
name_view.remove_suffix(SUFFIX.size());
// All domains containing '--' as 3rd/4th letter are reserved except for xn-- punycode domains
if (check_condition(name_view.size() >= 4 && name_view.substr(2, 2) == "--"sv && !tools::starts_with(name_view, "xn--"sv),
reason, "ONS type=", type, ", specifies reserved name `?\?--*.loki': ", name))
reason, "ONS type={} specifies reserved name `?\?--*.loki': {}", type, name))
return false;
// Must start with alphanumeric
if (check_condition(!char_is_alphanum(name_view.front()), reason, "ONS type=", type, ", specifies mapping from name->value where the name does not start with an alphanumeric character, name=", name))
if (check_condition(!char_is_alphanum(name_view.front()), reason,
"ONS type={} specifies mapping from name->value where the name does not start with an alphanumeric character, name={}", type, name))
return false;
name_view.remove_prefix(1);
if (!name_view.empty()) {
// Character preceding .loki must be alphanumeric
if (check_condition(!char_is_alphanum(name_view.back()), reason, "ONS type=", type ,", specifies mapping from name->value where the character preceding the .loki is not alphanumeric, char=", name_view.back(), ", name=", name))
if (check_condition(!char_is_alphanum(name_view.back()), reason,
"ONS type={} specifies mapping from name->value where the character preceding the .loki is not alphanumeric, char={}, name={}", type, name_view.back(), name))
return false;
name_view.remove_suffix(1);
}
// Inbetween start and preceding suffix, (alphanumeric or hyphen) characters permitted
if (check_condition(!std::all_of(name_view.begin(), name_view.end(), char_is_alphanum_or<'-'>),
reason, "ONS type=", type, ", specifies mapping from name->value where the domain name contains more than the permitted alphanumeric or hyphen characters, name=", name))
reason, "ONS type={} specifies mapping from name->value where the domain name contains more than the permitted alphanumeric or hyphen characters, name={}", type, name))
return false;
}
else if (type == mapping_type::session || type == mapping_type::wallet)
@ -840,20 +838,22 @@ bool validate_ons_name(mapping_type type, std::string name, std::string *reason)
// ^[a-z0-9_]([a-z0-9-_]*[a-z0-9_])?$
// Must start with (alphanumeric or underscore)
if (check_condition(!char_is_alphanum_or<'_'>(name_view.front()), reason, "ONS type=", type, ", specifies mapping from name->value where the name does not start with an alphanumeric or underscore character, name=", name))
if (check_condition(!char_is_alphanum_or<'_'>(name_view.front()), reason,
"ONS type={} specifies mapping from name->value where the name does not start with an alphanumeric or underscore character, name={}", type, name))
return false;
name_view.remove_prefix(1);
if (!name_view.empty()) {
// Must NOT end with a hyphen '-'
if (check_condition(!char_is_alphanum_or<'_'>(name_view.back()), reason, "ONS type=", type, ", specifies mapping from name->value where the last character is a hyphen '-' which is disallowed, name=", name))
if (check_condition(!char_is_alphanum_or<'_'>(name_view.back()), reason,
"ONS type={} specifies mapping from name->value where the last character is a hyphen '-' which is disallowed, name={}", type, name))
return false;
name_view.remove_suffix(1);
}
// Inbetween start and preceding suffix, (alphanumeric, hyphen or underscore) characters permitted
if (check_condition(!std::all_of(name_view.begin(), name_view.end(), char_is_alphanum_or<'-', '_'>),
reason, "ONS type=", type, ", specifies mapping from name->value where the name contains more than the permitted alphanumeric, underscore or hyphen characters, name=", name))
reason, "ONS type={} specifies mapping from name->value where the name contains more than the permitted alphanumeric, underscore or hyphen characters, name={}", type, name))
return false;
}
else
@ -886,11 +886,8 @@ static bool check_lengths(mapping_type type, std::string_view value, size_t max,
{
if (reason)
{
std::stringstream err_stream;
err_stream << "ONS type=" << type << ", specifies mapping from name_hash->encrypted_value where the value's length=" << value.size() << ", does not equal the required length=" << max << ", given value=";
if (binary_val) err_stream << oxenc::to_hex(value);
else err_stream << value;
*reason = err_stream.str();
*reason = "ONS type={} specifies mapping from name_hash->encrypted_value where the value's length={} does not equal the required length={}, given value={}"_format(
type, value.size(), max, binary_val ? oxenc::to_hex(value) : value);
}
}
@ -903,7 +900,6 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type
if (blob) *blob = {};
// Check length of the value
std::stringstream err_stream;
cryptonote::address_parse_info addr_info = {};
if (type == mapping_type::wallet)
{
@ -912,15 +908,9 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type
if (reason)
{
if (value.empty())
{
err_stream << "The value=" << value;
err_stream << ", mapping into the wallet address, specifies a wallet address of 0 length";
}
*reason = "The value={}, mapping into the wallet address, specifies a wallet address of 0 length"_format(value);
else
{
err_stream << "Could not convert the wallet address string, check it is correct, value=" << value;
}
*reason = err_stream.str();
*reason = "Could not convert the wallet address string, check it is correct, value={}"_format(value);
}
return false;
}
@ -955,7 +945,7 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type
// 51 base32z chars (=255 bits) followed by a 1-bit value ('y'=0, or 'o'=0b10000); anything else
// in the last spot isn't a valid lokinet address.
if (check_condition(value.size() != 57 || !tools::ends_with(value, ".loki") || !oxenc::is_base32z(value.substr(0, 52)) || !(value[51] == 'y' || value[51] == 'o'),
reason, "'", value, "' is not a valid lokinet address"))
reason, "'{}' is not a valid lokinet address", value))
return false;
if (blob)
@ -968,14 +958,17 @@ bool mapping_value::validate(cryptonote::network_type nettype, mapping_type type
{
assert(type == mapping_type::session);
// NOTE: Check value is hex of the right size
if (check_condition(value.size() != 2*SESSION_PUBLIC_KEY_BINARY_LENGTH, reason, "The value=", value, " is not the required ", 2*SESSION_PUBLIC_KEY_BINARY_LENGTH, "-character hex string session public key, length=", value.size()))
if (check_condition(value.size() != 2*SESSION_PUBLIC_KEY_BINARY_LENGTH, reason,
"The value={} is not the required {}-character hex string session public key, length={}", value, 2*SESSION_PUBLIC_KEY_BINARY_LENGTH, value.size()))
return false;
if (check_condition(!oxenc::is_hex(value), reason, ", specifies name -> value mapping where the value is not a hex string given value="))
if (check_condition(!oxenc::is_hex(value), reason,
"value={} specifies name -> value mapping where the value is not a hex string", value))
return false;
// NOTE: Session public keys are 33 bytes, with the first byte being 0x05 and the remaining 32 being the public key.
if (check_condition(!tools::starts_with(value, "05"), reason, "ONS type=session, specifies mapping from name -> ed25519 key where the key is not prefixed with 05, given ed25519=", value))
if (check_condition(!tools::starts_with(value, "05"), reason,
"ONS type=session specifies mapping from name -> ed25519 key where the key is not prefixed with 05, given ed25519={}", value))
return false;
if (blob) // NOTE: Given blob, write the binary output
@ -995,7 +988,6 @@ static_assert(SODIUM_ENCRYPTION_EXTRA_BYTES >= crypto_secretbox_MACBYTES);
bool mapping_value::validate_encrypted(mapping_type type, std::string_view value, mapping_value* blob, std::string *reason)
{
if (blob) *blob = {};
std::stringstream err_stream;
int value_len = crypto_aead_xchacha20poly1305_ietf_ABYTES + crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
@ -1017,10 +1009,7 @@ bool mapping_value::validate_encrypted(mapping_type type, std::string_view value
else
{
if (reason)
{
err_stream << "Unhandled type passed into " << __func__;
*reason = err_stream.str();
}
*reason = "Unhandled type passed into {}"_format(__func__);
return false;
}
@ -1090,9 +1079,6 @@ static bool verify_ons_signature(crypto::hash const &hash, ons::generic_signatur
static bool validate_against_previous_mapping(ons::name_system_db &ons_db, uint64_t blockchain_height, cryptonote::transaction const &tx, cryptonote::tx_extra_oxen_name_system const &ons_extra, std::string *reason)
{
std::stringstream err_stream;
OXEN_DEFER { if (reason && reason->empty()) *reason = err_stream.str(); };
crypto::hash expected_prev_txid = crypto::null_hash;
std::string name_hash = hash_to_base64(ons_extra.name_hash);
ons::mapping_record mapping = ons_db.get_mapping(ons_extra.type, name_hash);
@ -1102,20 +1088,25 @@ static bool validate_against_previous_mapping(ons::name_system_db &ons_db, uint6
// Updating: the mapping must exist and be active, the updated fields must actually change from
// the current value, and a valid signature over the updated values must be present.
if (check_condition(!mapping, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " update requested but mapping does not exist."))
if (check_condition(!mapping, reason,
"{}, {} update requested but mapping does not exist.", tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
if (check_condition(!mapping.active(blockchain_height), reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " TX requested to update mapping that has already expired"))
if (check_condition(!mapping.active(blockchain_height), reason,
"{}, {} TX requested to update mapping that has already expired", tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
expected_prev_txid = mapping.txid;
constexpr auto SPECIFYING_SAME_VALUE_ERR = " field to update is specifying the same mapping "sv;
if (check_condition(ons_extra.field_is_set(ons::extra_field::encrypted_value) && ons_extra.encrypted_value == mapping.encrypted_value.to_view(), reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), SPECIFYING_SAME_VALUE_ERR, "value"))
constexpr auto SPECIFYING_SAME_VALUE_ERR = "{}, {} field to update is specifying the same mapping {}"sv;
if (check_condition(ons_extra.field_is_set(ons::extra_field::encrypted_value) && ons_extra.encrypted_value == mapping.encrypted_value.to_view(), reason,
SPECIFYING_SAME_VALUE_ERR, tx, ons_extra_string(ons_db.network_type(), ons_extra), "value"))
return false;
if (check_condition(ons_extra.field_is_set(ons::extra_field::owner) && ons_extra.owner == mapping.owner, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), SPECIFYING_SAME_VALUE_ERR, "owner"))
if (check_condition(ons_extra.field_is_set(ons::extra_field::owner) && ons_extra.owner == mapping.owner, reason,
SPECIFYING_SAME_VALUE_ERR, tx, ons_extra_string(ons_db.network_type(), ons_extra), "owner"))
return false;
if (check_condition(ons_extra.field_is_set(ons::extra_field::backup_owner) && ons_extra.backup_owner == mapping.backup_owner, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), SPECIFYING_SAME_VALUE_ERR, "backup_owner"))
if (check_condition(ons_extra.field_is_set(ons::extra_field::backup_owner) && ons_extra.backup_owner == mapping.backup_owner, reason,
SPECIFYING_SAME_VALUE_ERR, tx, ons_extra_string(ons_db.network_type(), ons_extra), "backup_owner"))
return false;
// Validate signature
@ -1124,7 +1115,8 @@ static bool validate_against_previous_mapping(ons::name_system_db &ons_db, uint6
ons_extra.field_is_set(ons::extra_field::owner) ? &ons_extra.owner : nullptr,
ons_extra.field_is_set(ons::extra_field::backup_owner) ? &ons_extra.backup_owner : nullptr,
expected_prev_txid);
if (check_condition(data.empty(), reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " unexpectedly failed to generate signature, please inform the Loki developers"))
if (check_condition(data.empty(), reason,
"{}, {} unexpectedly failed to generate signature, please inform the Oxen developers", tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
crypto::hash hash;
@ -1132,52 +1124,65 @@ static bool validate_against_previous_mapping(ons::name_system_db &ons_db, uint6
if (check_condition(!verify_ons_signature(hash, ons_extra.signature, mapping.owner) &&
!verify_ons_signature(hash, ons_extra.signature, mapping.backup_owner), reason,
tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " failed to verify signature for ONS update, current owner=", mapping.owner.to_string(ons_db.network_type()), ", backup owner=", mapping.backup_owner.to_string(ons_db.network_type())))
"{}, {} failed to verify signature for ONS update, current owner={}, backup owner={}",
tx, ons_extra_string(ons_db.network_type(), ons_extra), mapping.owner.to_string(ons_db.network_type()), mapping.backup_owner.to_string(ons_db.network_type())))
return false;
}
else if (ons_extra.is_buying())
{
// If buying a new name then the existing name must not be active
if (check_condition(mapping.active(blockchain_height), reason,
"Cannot buy an ONS name that is already registered: name_hash=", mapping.name_hash, ", type=", mapping.type,
"; TX: ", tx, "; ", ons_extra_string(ons_db.network_type(), ons_extra)))
"Cannot buy an ONS name that is already registered: name_hash={}, type={}; TX: {}; {}",
mapping.name_hash, mapping.type, tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
// If buying a new wallet name then the existing session name must not be active and vice versa
// The owner of an existing name but different type is allowed to register but the owner and backup owners
// of the new mapping must be from the same owners and backup owners of the previous mapping ie no
// new addresses are allowed to be added as owner or backup owner.
if (ons_extra.type == mapping_type::wallet)
if (ons_extra.type == mapping_type::wallet || ons_extra.type == mapping_type::session)
{
ons::mapping_record session_mapping = ons_db.get_mapping(mapping_type::session, name_hash);
if (check_condition(session_mapping.active(blockchain_height) && (!(session_mapping.owner == ons_extra.owner || session_mapping.backup_owner == ons_extra.owner) || !(!ons_extra.field_is_set(ons::extra_field::backup_owner) || session_mapping.backup_owner == ons_extra.backup_owner || session_mapping.owner == ons_extra.backup_owner)), reason,
"Cannot buy an ONS wallet name that has an already registered session name: name_hash=", mapping.name_hash, ", type=", mapping.type,
"; TX: ", tx, "; ", ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
} else if (ons_extra.type == mapping_type::session) {
ons::mapping_record wallet_mapping = ons_db.get_mapping(mapping_type::wallet, name_hash);
if (check_condition(wallet_mapping.active(blockchain_height) && (!(wallet_mapping.owner == ons_extra.owner || wallet_mapping.backup_owner == ons_extra.owner) || !(!ons_extra.field_is_set(ons::extra_field::backup_owner) || wallet_mapping.backup_owner == ons_extra.backup_owner || wallet_mapping.owner == ons_extra.backup_owner)), reason,
"Cannot buy an ONS session name that has an already registered wallet name: name_hash=", mapping.name_hash, ", type=", mapping.type,
"; TX: ", tx, "; ", ons_extra_string(ons_db.network_type(), ons_extra)))
auto buy_type_name = ons_extra.type == mapping_type::wallet ? "wallet"sv : "session"sv;
auto alt_type_name = ons_extra.type == mapping_type::wallet ? "session"sv : "wallet"sv;
auto alt_type = ons_extra.type == mapping_type::wallet ? mapping_type::session : mapping_type::wallet;
ons::mapping_record alt_mapping = ons_db.get_mapping(alt_type, name_hash);
auto is_alt_record_owner = [&alt_mapping](const auto& new_owner) {
return new_owner == alt_mapping.owner || new_owner == alt_mapping.backup_owner;
};
if (check_condition(
alt_mapping.active(blockchain_height) && // alternative mapping exists
(
!is_alt_record_owner(ons_extra.owner) ||
(ons_extra.field_is_set(ons::extra_field::backup_owner) && !is_alt_record_owner(ons_extra.backup_owner))
),
reason,
"Cannot buy an ONS {} name that has an already registered {} name: name_hash={}, type={}; TX: {}; {}",
buy_type_name, alt_type_name, mapping.name_hash, mapping.type, tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
}
}
else if (ons_extra.is_renewing())
{
// We allow anyone to renew a name, but it has to exist and be currently active
if (check_condition(!mapping, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " renewal requested but mapping does not exist."))
if (check_condition(!mapping, reason, "{}, {} renewal requested but mapping does not exist.", tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
if (check_condition(!mapping.active(blockchain_height), reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " TX requested to renew mapping that has already expired"))
if (check_condition(!mapping.active(blockchain_height), reason,
"{}, {} TX requested to renew mapping that has already expired", tx, ons_extra_string(ons_db.network_type(), ons_extra)))
return false;
expected_prev_txid = mapping.txid;
}
else
{
check_condition(true, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " is not a valid buy, update, or renew ONS tx");
check_condition(true, reason, "{}, {} is not a valid buy, update, or renew ONS tx", tx, ons_extra_string(ons_db.network_type(), ons_extra));
return false;
}
if (check_condition(ons_extra.prev_txid != expected_prev_txid, reason, tx, ", ", ons_extra_string(ons_db.network_type(), ons_extra), " specified prior txid=", ons_extra.prev_txid, ", but ONS DB reports=", expected_prev_txid, ", possible competing TX was submitted and accepted before this TX was processed"))
if (check_condition(ons_extra.prev_txid != expected_prev_txid, reason,
"{}, {} specified prior txid {} but expected {}; perhaps a competing ONS TX was submitted and accepted before this ONS update TX was processed?",
tx, ons_extra_string(ons_db.network_type(), ons_extra), ons_extra.prev_txid, expected_prev_txid))
return false;
return true;
@ -1192,10 +1197,12 @@ bool name_system_db::validate_ons_tx(hf hf_version, uint64_t blockchain_height,
// Pull out ONS Extra from TX
// -----------------------------------------------------------------------------------------------
{
if (check_condition(tx.type != cryptonote::txtype::oxen_name_system, reason, tx, ", uses wrong tx type, expected=", cryptonote::txtype::oxen_name_system))
if (check_condition(tx.type != cryptonote::txtype::oxen_name_system, reason,
"{} uses wrong tx type, expected={}", tx, cryptonote::txtype::oxen_name_system))
return false;
if (check_condition(!cryptonote::get_field_from_tx_extra(tx.extra, ons_extra), reason, tx, ", didn't have oxen name service in the tx_extra"))
if (check_condition(!cryptonote::get_field_from_tx_extra(tx.extra, ons_extra), reason,
"{} didn't have oxen name service in the tx_extra", tx))
return false;
}
@ -1204,17 +1211,21 @@ bool name_system_db::validate_ons_tx(hf hf_version, uint64_t blockchain_height,
// Check TX ONS Serialized Fields are NULL if they are not specified
// -----------------------------------------------------------------------------------------------
{
constexpr auto VALUE_SPECIFIED_BUT_NOT_REQUESTED = ", given field but field is not requested to be serialised="sv;
if (check_condition(!ons_extra.field_is_set(ons::extra_field::encrypted_value) && ons_extra.encrypted_value.size(), reason, tx, ", ", ons_extra_string(nettype, ons_extra), VALUE_SPECIFIED_BUT_NOT_REQUESTED, "encrypted_value"))
constexpr auto VALUE_SPECIFIED_BUT_NOT_REQUESTED = "{}, {} given field {} but field is not requested to be serialised"sv;
if (check_condition(!ons_extra.field_is_set(ons::extra_field::encrypted_value) && ons_extra.encrypted_value.size(), reason,
VALUE_SPECIFIED_BUT_NOT_REQUESTED, tx, ons_extra_string(nettype, ons_extra), "encrypted_value"))
return false;
if (check_condition(!ons_extra.field_is_set(ons::extra_field::owner) && ons_extra.owner, reason, tx, ", ", ons_extra_string(nettype, ons_extra), VALUE_SPECIFIED_BUT_NOT_REQUESTED, "owner"))
if (check_condition(!ons_extra.field_is_set(ons::extra_field::owner) && ons_extra.owner, reason,
VALUE_SPECIFIED_BUT_NOT_REQUESTED, tx, ons_extra_string(nettype, ons_extra), "owner"))
return false;
if (check_condition(!ons_extra.field_is_set(ons::extra_field::backup_owner) && ons_extra.backup_owner, reason, tx, ", ", ons_extra_string(nettype, ons_extra), VALUE_SPECIFIED_BUT_NOT_REQUESTED, "backup_owner"))
if (check_condition(!ons_extra.field_is_set(ons::extra_field::backup_owner) && ons_extra.backup_owner, reason,
VALUE_SPECIFIED_BUT_NOT_REQUESTED, tx, ons_extra_string(nettype, ons_extra), "backup_owner"))
return false;
if (check_condition(!ons_extra.field_is_set(ons::extra_field::signature) && ons_extra.signature, reason, tx, ", ", ons_extra_string(nettype, ons_extra), VALUE_SPECIFIED_BUT_NOT_REQUESTED, "signature"))
if (check_condition(!ons_extra.field_is_set(ons::extra_field::signature) && ons_extra.signature, reason,
VALUE_SPECIFIED_BUT_NOT_REQUESTED, tx, ons_extra_string(nettype, ons_extra), "signature"))
return false;
}
@ -1222,22 +1233,28 @@ bool name_system_db::validate_ons_tx(hf hf_version, uint64_t blockchain_height,
// Simple ONS Extra Validation
// -----------------------------------------------------------------------------------------------
{
if (check_condition(ons_extra.version != 0, reason, tx, ", ", ons_extra_string(nettype, ons_extra), " unexpected version=", std::to_string(ons_extra.version), ", expected=0"))
if (check_condition(ons_extra.version != 0, reason,
"{}, {} unexpected version={:d}, expected 0", tx, ons_extra_string(nettype, ons_extra), ons_extra.version))
return false;
if (check_condition(!ons::mapping_type_allowed(hf_version, ons_extra.type), reason, tx, ", ", ons_extra_string(nettype, ons_extra), " specifying type=", ons_extra.type, " is disallowed in HF", +static_cast<uint8_t>(hf_version)))
if (check_condition(!ons::mapping_type_allowed(hf_version, ons_extra.type), reason,
"{}, {} specifying type={} is disallowed in HF{:d}", tx, ons_extra_string(nettype, ons_extra), ons_extra.type, static_cast<uint8_t>(hf_version)))
return false;
// -----------------------------------------------------------------------------------------------
// Serialized Values Check
// -----------------------------------------------------------------------------------------------
if (check_condition(!ons_extra.is_buying() && !ons_extra.is_updating() && !ons_extra.is_renewing(), reason, tx, ", ", ons_extra_string(nettype, ons_extra), " TX extra does not specify valid combination of bits for serialized fields=", std::bitset<sizeof(ons_extra.fields) * 8>(static_cast<size_t>(ons_extra.fields)).to_string()))
if (check_condition(!ons_extra.is_buying() && !ons_extra.is_updating() && !ons_extra.is_renewing(), reason,
"{}, {} TX extra does not specify valid combination of bits for serialized fields={}",
tx, ons_extra_string(nettype, ons_extra), std::bitset<sizeof(ons_extra.fields) * 8>(static_cast<size_t>(ons_extra.fields)).to_string()))
return false;
if (check_condition(ons_extra.field_is_set(ons::extra_field::owner) &&
ons_extra.field_is_set(ons::extra_field::backup_owner) &&
ons_extra.owner == ons_extra.backup_owner,
reason, tx, ", ", ons_extra_string(nettype, ons_extra), " specifying owner the same as the backup owner=", ons_extra.backup_owner.to_string(nettype)))
reason,
"{}, {} specifying owner the same as the backup owner={}",
tx, ons_extra_string(nettype, ons_extra), ons_extra.backup_owner.to_string(nettype)))
{
return false;
}
@ -1247,7 +1264,8 @@ bool name_system_db::validate_ons_tx(hf hf_version, uint64_t blockchain_height,
// ONS Field(s) Validation
// -----------------------------------------------------------------------------------------------
{
if (check_condition((ons_extra.name_hash == null_name_hash || ons_extra.name_hash == crypto::null_hash), reason, tx, ", ", ons_extra_string(nettype, ons_extra), " specified the null name hash"))
if (check_condition((ons_extra.name_hash == null_name_hash || ons_extra.name_hash == crypto::null_hash), reason,
"{}, {} specified the null name hash", tx, ons_extra_string(nettype, ons_extra)))
return false;
if (ons_extra.field_is_set(ons::extra_field::encrypted_value))
@ -1275,12 +1293,10 @@ bool name_system_db::validate_ons_tx(hf hf_version, uint64_t blockchain_height,
burn = burn_required;
}
if (burn != burn_required)
{
char const *over_or_under = burn > burn_required ? "too much " : "insufficient ";
if (check_condition(true, reason, tx, ", ", ons_extra_string(nettype, ons_extra), " burned ", over_or_under, "oxen=", burn, ", require=", burn_required))
if (check_condition(burn != burn_required, reason,
"{}, {} burned {} OXEN={}, required={}",
tx, ons_extra_string(nettype, ons_extra), burn > burn_required ? "too much" : "insufficient", burn, burn_required))
return false;
}
}
return true;

View File

@ -115,9 +115,8 @@ struct mapping_value
mapping_value();
mapping_value(std::string encrypted_value, std::string nonce);
};
inline std::ostream &operator<<(std::ostream &os, mapping_value const &v) { return os << oxenc::to_hex(v.to_view()); }
inline std::string_view mapping_type_str(mapping_type type)
inline constexpr std::string_view mapping_type_str(mapping_type type)
{
switch(type)
{
@ -130,7 +129,6 @@ inline std::string_view mapping_type_str(mapping_type type)
default: assert(false); return "xx_unhandled_type"sv;
}
}
inline std::ostream &operator<<(std::ostream &os, mapping_type type) { return os << mapping_type_str(type); }
constexpr bool mapping_type_allowed(cryptonote::hf hf_version, mapping_type type) {
return (type == mapping_type::session && hf_version >= cryptonote::hf::hf15_ons)

View File

@ -68,11 +68,6 @@ namespace service_nodes
END_SERIALIZE()
};
inline std::ostream &operator<<(std::ostream &os, quorum const &q)
{
return os << q.to_string();
}
struct quorum_manager
{
@ -166,9 +161,4 @@ namespace service_nodes
uint64_t quorum_checksum(const std::vector<crypto::public_key> &pubkeys, size_t offset = 0);
}
template <>
struct fmt::formatter<service_nodes::quorum> : fmt::formatter<std::string> {
auto format(service_nodes::quorum quorum, format_context& ctx) {
return formatter<std::string>::format(quorum.to_string(), ctx);
}
};
template <> inline constexpr bool formattable::via_to_string<service_nodes::quorum> = true;

View File

@ -75,10 +75,6 @@ namespace service_nodes
}
};
inline std::ostream &operator<<(std::ostream &os, quorum_type q) {
return os << to_string(q);
}
enum struct quorum_group : uint8_t { invalid, validator, worker, _count };
struct quorum_vote_t
{
@ -176,11 +172,5 @@ namespace service_nodes
mutable std::recursive_mutex m_lock;
};
}; // namespace service_nodes
//
template <>
struct fmt::formatter<service_nodes::quorum_type> : fmt::formatter<std::string_view> {
auto format(service_nodes::quorum_type quorum, format_context& ctx) {
return formatter<std::string_view>::format(to_string(quorum), ctx);
}
};
template <> inline constexpr bool formattable::via_to_string<service_nodes::quorum_type> = true;

View File

@ -406,14 +406,14 @@ bool command_parser_executor::is_key_image_spent(const std::vector<std::string>&
{
if (args.empty())
{
tools::fail_msg_writer() << "Invalid arguments. Expected: is_key_image_spent <key_image> [<key_image> ...]\n";
tools::fail_msg_writer("Invalid arguments. Expected: is_key_image_spent <key_image> [<key_image> ...]\n");
return true;
}
std::vector<crypto::key_image> kis;
for (const auto& hex : args) {
if (!tools::hex_to_type(hex, kis.emplace_back())) {
tools::fail_msg_writer() << "Invalid key image: '" << hex << "'";
tools::fail_msg_writer("Invalid key image: '{}'", hex);
return true;
}
}
@ -466,7 +466,7 @@ bool command_parser_executor::start_mining(const std::vector<std::string>& args)
}
if (info.is_subaddress)
{
tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!";
tools::fail_msg_writer("subaddress for mining reward is not yet supported!");
return true;
}
@ -476,7 +476,7 @@ bool command_parser_executor::start_mining(const std::vector<std::string>& args)
unsigned int threads_count = 1, num_blocks = 0;
if (threads_val.size() && !tools::parse_int(threads_val, threads_count))
{
tools::fail_msg_writer() << "Failed to parse threads value" << threads_val;
tools::fail_msg_writer("Failed to parse threads value {}", threads_val);
return false;
}
@ -510,14 +510,14 @@ bool command_parser_executor::set_limit(const std::vector<std::string>& args)
return m_executor.get_limit();
if (args.size() > 2) {
tools::fail_msg_writer() << "Too many arguments: expected 0-2 values";
tools::fail_msg_writer("Too many arguments ({}): expected 0-2 values", args.size());
return false;
}
int64_t limit_down;
if (args[0] == "default") // Accept "default" as a string because getting -1 through the cli arg parsing is a nuissance
limit_down = -1;
else if (!tools::parse_int(args[0], limit_down)) {
tools::fail_msg_writer() << "Failed to parse '" << args[0] << "' as a limit";
tools::fail_msg_writer("Failed to parse '{}' as a limit", args[0]);
return false;
}
@ -527,7 +527,7 @@ bool command_parser_executor::set_limit(const std::vector<std::string>& args)
else if (args[1] == "default")
limit_up = -1;
else if (!tools::parse_int(args[1], limit_up)) {
tools::fail_msg_writer() << "Failed to parse '" << args[1] << "' as a limit";
tools::fail_msg_writer("Failed to parse '{}' as a limit", args[1]);
return false;
}

File diff suppressed because it is too large Load Diff

View File

@ -83,11 +83,11 @@ public:
return true;
} catch (const std::exception& e) {
if (!error.empty())
tools::fail_msg_writer() << error << ": " << e.what();
tools::fail_msg_writer("{}: {}", error, e.what());
return false;
} catch (...) {}
if (!error.empty())
tools::fail_msg_writer() << error;
tools::fail_msg_writer(error);
return false;
}
@ -133,7 +133,7 @@ public:
if (!try_running([this] { return invoke<RPC>(); }, error_prefix))
return false;
tools::success_msg_writer() << success_msg;
tools::success_msg_writer(success_msg);
return true;
}

View File

@ -28,6 +28,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "common/string_util.h"
#include "device/io_ledger_tcp.hpp"
#include "io_hid.hpp"
#include "version.h"
@ -388,7 +389,7 @@ namespace hw::ledger {
void device_ledger::logRESP() {
if (apdu_verbose)
log::debug(logcat, "RESP (+{}): {} {}", tools::short_duration(std::chrono::steady_clock::now() - last_cmd), oxenc::to_hex(std::string_view{reinterpret_cast<const char*>(&sw), sizeof(sw)}), oxenc::to_hex(buffer_recv, buffer_recv + length_recv));
log::debug(logcat, "RESP (+{}): {} {}", tools::friendly_duration(std::chrono::steady_clock::now() - last_cmd), oxenc::to_hex(std::string_view{reinterpret_cast<const char*>(&sw), sizeof(sw)}), oxenc::to_hex(buffer_recv, buffer_recv + length_recv));
}
int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) {

View File

@ -34,7 +34,6 @@
#include <algorithm>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <oxenc/endian.h>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
@ -877,11 +876,7 @@ namespace trezor{
}
static std::string get_usb_path(uint8_t bus_id, const std::vector<uint8_t> &path){
std::ostringstream ss;
ss << WebUsbTransport::PATH_PREFIX << std::setw(3) << std::setfill('0') << (int)bus_id;
for (int port : path)
ss << ':' << port;
return ss.str();
return fmt::format("{}{:03d}:{:d}", WebUsbTransport::PATH_PREFIX, bus_id, fmt::join(path, ":"));
}
const char * WebUsbTransport::PATH_PREFIX = "webusb:";

View File

@ -35,11 +35,11 @@
* \brief Generates a set of multisig wallets
*/
#include <iostream>
#include <sstream>
#include <boost/program_options.hpp>
#include <boost/algorithm/string.hpp>
#include <fmt/core.h>
#include "crypto/crypto.h" // for crypto::secret_key definition
#include "common/fs-format.h"
#include "common/i18n.h"
#include "common/command_line.h"
#include "common/util.h"
@ -75,7 +75,7 @@ namespace
static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path& basename, network_type nettype, bool create_address_file)
{
tools::msg_writer() << fmt::format(genms::tr("Generating {:d} {:d}/{:d} multisig wallets"), total, threshold, total);
tools::msg_writer(genms::tr("Generating {:d} {:d}/{:d} multisig wallets"), total, threshold, total);
const auto pwd_container = tools::password_container::prompt(true, "Enter password for new multisig wallets");
@ -100,7 +100,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path
wallets[n]->decrypt_keys(pwd_container->password());
if (!tools::wallet2::verify_multisig_info(wallets[n]->get_multisig_info(), sk[n], pk[n]))
{
tools::fail_msg_writer() << genms::tr("Failed to verify multisig info");
tools::fail_msg_writer(genms::tr("Failed to verify multisig info"));
return false;
}
wallets[n]->encrypt_keys(pwd_container->password());
@ -108,10 +108,10 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path
// make the wallets multisig
std::vector<std::string> extra_info(total);
std::stringstream ss;
std::vector<fs::path> filenames;
for (size_t n = 0; n < total; ++n)
{
fs::path name = basename;
auto& name = filenames.emplace_back(basename);
name += "-" + std::to_string(n + 1);
std::vector<crypto::secret_key> skn;
std::vector<crypto::public_key> pkn;
@ -124,7 +124,6 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path
}
}
extra_info[n] = wallets[n]->make_multisig(pwd_container->password(), skn, pkn, threshold);
ss << " " << name << std::endl;
}
//exchange keys unless exchange_multisig_keys returns no extra info
@ -136,7 +135,7 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path
{
if (!tools::wallet2::verify_extra_multisig_info(extra_info[n], pkeys, signers[n]))
{
tools::fail_msg_writer() << genms::tr("Error verifying multisig extra info");
tools::fail_msg_writer(genms::tr("Error verifying multisig extra info"));
return false;
}
}
@ -146,12 +145,13 @@ static bool generate_multisig(uint32_t threshold, uint32_t total, const fs::path
}
}
std::string address = wallets[0]->get_account().get_public_address_str(wallets[0]->nettype());
tools::success_msg_writer() << genms::tr("Generated multisig wallets for address ") << address << std::endl << ss.str();
tools::success_msg_writer("{}{}\n{}", genms::tr("Generated multisig wallets for address "),
wallets[0]->get_account().get_public_address_str(wallets[0]->nettype()),
fmt::join(filenames, " "));
}
catch (const std::exception &e)
{
tools::fail_msg_writer() << genms::tr("Error creating multisig wallets: ") << e.what();
tools::fail_msg_writer("{}{}", genms::tr("Error creating multisig wallets: "), e.what());
return false;
}
@ -178,7 +178,7 @@ int main(int argc, char* argv[])
desc_params,
po::options_description{},
boost::program_options::positional_options_description(),
[](const std::string &s){ tools::scoped_message_writer() << s; },
[](const std::string &s){ tools::msg_writer(s); },
"oxen-gen-multisig.log"
);
if (!vm)
@ -193,14 +193,14 @@ int main(int argc, char* argv[])
devnet = command_line::get_arg(*vm, arg_devnet);
if (testnet && devnet)
{
tools::fail_msg_writer() << genms::tr("Error: Can't specify more than one of --testnet and --devnet");
tools::fail_msg_writer(genms::tr("Error: Can't specify more than one of --testnet and --devnet"));
return 1;
}
if (command_line::has_arg(*vm, arg_scheme))
{
if (sscanf(command_line::get_arg(*vm, arg_scheme).c_str(), "%u/%u", &threshold, &total) != 2)
{
tools::fail_msg_writer() << genms::tr("Error: expected N/M, but got: ") << command_line::get_arg(*vm, arg_scheme);
tools::fail_msg_writer("{}{}", genms::tr("Error: expected N/M, but got: "), command_line::get_arg(*vm, arg_scheme));
return 1;
}
}
@ -208,7 +208,7 @@ int main(int argc, char* argv[])
{
if (threshold)
{
tools::fail_msg_writer() << genms::tr("Error: either --scheme or both of --threshold and --participants may be given");
tools::fail_msg_writer(genms::tr("Error: either --scheme or both of --threshold and --participants may be given"));
return 1;
}
threshold = command_line::get_arg(*vm, arg_threshold);
@ -217,14 +217,14 @@ int main(int argc, char* argv[])
{
if (total)
{
tools::fail_msg_writer() << genms::tr("Error: either --scheme or both of --threshold and --participants may be given");
tools::fail_msg_writer(genms::tr("Error: either --scheme or both of --threshold and --participants may be given"));
return 1;
}
total = command_line::get_arg(*vm, arg_participants);
}
if (threshold <= 1 || threshold > total)
{
tools::fail_msg_writer() << fmt::format(genms::tr("Error: expected N > 1 and N <= M, but got N=={:d} and M=={:d}"), threshold, total);
tools::fail_msg_writer(genms::tr("Error: expected N > 1 and N <= M, but got N=={:d} and M=={:d}"), threshold, total);
return 1;
}
fs::path basename;
@ -234,7 +234,7 @@ int main(int argc, char* argv[])
}
else
{
tools::fail_msg_writer() << genms::tr("Error: --filename-base is required");
tools::fail_msg_writer(genms::tr("Error: --filename-base is required"));
return 1;
}

View File

@ -47,6 +47,7 @@
#include "epee/string_tools.h"
#include "epee/time_helper.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/pruning.h"
#include "net/error.h"
#include "common/periodic_task.h"

View File

@ -560,8 +560,13 @@ namespace rct {
inline const crypto::hash &rct2hash(const rct::key &k) { return (const crypto::hash&)k; }
inline bool operator==(const rct::key &k0, const crypto::public_key &k1) { return !crypto_verify_32(k0.bytes, (const unsigned char*)&k1); }
inline bool operator!=(const rct::key &k0, const crypto::public_key &k1) { return crypto_verify_32(k0.bytes, (const unsigned char*)&k1); }
inline std::string to_hex_string(const rct::key& v) {
return "<{}>"_format(tools::type_to_hex(v));
}
}
template <> inline constexpr bool formattable::via_to_hex_string<rct::key> = true;
namespace cryptonote {
inline bool operator==(const crypto::public_key &k0, const rct::key &k1) { return !crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
@ -570,12 +575,6 @@ namespace cryptonote {
inline bool operator!=(const crypto::secret_key &k0, const rct::key &k1) { return crypto_verify_32((const unsigned char*)&k0, k1.bytes); }
}
namespace rct {
inline std::ostream &operator <<(std::ostream &o, const rct::key &v) {
return o << '<' << tools::type_to_hex(v) << '>';
}
}
namespace std
{
template<> struct hash<rct::key> { std::size_t operator()(const rct::key &k) const { return reinterpret_cast<const std::size_t&>(k); } };

View File

@ -35,6 +35,7 @@
* \brief Source file that defines simple_wallet class.
*/
#include <fmt/color.h>
#include "common/string_util.h"
#include "oxen_economy.h"
#include <algorithm>
@ -63,6 +64,7 @@
#include "common/signal_handler.h"
#include "common/base58.h"
#include "common/scoped_message_writer.h"
#include "common/fs-format.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "cryptonote_core/service_node_voting.h"
#include "cryptonote_core/service_node_list.h"
@ -91,6 +93,12 @@ extern "C"
#include <sodium.h>
}
// grumble, grumble
namespace formattable {
std::string to_string(const boost::basic_format<char>& f) { return f.str(); }
template <> constexpr bool via_to_string<boost::basic_format<char>> = true;
}
namespace cryptonote
{
@ -302,22 +310,6 @@ namespace
return buf;
}
std::optional<tools::password_container> password_prompter(const char *prompt, bool verify)
{
rdln::suspend_readline pause_readline;
auto pwd_container = tools::password_container::prompt(verify, prompt);
if (!pwd_container)
{
tools::fail_msg_writer() << sw::tr("failed to read wallet password");
}
return pwd_container;
}
std::optional<tools::password_container> default_password_prompter(bool verify)
{
return password_prompter(verify ? sw::tr("Enter a new password for the wallet") : sw::tr("Wallet password"), verify);
}
inline std::string interpret_rpc_response(bool ok, const std::string& status)
{
std::string err;
@ -339,26 +331,59 @@ namespace
return err;
}
tools::scoped_message_writer success_msg_writer(bool color = false)
// Replacing all the << in here with proper formatting is just too painful, so make a crappy
// subclass that provides a << that just slams it through a basic format.
class simplewallet_crappy_message_writer : public tools::scoped_message_writer {
public:
using tools::scoped_message_writer::scoped_message_writer;
template <typename T>
auto& operator<<(T&& val) {
append("{}", std::forward<T>(val));
return *this;
}
};
simplewallet_crappy_message_writer success_msg_writer(bool color = false)
{
return tools::scoped_message_writer(color ? fmt::terminal_color::green : fmt::terminal_color::white, std::string{}, spdlog::level::info);
std::optional<fmt::terminal_color> c = std::nullopt;
if (color)
c = fmt::terminal_color::green;
return simplewallet_crappy_message_writer(c, std::string{}, spdlog::level::info);
}
tools::scoped_message_writer message_writer(fmt::terminal_color color = fmt::terminal_color::white)
simplewallet_crappy_message_writer message_writer(std::optional<fmt::terminal_color> color = std::nullopt)
{
return tools::scoped_message_writer(color);
return simplewallet_crappy_message_writer(color);
}
tools::scoped_message_writer fail_msg_writer()
simplewallet_crappy_message_writer fail_msg_writer()
{
return tools::scoped_message_writer(fmt::terminal_color::red, sw::tr("Error: "), spdlog::level::err);
return simplewallet_crappy_message_writer(fmt::terminal_color::red, sw::tr("Error: "), spdlog::level::err);
}
tools::scoped_message_writer warn_msg_writer()
simplewallet_crappy_message_writer warn_msg_writer()
{
return tools::scoped_message_writer(fmt::terminal_color::red, sw::tr("Warning: "), spdlog::level::warn);
return simplewallet_crappy_message_writer(fmt::terminal_color::red, sw::tr("Warning: "), spdlog::level::warn);
}
std::optional<tools::password_container> password_prompter(const char *prompt, bool verify)
{
rdln::suspend_readline pause_readline;
auto pwd_container = tools::password_container::prompt(verify, prompt);
if (!pwd_container)
{
fail_msg_writer() << sw::tr("failed to read wallet password");
}
return pwd_container;
}
std::optional<tools::password_container> default_password_prompter(bool verify)
{
return password_prompter(verify ? sw::tr("Enter a new password for the wallet") : sw::tr("Wallet password"), verify);
}
bool parse_bool(const std::string& s, bool& result)
{
if (command_line::is_yes(s, "1", "true", simple_wallet::tr("true")))
@ -498,7 +523,7 @@ namespace
}
catch (const tools::error::tx_rejected& e)
{
fail_msg_writer() << (boost::format(sw::tr("transaction %s was rejected by daemon")) % get_transaction_hash(e.tx()));
fail_msg_writer() << (boost::format(sw::tr("transaction %s was rejected by daemon")) % get_transaction_hash(e.tx())).str();
std::string reason = e.reason();
if (!reason.empty())
fail_msg_writer() << sw::tr("Reason: ") << reason;
@ -2468,7 +2493,7 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std:
bool simple_wallet::set_inactivity_lock_timeout(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
#ifdef _WIN32
tools::fail_msg_writer() << tr("Inactivity lock timeout disabled on Windows");
fail_msg_writer() << tr("Inactivity lock timeout disabled on Windows");
return true;
#endif
const auto pwd_container = get_and_verify_password();
@ -2482,7 +2507,7 @@ bool simple_wallet::set_inactivity_lock_timeout(const std::vector<std::string> &
}
else
{
tools::fail_msg_writer() << tr("Invalid number of seconds");
fail_msg_writer() << tr("Invalid number of seconds");
}
}
return true;
@ -5608,7 +5633,7 @@ void simple_wallet::check_for_inactivity_lock(bool user)
m_in_command = true;
if (!user)
{
tools::msg_writer() << R"(
message_writer() << R"(
...........
...............
....OOOOOOOOOOO.... Your Oxen Wallet was locked to
@ -5624,7 +5649,7 @@ void simple_wallet::check_for_inactivity_lock(bool user)
while (1)
{
const char *inactivity_msg = user ? "" : tr("Locked due to inactivity.");
tools::msg_writer() << inactivity_msg << (inactivity_msg[0] ? " " : "") << tr("The wallet password is required to unlock the console.");
message_writer() << inactivity_msg << (inactivity_msg[0] ? " " : "") << tr("The wallet password is required to unlock the console.");
try
{
if (get_and_verify_password())
@ -6178,7 +6203,7 @@ bool simple_wallet::stake(const std::vector<std::string> &args_)
}
if (!stake_result.msg.empty()) // i.e. warnings
tools::msg_writer() << stake_result.msg;
message_writer() << stake_result.msg;
std::vector<tools::wallet2::pending_tx> ptx_vector = {stake_result.ptx};
cryptonote::address_parse_info info = {};
@ -6233,7 +6258,7 @@ bool simple_wallet::request_stake_unlock(const std::vector<std::string> &args_)
tools::wallet2::request_stake_unlock_result unlock_result = m_wallet->can_request_stake_unlock(snode_key);
if (unlock_result.success)
{
tools::msg_writer() << unlock_result.msg;
message_writer() << unlock_result.msg;
}
else
{
@ -6542,7 +6567,7 @@ bool simple_wallet::query_locked_stakes(bool print_details, bool print_key_image
if (msg.empty() && print_details)
msg = "No locked stakes known for this wallet on the network";
if (!msg.empty())
tools::msg_writer() << msg;
message_writer() << msg;
return has_locked_stakes;
}
@ -6574,7 +6599,7 @@ static std::optional<ons::mapping_type> guess_ons_type(tools::wallet2& wallet, s
auto hf_version = wallet.get_hard_fork_version();
if (!hf_version)
{
tools::fail_msg_writer() << tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
fail_msg_writer() << tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
return std::nullopt;
}
@ -6633,7 +6658,7 @@ bool simple_wallet::ons_buy_mapping(std::vector<std::string> args)
if (ptx_vector.empty())
{
tools::fail_msg_writer() << reason;
fail_msg_writer() << reason;
return true;
}
@ -6731,7 +6756,7 @@ bool simple_wallet::ons_renew_mapping(std::vector<std::string> args)
&response);
if (ptx_vector.empty())
{
tools::fail_msg_writer() << reason;
fail_msg_writer() << reason;
return true;
}
@ -6816,7 +6841,7 @@ bool simple_wallet::ons_update_mapping(std::vector<std::string> args)
&response);
if (ptx_vector.empty())
{
tools::fail_msg_writer() << reason;
fail_msg_writer() << reason;
return true;
}
@ -6929,32 +6954,32 @@ bool simple_wallet::ons_encrypt(std::vector<std::string> args)
auto hf_version = m_wallet->get_hard_fork_version();
if (!hf_version)
{
tools::fail_msg_writer() << tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
fail_msg_writer() << tools::wallet2::ERR_MSG_NETWORK_VERSION_QUERY_FAILED;
return false;
}
std::string reason;
if (!ons::validate_ons_name(type, name, &reason))
{
tools::fail_msg_writer() << "Invalid ONS name '" << name << "': " << reason;
fail_msg_writer() << "Invalid ONS name '" << name << "': " << reason;
return false;
}
ons::mapping_value mval;
if (!ons::mapping_value::validate(m_wallet->nettype(), type, value, &mval, &reason))
{
tools::fail_msg_writer() << "Invalid ONS value '" << value << "': " << reason;
fail_msg_writer() << "Invalid ONS value '" << value << "': " << reason;
return false;
}
bool old_argon2 = type == ons::mapping_type::session && hf_version < hf::hf16_pulse;
if (!mval.encrypt(name, nullptr, old_argon2))
{
tools::fail_msg_writer() << "Value encryption failed";
fail_msg_writer() << "Value encryption failed";
return false;
}
tools::success_msg_writer() << "encrypted value=" << oxenc::to_hex(mval.to_view());
success_msg_writer() << "encrypted value=" << oxenc::to_hex(mval.to_view());
return true;
}
//----------------------------------------------------------------------------------------------------
@ -6984,7 +7009,7 @@ bool simple_wallet::ons_make_update_mapping_signature(std::vector<std::string> a
signature_binary,
m_current_subaddress_account,
&reason))
tools::success_msg_writer() << "signature=" << tools::type_to_hex(signature_binary.ed25519);
success_msg_writer() << "signature=" << tools::type_to_hex(signature_binary.ed25519);
else
fail_msg_writer() << reason;
@ -7091,7 +7116,7 @@ bool simple_wallet::ons_lookup(std::vector<std::string> args)
return false;
}
auto writer = tools::msg_writer();
auto writer = message_writer();
writer
<< "Name: " << name
<< "\n Type: " << static_cast<ons::mapping_type>(mapping["type"])
@ -7182,7 +7207,7 @@ bool simple_wallet::ons_by_owner(const std::vector<std::string>& args)
value = mv.to_readable_value(nettype, ons_type);
}
auto writer = tools::msg_writer();
auto writer = message_writer();
writer
<< "Name (hashed): " << entry["name_hash"];
if (!name.empty()) writer
@ -10336,7 +10361,7 @@ int main(int argc, char* argv[])
desc_params,
hidden_params,
positional_options,
[](const std::string &s){ tools::scoped_message_writer(fmt::terminal_color::white) << s; },
[](const std::string &s){ tools::scoped_message_writer() + s; },
"oxen-wallet-cli.log"
);

View File

@ -39,7 +39,6 @@
#include <memory>
#include <vector>
#include <sstream>
#include <boost/format.hpp>
namespace Wallet {

View File

@ -37,7 +37,6 @@
#include <memory>
#include <vector>
#include <sstream>
#include <boost/format.hpp>
namespace Wallet {

View File

@ -29,6 +29,7 @@
#include <lmdb.h>
#include "common/file.h"
#include "common/fs-format.h"
#include "epee/misc_log_ex.h"
#include "wallet_errors.h"
#include "ringdb.h"

View File

@ -64,6 +64,7 @@
#include "common/i18n.h"
#include "common/util.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "common/apply_permutation.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
@ -249,7 +250,7 @@ namespace {
if (auto got = m_vote_ctx.find("m_votes_not_sorted"); got != m_vote_ctx.end()) os << "Votes are not stored in ascending order";
if (tx)
os << "TX Version: " << tx->version << ", Type: " << tx->type;
os << "TX Version: {}, Type: {}"_format(tx->version, tx->type);
std::string buf = os.str();
if (buf.size() >= 2 && buf[buf.size() - 2] == ',')

View File

@ -54,7 +54,6 @@
#include "common/file.h"
#include "crypto/chacha.h"
#include "crypto/hash.h"
#include "crypto/fmt.h"
#include "ringct/rctTypes.h"
#include "ringct/rctOps.h"
#include "checkpoints/checkpoints.h"

View File

@ -33,6 +33,7 @@
#include "common/i18n.h"
#include "common/util.h"
#include "common/file.h"
#include "common/fs-format.h"
#include "epee/misc_log_ex.h"
#include "epee/string_tools.h"
#include "version.h"

View File

@ -43,6 +43,7 @@
#include "common/command_line.h"
#include "common/i18n.h"
#include "common/signal_handler.h"
#include "common/fs-format.h"
#include "cryptonote_config.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/account.h"

View File

@ -33,6 +33,7 @@ target_link_libraries(difficulty-tests
cncrypto
epee
cryptonote_basic
common
extra)
set_property(TARGET difficulty-tests
PROPERTY

View File

@ -48,7 +48,6 @@ namespace
"6c7251d54154cfa92c173a0dd39c1f948b655970153799af2aeadc9ff1add0ea";
template<typename T> void *addressof(T &t) { return &t; }
template<> void *addressof(crypto::secret_key &k) { return addressof(unwrap(unwrap(k))); }
template<typename T>
bool is_formatted()
@ -60,9 +59,7 @@ namespace
static_assert(sizeof(T) * 2 <= sizeof(expected), "T is too large for destination");
std::memcpy(addressof(value), source, sizeof(T));
std::stringstream out;
out << "BEGIN" << value << "END";
return out.str() == "BEGIN<" + std::string{expected, sizeof(T) * 2} + ">END";
return "{}"_format(value) == "<{}>"_format(std::string{expected, sizeof(T) * 2});
}
}
@ -71,7 +68,6 @@ TEST(Crypto, Ostream)
EXPECT_TRUE(is_formatted<crypto::hash8>());
EXPECT_TRUE(is_formatted<crypto::hash>());
EXPECT_TRUE(is_formatted<crypto::public_key>());
EXPECT_TRUE(is_formatted<crypto::secret_key>());
EXPECT_TRUE(is_formatted<crypto::signature>());
EXPECT_TRUE(is_formatted<crypto::key_derivation>());
EXPECT_TRUE(is_formatted<crypto::key_image>());

View File

@ -78,7 +78,7 @@ TEST(oxen_name_system, name_tests)
for (size_t i = 0; i < names_count; i++)
{
name_test const &entry = names[i];
ASSERT_EQ(ons::validate_ons_name(type, entry.name), entry.allowed) << "Values were {type=" << type << ", name=\"" << entry.name << "\"}";
ASSERT_EQ(ons::validate_ons_name(type, entry.name), entry.allowed) << "Values were {{type={}, name=\"{}\"}}"_format(type, entry.name);
}
}
}

View File

@ -778,11 +778,10 @@ TEST(ringct, reject_gen_simple_ver_non_simple)
TEST(ringct, key_ostream)
{
std::stringstream out;
out << "BEGIN" << rct::H << "END";
auto out = "BEGIN{}END"_format(rct::H);
EXPECT_EQ(
std::string{"BEGIN<8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94>END"},
out.str()
out
);
}