Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2601f8d
Introduce rpcspec 0.1.3 dependency
godexsoft Aug 11, 2026
8ce6b04
Add the missing cmake file back
godexsoft Aug 11, 2026
df88182
Fix precommit
godexsoft Aug 12, 2026
0cf14ab
Resolve conflicts
godexsoft Aug 12, 2026
3196ef5
Use errors from rpcspec
godexsoft Aug 12, 2026
95b28f7
Remove dead code
godexsoft Aug 12, 2026
e31d7b5
Fix clang-tidy
godexsoft Aug 12, 2026
aef5b35
Fix precommit
godexsoft Aug 12, 2026
9d4ee75
Fix doxy
godexsoft Aug 12, 2026
48faa0c
Fix more clang-tidy
godexsoft Aug 12, 2026
866deea
Merge branch 'develop' into refactor/consteval-specs-move-errors
godexsoft Aug 26, 2026
5ab47a9
Merge branch 'develop' of github.com:XRPLF/clio into refactor/constev…
godexsoft Aug 26, 2026
577bc40
Fix clang-tidy
godexsoft Aug 26, 2026
30621e6
Rename to RpcForwarding errors and move back to rpc-spec
godexsoft Aug 27, 2026
7f46527
Accept spec-library handlers alongside legacy ones
godexsoft Sep 1, 2026
a248882
Assert on incorrect shortcut
godexsoft Sep 1, 2026
72a854d
Merge remote-tracking branch 'upstream/develop' into refactor/constev…
godexsoft Sep 1, 2026
a1e9e49
Fix clang-tidy and doxy
godexsoft Sep 2, 2026
cad3768
Add coverage for fail path
godexsoft Sep 2, 2026
6c2ba13
Add coverage for write fail in forwarding
godexsoft Sep 2, 2026
f5fecc0
Remove test
godexsoft Sep 2, 2026
fbdfc34
Migrate first two handlers to spec system
godexsoft Sep 3, 2026
1c94b19
Merge branch 'develop' into refactor/consteval-specs-first-handlers
godexsoft Sep 7, 2026
711b676
Merge remote-tracking branch 'upstream/develop' into refactor/constev…
godexsoft Sep 8, 2026
bba396b
Merge remote-tracking branch 'upstream/develop' into refactor/constev…
godexsoft Sep 8, 2026
55464cb
Use explicit rpc::spec
godexsoft Sep 8, 2026
af24033
Remove some useless comments
godexsoft Sep 8, 2026
607ecfe
Merge branch 'refactor/consteval-specs-dual-path' into refactor/const…
godexsoft Sep 8, 2026
99b6ca5
Merge branch 'develop' into refactor/consteval-specs-first-handlers
godexsoft Sep 9, 2026
b13953e
Bring back new style processor code
godexsoft Sep 9, 2026
d485f59
Fully qualify rpc::spec
godexsoft Sep 9, 2026
401c285
Use 0.1.9 and remove explicit instantiations and includes
godexsoft Sep 10, 2026
7cc0f45
Merge remote-tracking branch 'upstream/develop' into refactor/constev…
godexsoft Sep 10, 2026
2574b08
Use 0.1.10 and hopefully fix clang-tidy
godexsoft Sep 11, 2026
a7d88ec
Merge branch 'develop' into refactor/consteval-specs-first-handlers
godexsoft Sep 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conan.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"requires": [
"zlib/1.3.2#1cb806da49011867778ffb6ac7190fcb%1782392402.122708",
"xxhash/0.8.3#681d36a0a6111fc56e5e45ea182c19cc%1782392402.420688",
"xrpl-rpc-spec/0.1.7#774d2f93c4b48a1523d8d5a94a2b082a%1787768955.574105",
"xrpl-rpc-spec/0.1.10#38d3a69d1802fbb7af5796fed8326888%1789129776.315907",
"xrpl/3.4.0-rc1#19678cbb46117ef8a669558ad19d6a1f%1789050823.813662",
"sqlite3/3.53.0#324ada52333108388a9a6108bfa96734%1782392403.185447",
"spdlog/1.17.0#bcbaaf7147bda6ad24ffbd1ac3d7142c%1782736610.443882",
Expand Down
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ClioConan(ConanFile):
"fmt/12.1.0",
"libbacktrace/cci.20210118",
"spdlog/1.17.0",
"xrpl-rpc-spec/0.1.7",
"xrpl-rpc-spec/0.1.10",
"xrpl/3.4.0-rc1",
]

