mirror of
https://github.com/XRPLF/clio.git
synced 2025-11-18 10:45:51 +00:00
chore: Commits from develop for 2.4.0-b2 (#1811)
This commit is contained in:
34
.clang-tidy
34
.clang-tidy
@@ -130,6 +130,7 @@ Checks: '-*,
|
||||
readability-enum-initial-value,
|
||||
readability-implicit-bool-conversion,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-identifier-naming,
|
||||
readability-make-member-function-const,
|
||||
readability-math-missing-parentheses,
|
||||
readability-misleading-indentation,
|
||||
@@ -149,6 +150,39 @@ Checks: '-*,
|
||||
|
||||
CheckOptions:
|
||||
readability-braces-around-statements.ShortStatementLines: 2
|
||||
readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
|
||||
readability-identifier-naming.ClassCase: CamelCase
|
||||
readability-identifier-naming.StructCase: CamelCase
|
||||
readability-identifier-naming.UnionCase: CamelCase
|
||||
readability-identifier-naming.EnumCase: CamelCase
|
||||
readability-identifier-naming.EnumConstantCase: CamelCase
|
||||
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
|
||||
readability-identifier-naming.GlobalConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.GlobalConstantPrefix: 'k'
|
||||
readability-identifier-naming.GlobalVariableCase: CamelCase
|
||||
readability-identifier-naming.GlobalVariablePrefix: 'g'
|
||||
readability-identifier-naming.ConstexprFunctionCase: camelBack
|
||||
readability-identifier-naming.ConstexprMethodCase: camelBack
|
||||
readability-identifier-naming.ClassMethodCase: camelBack
|
||||
readability-identifier-naming.ClassMemberCase: camelBack
|
||||
readability-identifier-naming.ClassConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.ClassConstantPrefix: 'k'
|
||||
readability-identifier-naming.StaticConstantCase: UPPER_CASE
|
||||
readability-identifier-naming.StaticConstantPrefix: 'k'
|
||||
readability-identifier-naming.StaticVariableCase: UPPER_CASE
|
||||
readability-identifier-naming.StaticVariablePrefix: 'k'
|
||||
readability-identifier-naming.ConstexprVariableCase: UPPER_CASE
|
||||
readability-identifier-naming.ConstexprVariablePrefix: 'k'
|
||||
readability-identifier-naming.LocalConstantCase: camelBack
|
||||
readability-identifier-naming.LocalVariableCase: camelBack
|
||||
readability-identifier-naming.TemplateParameterCase: CamelCase
|
||||
readability-identifier-naming.ParameterCase: camelBack
|
||||
readability-identifier-naming.FunctionCase: camelBack
|
||||
readability-identifier-naming.MemberCase: camelBack
|
||||
readability-identifier-naming.PrivateMemberSuffix: _
|
||||
readability-identifier-naming.ProtectedMemberSuffix: _
|
||||
readability-identifier-naming.PublicMemberSuffix: ''
|
||||
readability-identifier-naming.FunctionIgnoredRegexp: '.*tag_invoke.*'
|
||||
bugprone-unsafe-functions.ReportMoreUnsafeFunctions: true
|
||||
bugprone-unused-return-value.CheckedReturnTypes: ::std::error_code;::std::error_condition;::std::errc
|
||||
misc-include-cleaner.IgnoreHeaders: '.*/(detail|impl)/.*;.*(expected|unexpected).*;.*ranges_lower_bound\.h;time.h;stdlib.h'
|
||||
|
||||
2
.github/actions/prepare_runner/action.yml
vendored
2
.github/actions/prepare_runner/action.yml
vendored
@@ -11,7 +11,7 @@ runs:
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: bash
|
||||
run: |
|
||||
brew install llvm@14 pkg-config ninja bison cmake ccache jq gh conan@1
|
||||
brew install llvm@14 pkg-config ninja bison cmake ccache jq gh conan@1 ca-certificates
|
||||
echo "/opt/homebrew/opt/conan@1/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Fix git permissions on Linux
|
||||
|
||||
4
.github/actions/setup_conan/action.yml
vendored
4
.github/actions/setup_conan/action.yml
vendored
@@ -15,10 +15,10 @@ runs:
|
||||
if: ${{ runner.os == 'macOS' }}
|
||||
shell: bash
|
||||
env:
|
||||
CONAN_PROFILE: apple_clang_15
|
||||
CONAN_PROFILE: apple_clang_16
|
||||
id: conan_setup_mac
|
||||
run: |
|
||||
echo "Creating $CONAN_PROFILE conan profile";
|
||||
echo "Creating $CONAN_PROFILE conan profile"
|
||||
conan profile new $CONAN_PROFILE --detect --force
|
||||
conan profile update settings.compiler.libcxx=libc++ $CONAN_PROFILE
|
||||
conan profile update settings.compiler.cppstd=20 $CONAN_PROFILE
|
||||
|
||||
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -74,7 +74,7 @@ jobs:
|
||||
conan_profile: clang
|
||||
code_coverage: false
|
||||
static: true
|
||||
- os: macos14
|
||||
- os: macos15
|
||||
build_type: Release
|
||||
code_coverage: false
|
||||
static: false
|
||||
@@ -197,8 +197,8 @@ jobs:
|
||||
image: rippleci/clio_ci:latest
|
||||
conan_profile: clang
|
||||
build_type: Debug
|
||||
- os: macos14
|
||||
conan_profile: apple_clang_15
|
||||
- os: macos15
|
||||
conan_profile: apple_clang_16
|
||||
build_type: Release
|
||||
runs-on: [self-hosted, "${{ matrix.os }}"]
|
||||
container: ${{ matrix.container }}
|
||||
|
||||
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos14
|
||||
- os: macos15
|
||||
build_type: Release
|
||||
static: false
|
||||
- os: heavy
|
||||
@@ -90,7 +90,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: macos14
|
||||
- os: macos15
|
||||
build_type: Release
|
||||
integration_tests: false
|
||||
- os: heavy
|
||||
|
||||
@@ -188,10 +188,10 @@ public:
|
||||
static auto
|
||||
generateData()
|
||||
{
|
||||
constexpr auto TOTAL = 10'000;
|
||||
constexpr auto kTOTAL = 10'000;
|
||||
std::vector<uint64_t> data;
|
||||
data.reserve(TOTAL);
|
||||
for (auto i = 0; i < TOTAL; ++i)
|
||||
data.reserve(kTOTAL);
|
||||
for (auto i = 0; i < kTOTAL; ++i)
|
||||
data.push_back(util::Random::uniform(1, 100'000'000));
|
||||
|
||||
return data;
|
||||
|
||||
@@ -23,19 +23,19 @@
|
||||
|
||||
namespace util::build {
|
||||
|
||||
static constexpr char versionString[] = "@CLIO_VERSION@";
|
||||
static constexpr char versionString[] = "@CLIO_VERSION@"; // NOLINT(readability-identifier-naming)
|
||||
|
||||
std::string const&
|
||||
getClioVersionString()
|
||||
{
|
||||
static std::string const value = versionString;
|
||||
static std::string const value = versionString; // NOLINT(readability-identifier-naming)
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string const&
|
||||
getClioFullVersionString()
|
||||
{
|
||||
static std::string const value = "clio-" + getClioVersionString();
|
||||
static std::string const value = "clio-" + getClioVersionString(); // NOLINT(readability-identifier-naming)
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ CliArgs::parse(int argc, char const* argv[])
|
||||
description.add_options()
|
||||
("help,h", "print help message and exit")
|
||||
("version,v", "print version and exit")
|
||||
("conf,c", po::value<std::string>()->default_value(defaultConfigPath), "configuration file")
|
||||
("conf,c", po::value<std::string>()->default_value(kDEFAULT_CONFIG_PATH), "configuration file")
|
||||
("ng-web-server,w", "Use ng-web-server")
|
||||
("migrate", po::value<std::string>(), "start migration helper")
|
||||
;
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/**
|
||||
* @brief Default configuration path.
|
||||
*/
|
||||
static constexpr char defaultConfigPath[] = "/etc/opt/clio/config.json";
|
||||
static constexpr char kDEFAULT_CONFIG_PATH[] = "/etc/opt/clio/config.json";
|
||||
|
||||
/**
|
||||
* @brief An action parsed from the command line.
|
||||
|
||||
@@ -101,25 +101,25 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
auto sweepHandler = web::dosguard::IntervalSweepHandler{config_, ioc, dosGuard};
|
||||
|
||||
// Interface to the database
|
||||
auto backend = data::make_Backend(config_);
|
||||
auto backend = data::makeBackend(config_);
|
||||
|
||||
// Manages clients subscribed to streams
|
||||
auto subscriptions = feed::SubscriptionManager::make_SubscriptionManager(config_, backend);
|
||||
auto subscriptions = feed::SubscriptionManager::makeSubscriptionManager(config_, backend);
|
||||
|
||||
// Tracks which ledgers have been validated by the network
|
||||
auto ledgers = etl::NetworkValidatedLedgers::make_ValidatedLedgers();
|
||||
auto ledgers = etl::NetworkValidatedLedgers::makeValidatedLedgers();
|
||||
|
||||
// Handles the connection to one or more rippled nodes.
|
||||
// ETL uses the balancer to extract data.
|
||||
// The server uses the balancer to forward RPCs to a rippled node.
|
||||
// The balancer itself publishes to streams (transactions_proposed and accounts_proposed)
|
||||
auto balancer = etl::LoadBalancer::make_LoadBalancer(config_, ioc, backend, subscriptions, ledgers);
|
||||
auto balancer = etl::LoadBalancer::makeLoadBalancer(config_, ioc, backend, subscriptions, ledgers);
|
||||
|
||||
// ETL is responsible for writing and publishing to streams. In read-only mode, ETL only publishes
|
||||
auto etl = etl::ETLService::make_ETLService(config_, ioc, backend, subscriptions, balancer, ledgers);
|
||||
auto etl = etl::ETLService::makeETLService(config_, ioc, backend, subscriptions, balancer, ledgers);
|
||||
|
||||
auto workQueue = rpc::WorkQueue::make_WorkQueue(config_);
|
||||
auto counters = rpc::Counters::make_Counters(workQueue);
|
||||
auto workQueue = rpc::WorkQueue::makeWorkQueue(config_);
|
||||
auto counters = rpc::Counters::makeCounters(workQueue);
|
||||
auto const amendmentCenter = std::make_shared<data::AmendmentCenter const>(backend);
|
||||
auto const handlerProvider = std::make_shared<rpc::impl::ProductionHandlerProvider const>(
|
||||
config_, backend, subscriptions, balancer, etl, amendmentCenter, counters
|
||||
@@ -127,19 +127,19 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
|
||||
using RPCEngineType = rpc::RPCEngine<etl::LoadBalancer, rpc::Counters>;
|
||||
auto const rpcEngine =
|
||||
RPCEngineType::make_RPCEngine(config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider);
|
||||
RPCEngineType::makeRPCEngine(config_, backend, balancer, dosGuard, workQueue, counters, handlerProvider);
|
||||
|
||||
if (useNgWebServer or config_.get<bool>("server.__ng_web_server")) {
|
||||
web::ng::RPCServerHandler<RPCEngineType, etl::ETLService> handler{config_, backend, rpcEngine, etl};
|
||||
|
||||
auto expectedAdminVerifier = web::make_AdminVerificationStrategy(config_);
|
||||
auto expectedAdminVerifier = web::makeAdminVerificationStrategy(config_);
|
||||
if (not expectedAdminVerifier.has_value()) {
|
||||
LOG(util::LogService::error()) << "Error creating admin verifier: " << expectedAdminVerifier.error();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const adminVerifier = std::move(expectedAdminVerifier).value();
|
||||
|
||||
auto httpServer = web::ng::make_Server(config_, OnConnectCheck{dosGuard}, DisconnectHook{dosGuard}, ioc);
|
||||
auto httpServer = web::ng::makeServer(config_, OnConnectCheck{dosGuard}, DisconnectHook{dosGuard}, ioc);
|
||||
|
||||
if (not httpServer.has_value()) {
|
||||
LOG(util::LogService::error()) << "Error creating web server: " << httpServer.error();
|
||||
@@ -170,7 +170,7 @@ ClioApplication::run(bool const useNgWebServer)
|
||||
auto handler =
|
||||
std::make_shared<web::RPCServerHandler<RPCEngineType, etl::ETLService>>(config_, backend, rpcEngine, etl);
|
||||
|
||||
auto const httpServer = web::make_HttpServer(config_, ioc, dosGuard, handler);
|
||||
auto const httpServer = web::makeHttpServer(config_, ioc, dosGuard, handler);
|
||||
|
||||
// Blocks until stopped.
|
||||
// When stopped, shared_ptrs fall out of scope
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
//==============================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/SignalsHandler.hpp"
|
||||
#include "util/newconfig/ConfigDefinition.hpp"
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ HealthCheckHandler::operator()(
|
||||
boost::asio::yield_context
|
||||
)
|
||||
{
|
||||
static auto constexpr HealthCheckHTML = R"html(
|
||||
static auto constexpr kHEALTH_CHECK_HTML = R"html(
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Test page for Clio</title></head>
|
||||
@@ -105,7 +105,7 @@ HealthCheckHandler::operator()(
|
||||
</html>
|
||||
)html";
|
||||
|
||||
return web::ng::Response{boost::beast::http::status::ok, HealthCheckHTML, request};
|
||||
return web::ng::Response{boost::beast::http::status::ok, kHEALTH_CHECK_HTML, request};
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
@@ -213,9 +213,9 @@ public:
|
||||
auto jsonResponse = boost::json::parse(response.message()).as_object();
|
||||
jsonResponse["warning"] = "load";
|
||||
if (jsonResponse.contains("warnings") && jsonResponse["warnings"].is_array()) {
|
||||
jsonResponse["warnings"].as_array().push_back(rpc::makeWarning(rpc::warnRPC_RATE_LIMIT));
|
||||
jsonResponse["warnings"].as_array().push_back(rpc::makeWarning(rpc::WarnRpcRateLimit));
|
||||
} else {
|
||||
jsonResponse["warnings"] = boost::json::array{rpc::makeWarning(rpc::warnRPC_RATE_LIMIT)};
|
||||
jsonResponse["warnings"] = boost::json::array{rpc::makeWarning(rpc::WarnRpcRateLimit)};
|
||||
}
|
||||
response.setMessage(jsonResponse);
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
namespace {
|
||||
|
||||
std::unordered_set<std::string>&
|
||||
SUPPORTED_AMENDMENTS()
|
||||
supportedAmendments()
|
||||
{
|
||||
static std::unordered_set<std::string> amendments = {};
|
||||
return amendments;
|
||||
static std::unordered_set<std::string> kAMENDMENTS = {};
|
||||
return kAMENDMENTS;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -72,8 +72,8 @@ namespace impl {
|
||||
|
||||
WritingAmendmentKey::WritingAmendmentKey(std::string amendmentName) : AmendmentKey{std::move(amendmentName)}
|
||||
{
|
||||
ASSERT(not SUPPORTED_AMENDMENTS().contains(name), "Attempt to register the same amendment twice");
|
||||
SUPPORTED_AMENDMENTS().insert(name);
|
||||
ASSERT(not supportedAmendments().contains(name), "Attempt to register the same amendment twice");
|
||||
supportedAmendments().insert(name);
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
@@ -90,7 +90,7 @@ AmendmentKey::operator std::string_view() const
|
||||
|
||||
AmendmentKey::operator ripple::uint256() const
|
||||
{
|
||||
return Amendment::GetAmendmentId(name);
|
||||
return Amendment::getAmendmentId(name);
|
||||
}
|
||||
|
||||
AmendmentCenter::AmendmentCenter(std::shared_ptr<data::BackendInterface> const& backend) : backend_{backend}
|
||||
@@ -103,9 +103,9 @@ AmendmentCenter::AmendmentCenter(std::shared_ptr<data::BackendInterface> const&
|
||||
auto const& [name, support] = p;
|
||||
return Amendment{
|
||||
.name = name,
|
||||
.feature = Amendment::GetAmendmentId(name),
|
||||
.feature = Amendment::getAmendmentId(name),
|
||||
.isSupportedByXRPL = support != ripple::AmendmentSupport::Unsupported,
|
||||
.isSupportedByClio = rg::find(SUPPORTED_AMENDMENTS(), name) != rg::end(SUPPORTED_AMENDMENTS()),
|
||||
.isSupportedByClio = rg::find(supportedAmendments(), name) != rg::end(supportedAmendments()),
|
||||
.isRetired = support == ripple::AmendmentSupport::Retired
|
||||
};
|
||||
}),
|
||||
@@ -180,7 +180,7 @@ AmendmentCenter::operator[](AmendmentKey const& key) const
|
||||
}
|
||||
|
||||
ripple::uint256
|
||||
Amendment::GetAmendmentId(std::string_view name)
|
||||
Amendment::getAmendmentId(std::string_view name)
|
||||
{
|
||||
return ripple::sha512Half(ripple::Slice(name.data(), name.size()));
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ struct Amendments {
|
||||
// Most of the time it's going to be no changes at all.
|
||||
|
||||
/** @cond */
|
||||
// NOLINTBEGIN(readability-identifier-naming)
|
||||
REGISTER(OwnerPaysFee);
|
||||
REGISTER(Flow);
|
||||
REGISTER(FlowCross);
|
||||
@@ -154,6 +155,7 @@ struct Amendments {
|
||||
REGISTER(fix1512);
|
||||
REGISTER(fix1523);
|
||||
REGISTER(fix1528);
|
||||
// NOLINTEND(readability-identifier-naming)
|
||||
/** @endcond */
|
||||
};
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace data {
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<std::int64_t> const histogramBuckets{1, 2, 5, 10, 20, 50, 100, 200, 500, 700, 1000};
|
||||
std::vector<std::int64_t> const kHISTOGRAM_BUCKETS{1, 2, 5, 10, 20, 50, 100, 200, 500, 700, 1000};
|
||||
|
||||
std::int64_t
|
||||
durationInMillisecondsSince(std::chrono::steady_clock::time_point const startTime)
|
||||
@@ -69,13 +69,13 @@ BackendCounters::BackendCounters()
|
||||
, readDurationHistogram_(PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "read"}}),
|
||||
histogramBuckets,
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend read operations including retries"
|
||||
))
|
||||
, writeDurationHistogram_(PrometheusService::histogramInt(
|
||||
"backend_duration_milliseconds_histogram",
|
||||
Labels({Label{"operation", "write"}}),
|
||||
histogramBuckets,
|
||||
kHISTOGRAM_BUCKETS,
|
||||
"The duration of backend write operations including retries"
|
||||
))
|
||||
{
|
||||
|
||||
@@ -41,9 +41,9 @@ namespace data {
|
||||
* @return A shared_ptr<BackendInterface> with the selected implementation
|
||||
*/
|
||||
inline std::shared_ptr<BackendInterface>
|
||||
make_Backend(util::config::ClioConfigDefinition const& config)
|
||||
makeBackend(util::config::ClioConfigDefinition const& config)
|
||||
{
|
||||
static util::Logger const log{"Backend"};
|
||||
static util::Logger const log{"Backend"}; // NOLINT(readability-identifier-naming)
|
||||
LOG(log.info()) << "Constructing BackendInterface";
|
||||
|
||||
auto const readOnly = config.get<bool>("read_only");
|
||||
|
||||
@@ -267,7 +267,7 @@ std::optional<LedgerRange>
|
||||
BackendInterface::fetchLedgerRange() const
|
||||
{
|
||||
std::shared_lock const lck(rngMtx_);
|
||||
return range;
|
||||
return range_;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -276,16 +276,16 @@ BackendInterface::updateRange(uint32_t newMax)
|
||||
std::scoped_lock const lck(rngMtx_);
|
||||
|
||||
ASSERT(
|
||||
!range || newMax >= range->maxSequence,
|
||||
!range_ || newMax >= range_->maxSequence,
|
||||
"Range shouldn't exist yet or newMax should be greater. newMax = {}, range->maxSequence = {}",
|
||||
newMax,
|
||||
range->maxSequence
|
||||
range_->maxSequence
|
||||
);
|
||||
|
||||
if (!range) {
|
||||
range = {.minSequence = newMax, .maxSequence = newMax};
|
||||
if (!range_) {
|
||||
range_ = {.minSequence = newMax, .maxSequence = newMax};
|
||||
} else {
|
||||
range->maxSequence = newMax;
|
||||
range_->maxSequence = newMax;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,10 +296,10 @@ BackendInterface::setRange(uint32_t min, uint32_t max, bool force)
|
||||
|
||||
if (!force) {
|
||||
ASSERT(min <= max, "Range min must be less than or equal to max");
|
||||
ASSERT(not range.has_value(), "Range was already set");
|
||||
ASSERT(not range_.has_value(), "Range was already set");
|
||||
}
|
||||
|
||||
range = {.minSequence = min, .maxSequence = max};
|
||||
range_ = {.minSequence = min, .maxSequence = max};
|
||||
}
|
||||
|
||||
LedgerPage
|
||||
@@ -320,10 +320,10 @@ BackendInterface::fetchLedgerPage(
|
||||
ripple::uint256 const& curCursor = [&]() {
|
||||
if (!keys.empty())
|
||||
return keys.back();
|
||||
return (cursor ? *cursor : firstKey);
|
||||
return (cursor ? *cursor : kFIRST_KEY);
|
||||
}();
|
||||
|
||||
std::uint32_t const seq = outOfOrder ? range->maxSequence : ledgerSequence;
|
||||
std::uint32_t const seq = outOfOrder ? range_->maxSequence : ledgerSequence;
|
||||
auto succ = fetchSuccessorKey(curCursor, seq, yield);
|
||||
|
||||
if (!succ) {
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr std::size_t DEFAULT_WAIT_BETWEEN_RETRY = 500;
|
||||
static constexpr std::size_t kDEFAULT_WAIT_BETWEEN_RETRY = 500;
|
||||
/**
|
||||
* @brief A helper function that catches DatabaseTimout exceptions and retries indefinitely.
|
||||
*
|
||||
@@ -76,9 +76,9 @@ static constexpr std::size_t DEFAULT_WAIT_BETWEEN_RETRY = 500;
|
||||
*/
|
||||
template <typename FnType>
|
||||
auto
|
||||
retryOnTimeout(FnType func, size_t waitMs = DEFAULT_WAIT_BETWEEN_RETRY)
|
||||
retryOnTimeout(FnType func, size_t waitMs = kDEFAULT_WAIT_BETWEEN_RETRY)
|
||||
{
|
||||
static util::Logger const log{"Backend"};
|
||||
static util::Logger const log{"Backend"}; // NOLINT(readability-identifier-naming)
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
@@ -138,7 +138,7 @@ synchronousAndRetryOnTimeout(FnType&& func)
|
||||
class BackendInterface {
|
||||
protected:
|
||||
mutable std::shared_mutex rngMtx_;
|
||||
std::optional<LedgerRange> range;
|
||||
std::optional<LedgerRange> range_;
|
||||
LedgerCache cache_;
|
||||
std::optional<etl::CorruptionDetector<LedgerCache>> corruptionDetector_;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "data/BackendInterface.hpp"
|
||||
#include "data/DBHelpers.hpp"
|
||||
#include "data/Types.hpp"
|
||||
#include "data/cassandra/Concepts.hpp"
|
||||
#include "data/cassandra/Handle.hpp"
|
||||
#include "data/cassandra/Schema.hpp"
|
||||
#include "data/cassandra/SettingsProvider.hpp"
|
||||
@@ -193,7 +194,7 @@ public:
|
||||
// wait for other threads to finish their writes
|
||||
executor_.sync();
|
||||
|
||||
if (!range) {
|
||||
if (!range_) {
|
||||
executor_.writeSync(schema_->updateLedgerRange, ledgerSequence_, false, ledgerSequence_);
|
||||
}
|
||||
|
||||
@@ -649,7 +650,7 @@ public:
|
||||
{
|
||||
if (auto const res = executor_.read(yield, schema_->selectSuccessor, key, ledgerSequence); res) {
|
||||
if (auto const result = res->template get<ripple::uint256>(); result) {
|
||||
if (*result == lastKey)
|
||||
if (*result == kLAST_KEY)
|
||||
return std::nullopt;
|
||||
return result;
|
||||
}
|
||||
@@ -862,7 +863,7 @@ public:
|
||||
{
|
||||
LOG(log_.trace()) << " Writing ledger object " << key.size() << ":" << seq << " [" << blob.size() << " bytes]";
|
||||
|
||||
if (range)
|
||||
if (range_)
|
||||
executor_.write(schema_->insertDiff, seq, key);
|
||||
|
||||
executor_.write(schema_->insertObject, std::move(key), seq, std::move(blob));
|
||||
|
||||
@@ -190,11 +190,11 @@ template <typename T>
|
||||
inline bool
|
||||
isOffer(T const& object)
|
||||
{
|
||||
static constexpr short OFFER_OFFSET = 0x006f;
|
||||
static constexpr short SHIFT = 8;
|
||||
static constexpr short kOFFER_OFFSET = 0x006f;
|
||||
static constexpr short kSHIFT = 8;
|
||||
|
||||
short offer_bytes = (object[1] << SHIFT) | object[2];
|
||||
return offer_bytes == OFFER_OFFSET;
|
||||
short offerBytes = (object[1] << kSHIFT) | object[2];
|
||||
return offerBytes == kOFFER_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,9 +223,9 @@ template <typename T>
|
||||
inline bool
|
||||
isDirNode(T const& object)
|
||||
{
|
||||
static constexpr short DIR_NODE_SPACE_KEY = 0x0064;
|
||||
static constexpr short kDIR_NODE_SPACE_KEY = 0x0064;
|
||||
short const spaceKey = (object.data()[1] << 8) | object.data()[2];
|
||||
return spaceKey == DIR_NODE_SPACE_KEY;
|
||||
return spaceKey == kDIR_NODE_SPACE_KEY;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,12 +273,12 @@ template <typename T>
|
||||
inline ripple::uint256
|
||||
getBookBase(T const& key)
|
||||
{
|
||||
static constexpr size_t KEY_SIZE = 24;
|
||||
static constexpr size_t kEY_SIZE = 24;
|
||||
|
||||
ASSERT(key.size() == ripple::uint256::size(), "Invalid key size {}", key.size());
|
||||
|
||||
ripple::uint256 ret;
|
||||
for (size_t i = 0; i < KEY_SIZE; ++i)
|
||||
for (size_t i = 0; i < kEY_SIZE; ++i)
|
||||
ret.data()[i] = key.data()[i];
|
||||
|
||||
return ret;
|
||||
@@ -297,4 +297,4 @@ uint256ToString(ripple::uint256 const& input)
|
||||
}
|
||||
|
||||
/** @brief The ripple epoch start timestamp. Midnight on 1st January 2000. */
|
||||
static constexpr std::uint32_t rippleEpochStart = 946684800;
|
||||
static constexpr std::uint32_t kRIPPLE_EPOCH_START = 946684800;
|
||||
|
||||
@@ -266,7 +266,7 @@ struct Amendment {
|
||||
* @return The amendment Id as uint256
|
||||
*/
|
||||
static ripple::uint256
|
||||
GetAmendmentId(std::string_view const name);
|
||||
getAmendmentId(std::string_view const name);
|
||||
|
||||
/**
|
||||
* @brief Equality comparison operator
|
||||
@@ -312,8 +312,8 @@ struct AmendmentKey {
|
||||
operator<=>(AmendmentKey const& other) const = default;
|
||||
};
|
||||
|
||||
constexpr ripple::uint256 firstKey{"0000000000000000000000000000000000000000000000000000000000000000"};
|
||||
constexpr ripple::uint256 lastKey{"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"};
|
||||
constexpr ripple::uint256 hi192{"0000000000000000000000000000000000000000000000001111111111111111"};
|
||||
constexpr ripple::uint256 kFIRST_KEY{"0000000000000000000000000000000000000000000000000000000000000000"};
|
||||
constexpr ripple::uint256 kLAST_KEY{"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"};
|
||||
constexpr ripple::uint256 kHI192{"0000000000000000000000000000000000000000000000001111111111111111"};
|
||||
|
||||
} // namespace data
|
||||
|
||||
@@ -100,12 +100,12 @@ SettingsProvider::parseSettings() const
|
||||
|
||||
if (config_.getValueView("connect_timeout").hasValue()) {
|
||||
auto const connectTimeoutSecond = config_.get<uint32_t>("connect_timeout");
|
||||
settings.connectionTimeout = std::chrono::milliseconds{connectTimeoutSecond * util::MILLISECONDS_PER_SECOND};
|
||||
settings.connectionTimeout = std::chrono::milliseconds{connectTimeoutSecond * util::kMILLISECONDS_PER_SECOND};
|
||||
}
|
||||
|
||||
if (config_.getValueView("request_timeout").hasValue()) {
|
||||
auto const requestTimeoutSecond = config_.get<uint32_t>("request_timeout");
|
||||
settings.requestTimeout = std::chrono::milliseconds{requestTimeoutSecond * util::MILLISECONDS_PER_SECOND};
|
||||
settings.requestTimeout = std::chrono::milliseconds{requestTimeoutSecond * util::kMILLISECONDS_PER_SECOND};
|
||||
}
|
||||
|
||||
settings.certificate = parseOptionalCertificate();
|
||||
|
||||
@@ -31,14 +31,14 @@
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr auto batchDeleter = [](CassBatch* ptr) { cass_batch_free(ptr); };
|
||||
constexpr auto kBATCH_DELETER = [](CassBatch* ptr) { cass_batch_free(ptr); };
|
||||
} // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
// TODO: Use an appropriate value instead of CASS_BATCH_TYPE_LOGGED for different use cases
|
||||
Batch::Batch(std::vector<Statement> const& statements)
|
||||
: ManagedObject{cass_batch_new(CASS_BATCH_TYPE_LOGGED), batchDeleter}
|
||||
: ManagedObject{cass_batch_new(CASS_BATCH_TYPE_LOGGED), kBATCH_DELETER}
|
||||
{
|
||||
cass_batch_set_is_idempotent(*this, cass_true);
|
||||
|
||||
|
||||
@@ -33,13 +33,13 @@
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr auto clusterDeleter = [](CassCluster* ptr) { cass_cluster_free(ptr); };
|
||||
constexpr auto kCLUSTER_DELETER = [](CassCluster* ptr) { cass_cluster_free(ptr); };
|
||||
|
||||
}; // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
Cluster::Cluster(Settings const& settings) : ManagedObject{cass_cluster_new(), clusterDeleter}
|
||||
Cluster::Cluster(Settings const& settings) : ManagedObject{cass_cluster_new(), kCLUSTER_DELETER}
|
||||
{
|
||||
using std::to_string;
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <cassandra.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@@ -39,10 +41,10 @@ namespace data::cassandra::impl {
|
||||
* @brief Bundles all cassandra settings in one place.
|
||||
*/
|
||||
struct Settings {
|
||||
static constexpr std::size_t DEFAULT_CONNECTION_TIMEOUT = 10000;
|
||||
static constexpr uint32_t DEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING = 10'000;
|
||||
static constexpr uint32_t DEFAULT_MAX_READ_REQUESTS_OUTSTANDING = 100'000;
|
||||
static constexpr std::size_t DEFAULT_BATCH_SIZE = 20;
|
||||
static constexpr std::size_t kDEFAULT_CONNECTION_TIMEOUT = 10000;
|
||||
static constexpr uint32_t kDEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING = 10'000;
|
||||
static constexpr uint32_t kDEFAULT_MAX_READ_REQUESTS_OUTSTANDING = 100'000;
|
||||
static constexpr std::size_t kDEFAULT_BATCH_SIZE = 20;
|
||||
|
||||
/**
|
||||
* @brief Represents the configuration of contact points for cassandra.
|
||||
@@ -63,7 +65,7 @@ struct Settings {
|
||||
bool enableLog = false;
|
||||
|
||||
/** @brief Connect timeout specified in milliseconds */
|
||||
std::chrono::milliseconds connectionTimeout = std::chrono::milliseconds{DEFAULT_CONNECTION_TIMEOUT};
|
||||
std::chrono::milliseconds connectionTimeout = std::chrono::milliseconds{kDEFAULT_CONNECTION_TIMEOUT};
|
||||
|
||||
/** @brief Request timeout specified in milliseconds */
|
||||
std::chrono::milliseconds requestTimeout = std::chrono::milliseconds{0}; // no timeout at all
|
||||
@@ -75,16 +77,16 @@ struct Settings {
|
||||
uint32_t threads = std::thread::hardware_concurrency();
|
||||
|
||||
/** @brief The maximum number of outstanding write requests at any given moment */
|
||||
uint32_t maxWriteRequestsOutstanding = DEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING;
|
||||
uint32_t maxWriteRequestsOutstanding = kDEFAULT_MAX_WRITE_REQUESTS_OUTSTANDING;
|
||||
|
||||
/** @brief The maximum number of outstanding read requests at any given moment */
|
||||
uint32_t maxReadRequestsOutstanding = DEFAULT_MAX_READ_REQUESTS_OUTSTANDING;
|
||||
uint32_t maxReadRequestsOutstanding = kDEFAULT_MAX_READ_REQUESTS_OUTSTANDING;
|
||||
|
||||
/** @brief The number of connection per host to always have active */
|
||||
uint32_t coreConnectionsPerHost = 1u;
|
||||
|
||||
/** @brief Size of batches when writing */
|
||||
std::size_t writeBatchSize = DEFAULT_BATCH_SIZE;
|
||||
std::size_t writeBatchSize = kDEFAULT_BATCH_SIZE;
|
||||
|
||||
/** @brief Size of the IO queue */
|
||||
std::optional<uint32_t> queueSizeIO = std::nullopt; // NOLINT(readability-redundant-member-init)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
class Collection : public ManagedObject<CassCollection> {
|
||||
static constexpr auto deleter = [](CassCollection* ptr) { cass_collection_free(ptr); };
|
||||
static constexpr auto kDELETER = [](CassCollection* ptr) { cass_collection_free(ptr); };
|
||||
|
||||
static void
|
||||
throwErrorIfNeeded(CassError const rc, std::string_view const label)
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
|
||||
template <typename Type>
|
||||
explicit Collection(std::vector<Type> const& value)
|
||||
: ManagedObject{cass_collection_new(CASS_COLLECTION_TYPE_LIST, value.size()), deleter}
|
||||
: ManagedObject{cass_collection_new(CASS_COLLECTION_TYPE_LIST, value.size()), kDELETER}
|
||||
{
|
||||
bind(value);
|
||||
}
|
||||
|
||||
@@ -32,12 +32,12 @@
|
||||
#include <utility>
|
||||
|
||||
namespace {
|
||||
constexpr auto futureDeleter = [](CassFuture* ptr) { cass_future_free(ptr); };
|
||||
constexpr auto kFUTURE_DELETER = [](CassFuture* ptr) { cass_future_free(ptr); };
|
||||
} // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
/* implicit */ Future::Future(CassFuture* ptr) : ManagedObject{ptr, futureDeleter}
|
||||
/* implicit */ Future::Future(CassFuture* ptr) : ManagedObject{ptr, kFUTURE_DELETER}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ protected:
|
||||
std::unique_ptr<Managed, void (*)(Managed*)> ptr_;
|
||||
|
||||
public:
|
||||
template <typename deleterCallable>
|
||||
ManagedObject(Managed* rawPtr, deleterCallable deleter) : ptr_{rawPtr, deleter}
|
||||
template <typename DeleterCallable>
|
||||
ManagedObject(Managed* rawPtr, DeleterCallable deleter) : ptr_{rawPtr, deleter}
|
||||
{
|
||||
if (rawPtr == nullptr)
|
||||
throw std::runtime_error("Could not create DB object - got nullptr");
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
#include <cstddef>
|
||||
|
||||
namespace {
|
||||
constexpr auto resultDeleter = [](CassResult const* ptr) { cass_result_free(ptr); };
|
||||
constexpr auto resultIteratorDeleter = [](CassIterator* ptr) { cass_iterator_free(ptr); };
|
||||
constexpr auto kRESULT_DELETER = [](CassResult const* ptr) { cass_result_free(ptr); };
|
||||
constexpr auto kRESULT_ITERATOR_DELETER = [](CassIterator* ptr) { cass_iterator_free(ptr); };
|
||||
} // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
/* implicit */ Result::Result(CassResult const* ptr) : ManagedObject{ptr, resultDeleter}
|
||||
/* implicit */ Result::Result(CassResult const* ptr) : ManagedObject{ptr, kRESULT_DELETER}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ Result::hasRows() const
|
||||
}
|
||||
|
||||
/* implicit */ ResultIterator::ResultIterator(CassIterator* ptr)
|
||||
: ManagedObject{ptr, resultIteratorDeleter}, hasMore_{cass_iterator_next(ptr) != 0u}
|
||||
: ManagedObject{ptr, kRESULT_ITERATOR_DELETER}, hasMore_{cass_iterator_next(ptr) != 0u}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
class Session : public ManagedObject<CassSession> {
|
||||
static constexpr auto deleter = [](CassSession* ptr) { cass_session_free(ptr); };
|
||||
static constexpr auto kDELETER = [](CassSession* ptr) { cass_session_free(ptr); };
|
||||
|
||||
public:
|
||||
Session() : ManagedObject{cass_session_new(), deleter}
|
||||
Session() : ManagedObject{cass_session_new(), kDELETER}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
constexpr auto contextDeleter = [](CassSsl* ptr) { cass_ssl_free(ptr); };
|
||||
constexpr auto kCONTEXT_DELETER = [](CassSsl* ptr) { cass_ssl_free(ptr); };
|
||||
} // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
SslContext::SslContext(std::string const& certificate) : ManagedObject{cass_ssl_new(), contextDeleter}
|
||||
SslContext::SslContext(std::string const& certificate) : ManagedObject{cass_ssl_new(), kCONTEXT_DELETER}
|
||||
{
|
||||
cass_ssl_set_verify_flags(*this, CASS_SSL_VERIFY_NONE);
|
||||
if (auto const rc = cass_ssl_add_trusted_cert(*this, certificate.c_str()); rc != CASS_OK) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
class Statement : public ManagedObject<CassStatement> {
|
||||
static constexpr auto deleter = [](CassStatement* ptr) { cass_statement_free(ptr); };
|
||||
static constexpr auto kDELETER = [](CassStatement* ptr) { cass_statement_free(ptr); };
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -54,14 +54,14 @@ public:
|
||||
*/
|
||||
template <typename... Args>
|
||||
explicit Statement(std::string_view query, Args&&... args)
|
||||
: ManagedObject{cass_statement_new_n(query.data(), query.size(), sizeof...(args)), deleter}
|
||||
: ManagedObject{cass_statement_new_n(query.data(), query.size(), sizeof...(args)), kDELETER}
|
||||
{
|
||||
cass_statement_set_consistency(*this, CASS_CONSISTENCY_QUORUM);
|
||||
cass_statement_set_is_idempotent(*this, cass_true);
|
||||
bind<Args...>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/* implicit */ Statement(CassStatement* ptr) : ManagedObject{ptr, deleter}
|
||||
/* implicit */ Statement(CassStatement* ptr) : ManagedObject{ptr, kDELETER}
|
||||
{
|
||||
cass_statement_set_consistency(*this, CASS_CONSISTENCY_QUORUM);
|
||||
cass_statement_set_is_idempotent(*this, cass_true);
|
||||
@@ -153,10 +153,10 @@ public:
|
||||
* This is used to produce Statement objects that can be executed.
|
||||
*/
|
||||
class PreparedStatement : public ManagedObject<CassPrepared const> {
|
||||
static constexpr auto deleter = [](CassPrepared const* ptr) { cass_prepared_free(ptr); };
|
||||
static constexpr auto kDELETER = [](CassPrepared const* ptr) { cass_prepared_free(ptr); };
|
||||
|
||||
public:
|
||||
/* implicit */ PreparedStatement(CassPrepared const* ptr) : ManagedObject{ptr, deleter}
|
||||
/* implicit */ PreparedStatement(CassPrepared const* ptr) : ManagedObject{ptr, kDELETER}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,17 @@
|
||||
#include <cassandra.h>
|
||||
|
||||
namespace {
|
||||
constexpr auto tupleDeleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
|
||||
constexpr auto tupleIteratorDeleter = [](CassIterator* ptr) { cass_iterator_free(ptr); };
|
||||
constexpr auto kTUPLE_DELETER = [](CassTuple* ptr) { cass_tuple_free(ptr); };
|
||||
constexpr auto kTUPLE_ITERATOR_DELETER = [](CassIterator* ptr) { cass_iterator_free(ptr); };
|
||||
} // namespace
|
||||
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
/* implicit */ Tuple::Tuple(CassTuple* ptr) : ManagedObject{ptr, tupleDeleter}
|
||||
/* implicit */ Tuple::Tuple(CassTuple* ptr) : ManagedObject{ptr, kTUPLE_DELETER}
|
||||
{
|
||||
}
|
||||
|
||||
/* implicit */ TupleIterator::TupleIterator(CassIterator* ptr) : ManagedObject{ptr, tupleIteratorDeleter}
|
||||
/* implicit */ TupleIterator::TupleIterator(CassIterator* ptr) : ManagedObject{ptr, kTUPLE_ITERATOR_DELETER}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -37,14 +37,14 @@
|
||||
namespace data::cassandra::impl {
|
||||
|
||||
class Tuple : public ManagedObject<CassTuple> {
|
||||
static constexpr auto deleter = [](CassTuple* ptr) { cass_tuple_free(ptr); };
|
||||
static constexpr auto kDELETER = [](CassTuple* ptr) { cass_tuple_free(ptr); };
|
||||
|
||||
public:
|
||||
/* implicit */ Tuple(CassTuple* ptr);
|
||||
|
||||
template <typename... Types>
|
||||
explicit Tuple(std::tuple<Types...>&& value)
|
||||
: ManagedObject{cass_tuple_new(std::tuple_size<std::tuple<Types...>>{}), deleter}
|
||||
: ManagedObject{cass_tuple_new(std::tuple_size<std::tuple<Types...>>{}), kDELETER}
|
||||
{
|
||||
std::apply(std::bind_front(&Tuple::bind<Types...>, this), std::move(value));
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
std::shared_ptr<BackendInterface> const& backend,
|
||||
CacheType& cache
|
||||
)
|
||||
: backend_{backend}, cache_{cache}, settings_{make_CacheLoaderSettings(config)}, ctx_{settings_.numThreads}
|
||||
: backend_{backend}, cache_{cache}, settings_{makeCacheLoaderSettings(config)}, ctx_{settings_.numThreads}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ CacheLoaderSettings::isDisabled() const
|
||||
}
|
||||
|
||||
[[nodiscard]] CacheLoaderSettings
|
||||
make_CacheLoaderSettings(util::config::ClioConfigDefinition const& config)
|
||||
makeCacheLoaderSettings(util::config::ClioConfigDefinition const& config)
|
||||
{
|
||||
CacheLoaderSettings settings;
|
||||
settings.numThreads = config.get<uint16_t>("io_threads");
|
||||
|
||||
@@ -64,6 +64,6 @@ struct CacheLoaderSettings {
|
||||
* @returns The CacheLoaderSettings object
|
||||
*/
|
||||
[[nodiscard]] CacheLoaderSettings
|
||||
make_CacheLoaderSettings(util::config::ClioConfigDefinition const& config);
|
||||
makeCacheLoaderSettings(util::config::ClioConfigDefinition const& config);
|
||||
|
||||
} // namespace etl
|
||||
|
||||
@@ -88,9 +88,9 @@ ETLService::runETLPipeline(uint32_t startSequence, uint32_t numExtractors)
|
||||
|
||||
auto const end = std::chrono::system_clock::now();
|
||||
auto const lastPublishedSeq = ledgerPublisher_.getLastPublishedSequence();
|
||||
static constexpr auto NANOSECONDS_PER_SECOND = 1'000'000'000.0;
|
||||
static constexpr auto kNANOSECONDS_PER_SECOND = 1'000'000'000.0;
|
||||
LOG(log_.debug()) << "Extracted and wrote " << lastPublishedSeq.value_or(startSequence) - startSequence << " in "
|
||||
<< ((end - begin).count()) / NANOSECONDS_PER_SECOND;
|
||||
<< ((end - begin).count()) / kNANOSECONDS_PER_SECOND;
|
||||
|
||||
state_.isWriting = false;
|
||||
|
||||
@@ -168,7 +168,7 @@ ETLService::publishNextSequence(uint32_t nextSequence)
|
||||
if (auto rng = backend_->hardFetchLedgerRangeNoThrow(); rng && rng->maxSequence >= nextSequence) {
|
||||
ledgerPublisher_.publish(nextSequence, {});
|
||||
++nextSequence;
|
||||
} else if (networkValidatedLedgers_->waitUntilValidatedByNetwork(nextSequence, util::MILLISECONDS_PER_SECOND)) {
|
||||
} else if (networkValidatedLedgers_->waitUntilValidatedByNetwork(nextSequence, util::kMILLISECONDS_PER_SECOND)) {
|
||||
LOG(log_.info()) << "Ledger with sequence = " << nextSequence << " has been validated by the network. "
|
||||
<< "Attempting to find in database and publish";
|
||||
|
||||
@@ -178,8 +178,8 @@ ETLService::publishNextSequence(uint32_t nextSequence)
|
||||
// database after the specified number of attempts. publishLedger()
|
||||
// waits one second between each attempt to read the ledger from the
|
||||
// database
|
||||
constexpr size_t timeoutSeconds = 10;
|
||||
bool const success = ledgerPublisher_.publish(nextSequence, timeoutSeconds);
|
||||
constexpr size_t kTIMEOUT_SECONDS = 10;
|
||||
bool const success = ledgerPublisher_.publish(nextSequence, kTIMEOUT_SECONDS);
|
||||
|
||||
if (!success) {
|
||||
LOG(log_.warn()) << "Failed to publish ledger with sequence = " << nextSequence << " . Beginning ETL";
|
||||
@@ -233,7 +233,7 @@ ETLService::monitorReadOnly()
|
||||
// if we can't, wait until it's validated by the network, or 1 second passes, whichever occurs
|
||||
// first. Even if we don't hear from rippled, if ledgers are being written to the db, we publish
|
||||
// them.
|
||||
networkValidatedLedgers_->waitUntilValidatedByNetwork(latestSequence, util::MILLISECONDS_PER_SECOND);
|
||||
networkValidatedLedgers_->waitUntilValidatedByNetwork(latestSequence, util::kMILLISECONDS_PER_SECOND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
* @return A shared pointer to a new instance of ETLService
|
||||
*/
|
||||
static std::shared_ptr<ETLService>
|
||||
make_ETLService(
|
||||
makeETLService(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
|
||||
@@ -59,7 +59,7 @@ using namespace util::config;
|
||||
namespace etl {
|
||||
|
||||
std::shared_ptr<LoadBalancer>
|
||||
LoadBalancer::make_LoadBalancer(
|
||||
LoadBalancer::makeLoadBalancer(
|
||||
ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
@@ -235,7 +235,7 @@ LoadBalancer::forwardToRippled(
|
||||
)
|
||||
{
|
||||
if (not request.contains("command"))
|
||||
return std::unexpected{rpc::ClioError::rpcCOMMAND_IS_MISSING};
|
||||
return std::unexpected{rpc::ClioError::RpcCommandIsMissing};
|
||||
|
||||
auto const cmd = boost::json::value_to<std::string>(request.at("command"));
|
||||
if (forwardingCache_) {
|
||||
@@ -249,10 +249,10 @@ LoadBalancer::forwardToRippled(
|
||||
|
||||
auto numAttempts = 0u;
|
||||
|
||||
auto xUserValue = isAdmin ? ADMIN_FORWARDING_X_USER_VALUE : USER_FORWARDING_X_USER_VALUE;
|
||||
auto xUserValue = isAdmin ? kADMIN_FORWARDING_X_USER_VALUE : kUSER_FORWARDING_X_USER_VALUE;
|
||||
|
||||
std::optional<boost::json::object> response;
|
||||
rpc::ClioError error = rpc::ClioError::etlCONNECTION_ERROR;
|
||||
rpc::ClioError error = rpc::ClioError::EtlConnectionError;
|
||||
while (numAttempts < sources_.size()) {
|
||||
auto res = sources_[sourceIdx]->forwardToRippled(request, clientIp, xUserValue, yield);
|
||||
if (res) {
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
using OptionalGetLedgerResponseType = std::optional<GetLedgerResponseType>;
|
||||
|
||||
private:
|
||||
static constexpr std::uint32_t DEFAULT_DOWNLOAD_RANGES = 16;
|
||||
static constexpr std::uint32_t kDEFAULT_DOWNLOAD_RANGES = 16;
|
||||
|
||||
util::Logger log_{"ETL"};
|
||||
// Forwarding cache must be destroyed after sources because sources have a callback to invalidate cache
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
std::vector<SourcePtr> sources_;
|
||||
std::optional<ETLState> etlState_;
|
||||
std::uint32_t downloadRanges_ =
|
||||
DEFAULT_DOWNLOAD_RANGES; /*< The number of markers to use when downloading initial ledger */
|
||||
kDEFAULT_DOWNLOAD_RANGES; /*< The number of markers to use when downloading initial ledger */
|
||||
|
||||
// Using mutext instead of atomic_bool because choosing a new source to
|
||||
// forward messages should be done with a mutual exclusion otherwise there will be a race condition
|
||||
@@ -85,12 +85,12 @@ public:
|
||||
/**
|
||||
* @brief Value for the X-User header when forwarding admin requests
|
||||
*/
|
||||
static constexpr std::string_view ADMIN_FORWARDING_X_USER_VALUE = "clio_admin";
|
||||
static constexpr std::string_view kADMIN_FORWARDING_X_USER_VALUE = "clio_admin";
|
||||
|
||||
/**
|
||||
* @brief Value for the X-User header when forwarding user requests
|
||||
*/
|
||||
static constexpr std::string_view USER_FORWARDING_X_USER_VALUE = "clio_user";
|
||||
static constexpr std::string_view kUSER_FORWARDING_X_USER_VALUE = "clio_user";
|
||||
|
||||
/**
|
||||
* @brief Create an instance of the load balancer.
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
std::shared_ptr<feed::SubscriptionManagerInterface> subscriptions,
|
||||
std::shared_ptr<NetworkValidatedLedgersInterface> validatedLedgers,
|
||||
SourceFactory sourceFactory = make_Source
|
||||
SourceFactory sourceFactory = makeSource
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -123,13 +123,13 @@ public:
|
||||
* @return A shared pointer to a new instance of LoadBalancer
|
||||
*/
|
||||
static std::shared_ptr<LoadBalancer>
|
||||
make_LoadBalancer(
|
||||
makeLoadBalancer(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
std::shared_ptr<feed::SubscriptionManagerInterface> subscriptions,
|
||||
std::shared_ptr<NetworkValidatedLedgersInterface> validatedLedgers,
|
||||
SourceFactory sourceFactory = make_Source
|
||||
SourceFactory sourceFactory = makeSource
|
||||
);
|
||||
|
||||
~LoadBalancer();
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace etl {
|
||||
std::shared_ptr<NetworkValidatedLedgers>
|
||||
NetworkValidatedLedgers::make_ValidatedLedgers()
|
||||
NetworkValidatedLedgers::makeValidatedLedgers()
|
||||
{
|
||||
return std::make_shared<NetworkValidatedLedgers>();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
* @return A shared pointer to a new instance of NetworkValidatedLedgers
|
||||
*/
|
||||
static std::shared_ptr<NetworkValidatedLedgers>
|
||||
make_ValidatedLedgers();
|
||||
makeValidatedLedgers();
|
||||
|
||||
/**
|
||||
* @brief Notify the datastructure that idx has been validated by the network.
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
namespace etl {
|
||||
|
||||
SourcePtr
|
||||
make_Source(
|
||||
makeSource(
|
||||
util::config::ObjectView const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
|
||||
@@ -175,7 +175,7 @@ using SourceFactory = std::function<SourcePtr(
|
||||
* @return The created source
|
||||
*/
|
||||
SourcePtr
|
||||
make_Source(
|
||||
makeSource(
|
||||
util::config::ObjectView const& config,
|
||||
boost::asio::io_context& ioc,
|
||||
std::shared_ptr<BackendInterface> backend,
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
namespace etl::impl {
|
||||
|
||||
AmendmentBlockHandler::ActionType const AmendmentBlockHandler::defaultAmendmentBlockAction = []() {
|
||||
static util::Logger const log{"ETL"};
|
||||
AmendmentBlockHandler::ActionType const AmendmentBlockHandler::kDEFAULT_AMENDMENT_BLOCK_ACTION = []() {
|
||||
static util::Logger const log{"ETL"}; // NOLINT(readability-identifier-naming)
|
||||
LOG(log.fatal()) << "Can't process new ledgers: The current ETL source is not compatible with the version of "
|
||||
<< "the libxrpl Clio is currently using. Please upgrade Clio to a newer version.";
|
||||
};
|
||||
|
||||
@@ -43,13 +43,13 @@ private:
|
||||
ActionType action_;
|
||||
|
||||
public:
|
||||
static ActionType const defaultAmendmentBlockAction;
|
||||
static ActionType const kDEFAULT_AMENDMENT_BLOCK_ACTION;
|
||||
|
||||
AmendmentBlockHandler(
|
||||
boost::asio::io_context& ioc,
|
||||
SystemState& state,
|
||||
std::chrono::steady_clock::duration interval = std::chrono::seconds{1},
|
||||
ActionType action = defaultAmendmentBlockAction
|
||||
ActionType action = kDEFAULT_AMENDMENT_BLOCK_ACTION
|
||||
);
|
||||
|
||||
void
|
||||
|
||||
@@ -58,10 +58,10 @@ public:
|
||||
}();
|
||||
|
||||
rg::sort(accountRoots);
|
||||
std::vector<ripple::uint256> cursors{data::firstKey};
|
||||
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
|
||||
rg::copy(accountRoots.begin(), accountRoots.end(), std::back_inserter(cursors));
|
||||
rg::sort(cursors);
|
||||
cursors.push_back(data::lastKey);
|
||||
cursors.push_back(data::kLAST_KEY);
|
||||
|
||||
std::vector<CursorPair> pairs;
|
||||
pairs.reserve(cursors.size());
|
||||
|
||||
@@ -85,10 +85,10 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<ripple::uint256> cursors{data::firstKey};
|
||||
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
|
||||
rg::copy(liveCursors | vs::take(std::min(liveCursors.size(), numCursors_)), std::back_inserter(cursors));
|
||||
rg::sort(cursors);
|
||||
cursors.push_back(data::lastKey);
|
||||
cursors.push_back(data::kLAST_KEY);
|
||||
|
||||
std::vector<CursorPair> pairs;
|
||||
pairs.reserve(cursors.size());
|
||||
|
||||
@@ -74,14 +74,14 @@ public:
|
||||
rg::unique(diffs, [](auto const& a, auto const& b) { return a.key == b.key; });
|
||||
diffs.erase(removalCursor, last);
|
||||
|
||||
std::vector<ripple::uint256> cursors{data::firstKey};
|
||||
std::vector<ripple::uint256> cursors{data::kFIRST_KEY};
|
||||
rg::copy(
|
||||
diffs //
|
||||
| vs::filter([](auto const& obj) { return not obj.blob.empty(); }) //
|
||||
| vs::transform([](auto const& obj) { return obj.key; }),
|
||||
std::back_inserter(cursors)
|
||||
);
|
||||
cursors.push_back(data::lastKey); // last pair should cover the remaining range
|
||||
cursors.push_back(data::kLAST_KEY); // last pair should cover the remaining range
|
||||
|
||||
std::vector<CursorPair> pairs;
|
||||
pairs.reserve(cursors.size());
|
||||
|
||||
@@ -39,7 +39,7 @@ public:
|
||||
using DataType = std::optional<RawDataType>;
|
||||
using QueueType = ThreadSafeQueue<DataType>; // TODO: probably should use boost::lockfree::queue instead?
|
||||
|
||||
constexpr static auto TOTAL_MAX_IN_QUEUE = 1000u;
|
||||
static constexpr auto kTOTAL_MAX_IN_QUEUE = 1000u;
|
||||
|
||||
private:
|
||||
util::Logger log_{"ETL"};
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
*/
|
||||
ExtractionDataPipe(uint32_t stride, uint32_t startSequence) : stride_{stride}, startSequence_{startSequence}
|
||||
{
|
||||
auto const maxQueueSize = TOTAL_MAX_IN_QUEUE / stride;
|
||||
auto const maxQueueSize = kTOTAL_MAX_IN_QUEUE / stride;
|
||||
for (size_t i = 0; i < stride_; ++i)
|
||||
queues_.push_back(std::make_unique<QueueType>(maxQueueSize));
|
||||
}
|
||||
|
||||
@@ -44,13 +44,13 @@ ForwardingSource::ForwardingSource(
|
||||
std::string ip,
|
||||
std::string wsPort,
|
||||
std::chrono::steady_clock::duration forwardingTimeout,
|
||||
std::chrono::steady_clock::duration connectionTimeout
|
||||
std::chrono::steady_clock::duration connTimeout
|
||||
)
|
||||
: log_(fmt::format("ForwardingSource[{}:{}]", ip, wsPort))
|
||||
, connectionBuilder_(std::move(ip), std::move(wsPort))
|
||||
, forwardingTimeout_{forwardingTimeout}
|
||||
{
|
||||
connectionBuilder_.setConnectionTimeout(connectionTimeout)
|
||||
connectionBuilder_.setConnectionTimeout(connTimeout)
|
||||
.addHeader(
|
||||
{boost::beast::http::field::user_agent, fmt::format("{} websocket-client-coro", BOOST_BEAST_VERSION_STRING)}
|
||||
);
|
||||
@@ -76,14 +76,14 @@ ForwardingSource::forwardToRippled(
|
||||
auto expectedConnection = connectionBuilder.connect(yield);
|
||||
if (not expectedConnection) {
|
||||
LOG(log_.debug()) << "Couldn't connect to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::etlCONNECTION_ERROR};
|
||||
return std::unexpected{rpc::ClioError::EtlConnectionError};
|
||||
}
|
||||
auto& connection = expectedConnection.value();
|
||||
|
||||
auto writeError = connection->write(boost::json::serialize(request), yield, forwardingTimeout_);
|
||||
if (writeError) {
|
||||
LOG(log_.debug()) << "Error sending request to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::etlREQUEST_ERROR};
|
||||
return std::unexpected{rpc::ClioError::EtlRequestError};
|
||||
}
|
||||
|
||||
auto response = connection->read(yield, forwardingTimeout_);
|
||||
@@ -91,10 +91,10 @@ ForwardingSource::forwardToRippled(
|
||||
if (auto errorCode = response.error().errorCode();
|
||||
errorCode.has_value() and errorCode->value() == boost::system::errc::timed_out) {
|
||||
LOG(log_.debug()) << "Request to rippled timed out";
|
||||
return std::unexpected{rpc::ClioError::etlREQUEST_TIMEOUT};
|
||||
return std::unexpected{rpc::ClioError::EtlRequestTimeout};
|
||||
}
|
||||
LOG(log_.debug()) << "Error sending request to rippled to forward request.";
|
||||
return std::unexpected{rpc::ClioError::etlREQUEST_ERROR};
|
||||
return std::unexpected{rpc::ClioError::EtlRequestError};
|
||||
}
|
||||
|
||||
boost::json::value parsedResponse;
|
||||
@@ -104,7 +104,7 @@ ForwardingSource::forwardToRippled(
|
||||
throw std::runtime_error("response is not an object");
|
||||
} catch (std::exception const& e) {
|
||||
LOG(log_.debug()) << "Error parsing response from rippled: " << e.what() << ". Response: " << *response;
|
||||
return std::unexpected{rpc::ClioError::etlINVALID_RESPONSE};
|
||||
return std::unexpected{rpc::ClioError::EtlInvalidResponse};
|
||||
}
|
||||
|
||||
auto responseObject = parsedResponse.as_object();
|
||||
|
||||
@@ -39,14 +39,14 @@ class ForwardingSource {
|
||||
util::requests::WsConnectionBuilder connectionBuilder_;
|
||||
std::chrono::steady_clock::duration forwardingTimeout_;
|
||||
|
||||
static constexpr std::chrono::seconds CONNECTION_TIMEOUT{3};
|
||||
static constexpr std::chrono::seconds kCONNECTION_TIMEOUT{3};
|
||||
|
||||
public:
|
||||
ForwardingSource(
|
||||
std::string ip,
|
||||
std::string wsPort,
|
||||
std::chrono::steady_clock::duration forwardingTimeout,
|
||||
std::chrono::steady_clock::duration connectionTimeout = CONNECTION_TIMEOUT
|
||||
std::chrono::steady_clock::duration connTimeout = ForwardingSource::kCONNECTION_TIMEOUT
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -131,8 +131,8 @@ public:
|
||||
result.mptHoldersData.push_back(*maybeMPTHolder);
|
||||
|
||||
result.accountTxData.emplace_back(txMeta, sttx.getTransactionID());
|
||||
static constexpr std::size_t KEY_SIZE = 32;
|
||||
std::string keyStr{reinterpret_cast<char const*>(sttx.getTransactionID().data()), KEY_SIZE};
|
||||
static constexpr std::size_t kEY_SIZE = 32;
|
||||
std::string keyStr{reinterpret_cast<char const*>(sttx.getTransactionID().data()), kEY_SIZE};
|
||||
backend_->writeTransaction(
|
||||
std::move(keyStr),
|
||||
ledger.seq,
|
||||
@@ -204,10 +204,10 @@ public:
|
||||
backend_->writeSuccessor(std::move(key), sequence, uint256ToString(succ->key));
|
||||
}
|
||||
|
||||
ripple::uint256 prev = data::firstKey;
|
||||
ripple::uint256 prev = data::kFIRST_KEY;
|
||||
while (auto cur = backend_->cache().getSuccessor(prev, sequence)) {
|
||||
ASSERT(cur.has_value(), "Succesor for key {} must exist", ripple::strHex(prev));
|
||||
if (prev == data::firstKey)
|
||||
if (prev == data::kFIRST_KEY)
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(cur->key));
|
||||
|
||||
if (isBookDir(cur->key, cur->blob)) {
|
||||
@@ -228,12 +228,12 @@ public:
|
||||
}
|
||||
|
||||
prev = cur->key;
|
||||
static constexpr std::size_t LOG_INTERVAL = 100000;
|
||||
if (numWrites % LOG_INTERVAL == 0 && numWrites != 0)
|
||||
static constexpr std::size_t kLOG_INTERVAL = 100000;
|
||||
if (numWrites % kLOG_INTERVAL == 0 && numWrites != 0)
|
||||
LOG(log_.info()) << "Wrote " << numWrites << " book successors";
|
||||
}
|
||||
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::lastKey));
|
||||
backend_->writeSuccessor(uint256ToString(prev), sequence, uint256ToString(data::kLAST_KEY));
|
||||
++numWrites;
|
||||
});
|
||||
|
||||
|
||||
@@ -184,8 +184,8 @@ public:
|
||||
|
||||
// if the ledger closed over MAX_LEDGER_AGE_SECONDS ago, assume we are still catching up and don't publish
|
||||
// TODO: this probably should be a strategy
|
||||
static constexpr std::uint32_t MAX_LEDGER_AGE_SECONDS = 600;
|
||||
if (age < MAX_LEDGER_AGE_SECONDS) {
|
||||
static constexpr std::uint32_t kMAX_LEDGER_AGE_SECONDS = 600;
|
||||
if (age < kMAX_LEDGER_AGE_SECONDS) {
|
||||
std::optional<ripple::Fees> fees = data::synchronousAndRetryOnTimeout([&](auto yield) {
|
||||
return backend_->fetchFees(lgrInfo.seq, yield);
|
||||
});
|
||||
@@ -260,9 +260,9 @@ public:
|
||||
auto now = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
auto closeTime = lastCloseTime_.time_since_epoch().count();
|
||||
if (now < (rippleEpochStart + closeTime))
|
||||
if (now < (kRIPPLE_EPOCH_START + closeTime))
|
||||
return 0;
|
||||
return now - (rippleEpochStart + closeTime);
|
||||
return now - (kRIPPLE_EPOCH_START + closeTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,7 +77,7 @@ SubscriptionSource::SubscriptionSource(
|
||||
, subscriptions_(std::move(subscriptions))
|
||||
, strand_(boost::asio::make_strand(ioContext))
|
||||
, wsTimeout_(wsTimeout)
|
||||
, retry_(util::makeRetryExponentialBackoff(retryDelay, RETRY_MAX_DELAY, strand_))
|
||||
, retry_(util::makeRetryExponentialBackoff(retryDelay, kRETRY_MAX_DELAY, strand_))
|
||||
, onConnect_(std::move(onConnect))
|
||||
, onDisconnect_(std::move(onDisconnect))
|
||||
, onLedgerClosed_(std::move(onLedgerClosed))
|
||||
@@ -222,9 +222,9 @@ SubscriptionSource::handleMessage(std::string const& message)
|
||||
auto const object = raw.as_object();
|
||||
uint32_t ledgerIndex = 0;
|
||||
|
||||
static constexpr char const* const JS_LedgerClosed = "ledgerClosed";
|
||||
static constexpr char const* const JS_ValidationReceived = "validationReceived";
|
||||
static constexpr char const* const JS_ManifestReceived = "manifestReceived";
|
||||
static constexpr auto kJS_LEDGER_CLOSED = "ledgerClosed";
|
||||
static constexpr auto kJS_VALIDATION_RECEIVED = "validationReceived";
|
||||
static constexpr auto kJS_MANIFEST_RECEIVED = "manifestReceived";
|
||||
|
||||
if (object.contains(JS(result))) {
|
||||
auto const& result = object.at(JS(result)).as_object();
|
||||
@@ -237,7 +237,7 @@ SubscriptionSource::handleMessage(std::string const& message)
|
||||
}
|
||||
LOG(log_.debug()) << "Received a message on ledger subscription stream. Message: " << object;
|
||||
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == JS_LedgerClosed) {
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == kJS_LEDGER_CLOSED) {
|
||||
LOG(log_.debug()) << "Received a message of type 'ledgerClosed' on ledger subscription stream. Message: "
|
||||
<< object;
|
||||
if (object.contains(JS(ledger_index))) {
|
||||
@@ -259,10 +259,10 @@ SubscriptionSource::handleMessage(std::string const& message)
|
||||
if (object.contains(JS(transaction)) and !object.contains(JS(meta))) {
|
||||
LOG(log_.debug()) << "Forwarding proposed transaction: " << object;
|
||||
subscriptions_->forwardProposedTransaction(object);
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == JS_ValidationReceived) {
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == kJS_VALIDATION_RECEIVED) {
|
||||
LOG(log_.debug()) << "Forwarding validation: " << object;
|
||||
subscriptions_->forwardValidation(object);
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == JS_ManifestReceived) {
|
||||
} else if (object.contains(JS(type)) && object.at(JS(type)) == kJS_MANIFEST_RECEIVED) {
|
||||
LOG(log_.debug()) << "Forwarding manifest: " << object;
|
||||
subscriptions_->forwardManifest(object);
|
||||
}
|
||||
@@ -363,12 +363,12 @@ SubscriptionSource::setValidatedRange(std::string range)
|
||||
std::string const&
|
||||
SubscriptionSource::getSubscribeCommandJson()
|
||||
{
|
||||
static boost::json::object const jsonValue{
|
||||
static boost::json::object const kJSON_VALUE{
|
||||
{"command", "subscribe"},
|
||||
{"streams", {"ledger", "manifests", "validations", "transactions_proposed"}},
|
||||
};
|
||||
static std::string const jsonString = boost::json::serialize(jsonValue);
|
||||
return jsonString;
|
||||
static std::string const kJSON_STRING = boost::json::serialize(kJSON_VALUE);
|
||||
return kJSON_STRING;
|
||||
}
|
||||
|
||||
} // namespace etl::impl
|
||||
|
||||
@@ -91,9 +91,9 @@ private:
|
||||
|
||||
std::future<void> runFuture_;
|
||||
|
||||
static constexpr std::chrono::seconds WS_TIMEOUT{30};
|
||||
static constexpr std::chrono::seconds RETRY_MAX_DELAY{30};
|
||||
static constexpr std::chrono::seconds RETRY_DELAY{1};
|
||||
static constexpr std::chrono::seconds kWS_TIMEOUT{30};
|
||||
static constexpr std::chrono::seconds kRETRY_MAX_DELAY{30};
|
||||
static constexpr std::chrono::seconds kRETRY_DELAY{1};
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -107,8 +107,7 @@ public:
|
||||
* @param subscriptions The subscription manager object
|
||||
* @param onConnect The onConnect hook. Called when the connection is established
|
||||
* @param onDisconnect The onDisconnect hook. Called when the connection is lost
|
||||
* @param onLedgerClosed The onLedgerClosed hook. Called when the ledger is closed but only if the source is
|
||||
* forwarding
|
||||
* @param onLedgerClosed The onLedgerClosed hook. Called when the ledger is closed if the source is forwarding
|
||||
* @param wsTimeout A timeout for websocket operations. Defaults to 30 seconds
|
||||
* @param retryDelay The retry delay. Defaults to 1 second
|
||||
*/
|
||||
@@ -121,8 +120,8 @@ public:
|
||||
OnConnectHook onConnect,
|
||||
OnDisconnectHook onDisconnect,
|
||||
OnLedgerClosedHook onLedgerClosed,
|
||||
std::chrono::steady_clock::duration const wsTimeout = WS_TIMEOUT,
|
||||
std::chrono::steady_clock::duration const retryDelay = RETRY_DELAY
|
||||
std::chrono::steady_clock::duration const wsTimeout = SubscriptionSource::kWS_TIMEOUT,
|
||||
std::chrono::steady_clock::duration const retryDelay = SubscriptionSource::kRETRY_DELAY
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -308,11 +308,11 @@ private:
|
||||
|
||||
auto lb = backend_->cache().getPredecessor(obj.key, lgrInfo.seq);
|
||||
if (!lb)
|
||||
lb = {.key = data::firstKey, .blob = {}};
|
||||
lb = {.key = data::kFIRST_KEY, .blob = {}};
|
||||
|
||||
auto ub = backend_->cache().getSuccessor(obj.key, lgrInfo.seq);
|
||||
if (!ub)
|
||||
ub = {.key = data::lastKey, .blob = {}};
|
||||
ub = {.key = data::kLAST_KEY, .blob = {}};
|
||||
|
||||
if (obj.blob.empty()) {
|
||||
LOG(log_.debug()) << "writing successor for deleted object " << ripple::strHex(obj.key) << " - "
|
||||
@@ -336,10 +336,10 @@ private:
|
||||
LOG(log_.debug()) << "Updating book successor " << ripple::strHex(base) << " - "
|
||||
<< ripple::strHex(succ->key);
|
||||
} else {
|
||||
backend_->writeSuccessor(uint256ToString(base), lgrInfo.seq, uint256ToString(data::lastKey));
|
||||
backend_->writeSuccessor(uint256ToString(base), lgrInfo.seq, uint256ToString(data::kLAST_KEY));
|
||||
|
||||
LOG(log_.debug()) << "Updating book successor " << ripple::strHex(base) << " - "
|
||||
<< ripple::strHex(data::lastKey);
|
||||
<< ripple::strHex(data::kLAST_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,7 +361,7 @@ private:
|
||||
for (auto& obj : *(rawData.mutable_book_successors())) {
|
||||
auto firstBook = std::move(*obj.mutable_first_book());
|
||||
if (!firstBook.size())
|
||||
firstBook = uint256ToString(data::lastKey);
|
||||
firstBook = uint256ToString(data::kLAST_KEY);
|
||||
LOG(log_.debug()) << "writing book successor " << ripple::strHex(obj.book_base()) << " - "
|
||||
<< ripple::strHex(firstBook);
|
||||
|
||||
@@ -372,10 +372,10 @@ private:
|
||||
if (obj.mod_type() != RawLedgerObjectType::MODIFIED) {
|
||||
std::string* predPtr = obj.mutable_predecessor();
|
||||
if (predPtr->empty())
|
||||
*predPtr = uint256ToString(data::firstKey);
|
||||
*predPtr = uint256ToString(data::kFIRST_KEY);
|
||||
std::string* succPtr = obj.mutable_successor();
|
||||
if (succPtr->empty())
|
||||
*succPtr = uint256ToString(data::lastKey);
|
||||
*succPtr = uint256ToString(data::kLAST_KEY);
|
||||
|
||||
if (obj.mod_type() == RawLedgerObjectType::DELETED) {
|
||||
LOG(log_.debug()) << "Modifying successors for deleted object " << ripple::strHex(obj.key())
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace etlng::model {
|
||||
template <ripple::TxType... Types>
|
||||
requires(util::hasNoDuplicates(Types...))
|
||||
struct Spec {
|
||||
static constexpr bool SpecTag = true;
|
||||
static constexpr bool kSPEC_TAG = true;
|
||||
|
||||
/**
|
||||
* @brief Checks if the transaction type was requested.
|
||||
@@ -57,7 +57,7 @@ struct Spec {
|
||||
* @param type The transaction type
|
||||
* @return true if the transaction was requested; false otherwise
|
||||
*/
|
||||
[[nodiscard]] constexpr static bool
|
||||
[[nodiscard]] static constexpr bool
|
||||
wants(ripple::TxType type) noexcept
|
||||
{
|
||||
return ((Types == type) || ...);
|
||||
|
||||
@@ -118,8 +118,8 @@ extractObj(PBObjType obj)
|
||||
.keyRaw = std::move(*obj.mutable_key()),
|
||||
.data = {obj.mutable_data()->begin(), obj.mutable_data()->end()},
|
||||
.dataRaw = std::move(*obj.mutable_data()),
|
||||
.successor = valueOr(obj.successor(), uint256ToString(data::firstKey)),
|
||||
.predecessor = valueOr(obj.predecessor(), uint256ToString(data::lastKey)),
|
||||
.successor = valueOr(obj.successor(), uint256ToString(data::kFIRST_KEY)),
|
||||
.predecessor = valueOr(obj.predecessor(), uint256ToString(data::kLAST_KEY)),
|
||||
.type = extractModType(obj.mod_type()),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ concept HasInitialObjectHook = requires(T p) {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept ContainsSpec = std::decay_t<T>::spec::SpecTag;
|
||||
concept ContainsSpec = std::decay_t<T>::spec::kSPEC_TAG;
|
||||
|
||||
template <typename T>
|
||||
concept ContainsValidHook = HasLedgerDataHook<T> or HasInitialDataHook<T> or
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
* @return A shared pointer to a new instance of SubscriptionManager
|
||||
*/
|
||||
static std::shared_ptr<SubscriptionManager>
|
||||
make_SubscriptionManager(
|
||||
makeSubscriptionManager(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
std::shared_ptr<data::BackendInterface const> const& backend
|
||||
)
|
||||
|
||||
@@ -41,35 +41,35 @@ try {
|
||||
return action.apply(
|
||||
[](app::CliArgs::Action::Exit const& exit) { return exit.exitCode; },
|
||||
[](app::CliArgs::Action::Run const& run) {
|
||||
auto const json = ConfigFileJson::make_ConfigFileJson(run.configPath);
|
||||
auto const json = ConfigFileJson::makeConfigFileJson(run.configPath);
|
||||
if (!json.has_value()) {
|
||||
std::cerr << json.error().error << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const errors = ClioConfig.parse(json.value());
|
||||
auto const errors = gClioConfig.parse(json.value());
|
||||
if (errors.has_value()) {
|
||||
for (auto const& err : errors.value())
|
||||
std::cerr << err.error << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
util::LogService::init(ClioConfig);
|
||||
app::ClioApplication clio{ClioConfig};
|
||||
util::LogService::init(gClioConfig);
|
||||
app::ClioApplication clio{gClioConfig};
|
||||
return clio.run(run.useNgWebServer);
|
||||
},
|
||||
[](app::CliArgs::Action::Migrate const& migrate) {
|
||||
auto const json = ConfigFileJson::make_ConfigFileJson(migrate.configPath);
|
||||
auto const json = ConfigFileJson::makeConfigFileJson(migrate.configPath);
|
||||
if (!json.has_value()) {
|
||||
std::cerr << json.error().error << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
auto const errors = ClioConfig.parse(json.value());
|
||||
auto const errors = gClioConfig.parse(json.value());
|
||||
if (errors.has_value()) {
|
||||
for (auto const& err : errors.value())
|
||||
std::cerr << err.error << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
util::LogService::init(ClioConfig);
|
||||
app::MigratorApplication migrator{ClioConfig, migrate.subCmd};
|
||||
util::LogService::init(gClioConfig);
|
||||
app::MigratorApplication migrator{gClioConfig, migrate.subCmd};
|
||||
return migrator.run();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
fromString(std::string const& statusStr);
|
||||
|
||||
private:
|
||||
static constexpr std::array<char const*, static_cast<size_t>(NumStatuses)> statusStrMap = {
|
||||
static constexpr std::array<char const*, static_cast<size_t>(NumStatuses)> kSTATUS_STR_MAP = {
|
||||
"Migrated",
|
||||
"NotMigrated",
|
||||
"NotKnown"
|
||||
|
||||
@@ -39,14 +39,14 @@ MigratorStatus::operator==(Status const& other) const
|
||||
std::string
|
||||
MigratorStatus::toString() const
|
||||
{
|
||||
return statusStrMap[static_cast<size_t>(status_)];
|
||||
return kSTATUS_STR_MAP[static_cast<size_t>(status_)];
|
||||
}
|
||||
|
||||
MigratorStatus
|
||||
MigratorStatus::fromString(std::string const& statusStr)
|
||||
{
|
||||
for (std::size_t i = 0; i < statusStrMap.size(); ++i) {
|
||||
if (statusStr == statusStrMap[i]) {
|
||||
for (std::size_t i = 0; i < kSTATUS_STR_MAP.size(); ++i) {
|
||||
if (statusStr == kSTATUS_STR_MAP[i]) {
|
||||
return MigratorStatus(static_cast<Status>(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,23 +76,23 @@ public:
|
||||
)
|
||||
{
|
||||
LOG(log_.debug()) << "Travsering token range: " << start << " - " << end
|
||||
<< " ; table: " << TableDesc::TABLE_NAME;
|
||||
<< " ; table: " << TableDesc::kTABLE_NAME;
|
||||
// for each table we only have one prepared statement
|
||||
static auto statementPrepared =
|
||||
migrationSchema_.getPreparedFullScanStatement(handle_, TableDesc::TABLE_NAME, TableDesc::PARTITION_KEY);
|
||||
static auto kSTATEMENT_PREPARED =
|
||||
migrationSchema_.getPreparedFullScanStatement(handle_, TableDesc::kTABLE_NAME, TableDesc::kPARTITION_KEY);
|
||||
|
||||
auto const statement = statementPrepared.bind(start, end);
|
||||
auto const statement = kSTATEMENT_PREPARED.bind(start, end);
|
||||
|
||||
auto const res = this->executor_.read(yield, statement);
|
||||
if (not res) {
|
||||
LOG(log_.error()) << "Could not fetch data from table: " << TableDesc::TABLE_NAME << " range: " << start
|
||||
LOG(log_.error()) << "Could not fetch data from table: " << TableDesc::kTABLE_NAME << " range: " << start
|
||||
<< " - " << end << ";" << res.error();
|
||||
return;
|
||||
}
|
||||
|
||||
auto const& results = res.value();
|
||||
if (not results.hasRows()) {
|
||||
LOG(log_.debug()) << "No rows returned - table: " << TableDesc::TABLE_NAME << " range: " << start << " - "
|
||||
LOG(log_.debug()) << "No rows returned - table: " << TableDesc::kTABLE_NAME << " range: " << start << " - "
|
||||
<< end;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
data::cassandra::PreparedStatement const&
|
||||
getPreparedInsertMigratedMigrator(data::cassandra::Handle const& handler)
|
||||
{
|
||||
static auto prepared = handler.prepare(fmt::format(
|
||||
static auto kPREPARED = handler.prepare(fmt::format(
|
||||
R"(
|
||||
INSERT INTO {}
|
||||
(migrator_name, status)
|
||||
@@ -92,7 +92,7 @@ public:
|
||||
)",
|
||||
data::cassandra::qualifiedTableName<SettingsProviderType>(settingsProvider_.get(), "migrator_status")
|
||||
));
|
||||
return prepared;
|
||||
return kPREPARED;
|
||||
}
|
||||
};
|
||||
} // namespace migration::cassandra::impl
|
||||
|
||||
@@ -74,9 +74,9 @@ class FullTableScanner {
|
||||
* @brief The helper to generate the token ranges.
|
||||
*/
|
||||
struct TokenRangesProvider {
|
||||
uint32_t numRanges_;
|
||||
uint32_t numRanges;
|
||||
|
||||
TokenRangesProvider(uint32_t numRanges) : numRanges_{numRanges}
|
||||
TokenRangesProvider(uint32_t numRanges) : numRanges{numRanges}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -85,18 +85,18 @@ class FullTableScanner {
|
||||
{
|
||||
auto const minValue = std::numeric_limits<std::int64_t>::min();
|
||||
auto const maxValue = std::numeric_limits<std::int64_t>::max();
|
||||
if (numRanges_ == 1)
|
||||
if (numRanges == 1)
|
||||
return {TokenRange{minValue, maxValue}};
|
||||
|
||||
// Safely calculate the range size using uint64_t to avoid overflow
|
||||
uint64_t const rangeSize = (static_cast<uint64_t>(maxValue) * 2) / numRanges_;
|
||||
uint64_t const rangeSize = (static_cast<uint64_t>(maxValue) * 2) / numRanges;
|
||||
|
||||
std::vector<TokenRange> ranges;
|
||||
ranges.reserve(numRanges_);
|
||||
ranges.reserve(numRanges);
|
||||
|
||||
for (std::int64_t i = 0; i < numRanges_; ++i) {
|
||||
for (std::int64_t i = 0; i < numRanges; ++i) {
|
||||
int64_t const start = minValue + (i * rangeSize);
|
||||
int64_t const end = (i == numRanges_ - 1) ? maxValue : start + static_cast<int64_t>(rangeSize) - 1;
|
||||
int64_t const end = (i == numRanges - 1) ? maxValue : start + static_cast<int64_t>(rangeSize) - 1;
|
||||
ranges.emplace_back(start, end);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace migration::cassandra::impl {
|
||||
*/
|
||||
struct TableObjectsDesc {
|
||||
using Row = std::tuple<ripple::uint256, std::uint32_t, data::Blob>;
|
||||
static constexpr char const* PARTITION_KEY = "key";
|
||||
static constexpr char const* TABLE_NAME = "objects";
|
||||
static constexpr char const* kPARTITION_KEY = "key";
|
||||
static constexpr char const* kTABLE_NAME = "objects";
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ concept TableSpec = requires {
|
||||
requires std::tuple_size<typename T::Row>::value >= 0; // Ensures 'row' is a tuple
|
||||
|
||||
// Check that static constexpr members 'partitionKey' and 'tableName' exist
|
||||
{ T::PARTITION_KEY } -> std::convertible_to<char const*>;
|
||||
{ T::TABLE_NAME } -> std::convertible_to<char const*>;
|
||||
{ T::kPARTITION_KEY } -> std::convertible_to<char const*>;
|
||||
{ T::kTABLE_NAME } -> std::convertible_to<char const*>;
|
||||
};
|
||||
} // namespace migration::cassandra::impl
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace migration::cassandra::impl {
|
||||
struct TableTransactionsDesc {
|
||||
// hash, date, ledger_seq, metadata, transaction
|
||||
using Row = std::tuple<ripple::uint256, std::uint64_t, std::uint32_t, ripple::Blob, ripple::Blob>;
|
||||
static constexpr char const* PARTITION_KEY = "hash";
|
||||
static constexpr char const* TABLE_NAME = "transactions";
|
||||
static constexpr char const* kPARTITION_KEY = "hash";
|
||||
static constexpr char const* kTABLE_NAME = "transactions";
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace migration::impl {
|
||||
std::expected<std::shared_ptr<MigrationManagerInterface>, std::string>
|
||||
makeMigrationManager(util::config::ClioConfigDefinition const& config)
|
||||
{
|
||||
static util::Logger const log{"Migration"};
|
||||
static util::Logger const log{"Migration"}; // NOLINT(readability-identifier-naming)
|
||||
LOG(log.info()) << "Constructing MigrationManager";
|
||||
|
||||
auto const type = config.get<std::string>("database.type");
|
||||
|
||||
@@ -66,7 +66,7 @@ class MigratorsRegister {
|
||||
void
|
||||
callMigration(std::string const& name, util::config::ObjectView const& config)
|
||||
{
|
||||
if (name == Migrator::name) {
|
||||
if (name == Migrator::kNAME) {
|
||||
LOG(log_.info()) << "Running migration: " << name;
|
||||
Migrator::runMigration(backend_, config);
|
||||
backend_->writeMigratorStatus(name, MigratorStatus(MigratorStatus::Migrated).toString());
|
||||
@@ -78,7 +78,7 @@ class MigratorsRegister {
|
||||
static constexpr std::string_view
|
||||
getDescriptionIfMatch(std::string_view targetName)
|
||||
{
|
||||
return (T::name == targetName) ? T::description : "";
|
||||
return (T::kNAME == targetName) ? T::kDESCRIPTION : "";
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
constexpr auto
|
||||
getMigratorNames() const
|
||||
{
|
||||
return std::array<std::string_view, sizeof...(MigratorType)>{MigratorType::name...};
|
||||
return std::array<std::string_view, sizeof...(MigratorType)>{MigratorType::kNAME...};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,11 +34,11 @@ namespace migration::impl {
|
||||
*/
|
||||
template <typename T, typename Backend>
|
||||
concept MigratorSpec = requires(std::shared_ptr<Backend> const& backend, util::config::ObjectView const& cfg) {
|
||||
// Check that 'name' exists and is a string
|
||||
{ T::name } -> std::convertible_to<std::string>;
|
||||
// Check that 'kNAME' exists and is a string
|
||||
{ T::kNAME } -> std::convertible_to<std::string>;
|
||||
|
||||
// Check that 'description' exists and is a string
|
||||
{ T::description } -> std::convertible_to<std::string>;
|
||||
// Check that 'kDESCRIPTION' exists and is a string
|
||||
{ T::kDESCRIPTION } -> std::convertible_to<std::string>;
|
||||
|
||||
// Check that the migrator specifies the backend type it supports
|
||||
typename T::Backend;
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
* @return The new instance
|
||||
*/
|
||||
static Counters
|
||||
make_Counters(WorkQueue const& wq)
|
||||
makeCounters(WorkQueue const& wq)
|
||||
{
|
||||
return Counters{wq};
|
||||
}
|
||||
|
||||
@@ -42,20 +42,20 @@ namespace rpc {
|
||||
WarningInfo const&
|
||||
getWarningInfo(WarningCode code)
|
||||
{
|
||||
constexpr static WarningInfo infos[]{
|
||||
{warnUNKNOWN, "Unknown warning"},
|
||||
{warnRPC_CLIO,
|
||||
static constexpr WarningInfo kINFOS[]{
|
||||
{WarnUnknown, "Unknown warning"},
|
||||
{WarnRpcClio,
|
||||
"This is a clio server. clio only serves validated data. If you want to talk to rippled, include "
|
||||
"'ledger_index':'current' in your request"},
|
||||
{warnRPC_OUTDATED, "This server may be out of date"},
|
||||
{warnRPC_RATE_LIMIT, "You are about to be rate limited"},
|
||||
{warnRPC_DEPRECATED,
|
||||
{WarnRpcOutdated, "This server may be out of date"},
|
||||
{WarnRpcRateLimit, "You are about to be rate limited"},
|
||||
{WarnRpcDeprecated,
|
||||
"Some fields from your request are deprecated. Please check the documentation at "
|
||||
"https://xrpl.org/docs/references/http-websocket-apis/ and update your request."}
|
||||
};
|
||||
|
||||
auto matchByCode = [code](auto const& info) { return info.code == code; };
|
||||
if (auto it = std::ranges::find_if(infos, matchByCode); it != end(infos))
|
||||
if (auto it = ranges::find_if(kINFOS, matchByCode); it != end(kINFOS))
|
||||
return *it;
|
||||
|
||||
throw(out_of_range("Invalid WarningCode"));
|
||||
@@ -74,44 +74,43 @@ makeWarning(WarningCode code)
|
||||
ClioErrorInfo const&
|
||||
getErrorInfo(ClioError code)
|
||||
{
|
||||
constexpr static ClioErrorInfo infos[]{
|
||||
{.code = ClioError::rpcMALFORMED_CURRENCY, .error = "malformedCurrency", .message = "Malformed currency."},
|
||||
{.code = ClioError::rpcMALFORMED_REQUEST, .error = "malformedRequest", .message = "Malformed request."},
|
||||
{.code = ClioError::rpcMALFORMED_OWNER, .error = "malformedOwner", .message = "Malformed owner."},
|
||||
{.code = ClioError::rpcMALFORMED_ADDRESS, .error = "malformedAddress", .message = "Malformed address."},
|
||||
{.code = ClioError::rpcINVALID_HOT_WALLET, .error = "invalidHotWallet", .message = "Invalid hot wallet."},
|
||||
{.code = ClioError::rpcUNKNOWN_OPTION, .error = "unknownOption", .message = "Unknown option."},
|
||||
{.code = ClioError::rpcFIELD_NOT_FOUND_TRANSACTION,
|
||||
constexpr static ClioErrorInfo kINFOS[]{
|
||||
{.code = ClioError::RpcMalformedCurrency, .error = "malformedCurrency", .message = "Malformed currency."},
|
||||
{.code = ClioError::RpcMalformedRequest, .error = "malformedRequest", .message = "Malformed request."},
|
||||
{.code = ClioError::RpcMalformedOwner, .error = "malformedOwner", .message = "Malformed owner."},
|
||||
{.code = ClioError::RpcMalformedAddress, .error = "malformedAddress", .message = "Malformed address."},
|
||||
{.code = ClioError::RpcInvalidHotWallet, .error = "invalidHotWallet", .message = "Invalid hot wallet."},
|
||||
{.code = ClioError::RpcUnknownOption, .error = "unknownOption", .message = "Unknown option."},
|
||||
{.code = ClioError::RpcFieldNotFoundTransaction,
|
||||
.error = "fieldNotFoundTransaction",
|
||||
.message = "Missing field."},
|
||||
{.code = ClioError::rpcMALFORMED_ORACLE_DOCUMENT_ID,
|
||||
{.code = ClioError::RpcMalformedOracleDocumentId,
|
||||
.error = "malformedDocumentID",
|
||||
.message = "Malformed oracle_document_id."},
|
||||
{.code = ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS,
|
||||
{.code = ClioError::RpcMalformedAuthorizedCredentials,
|
||||
.error = "malformedAuthorizedCredentials",
|
||||
.message = "Malformed authorized credentials."},
|
||||
// special system errors
|
||||
{.code = ClioError::rpcINVALID_API_VERSION, .error = JS(invalid_API_version), .message = "Invalid API version."
|
||||
},
|
||||
{.code = ClioError::rpcCOMMAND_IS_MISSING,
|
||||
{.code = ClioError::RpcInvalidApiVersion, .error = JS(invalid_API_version), .message = "Invalid API version."},
|
||||
{.code = ClioError::RpcCommandIsMissing,
|
||||
.error = JS(missingCommand),
|
||||
.message = "Method is not specified or is not a string."},
|
||||
{.code = ClioError::rpcCOMMAND_NOT_STRING, .error = "commandNotString", .message = "Method is not a string."},
|
||||
{.code = ClioError::rpcCOMMAND_IS_EMPTY, .error = "emptyCommand", .message = "Method is an empty string."},
|
||||
{.code = ClioError::rpcPARAMS_UNPARSEABLE,
|
||||
{.code = ClioError::RpcCommandNotString, .error = "commandNotString", .message = "Method is not a string."},
|
||||
{.code = ClioError::RpcCommandIsEmpty, .error = "emptyCommand", .message = "Method is an empty string."},
|
||||
{.code = ClioError::RpcParamsUnparseable,
|
||||
.error = "paramsUnparseable",
|
||||
.message = "Params must be an array holding exactly one object."},
|
||||
// etl related errors
|
||||
{.code = ClioError::etlCONNECTION_ERROR, .error = "connectionError", .message = "Couldn't connect to rippled."},
|
||||
{.code = ClioError::etlREQUEST_ERROR, .error = "requestError", .message = "Error sending request to rippled."},
|
||||
{.code = ClioError::etlREQUEST_TIMEOUT, .error = "timeout", .message = "Request to rippled timed out."},
|
||||
{.code = ClioError::etlINVALID_RESPONSE,
|
||||
{.code = ClioError::EtlConnectionError, .error = "connectionError", .message = "Couldn't connect to rippled."},
|
||||
{.code = ClioError::EtlRequestError, .error = "requestError", .message = "Error sending request to rippled."},
|
||||
{.code = ClioError::EtlRequestTimeout, .error = "timeout", .message = "Request to rippled timed out."},
|
||||
{.code = ClioError::EtlInvalidResponse,
|
||||
.error = "invalidResponse",
|
||||
.message = "Rippled returned an invalid response."}
|
||||
};
|
||||
|
||||
auto matchByCode = [code](auto const& info) { return info.code == code; };
|
||||
if (auto it = std::ranges::find_if(infos, matchByCode); it != end(infos))
|
||||
if (auto it = ranges::find_if(kINFOS, matchByCode); it != end(kINFOS))
|
||||
return *it;
|
||||
|
||||
throw(out_of_range("Invalid error code"));
|
||||
|
||||
@@ -35,30 +35,30 @@ namespace rpc {
|
||||
/** @brief Custom clio RPC Errors. */
|
||||
enum class ClioError {
|
||||
// normal clio errors start with 5000
|
||||
rpcMALFORMED_CURRENCY = 5000,
|
||||
rpcMALFORMED_REQUEST = 5001,
|
||||
rpcMALFORMED_OWNER = 5002,
|
||||
rpcMALFORMED_ADDRESS = 5003,
|
||||
rpcINVALID_HOT_WALLET = 5004,
|
||||
rpcUNKNOWN_OPTION = 5005,
|
||||
rpcFIELD_NOT_FOUND_TRANSACTION = 5006,
|
||||
rpcMALFORMED_ORACLE_DOCUMENT_ID = 5007,
|
||||
rpcMALFORMED_AUTHORIZED_CREDENTIALS = 5008,
|
||||
RpcMalformedCurrency = 5000,
|
||||
RpcMalformedRequest = 5001,
|
||||
RpcMalformedOwner = 5002,
|
||||
RpcMalformedAddress = 5003,
|
||||
RpcInvalidHotWallet = 5004,
|
||||
RpcUnknownOption = 5005,
|
||||
RpcFieldNotFoundTransaction = 5006,
|
||||
RpcMalformedOracleDocumentId = 5007,
|
||||
RpcMalformedAuthorizedCredentials = 5008,
|
||||
|
||||
// special system errors start with 6000
|
||||
rpcINVALID_API_VERSION = 6000,
|
||||
rpcCOMMAND_IS_MISSING = 6001,
|
||||
rpcCOMMAND_NOT_STRING = 6002,
|
||||
rpcCOMMAND_IS_EMPTY = 6003,
|
||||
rpcPARAMS_UNPARSEABLE = 6004,
|
||||
RpcInvalidApiVersion = 6000,
|
||||
RpcCommandIsMissing = 6001,
|
||||
RpcCommandNotString = 6002,
|
||||
RpcCommandIsEmpty = 6003,
|
||||
RpcParamsUnparseable = 6004,
|
||||
|
||||
// TODO: Since it is not only rpc errors here now, we should move it to util
|
||||
// etl related errors start with 7000
|
||||
// Higher value in this errors means better progress in the forwarding
|
||||
etlCONNECTION_ERROR = 7000,
|
||||
etlREQUEST_ERROR = 7001,
|
||||
etlREQUEST_TIMEOUT = 7002,
|
||||
etlINVALID_RESPONSE = 7003,
|
||||
EtlConnectionError = 7000,
|
||||
EtlRequestError = 7001,
|
||||
EtlRequestTimeout = 7002,
|
||||
EtlInvalidResponse = 7003,
|
||||
};
|
||||
|
||||
/** @brief Holds info about a particular @ref ClioError. */
|
||||
@@ -186,11 +186,11 @@ struct Status {
|
||||
|
||||
/** @brief Warning codes that can be returned by clio. */
|
||||
enum WarningCode {
|
||||
warnUNKNOWN = -1,
|
||||
warnRPC_CLIO = 2001,
|
||||
warnRPC_OUTDATED = 2002,
|
||||
warnRPC_RATE_LIMIT = 2003,
|
||||
warnRPC_DEPRECATED = 2004
|
||||
WarnUnknown = -1,
|
||||
WarnRpcClio = 2001,
|
||||
WarnRpcOutdated = 2002,
|
||||
WarnRpcRateLimit = 2003,
|
||||
WarnRpcDeprecated = 2004
|
||||
};
|
||||
|
||||
/** @brief Holds information about a clio warning. */
|
||||
@@ -207,13 +207,13 @@ struct WarningInfo {
|
||||
{
|
||||
}
|
||||
|
||||
WarningCode code = warnUNKNOWN;
|
||||
WarningCode code = WarnUnknown;
|
||||
std::string_view const message = "unknown warning";
|
||||
};
|
||||
|
||||
/** @brief Invalid parameters error. */
|
||||
class InvalidParamsError : public std::exception {
|
||||
std::string msg;
|
||||
std::string msg_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
*
|
||||
* @param msg The error message
|
||||
*/
|
||||
explicit InvalidParamsError(std::string msg) : msg(std::move(msg))
|
||||
explicit InvalidParamsError(std::string msg) : msg_(std::move(msg))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -233,13 +233,13 @@ public:
|
||||
char const*
|
||||
what() const throw() override
|
||||
{
|
||||
return msg.c_str();
|
||||
return msg_.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief Account not found error. */
|
||||
class AccountNotFoundError : public std::exception {
|
||||
std::string account;
|
||||
std::string account_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
*
|
||||
* @param acct The account
|
||||
*/
|
||||
explicit AccountNotFoundError(std::string acct) : account(std::move(acct))
|
||||
explicit AccountNotFoundError(std::string acct) : account_(std::move(acct))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -259,12 +259,12 @@ public:
|
||||
char const*
|
||||
what() const throw() override
|
||||
{
|
||||
return account.c_str();
|
||||
return account_.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
/** @brief A globally available @ref rpc::Status that represents a successful state. */
|
||||
static Status OK;
|
||||
static Status gOk;
|
||||
|
||||
/**
|
||||
* @brief Get the warning info object from a warning code.
|
||||
|
||||
@@ -44,7 +44,7 @@ using namespace util;
|
||||
namespace rpc {
|
||||
|
||||
std::expected<web::Context, Status>
|
||||
make_WsContext(
|
||||
makeWsContext(
|
||||
boost::asio::yield_context yc,
|
||||
boost::json::object const& request,
|
||||
web::SubscriptionContextPtr session,
|
||||
@@ -63,18 +63,18 @@ make_WsContext(
|
||||
}
|
||||
|
||||
if (!commandValue.is_string())
|
||||
return Error{{ClioError::rpcCOMMAND_IS_MISSING, "Method/Command is not specified or is not a string."}};
|
||||
return Error{{ClioError::RpcCommandIsMissing, "Method/Command is not specified or is not a string."}};
|
||||
|
||||
auto const apiVersion = apiVersionParser.get().parse(request);
|
||||
if (!apiVersion)
|
||||
return Error{{ClioError::rpcINVALID_API_VERSION, apiVersion.error()}};
|
||||
return Error{{ClioError::RpcInvalidApiVersion, apiVersion.error()}};
|
||||
|
||||
auto const command = boost::json::value_to<std::string>(commandValue);
|
||||
return web::Context(yc, command, *apiVersion, request, std::move(session), tagFactory, range, clientIp, isAdmin);
|
||||
}
|
||||
|
||||
std::expected<web::Context, Status>
|
||||
make_HttpContext(
|
||||
makeHttpContext(
|
||||
boost::asio::yield_context yc,
|
||||
boost::json::object const& request,
|
||||
util::TagDecoratorFactory const& tagFactory,
|
||||
@@ -85,13 +85,13 @@ make_HttpContext(
|
||||
)
|
||||
{
|
||||
if (!request.contains("method"))
|
||||
return Error{{ClioError::rpcCOMMAND_IS_MISSING}};
|
||||
return Error{{ClioError::RpcCommandIsMissing}};
|
||||
|
||||
if (!request.at("method").is_string())
|
||||
return Error{{ClioError::rpcCOMMAND_NOT_STRING}};
|
||||
return Error{{ClioError::RpcCommandNotString}};
|
||||
|
||||
if (request.at("method").as_string().empty())
|
||||
return Error{{ClioError::rpcCOMMAND_IS_EMPTY}};
|
||||
return Error{{ClioError::RpcCommandIsEmpty}};
|
||||
|
||||
auto const command = boost::json::value_to<std::string>(request.at("method"));
|
||||
|
||||
@@ -99,16 +99,16 @@ make_HttpContext(
|
||||
return Error{{RippledError::rpcBAD_SYNTAX, "Subscribe and unsubscribe are only allowed for websocket."}};
|
||||
|
||||
if (!request.at("params").is_array())
|
||||
return Error{{ClioError::rpcPARAMS_UNPARSEABLE, "Missing params array."}};
|
||||
return Error{{ClioError::RpcParamsUnparseable, "Missing params array."}};
|
||||
|
||||
boost::json::array const& array = request.at("params").as_array();
|
||||
|
||||
if (array.size() != 1 || !array.at(0).is_object())
|
||||
return Error{{ClioError::rpcPARAMS_UNPARSEABLE}};
|
||||
return Error{{ClioError::RpcParamsUnparseable}};
|
||||
|
||||
auto const apiVersion = apiVersionParser.get().parse(request.at("params").as_array().at(0).as_object());
|
||||
if (!apiVersion)
|
||||
return Error{{ClioError::rpcINVALID_API_VERSION, apiVersion.error()}};
|
||||
return Error{{ClioError::RpcInvalidApiVersion, apiVersion.error()}};
|
||||
|
||||
return web::Context(
|
||||
yc, command, *apiVersion, array.at(0).as_object(), nullptr, tagFactory, range, clientIp, isAdmin
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace rpc {
|
||||
* @return A Websocket context or error Status
|
||||
*/
|
||||
std::expected<web::Context, Status>
|
||||
make_WsContext(
|
||||
makeWsContext(
|
||||
boost::asio::yield_context yc,
|
||||
boost::json::object const& request,
|
||||
web::SubscriptionContextPtr session,
|
||||
@@ -81,7 +81,7 @@ make_WsContext(
|
||||
* @return A HTTP context or error Status
|
||||
*/
|
||||
std::expected<web::Context, Status>
|
||||
make_HttpContext(
|
||||
makeHttpContext(
|
||||
boost::asio::yield_context yc,
|
||||
boost::json::object const& request,
|
||||
util::TagDecoratorFactory const& tagFactory,
|
||||
|
||||
@@ -125,7 +125,7 @@ public:
|
||||
* @return A new instance of the RPC engine
|
||||
*/
|
||||
static std::shared_ptr<RPCEngine>
|
||||
make_RPCEngine(
|
||||
makeRPCEngine(
|
||||
util::config::ClioConfigDefinition const& config,
|
||||
std::shared_ptr<BackendInterface> const& backend,
|
||||
std::shared_ptr<LoadBalancerType> const& balancer,
|
||||
|
||||
@@ -156,9 +156,9 @@ getDeliveredAmount(
|
||||
// then its absence indicates that the amount delivered is listed in the
|
||||
// Amount field. DeliveredAmount went live January 24, 2014.
|
||||
// 446000000 is in Feb 2014, well after DeliveredAmount went live
|
||||
static std::uint32_t constexpr FIRST_LEDGER_WITH_DELIVERED_AMOUNT = 4594095;
|
||||
static std::uint32_t constexpr DELIVERED_AMOUNT_LIVE_DATE = 446000000;
|
||||
if (ledgerSequence >= FIRST_LEDGER_WITH_DELIVERED_AMOUNT || date > DELIVERED_AMOUNT_LIVE_DATE) {
|
||||
static constexpr std::uint32_t kFIRST_LEDGER_WITH_DELIVERED_AMOUNT = 4594095;
|
||||
static constexpr std::uint32_t kDELIVERED_AMOUNT_LIVE_DATE = 446000000;
|
||||
if (ledgerSequence >= kFIRST_LEDGER_WITH_DELIVERED_AMOUNT || date > kDELIVERED_AMOUNT_LIVE_DATE) {
|
||||
return txn->getFieldAmount(ripple::sfAmount);
|
||||
}
|
||||
}
|
||||
@@ -286,13 +286,13 @@ toExpandedJson(
|
||||
std::optional<std::string>
|
||||
encodeCTID(uint32_t ledgerSeq, uint16_t txnIndex, uint16_t networkId) noexcept
|
||||
{
|
||||
static uint32_t constexpr MAX_LEDGER_SEQ = 0x0FFF'FFFF;
|
||||
if (ledgerSeq > MAX_LEDGER_SEQ)
|
||||
static constexpr uint32_t kMAX_LEDGER_SEQ = 0x0FFF'FFFF;
|
||||
if (ledgerSeq > kMAX_LEDGER_SEQ)
|
||||
return {};
|
||||
|
||||
static uint64_t constexpr CTID_PREFIX = 0xC000'0000;
|
||||
static constexpr uint64_t kCTID_PREFIX = 0xC000'0000;
|
||||
uint64_t const ctidValue =
|
||||
((CTID_PREFIX + static_cast<uint64_t>(ledgerSeq)) << 32) + (static_cast<uint64_t>(txnIndex) << 16) + networkId;
|
||||
((kCTID_PREFIX + static_cast<uint64_t>(ledgerSeq)) << 32) + (static_cast<uint64_t>(txnIndex) << 16) + networkId;
|
||||
|
||||
return {fmt::format("{:016X}", ctidValue)};
|
||||
}
|
||||
@@ -711,8 +711,8 @@ traverseOwnedNodes(
|
||||
// Only reserve 2048 nodes when fetching all owned ledger objects. If there
|
||||
// are more, then keys will allocate more memory, which is suboptimal, but
|
||||
// should only occur occasionally.
|
||||
static std::uint32_t constexpr MIN_NODES = 2048;
|
||||
keys.reserve(std::min(MIN_NODES, limit));
|
||||
static constexpr std::uint32_t kMIN_NODES = 2048;
|
||||
keys.reserve(std::min(kMIN_NODES, limit));
|
||||
|
||||
auto start = std::chrono::system_clock::now();
|
||||
|
||||
@@ -848,10 +848,10 @@ parseRippleLibSeed(boost::json::value const& value)
|
||||
|
||||
auto const result = ripple::decodeBase58Token(boost::json::value_to<std::string>(value), ripple::TokenType::None);
|
||||
|
||||
static std::size_t constexpr SEED_SIZE = 18;
|
||||
static std::array<std::uint8_t, 2> constexpr SEED_PREFIX = {0xE1, 0x4B};
|
||||
if (result.size() == SEED_SIZE && static_cast<std::uint8_t>(result[0]) == SEED_PREFIX[0] &&
|
||||
static_cast<std::uint8_t>(result[1]) == SEED_PREFIX[1])
|
||||
static constexpr std::size_t kSEED_SIZE = 18;
|
||||
static constexpr std::array<std::uint8_t, 2> kSEED_PREFIX = {0xE1, 0x4B};
|
||||
if (result.size() == kSEED_SIZE && static_cast<std::uint8_t>(result[0]) == kSEED_PREFIX[0] &&
|
||||
static_cast<std::uint8_t>(result[1]) == kSEED_PREFIX[1])
|
||||
return ripple::Seed(ripple::makeSlice(result.substr(2)));
|
||||
|
||||
return {};
|
||||
@@ -1212,94 +1212,94 @@ parseBook(boost::json::object const& request)
|
||||
if (!request.at("taker_gets").is_object())
|
||||
return Status{RippledError::rpcINVALID_PARAMS, "Field 'taker_gets' is not an object"};
|
||||
|
||||
auto taker_pays = request.at("taker_pays").as_object();
|
||||
if (!taker_pays.contains("currency"))
|
||||
auto takerPays = request.at("taker_pays").as_object();
|
||||
if (!takerPays.contains("currency"))
|
||||
return Status{RippledError::rpcSRC_CUR_MALFORMED};
|
||||
|
||||
if (!taker_pays.at("currency").is_string())
|
||||
if (!takerPays.at("currency").is_string())
|
||||
return Status{RippledError::rpcSRC_CUR_MALFORMED};
|
||||
|
||||
auto taker_gets = request.at("taker_gets").as_object();
|
||||
if (!taker_gets.contains("currency"))
|
||||
auto takerGets = request.at("taker_gets").as_object();
|
||||
if (!takerGets.contains("currency"))
|
||||
return Status{RippledError::rpcDST_AMT_MALFORMED};
|
||||
|
||||
if (!taker_gets.at("currency").is_string()) {
|
||||
if (!takerGets.at("currency").is_string()) {
|
||||
return Status{
|
||||
RippledError::rpcDST_AMT_MALFORMED,
|
||||
};
|
||||
}
|
||||
|
||||
ripple::Currency pay_currency;
|
||||
if (!ripple::to_currency(pay_currency, boost::json::value_to<std::string>(taker_pays.at("currency"))))
|
||||
ripple::Currency payCurrency;
|
||||
if (!ripple::to_currency(payCurrency, boost::json::value_to<std::string>(takerPays.at("currency"))))
|
||||
return Status{RippledError::rpcSRC_CUR_MALFORMED};
|
||||
|
||||
ripple::Currency get_currency;
|
||||
if (!ripple::to_currency(get_currency, boost::json::value_to<std::string>(taker_gets["currency"])))
|
||||
ripple::Currency getCurrency;
|
||||
if (!ripple::to_currency(getCurrency, boost::json::value_to<std::string>(takerGets["currency"])))
|
||||
return Status{RippledError::rpcDST_AMT_MALFORMED};
|
||||
|
||||
ripple::AccountID pay_issuer;
|
||||
if (taker_pays.contains("issuer")) {
|
||||
if (!taker_pays.at("issuer").is_string())
|
||||
ripple::AccountID payIssuer;
|
||||
if (takerPays.contains("issuer")) {
|
||||
if (!takerPays.at("issuer").is_string())
|
||||
return Status{RippledError::rpcINVALID_PARAMS, "takerPaysIssuerNotString"};
|
||||
|
||||
if (!ripple::to_issuer(pay_issuer, boost::json::value_to<std::string>(taker_pays.at("issuer"))))
|
||||
if (!ripple::to_issuer(payIssuer, boost::json::value_to<std::string>(takerPays.at("issuer"))))
|
||||
return Status{RippledError::rpcSRC_ISR_MALFORMED};
|
||||
|
||||
if (pay_issuer == ripple::noAccount())
|
||||
if (payIssuer == ripple::noAccount())
|
||||
return Status{RippledError::rpcSRC_ISR_MALFORMED};
|
||||
} else {
|
||||
pay_issuer = ripple::xrpAccount();
|
||||
payIssuer = ripple::xrpAccount();
|
||||
}
|
||||
|
||||
if (isXRP(pay_currency) && !isXRP(pay_issuer)) {
|
||||
if (isXRP(payCurrency) && !isXRP(payIssuer)) {
|
||||
return Status{
|
||||
RippledError::rpcSRC_ISR_MALFORMED, "Unneeded field 'taker_pays.issuer' for XRP currency specification."
|
||||
};
|
||||
}
|
||||
|
||||
if (!isXRP(pay_currency) && isXRP(pay_issuer)) {
|
||||
if (!isXRP(payCurrency) && isXRP(payIssuer)) {
|
||||
return Status{
|
||||
RippledError::rpcSRC_ISR_MALFORMED, "Invalid field 'taker_pays.issuer', expected non-XRP issuer."
|
||||
};
|
||||
}
|
||||
|
||||
if ((!isXRP(pay_currency)) && (!taker_pays.contains("issuer")))
|
||||
if ((!isXRP(payCurrency)) && (!takerPays.contains("issuer")))
|
||||
return Status{RippledError::rpcSRC_ISR_MALFORMED, "Missing non-XRP issuer."};
|
||||
|
||||
ripple::AccountID get_issuer;
|
||||
ripple::AccountID getIssuer;
|
||||
|
||||
if (taker_gets.contains("issuer")) {
|
||||
if (!taker_gets["issuer"].is_string())
|
||||
if (takerGets.contains("issuer")) {
|
||||
if (!takerGets["issuer"].is_string())
|
||||
return Status{RippledError::rpcINVALID_PARAMS, "taker_gets.issuer should be string"};
|
||||
|
||||
if (!ripple::to_issuer(get_issuer, boost::json::value_to<std::string>(taker_gets.at("issuer"))))
|
||||
if (!ripple::to_issuer(getIssuer, boost::json::value_to<std::string>(takerGets.at("issuer"))))
|
||||
return Status{RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer."};
|
||||
|
||||
if (get_issuer == ripple::noAccount()) {
|
||||
if (getIssuer == ripple::noAccount()) {
|
||||
return Status{
|
||||
RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', bad issuer account one."
|
||||
};
|
||||
}
|
||||
} else {
|
||||
get_issuer = ripple::xrpAccount();
|
||||
getIssuer = ripple::xrpAccount();
|
||||
}
|
||||
|
||||
if (ripple::isXRP(get_currency) && !ripple::isXRP(get_issuer)) {
|
||||
if (ripple::isXRP(getCurrency) && !ripple::isXRP(getIssuer)) {
|
||||
return Status{
|
||||
RippledError::rpcDST_ISR_MALFORMED, "Unneeded field 'taker_gets.issuer' for XRP currency specification."
|
||||
};
|
||||
}
|
||||
|
||||
if (!ripple::isXRP(get_currency) && ripple::isXRP(get_issuer)) {
|
||||
if (!ripple::isXRP(getCurrency) && ripple::isXRP(getIssuer)) {
|
||||
return Status{
|
||||
RippledError::rpcDST_ISR_MALFORMED, "Invalid field 'taker_gets.issuer', expected non-XRP issuer."
|
||||
};
|
||||
}
|
||||
|
||||
if (pay_currency == get_currency && pay_issuer == get_issuer)
|
||||
if (payCurrency == getCurrency && payIssuer == getIssuer)
|
||||
return Status{RippledError::rpcBAD_MARKET, "badMarket"};
|
||||
|
||||
return ripple::Book{{pay_currency, pay_issuer}, {get_currency, get_issuer}};
|
||||
return ripple::Book{{payCurrency, payIssuer}, {getCurrency, getIssuer}};
|
||||
}
|
||||
|
||||
std::variant<Status, ripple::AccountID>
|
||||
|
||||
@@ -616,8 +616,8 @@ decodeCTID(T const ctid) noexcept
|
||||
auto const getCTID64 = [](T const ctid) noexcept -> std::optional<uint64_t> {
|
||||
if constexpr (std::is_convertible_v<T, std::string>) {
|
||||
std::string const ctidString(ctid);
|
||||
static std::size_t constexpr CTID_STRING_LENGTH = 16;
|
||||
if (ctidString.length() != CTID_STRING_LENGTH)
|
||||
static constexpr std::size_t kCTID_STRING_LENGTH = 16;
|
||||
if (ctidString.length() != kCTID_STRING_LENGTH)
|
||||
return {};
|
||||
|
||||
if (!boost::regex_match(ctidString, boost::regex("^[0-9A-F]+$")))
|
||||
@@ -634,10 +634,10 @@ decodeCTID(T const ctid) noexcept
|
||||
|
||||
auto const ctidValue = getCTID64(ctid).value_or(0);
|
||||
|
||||
static uint64_t constexpr CTID_PREFIX = 0xC000'0000'0000'0000ULL;
|
||||
static uint64_t constexpr CTID_PREFIX_MASK = 0xF000'0000'0000'0000ULL;
|
||||
static constexpr uint64_t kCTID_PREFIX = 0xC000'0000'0000'0000ULL;
|
||||
static constexpr uint64_t kCTID_PREFIX_MASK = 0xF000'0000'0000'0000ULL;
|
||||
|
||||
if ((ctidValue & CTID_PREFIX_MASK) != CTID_PREFIX)
|
||||
if ((ctidValue & kCTID_PREFIX_MASK) != kCTID_PREFIX)
|
||||
return {};
|
||||
|
||||
uint32_t const ledgerSeq = (ctidValue >> 32) & 0xFFFF'FFFUL;
|
||||
@@ -659,8 +659,8 @@ logDuration(web::Context const& ctx, T const& dur)
|
||||
{
|
||||
using boost::json::serialize;
|
||||
|
||||
static util::Logger const log{"RPC"};
|
||||
static std::int64_t constexpr DURATION_ERROR_THRESHOLD_SECONDS = 10;
|
||||
static util::Logger const log{"RPC"}; // NOLINT(readability-identifier-naming)
|
||||
static constexpr std::int64_t kDURATION_ERROR_THRESHOLD_SECONDS = 10;
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
|
||||
auto const seconds = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
|
||||
@@ -668,7 +668,7 @@ logDuration(web::Context const& ctx, T const& dur)
|
||||
"Request processing duration = {} milliseconds. request = {}", millis, serialize(util::removeSecret(ctx.params))
|
||||
);
|
||||
|
||||
if (seconds > DURATION_ERROR_THRESHOLD_SECONDS) {
|
||||
if (seconds > kDURATION_ERROR_THRESHOLD_SECONDS) {
|
||||
LOG(log.error()) << ctx.tag() << msg;
|
||||
} else if (seconds > 1) {
|
||||
LOG(log.warn()) << ctx.tag() << msg;
|
||||
|
||||
@@ -90,9 +90,9 @@ WorkQueue::stop(std::function<void()> onQueueEmpty)
|
||||
}
|
||||
|
||||
WorkQueue
|
||||
WorkQueue::make_WorkQueue(util::config::ClioConfigDefinition const& config)
|
||||
WorkQueue::makeWorkQueue(util::config::ClioConfigDefinition const& config)
|
||||
{
|
||||
static util::Logger const log{"RPC"};
|
||||
static util::Logger const log{"RPC"}; // NOLINT(readability-identifier-naming)
|
||||
auto const serverConfig = config.getObject("server");
|
||||
auto const numThreads = config.get<uint32_t>("workers");
|
||||
auto const maxQueueSize = serverConfig.get<uint32_t>("max_queue_size");
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
* @return The work queue
|
||||
*/
|
||||
static WorkQueue
|
||||
make_WorkQueue(util::config::ClioConfigDefinition const& config);
|
||||
makeWorkQueue(util::config::ClioConfigDefinition const& config);
|
||||
|
||||
/**
|
||||
* @brief Submit a job to the work queue.
|
||||
|
||||
@@ -30,17 +30,17 @@ namespace rpc {
|
||||
/**
|
||||
* @brief Default API version to use if no version is specified by clients
|
||||
*/
|
||||
static constexpr uint32_t API_VERSION_DEFAULT = 1u;
|
||||
static constexpr uint32_t kAPI_VERSION_DEFAULT = 1u;
|
||||
|
||||
/**
|
||||
* @brief Minimum API version supported by this build
|
||||
*/
|
||||
static constexpr uint32_t API_VERSION_MIN = 1u;
|
||||
static constexpr uint32_t kAPI_VERSION_MIN = 1u;
|
||||
|
||||
/**
|
||||
* @brief Maximum API version supported by this build
|
||||
*/
|
||||
static constexpr uint32_t API_VERSION_MAX = 3u;
|
||||
static constexpr uint32_t kAPI_VERSION_MAX = 3u;
|
||||
|
||||
/**
|
||||
* @brief A baseclass for API version helper
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
check(boost::json::value const& value, std::string_view key)
|
||||
{
|
||||
if (value.is_object() and value.as_object().contains(key))
|
||||
return Warning{WarningCode::warnRPC_DEPRECATED, fmt::format("Field '{}' is deprecated.", key)};
|
||||
return Warning{WarningCode::WarnRpcDeprecated, fmt::format("Field '{}' is deprecated.", key)};
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
auto const res = value_to<T>(value.as_object().at(key));
|
||||
if (value_ == res) {
|
||||
return Warning{
|
||||
WarningCode::warnRPC_DEPRECATED, fmt::format("Value '{}' for field '{}' is deprecated", value_, key)
|
||||
WarningCode::WarnRpcDeprecated, fmt::format("Value '{}' for field '{}' is deprecated", value_, key)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ Section::verify(boost::json::value& value, std::string_view key) const
|
||||
if (!res.is_object())
|
||||
return {};
|
||||
|
||||
for (auto const& spec : specs) {
|
||||
for (auto const& spec : specs_) {
|
||||
if (auto const ret = spec.process(res); not ret)
|
||||
return Error{ret.error()};
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "rpc/Errors.hpp"
|
||||
#include "rpc/common/Concepts.hpp"
|
||||
#include "rpc/common/Specs.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
|
||||
@@ -40,7 +41,7 @@ namespace rpc::meta {
|
||||
* @brief A meta-processor that acts as a spec for a sub-object/section.
|
||||
*/
|
||||
class Section final {
|
||||
std::vector<FieldSpec> specs;
|
||||
std::vector<FieldSpec> specs_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -48,7 +49,7 @@ public:
|
||||
*
|
||||
* @param specs List of specs @ref FieldSpec
|
||||
*/
|
||||
explicit Section(std::initializer_list<FieldSpec> specs) : specs{specs}
|
||||
explicit Section(std::initializer_list<FieldSpec> specs) : specs_{specs}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -163,8 +164,8 @@ private:
|
||||
template <typename RequirementOrModifierType>
|
||||
requires SomeRequirement<RequirementOrModifierType> or SomeModifier<RequirementOrModifierType>
|
||||
class WithCustomError final {
|
||||
RequirementOrModifierType reqOrModifier;
|
||||
Status error;
|
||||
RequirementOrModifierType reqOrModifier_;
|
||||
Status error_;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -175,7 +176,7 @@ public:
|
||||
* @param err The custom error to return in case `req` fails
|
||||
*/
|
||||
WithCustomError(RequirementOrModifierType reqOrModifier, Status err)
|
||||
: reqOrModifier{std::move(reqOrModifier)}, error{std::move(err)}
|
||||
: reqOrModifier_{std::move(reqOrModifier)}, error_{std::move(err)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -190,8 +191,8 @@ public:
|
||||
verify(boost::json::value const& value, std::string_view key) const
|
||||
requires SomeRequirement<RequirementOrModifierType>
|
||||
{
|
||||
if (auto const res = reqOrModifier.verify(value, key); not res)
|
||||
return Error{error};
|
||||
if (auto const res = reqOrModifier_.verify(value, key); not res)
|
||||
return Error{error_};
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -208,8 +209,8 @@ public:
|
||||
verify(boost::json::value& value, std::string_view key) const
|
||||
requires SomeRequirement<RequirementOrModifierType>
|
||||
{
|
||||
if (auto const res = reqOrModifier.verify(value, key); not res)
|
||||
return Error{error};
|
||||
if (auto const res = reqOrModifier_.verify(value, key); not res)
|
||||
return Error{error_};
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -226,8 +227,8 @@ public:
|
||||
requires SomeModifier<RequirementOrModifierType>
|
||||
|
||||
{
|
||||
if (auto const res = reqOrModifier.modify(value, key); not res)
|
||||
return Error{error};
|
||||
if (auto const res = reqOrModifier_.modify(value, key); not res)
|
||||
return Error{error_};
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@ struct FieldSpec final {
|
||||
template <SomeProcessor... Processors>
|
||||
FieldSpec(std::string const& key, Processors&&... processors)
|
||||
: processor_{impl::makeFieldProcessor<Processors...>(key, std::forward<Processors>(processors)...)}
|
||||
, checker_{impl::EMPTY_FIELD_CHECKER}
|
||||
, checker_{impl::kEMPTY_FIELD_CHECKER}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ struct FieldSpec final {
|
||||
*/
|
||||
template <SomeCheck... Checks>
|
||||
FieldSpec(std::string const& key, Checks&&... checks)
|
||||
: processor_{impl::EMPTY_FIELD_PROCESSOR}
|
||||
: processor_{impl::kEMPTY_FIELD_PROCESSOR}
|
||||
, checker_{impl::makeFieldChecker<Checks...>(key, std::forward<Checks>(checks)...)}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ TimeFormatValidator::verify(boost::json::value const& value, std::string_view ke
|
||||
if (not value.as_object().at(key).is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||
|
||||
auto const ret = util::SystemTpFromUTCStr(value_to<std::string>(value.as_object().at(key)), format_);
|
||||
auto const ret = util::systemTpFromUtcStr(value_to<std::string>(value.as_object().at(key)), format_);
|
||||
if (!ret)
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS}};
|
||||
|
||||
@@ -91,22 +91,22 @@ checkIsU32Numeric(std::string_view sv)
|
||||
return ec == std::errc();
|
||||
}
|
||||
|
||||
CustomValidator CustomValidators::Uint160HexStringValidator =
|
||||
CustomValidator CustomValidators::uint160HexStringValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
return makeHexStringValidator<ripple::uint160>(value, key);
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::Uint192HexStringValidator =
|
||||
CustomValidator CustomValidators::uint192HexStringValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
return makeHexStringValidator<ripple::uint192>(value, key);
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::Uint256HexStringValidator =
|
||||
CustomValidator CustomValidators::uint256HexStringValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
return makeHexStringValidator<ripple::uint256>(value, key);
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::LedgerIndexValidator =
|
||||
CustomValidator CustomValidators::ledgerIndexValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view /* key */) -> MaybeError {
|
||||
auto err = Error{Status{RippledError::rpcINVALID_PARAMS, "ledgerIndexMalformed"}};
|
||||
|
||||
@@ -120,7 +120,7 @@ CustomValidator CustomValidators::LedgerIndexValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::AccountValidator =
|
||||
CustomValidator CustomValidators::accountValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
@@ -133,19 +133,19 @@ CustomValidator CustomValidators::AccountValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::AccountBase58Validator =
|
||||
CustomValidator CustomValidators::accountBase58Validator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
|
||||
auto const account = util::parseBase58Wrapper<ripple::AccountID>(boost::json::value_to<std::string>(value));
|
||||
if (!account || account->isZero())
|
||||
return Error{Status{ClioError::rpcMALFORMED_ADDRESS}};
|
||||
return Error{Status{ClioError::RpcMalformedAddress}};
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::AccountMarkerValidator =
|
||||
CustomValidator CustomValidators::accountMarkerValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
@@ -160,7 +160,7 @@ CustomValidator CustomValidators::AccountMarkerValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::CurrencyValidator =
|
||||
CustomValidator CustomValidators::currencyValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
@@ -171,12 +171,12 @@ CustomValidator CustomValidators::CurrencyValidator =
|
||||
|
||||
ripple::Currency currency;
|
||||
if (!ripple::to_currency(currency, currencyStr))
|
||||
return Error{Status{ClioError::rpcMALFORMED_CURRENCY, "malformedCurrency"}};
|
||||
return Error{Status{ClioError::RpcMalformedCurrency, "malformedCurrency"}};
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::IssuerValidator =
|
||||
CustomValidator CustomValidators::issuerValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
@@ -196,31 +196,31 @@ CustomValidator CustomValidators::IssuerValidator =
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::SubscribeStreamValidator =
|
||||
CustomValidator CustomValidators::subscribeStreamValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_array())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotArray"}};
|
||||
|
||||
static std::unordered_set<std::string> const validStreams = {
|
||||
static std::unordered_set<std::string> const kVALID_STREAMS = {
|
||||
"ledger", "transactions", "transactions_proposed", "book_changes", "manifests", "validations"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> const notSupportStreams = {"peer_status", "consensus", "server"};
|
||||
static std::unordered_set<std::string> const kNOT_SUPPORT_STREAMS = {"peer_status", "consensus", "server"};
|
||||
for (auto const& v : value.as_array()) {
|
||||
if (!v.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, "streamNotString"}};
|
||||
|
||||
if (notSupportStreams.contains(boost::json::value_to<std::string>(v)))
|
||||
if (kNOT_SUPPORT_STREAMS.contains(boost::json::value_to<std::string>(v)))
|
||||
return Error{Status{RippledError::rpcNOT_SUPPORTED}};
|
||||
|
||||
if (not validStreams.contains(boost::json::value_to<std::string>(v)))
|
||||
if (not kVALID_STREAMS.contains(boost::json::value_to<std::string>(v)))
|
||||
return Error{Status{RippledError::rpcSTREAM_MALFORMED}};
|
||||
}
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::SubscribeAccountsValidator =
|
||||
CustomValidator CustomValidators::subscribeAccountsValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (!value.is_array())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotArray"}};
|
||||
@@ -234,14 +234,14 @@ CustomValidator CustomValidators::SubscribeAccountsValidator =
|
||||
|
||||
obj[keyItem] = v;
|
||||
|
||||
if (auto err = AccountValidator.verify(obj, keyItem); !err)
|
||||
if (auto err = accountValidator.verify(obj, keyItem); !err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::CurrencyIssueValidator =
|
||||
CustomValidator CustomValidators::currencyIssueValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (not value.is_object())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotObject"}};
|
||||
@@ -249,49 +249,49 @@ CustomValidator CustomValidators::CurrencyIssueValidator =
|
||||
try {
|
||||
parseIssue(value.as_object());
|
||||
} catch (std::runtime_error const&) {
|
||||
return Error{Status{ClioError::rpcMALFORMED_REQUEST}};
|
||||
return Error{Status{ClioError::RpcMalformedRequest}};
|
||||
}
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::CredentialTypeValidator =
|
||||
CustomValidator CustomValidators::credentialTypeValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (not value.is_string())
|
||||
return Error{Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, std::string(key) + " NotString"}};
|
||||
return Error{Status{ClioError::RpcMalformedAuthorizedCredentials, std::string(key) + " NotString"}};
|
||||
|
||||
auto const& credTypeHex = ripple::strViewUnHex(value.as_string());
|
||||
if (!credTypeHex.has_value())
|
||||
return Error{Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, std::string(key) + " NotHexString"}};
|
||||
return Error{Status{ClioError::RpcMalformedAuthorizedCredentials, std::string(key) + " NotHexString"}};
|
||||
|
||||
if (credTypeHex->empty())
|
||||
return Error{Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, std::string(key) + " is empty"}};
|
||||
return Error{Status{ClioError::RpcMalformedAuthorizedCredentials, std::string(key) + " is empty"}};
|
||||
|
||||
if (credTypeHex->size() > ripple::maxCredentialTypeLength) {
|
||||
return Error{
|
||||
Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, std::string(key) + " greater than max length"}
|
||||
Status{ClioError::RpcMalformedAuthorizedCredentials, std::string(key) + " greater than max length"}
|
||||
};
|
||||
}
|
||||
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
CustomValidator CustomValidators::AuthorizeCredentialValidator =
|
||||
CustomValidator CustomValidators::authorizeCredentialValidator =
|
||||
CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (not value.is_array())
|
||||
return Error{Status{ClioError::rpcMALFORMED_REQUEST, std::string(key) + " not array"}};
|
||||
return Error{Status{ClioError::RpcMalformedRequest, std::string(key) + " not array"}};
|
||||
|
||||
auto const& authCred = value.as_array();
|
||||
if (authCred.empty()) {
|
||||
return Error{Status{
|
||||
ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS,
|
||||
ClioError::RpcMalformedAuthorizedCredentials,
|
||||
fmt::format("Requires at least one element in authorized_credentials array.")
|
||||
}};
|
||||
}
|
||||
|
||||
if (authCred.size() > ripple::maxCredentialsArraySize) {
|
||||
return Error{Status{
|
||||
ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS,
|
||||
ClioError::RpcMalformedAuthorizedCredentials,
|
||||
fmt::format(
|
||||
"Max {} number of credentials in authorized_credentials array", ripple::maxCredentialsArraySize
|
||||
)
|
||||
@@ -301,7 +301,7 @@ CustomValidator CustomValidators::AuthorizeCredentialValidator =
|
||||
for (auto const& credObj : value.as_array()) {
|
||||
if (!credObj.is_object()) {
|
||||
return Error{Status{
|
||||
ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS,
|
||||
ClioError::RpcMalformedAuthorizedCredentials,
|
||||
"authorized_credentials elements in array are not objects."
|
||||
}};
|
||||
}
|
||||
@@ -309,21 +309,21 @@ CustomValidator CustomValidators::AuthorizeCredentialValidator =
|
||||
|
||||
if (!obj.contains("issuer")) {
|
||||
return Error{
|
||||
Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, "Field 'Issuer' is required but missing."}
|
||||
Status{ClioError::RpcMalformedAuthorizedCredentials, "Field 'Issuer' is required but missing."}
|
||||
};
|
||||
}
|
||||
|
||||
// don't want to change issuer error message to be about credentials
|
||||
if (!IssuerValidator.verify(credObj, "issuer"))
|
||||
return Error{Status{ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, "issuer NotString"}};
|
||||
if (!issuerValidator.verify(credObj, "issuer"))
|
||||
return Error{Status{ClioError::RpcMalformedAuthorizedCredentials, "issuer NotString"}};
|
||||
|
||||
if (!obj.contains("credential_type")) {
|
||||
return Error{Status{
|
||||
ClioError::rpcMALFORMED_AUTHORIZED_CREDENTIALS, "Field 'CredentialType' is required but missing."
|
||||
ClioError::RpcMalformedAuthorizedCredentials, "Field 'CredentialType' is required but missing."
|
||||
}};
|
||||
}
|
||||
|
||||
if (auto const err = CredentialTypeValidator.verify(credObj, "credential_type"); !err)
|
||||
if (auto const err = credentialTypeValidator.verify(credObj, "credential_type"); !err)
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -481,21 +481,21 @@ struct CustomValidators final {
|
||||
* LedgerIndex must be a string or an int. If the specified LedgerIndex is a string, its value must be either
|
||||
* "validated" or a valid integer value represented as a string.
|
||||
*/
|
||||
static CustomValidator LedgerIndexValidator;
|
||||
static CustomValidator ledgerIndexValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for accounts.
|
||||
*
|
||||
* Account must be a string and the converted public key is valid.
|
||||
*/
|
||||
static CustomValidator AccountValidator;
|
||||
static CustomValidator accountValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for accounts.
|
||||
*
|
||||
* Account must be a string and can convert to base58.
|
||||
*/
|
||||
static CustomValidator AccountBase58Validator;
|
||||
static CustomValidator accountBase58Validator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for markers.
|
||||
@@ -503,7 +503,7 @@ struct CustomValidators final {
|
||||
* A marker is composed of a comma-separated index and a start hint.
|
||||
* The former will be read as hex, and the latter can be cast to uint64.
|
||||
*/
|
||||
static CustomValidator AccountMarkerValidator;
|
||||
static CustomValidator accountMarkerValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for uint160(AccountID) hex string.
|
||||
@@ -511,7 +511,7 @@ struct CustomValidators final {
|
||||
* It must be a string and also a decodable hex.
|
||||
* AccountID uses this validator.
|
||||
*/
|
||||
static CustomValidator Uint160HexStringValidator;
|
||||
static CustomValidator uint160HexStringValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for uint192 hex string.
|
||||
@@ -519,7 +519,7 @@ struct CustomValidators final {
|
||||
* It must be a string and also a decodable hex.
|
||||
* MPTIssuanceID uses this validator.
|
||||
*/
|
||||
static CustomValidator Uint192HexStringValidator;
|
||||
static CustomValidator uint192HexStringValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for uint256 hex string.
|
||||
@@ -527,50 +527,50 @@ struct CustomValidators final {
|
||||
* It must be a string and also a decodable hex.
|
||||
* Transaction index, ledger hash all use this validator.
|
||||
*/
|
||||
static CustomValidator Uint256HexStringValidator;
|
||||
static CustomValidator uint256HexStringValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for currency, including standard currency code and token code.
|
||||
*/
|
||||
static CustomValidator CurrencyValidator;
|
||||
static CustomValidator currencyValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a commonly used validator for issuer type.
|
||||
*
|
||||
* It must be a hex string or base58 string.
|
||||
*/
|
||||
static CustomValidator IssuerValidator;
|
||||
static CustomValidator issuerValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for validating streams used in subscribe/unsubscribe.
|
||||
*/
|
||||
static CustomValidator SubscribeStreamValidator;
|
||||
static CustomValidator subscribeStreamValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for validating accounts used in subscribe/unsubscribe.
|
||||
*/
|
||||
static CustomValidator SubscribeAccountsValidator;
|
||||
static CustomValidator subscribeAccountsValidator;
|
||||
|
||||
/**
|
||||
* @brief Validates an asset (ripple::Issue).
|
||||
*
|
||||
* Used by amm_info.
|
||||
*/
|
||||
static CustomValidator CurrencyIssueValidator;
|
||||
static CustomValidator currencyIssueValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for validating authorized_credentials json array.
|
||||
*
|
||||
* Used by deposit_preauth.
|
||||
*/
|
||||
static CustomValidator AuthorizeCredentialValidator;
|
||||
static CustomValidator authorizeCredentialValidator;
|
||||
|
||||
/**
|
||||
* @brief Provides a validator for validating credential_type.
|
||||
*
|
||||
* Used by AuthorizeCredentialValidator in deposit_preauth.
|
||||
*/
|
||||
static CustomValidator CredentialTypeValidator;
|
||||
static CustomValidator credentialTypeValidator;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,9 +40,9 @@ class ProductionAPIVersionParser : public APIVersionParser {
|
||||
|
||||
public:
|
||||
ProductionAPIVersionParser(
|
||||
uint32_t defaultVersion = API_VERSION_DEFAULT,
|
||||
uint32_t minVersion = API_VERSION_MIN,
|
||||
uint32_t maxVersion = API_VERSION_MAX
|
||||
uint32_t defaultVersion = kAPI_VERSION_DEFAULT,
|
||||
uint32_t minVersion = kAPI_VERSION_MIN,
|
||||
uint32_t maxVersion = kAPI_VERSION_MAX
|
||||
);
|
||||
|
||||
ProductionAPIVersionParser(util::config::ObjectView const& config);
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace rpc::impl {
|
||||
|
||||
using FieldSpecProcessor = std::function<MaybeError(boost::json::value&)>;
|
||||
|
||||
static FieldSpecProcessor const EMPTY_FIELD_PROCESSOR = [](boost::json::value&) -> MaybeError { return {}; };
|
||||
static FieldSpecProcessor const kEMPTY_FIELD_PROCESSOR = [](boost::json::value&) -> MaybeError { return {}; };
|
||||
|
||||
template <SomeProcessor... Processors>
|
||||
[[nodiscard]] FieldSpecProcessor
|
||||
@@ -77,7 +77,7 @@ makeFieldProcessor(std::string const& key, Processors&&... procs)
|
||||
|
||||
using FieldChecker = std::function<check::Warnings(boost::json::value const&)>;
|
||||
|
||||
static FieldChecker const EMPTY_FIELD_CHECKER = [](boost::json::value const&) -> check::Warnings { return {}; };
|
||||
static FieldChecker const kEMPTY_FIELD_CHECKER = [](boost::json::value const&) -> check::Warnings { return {}; };
|
||||
|
||||
template <SomeCheck... Checks>
|
||||
[[nodiscard]] FieldChecker
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
bool
|
||||
isProxied(std::string const& method) const
|
||||
{
|
||||
static std::unordered_set<std::string> const proxiedCommands{
|
||||
static std::unordered_set<std::string> const kPROXIED_COMMANDS{
|
||||
"server_definitions",
|
||||
"server_state",
|
||||
"submit",
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
"channel_verify",
|
||||
};
|
||||
|
||||
return proxiedCommands.contains(method);
|
||||
return kPROXIED_COMMANDS.contains(method);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -145,9 +145,9 @@ private:
|
||||
bool
|
||||
isForcedForward(web::Context const& ctx) const
|
||||
{
|
||||
static constexpr auto FORCE_FORWARD = "force_forward";
|
||||
return ctx.isAdmin and ctx.params.contains(FORCE_FORWARD) and ctx.params.at(FORCE_FORWARD).is_bool() and
|
||||
ctx.params.at(FORCE_FORWARD).as_bool();
|
||||
static constexpr auto kFORCE_FORWARD = "force_forward";
|
||||
return ctx.isAdmin and ctx.params.contains(kFORCE_FORWARD) and ctx.params.at(kFORCE_FORWARD).is_bool() and
|
||||
ctx.params.at(kFORCE_FORWARD).as_bool();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,14 +21,12 @@
|
||||
|
||||
#include "rpc/common/Concepts.hpp"
|
||||
#include "rpc/common/Types.hpp"
|
||||
#include "util/UnsupportedType.hpp"
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
namespace rpc::impl {
|
||||
|
||||
template <typename>
|
||||
static constexpr bool unsupported_handler_v = false;
|
||||
|
||||
template <SomeHandler HandlerType>
|
||||
struct DefaultProcessor final {
|
||||
[[nodiscard]] ReturnType
|
||||
@@ -63,7 +61,7 @@ struct DefaultProcessor final {
|
||||
return ReturnType{value_from(ret.value())};
|
||||
} else {
|
||||
// when concept SomeHandlerWithInput and SomeHandlerWithoutInput not cover all Handler case
|
||||
static_assert(unsupported_handler_v<HandlerType>);
|
||||
static_assert(util::Unsupported<HandlerType>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,11 +65,11 @@ std::string
|
||||
toIso8601(ripple::NetClock::time_point tp)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
static auto constexpr rippleEpochOffset = seconds{rippleEpochStart};
|
||||
static constexpr auto kRIPPLE_EPOCH_OFFSET = seconds{kRIPPLE_EPOCH_START};
|
||||
|
||||
return date::format(
|
||||
"%Y-%Om-%dT%H:%M:%OS%z",
|
||||
date::sys_time<system_clock::duration>(system_clock::time_point{tp.time_since_epoch() + rippleEpochOffset})
|
||||
date::sys_time<system_clock::duration>(system_clock::time_point{tp.time_since_epoch() + kRIPPLE_EPOCH_OFFSET})
|
||||
);
|
||||
};
|
||||
|
||||
@@ -229,7 +229,7 @@ AMMInfoHandler::process(AMMInfoHandler::Input input, Context const& ctx) const
|
||||
RpcSpecConstRef
|
||||
AMMInfoHandler::spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
static auto const stringIssueValidator =
|
||||
static auto const kSTRING_ISSUE_VALIDATOR =
|
||||
validation::CustomValidator{[](boost::json::value const& value, std::string_view key) -> MaybeError {
|
||||
if (not value.is_string())
|
||||
return Error{Status{RippledError::rpcINVALID_PARAMS, std::string(key) + "NotString"}};
|
||||
@@ -243,36 +243,36 @@ AMMInfoHandler::spec([[maybe_unused]] uint32_t apiVersion)
|
||||
return MaybeError{};
|
||||
}};
|
||||
|
||||
static auto const rpcSpec = RpcSpec{
|
||||
{JS(ledger_hash), validation::CustomValidators::Uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::LedgerIndexValidator},
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::ledgerIndexValidator},
|
||||
{JS(asset),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
},
|
||||
meta::IfType<std::string>{stringIssueValidator},
|
||||
meta::IfType<std::string>{kSTRING_ISSUE_VALIDATOR},
|
||||
meta::IfType<boost::json::object>{
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::CurrencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
validation::CustomValidators::currencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
},
|
||||
}},
|
||||
{JS(asset2),
|
||||
meta::WithCustomError{
|
||||
validation::Type<std::string, boost::json::object>{}, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
},
|
||||
meta::IfType<std::string>{stringIssueValidator},
|
||||
meta::IfType<std::string>{kSTRING_ISSUE_VALIDATOR},
|
||||
meta::IfType<boost::json::object>{
|
||||
meta::WithCustomError{
|
||||
validation::CustomValidators::CurrencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
validation::CustomValidators::currencyIssueValidator, Status(RippledError::rpcISSUE_MALFORMED)
|
||||
},
|
||||
}},
|
||||
{JS(amm_account),
|
||||
meta::WithCustomError{validation::CustomValidators::AccountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
meta::WithCustomError{validation::CustomValidators::accountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
{JS(account),
|
||||
meta::WithCustomError{validation::CustomValidators::AccountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
meta::WithCustomError{validation::CustomValidators::accountValidator, Status(RippledError::rpcACT_MALFORMED)}},
|
||||
};
|
||||
|
||||
return rpcSpec;
|
||||
return kRPC_SPEC;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -51,9 +51,9 @@ class AccountChannelsHandler {
|
||||
std::shared_ptr<BackendInterface> const sharedPtrBackend_;
|
||||
|
||||
public:
|
||||
static constexpr auto LIMIT_MIN = 10;
|
||||
static constexpr auto LIMIT_MAX = 400;
|
||||
static constexpr auto LIMIT_DEFAULT = 200;
|
||||
static constexpr auto kLIMIT_MIN = 10;
|
||||
static constexpr auto kLIMIT_MAX = 400;
|
||||
static constexpr auto kLIMIT_DEFAULT = 200;
|
||||
|
||||
/**
|
||||
* @brief A struct to hold data for one channel response
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
std::optional<std::string> destinationAccount;
|
||||
std::optional<std::string> ledgerHash;
|
||||
std::optional<uint32_t> ledgerIndex;
|
||||
uint32_t limit = LIMIT_DEFAULT;
|
||||
uint32_t limit = kLIMIT_DEFAULT;
|
||||
std::optional<std::string> marker;
|
||||
};
|
||||
|
||||
@@ -122,19 +122,19 @@ public:
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
static auto const rpcSpec = RpcSpec{
|
||||
{JS(account), validation::Required{}, validation::CustomValidators::AccountValidator},
|
||||
{JS(destination_account), validation::Type<std::string>{}, validation::CustomValidators::AccountValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::Uint256HexStringValidator},
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(account), validation::Required{}, validation::CustomValidators::accountValidator},
|
||||
{JS(destination_account), validation::Type<std::string>{}, validation::CustomValidators::accountValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},
|
||||
{JS(limit),
|
||||
validation::Type<uint32_t>{},
|
||||
validation::Min(1u),
|
||||
modifiers::Clamp<int32_t>{LIMIT_MIN, LIMIT_MAX}},
|
||||
{JS(ledger_index), validation::CustomValidators::LedgerIndexValidator},
|
||||
{JS(marker), validation::CustomValidators::AccountMarkerValidator},
|
||||
modifiers::Clamp<int32_t>{kLIMIT_MIN, kLIMIT_MAX}},
|
||||
{JS(ledger_index), validation::CustomValidators::ledgerIndexValidator},
|
||||
{JS(marker), validation::CustomValidators::accountMarkerValidator},
|
||||
};
|
||||
|
||||
return rpcSpec;
|
||||
return kRPC_SPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,15 +91,15 @@ public:
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
static auto const rpcSpec = RpcSpec{
|
||||
{JS(account), validation::Required{}, validation::CustomValidators::AccountValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::Uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::LedgerIndexValidator},
|
||||
static auto const kRPC_SPEC = RpcSpec{
|
||||
{JS(account), validation::Required{}, validation::CustomValidators::accountValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::ledgerIndexValidator},
|
||||
{"account_index", check::Deprecated{}},
|
||||
{JS(strict), check::Deprecated{}}
|
||||
};
|
||||
|
||||
return rpcSpec;
|
||||
return kRPC_SPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -136,19 +136,19 @@ public:
|
||||
static RpcSpecConstRef
|
||||
spec([[maybe_unused]] uint32_t apiVersion)
|
||||
{
|
||||
static auto const rpcSpecV1 = RpcSpec{
|
||||
{JS(account), validation::CustomValidators::AccountValidator},
|
||||
{JS(ident), validation::CustomValidators::AccountValidator},
|
||||
static auto const kRPC_SPEC_V1 = RpcSpec{
|
||||
{JS(account), validation::CustomValidators::accountValidator},
|
||||
{JS(ident), validation::CustomValidators::accountValidator},
|
||||
{JS(ident), check::Deprecated{}},
|
||||
{JS(ledger_hash), validation::CustomValidators::Uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::LedgerIndexValidator},
|
||||
{JS(ledger_hash), validation::CustomValidators::uint256HexStringValidator},
|
||||
{JS(ledger_index), validation::CustomValidators::ledgerIndexValidator},
|
||||
{JS(ledger), check::Deprecated{}},
|
||||
{JS(strict), check::Deprecated{}}
|
||||
};
|
||||
|
||||
static auto const rpcSpec = RpcSpec{rpcSpecV1, {{JS(signer_lists), validation::Type<bool>{}}}};
|
||||
static auto const kRPC_SPEC = RpcSpec{kRPC_SPEC_V1, {{JS(signer_lists), validation::Type<bool>{}}}};
|
||||
|
||||
return apiVersion == 1 ? rpcSpecV1 : rpcSpec;
|
||||
return apiVersion == 1 ? kRPC_SPEC_V1 : kRPC_SPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user