Expand Down
3 changes: 3 additions & 0 deletions src/rpc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ target_sources(
handlers/VaultInfo.cpp
)

rpcspec_generate_instantiations(OUT_VAR rpcspec_instantiations)
target_sources(clio_rpc PRIVATE ${rpcspec_instantiations})

target_link_libraries(clio_rpc PUBLIC clio_util clio_data rpcspec::rpcspec)
36 changes: 5 additions & 31 deletions src/rpc/handlers/AccountCurrencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
#include "rpc/RPCHelpers.hpp"
#include "rpc/common/Types.hpp"
#include "util/Assert.hpp"
#include "util/JsonUtils.hpp"

#include <boost/json/conversion.hpp>
#include <boost/json/value.hpp>
#include <boost/json/value_to.hpp>
#include <rpcspec/Errors.hpp>
#include <xrpl/basics/strHex.h>
#include <xrpl/protocol/Indexes.h>
Expand All @@ -33,25 +31,21 @@ AccountCurrenciesHandler::process(
{
auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountCurrencies' ledger range must be available");
auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
auto const expectedLgrInfo = getLedgerHeaderFromLedgerSpecifier(
*sharedPtrBackend_,
ctx.yield,
input.ledgerHash,
input.ledgerIndex,
input.ledger,
range->maxSequence // NOLINT(bugprone-unchecked-optional-access)
);

if (not expectedLgrInfo.has_value())
return Error{expectedLgrInfo.error()};

auto const& lgrInfo = *expectedLgrInfo;
auto const accountID = accountFromStringStrict(input.account);
auto const& accountID = input.account;
Comment thread
mathbunnyru marked this conversation as resolved.

auto const accountLedgerObject = sharedPtrBackend_->fetchLedgerObject(
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
xrpl::keylet::account(*accountID).key,
lgrInfo.seq,
ctx.yield
xrpl::keylet::account(accountID).key, lgrInfo.seq, ctx.yield
);
if (!accountLedgerObject)
return Error{Status{RippledError::RpcActNotFound}};
Expand Down Expand Up @@ -88,7 +82,7 @@ AccountCurrenciesHandler::process(
// traverse all owned nodes, limit->max, marker->empty
traverseOwnedNodes(
*sharedPtrBackend_,
*accountID, // NOLINT(bugprone-unchecked-optional-access)
accountID,
lgrInfo.seq,
std::numeric_limits<std::uint32_t>::max(),
{},
Expand Down Expand Up @@ -120,24 +114,4 @@ tag_invoke(
};
}

AccountCurrenciesHandler::Input
tag_invoke(boost::json::value_to_tag<AccountCurrenciesHandler::Input>, boost::json::value const& jv)
{
auto input = AccountCurrenciesHandler::Input{};
auto const& jsonObject = jv.as_object();

input.account = boost::json::value_to<std::string>(jv.at(JS(account)));

if (jsonObject.contains(JS(ledger_hash)))
input.ledgerHash = boost::json::value_to<std::string>(jv.at(JS(ledger_hash)));

if (jsonObject.contains(JS(ledger_index))) {
auto const expectedLedgerIndex = util::getLedgerIndex(jv.at(JS(ledger_index)));
if (expectedLedgerIndex.has_value())
input.ledgerIndex = *expectedLedgerIndex;
}

return input;
}

} // namespace rpc
49 changes: 4 additions & 45 deletions src/rpc/handlers/AccountCurrencies.hpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
#pragma once

#include "data/BackendInterface.hpp"
#include "rpc/JS.hpp"
#include "rpc/common/Checkers.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
#include "rpc/common/Validators.hpp"

#include <boost/json/conversion.hpp>
#include <boost/json/value.hpp>
#include <xrpl/protocol/jss.h>
#include <rpcspec/HandlerFor.hpp>
#include <rpcspec/handlers/account_currencies/Types.hpp>

#include <cstdint>
#include <memory>
#include <optional>
#include <set>
#include <string>

Expand All @@ -25,7 +21,8 @@ namespace rpc {
*
* For more details see: https://xrpl.org/account_currencies.html
*/
class AccountCurrenciesHandler {
class AccountCurrenciesHandler
: public rpc::spec::HandlerFor<rpc::spec::handlers::account_currencies::Input> {
// dependencies
std::shared_ptr<BackendInterface> sharedPtrBackend_;

Expand All @@ -42,15 +39,6 @@ class AccountCurrenciesHandler {
bool validated = true;
};

/**
* @brief A struct to hold the input data for the command
*/
struct Input {
std::string account;
std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex;
};

using Result = HandlerReturnType<Output>;

/**
Expand All @@ -63,26 +51,6 @@ class AccountCurrenciesHandler {
{
}

/**
* @brief Returns the API specification for the command
*
* @param apiVersion The api version to return the spec for
* @return The spec for the given apiVersion
*/
static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion)
{
static auto const kRpcSpec = 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 kRpcSpec;
}

/**
* @brief Process the AccountCurrencies command
*
Expand All @@ -102,15 +70,6 @@ class AccountCurrenciesHandler {
*/
friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);

/**
* @brief Convert a JSON object to Input type
*
* @param jv The JSON object to convert
* @return Input parsed from the JSON object
*/
friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
};

} // namespace rpc
44 changes: 5 additions & 39 deletions src/rpc/handlers/AccountInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@
#include "data/AmendmentCenter.hpp"
#include "rpc/JS.hpp"
#include "rpc/RPCHelpers.hpp"
#include "rpc/common/JsonBool.hpp"
#include "rpc/common/Types.hpp"
#include "util/Assert.hpp"
#include "util/JsonUtils.hpp"

#include <boost/json/array.hpp>
#include <boost/json/conversion.hpp>
#include <boost/json/object.hpp>
#include <boost/json/value.hpp>
#include <boost/json/value_to.hpp>
#include <rpcspec/Errors.hpp>
#include <xrpl/basics/strHex.h>
#include <xrpl/ledger/helpers/AccountRootHelpers.h>
Expand Down Expand Up @@ -46,22 +43,19 @@ AccountInfoHandler::process(AccountInfoHandler::Input const& input, Context cons

auto const range = sharedPtrBackend_->fetchLedgerRange();
ASSERT(range.has_value(), "AccountInfo's ledger range must be available");
auto const expectedLgrInfo = getLedgerHeaderFromHashOrSeq(
auto const expectedLgrInfo = getLedgerHeaderFromLedgerSpecifier(
*sharedPtrBackend_,
ctx.yield,
input.ledgerHash,
input.ledgerIndex,
input.ledger,
range->maxSequence // NOLINT(bugprone-unchecked-optional-access)
);

if (not expectedLgrInfo.has_value())
return Error{expectedLgrInfo.error()};

auto const& lgrInfo = *expectedLgrInfo;
auto const accountStr = input.account.value_or(input.ident.value_or(""));
auto const accountID = accountFromStringStrict(accountStr);
auto const accountKeylet =
xrpl::keylet::account(*accountID); // NOLINT(bugprone-unchecked-optional-access)
auto const accountID = input.account ? *input.account : *input.ident;
auto const accountKeylet = xrpl::keylet::account(accountID);
auto const accountLedgerObject =
sharedPtrBackend_->fetchLedgerObject(accountKeylet.key, lgrInfo.seq, ctx.yield);

Expand Down Expand Up @@ -99,8 +93,7 @@ AccountInfoHandler::process(AccountInfoHandler::Input const& input, Context cons
if (input.signerLists) {
// We put the SignerList in an array because of an anticipated
// future when we support multiple signer lists on one account.
auto const signersKey =
xrpl::keylet::signerList(*accountID); // NOLINT(bugprone-unchecked-optional-access)
auto const signersKey = xrpl::keylet::signerList(accountID);

// This code will need to be revisited if in the future we
// support multiple SignerLists on one account.
Expand Down Expand Up @@ -203,31 +196,4 @@ tag_invoke(
}
}

AccountInfoHandler::Input
tag_invoke(boost::json::value_to_tag<AccountInfoHandler::Input>, boost::json::value const& jv)
{
auto input = AccountInfoHandler::Input{};
auto const& jsonObject = jv.as_object();

if (jsonObject.contains(JS(ident)))
input.ident = boost::json::value_to<std::string>(jsonObject.at(JS(ident)));

if (jsonObject.contains(JS(account)))
input.account = boost::json::value_to<std::string>(jsonObject.at(JS(account)));

if (jsonObject.contains(JS(ledger_hash)))
input.ledgerHash = boost::json::value_to<std::string>(jsonObject.at(JS(ledger_hash)));

if (jsonObject.contains(JS(ledger_index))) {
auto const expectedLedgerIndex = util::getLedgerIndex(jsonObject.at(JS(ledger_index)));
if (expectedLedgerIndex.has_value())
input.ledgerIndex = *expectedLedgerIndex;
}

if (jsonObject.contains(JS(signer_lists)))
input.signerLists = boost::json::value_to<JsonBool>(jsonObject.at(JS(signer_lists)));

return input;
}

} // namespace rpc
58 changes: 3 additions & 55 deletions src/rpc/handlers/AccountInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

#include "data/AmendmentCenterInterface.hpp"
#include "data/BackendInterface.hpp"
#include "rpc/JS.hpp"
#include "rpc/common/Checkers.hpp"
#include "rpc/common/JsonBool.hpp"
#include "rpc/common/Specs.hpp"
#include "rpc/common/Types.hpp"
#include "rpc/common/Validators.hpp"

#include <boost/json/conversion.hpp>
#include <boost/json/value.hpp>
#include <rpcspec/HandlerFor.hpp>
#include <rpcspec/handlers/account_info/Types.hpp>
#include <xrpl/protocol/STLedgerEntry.h>
#include <xrpl/protocol/jss.h>

#include <cstdint>
#include <memory>
Expand All @@ -28,7 +24,7 @@ namespace rpc {
*
* For more details see: https://xrpl.org/account_info.html
*/
class AccountInfoHandler {
class AccountInfoHandler : public rpc::spec::HandlerFor<rpc::spec::handlers::account_info::Input> {
std::shared_ptr<BackendInterface> sharedPtrBackend_;
std::shared_ptr<data::AmendmentCenterInterface const> amendmentCenter_;

Expand All @@ -49,20 +45,6 @@ class AccountInfoHandler {
bool validated = true;
};

/**
* @brief A struct to hold the input data for the command
*
* `queue` is not available in Reporting mode
* `ident` is deprecated, keep it for now, in line with rippled
*/
struct Input {
std::optional<std::string> account;
std::optional<std::string> ident;
std::optional<std::string> ledgerHash;
std::optional<uint32_t> ledgerIndex;
JsonBool signerLists{false};
};

using Result = HandlerReturnType<Output>;

/**
Expand All @@ -79,31 +61,6 @@ class AccountInfoHandler {
{
}

/**
* @brief Returns the API specification for the command
*
* @param apiVersion The api version to return the spec for
* @return The spec for the given apiVersion
*/
static RpcSpecConstRef
spec([[maybe_unused]] uint32_t apiVersion)
{
static auto const kRpcSpecV1 = 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), check::Deprecated{}},
{JS(strict), check::Deprecated{}}
};

static auto const kRpcSpec =
RpcSpec{kRpcSpecV1, {{JS(signer_lists), validation::Type<bool>{}}}};

return apiVersion == 1 ? kRpcSpecV1 : kRpcSpec;
}

/**
* @brief Process the AccountInfo command
*
Expand All @@ -123,15 +80,6 @@ class AccountInfoHandler {
*/
friend void
tag_invoke(boost::json::value_from_tag, boost::json::value& jv, Output const& output);

/**
* @brief Convert a JSON object to Input type
*
* @param jv The JSON object to convert
* @return Input parsed from the JSON object
*/
friend Input
tag_invoke(boost::json::value_to_tag<Input>, boost::json::value const& jv);
};

} // namespace rpc
Loading
Loading