rippled
Loading...
Searching...
No Matches
Handler.cpp
1#include <xrpld/rpc/detail/Handler.h>
2#include <xrpld/rpc/handlers/Handlers.h>
3#include <xrpld/rpc/handlers/Version.h>
4
5#include <xrpl/basics/contract.h>
6#include <xrpl/protocol/ApiVersion.h>
7
8#include <map>
9
10namespace xrpl {
11namespace RPC {
12namespace {
13
15template <typename Function>
16Handler::Method<Json::Value>
17byRef(Function const& f)
18{
19 return [f](JsonContext& context, Json::Value& result) {
20 result = f(context);
21 if (result.type() != Json::objectValue)
22 {
23 // LCOV_EXCL_START
24 UNREACHABLE("xrpl::RPC::byRef : result is object");
25 result = RPC::makeObjectValue(result);
26 // LCOV_EXCL_STOP
27 }
28
29 return Status();
30 };
31}
32
33template <class Object, class HandlerImpl>
35handle(JsonContext& context, Object& object)
36{
37 XRPL_ASSERT(
38 context.apiVersion >= HandlerImpl::minApiVer && context.apiVersion <= HandlerImpl::maxApiVer,
39 "xrpl::RPC::handle : valid API version");
40 HandlerImpl handler(context);
41
42 auto status = handler.check();
43 if (status)
44 status.inject(object);
45 else
46 handler.writeResult(object);
47 return status;
48}
49
50template <typename HandlerImpl>
51Handler
52handlerFrom()
53{
54 return {
55 HandlerImpl::name,
56 &handle<Json::Value, HandlerImpl>,
57 HandlerImpl::role,
58 HandlerImpl::condition,
59 HandlerImpl::minApiVer,
60 HandlerImpl::maxApiVer};
61}
62
63Handler const handlerArray[]{
64 // Some handlers not specified here are added to the table via addHandler()
65 // Request-response methods
66 {"account_info", byRef(&doAccountInfo), Role::USER, NO_CONDITION},
67 {"account_currencies", byRef(&doAccountCurrencies), Role::USER, NO_CONDITION},
68 {"account_lines", byRef(&doAccountLines), Role::USER, NO_CONDITION},
69 {"account_channels", byRef(&doAccountChannels), Role::USER, NO_CONDITION},
70 {"account_nfts", byRef(&doAccountNFTs), Role::USER, NO_CONDITION},
71 {"account_objects", byRef(&doAccountObjects), Role::USER, NO_CONDITION},
72 {"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
73 {"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
74 {"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
75 {"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
76 {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
77 {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
78 {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION},
79 {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION},
80 {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION},
81 {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION},
82 {"consensus_info", byRef(&doConsensusInfo), Role::ADMIN, NO_CONDITION},
83 {"deposit_authorized", byRef(&doDepositAuthorized), Role::USER, NO_CONDITION},
84 {"feature", byRef(&doFeature), Role::USER, NO_CONDITION},
85 {"fee", byRef(&doFee), Role::USER, NEEDS_CURRENT_LEDGER},
86 {"fetch_info", byRef(&doFetchInfo), Role::ADMIN, NO_CONDITION},
87 {"gateway_balances", byRef(&doGatewayBalances), Role::USER, NO_CONDITION},
88 {"get_counts", byRef(&doGetCounts), Role::ADMIN, NO_CONDITION},
89 {"get_aggregate_price", byRef(&doGetAggregatePrice), Role::USER, NO_CONDITION},
90 {"ledger_accept", byRef(&doLedgerAccept), Role::ADMIN, NEEDS_CURRENT_LEDGER},
91 {"ledger_cleaner", byRef(&doLedgerCleaner), Role::ADMIN, NEEDS_NETWORK_CONNECTION},
92 {"ledger_closed", byRef(&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER},
93 {"ledger_current", byRef(&doLedgerCurrent), Role::USER, NEEDS_CURRENT_LEDGER},
94 {"ledger_data", byRef(&doLedgerData), Role::USER, NO_CONDITION},
95 {"ledger_entry", byRef(&doLedgerEntry), Role::USER, NO_CONDITION},
96 {"ledger_header", byRef(&doLedgerHeader), Role::USER, NO_CONDITION, 1, 1},
97 {"ledger_request", byRef(&doLedgerRequest), Role::ADMIN, NO_CONDITION},
98 {"log_level", byRef(&doLogLevel), Role::ADMIN, NO_CONDITION},
99 {"logrotate", byRef(&doLogRotate), Role::ADMIN, NO_CONDITION},
100 {"manifest", byRef(&doManifest), Role::USER, NO_CONDITION},
101 {"nft_buy_offers", byRef(&doNFTBuyOffers), Role::USER, NO_CONDITION},
102 {"nft_sell_offers", byRef(&doNFTSellOffers), Role::USER, NO_CONDITION},
103 {"noripple_check", byRef(&doNoRippleCheck), Role::USER, NO_CONDITION},
104 {"owner_info", byRef(&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER},
105 {"peers", byRef(&doPeers), Role::ADMIN, NO_CONDITION},
106 {"path_find", byRef(&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER},
107 {"ping", byRef(&doPing), Role::USER, NO_CONDITION},
108 {"print", byRef(&doPrint), Role::ADMIN, NO_CONDITION},
109 // { "profile", byRef (&doProfile), Role::USER,
110 // NEEDS_CURRENT_LEDGER },
111 {"random", byRef(&doRandom), Role::USER, NO_CONDITION},
112 {"peer_reservations_add", byRef(&doPeerReservationsAdd), Role::ADMIN, NO_CONDITION},
113 {"peer_reservations_del", byRef(&doPeerReservationsDel), Role::ADMIN, NO_CONDITION},
114 {"peer_reservations_list", byRef(&doPeerReservationsList), Role::ADMIN, NO_CONDITION},
115 {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION},
116 {"server_definitions", byRef(&doServerDefinitions), Role::USER, NO_CONDITION},
117 {"server_info", byRef(&doServerInfo), Role::USER, NO_CONDITION},
118 {"server_state", byRef(&doServerState), Role::USER, NO_CONDITION},
119 {"sign", byRef(&doSign), Role::USER, NO_CONDITION},
120 {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION},
121 {"simulate", byRef(&doSimulate), Role::USER, NEEDS_CURRENT_LEDGER},
122 {"stop", byRef(&doStop), Role::ADMIN, NO_CONDITION},
123 {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER},
124 {"submit_multisigned", byRef(&doSubmitMultiSigned), Role::USER, NEEDS_CURRENT_LEDGER},
125 {"transaction_entry", byRef(&doTransactionEntry), Role::USER, NO_CONDITION},
127 {"tx_history", byRef(&doTxHistory), Role::USER, NO_CONDITION, 1, 1},
128 {"tx_reduce_relay", byRef(&doTxReduceRelay), Role::USER, NO_CONDITION},
129 {"unl_list", byRef(&doUnlList), Role::ADMIN, NO_CONDITION},
130 {"validation_create", byRef(&doValidationCreate), Role::ADMIN, NO_CONDITION},
131 {"validators", byRef(&doValidators), Role::ADMIN, NO_CONDITION},
132 {"validator_list_sites", byRef(&doValidatorListSites), Role::ADMIN, NO_CONDITION},
133 {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION},
134 {"vault_info", byRef(&doVaultInfo), Role::USER, NO_CONDITION},
135 {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION},
136 // Event methods
137 {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION},
138 {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION},
139};
140
141class HandlerTable
142{
143private:
144 using handler_table_t = std::multimap<std::string, Handler>;
145
146 // Use with equal_range to enforce that API range of a newly added handler
147 // does not overlap with API range of an existing handler with same name
148 [[nodiscard]] bool
149 overlappingApiVersion(
151 unsigned minVer,
152 unsigned maxVer)
153 {
154 XRPL_ASSERT(minVer <= maxVer, "xrpl::RPC::HandlerTable : valid API version range");
155 XRPL_ASSERT(maxVer <= RPC::apiMaximumValidVersion, "xrpl::RPC::HandlerTable : valid max API version");
156
157 return std::any_of(
158 range.first,
159 range.second, //
160 [minVer, maxVer](auto const& item) {
161 return item.second.minApiVer_ <= maxVer && item.second.maxApiVer_ >= minVer;
162 });
163 }
164
165 template <std::size_t N>
166 explicit HandlerTable(Handler const (&entries)[N])
167 {
168 for (auto const& entry : entries)
169 {
170 if (overlappingApiVersion(table_.equal_range(entry.name_), entry.minApiVer_, entry.maxApiVer_))
171 LogicError(std::string("Handler for ") + entry.name_ + " overlaps with an existing handler");
172
173 table_.insert({entry.name_, entry});
174 }
175
176 // This is where the new-style handlers are added.
177 addHandler<LedgerHandler>();
178 addHandler<VersionHandler>();
179 }
180
181public:
182 static HandlerTable const&
183 instance()
184 {
185 static HandlerTable const handlerTable(handlerArray);
186 return handlerTable;
187 }
188
189 [[nodiscard]] Handler const*
190 getHandler(unsigned version, bool betaEnabled, std::string const& name) const
191 {
192 if (version < RPC::apiMinimumSupportedVersion ||
193 version > (betaEnabled ? RPC::apiBetaVersion : RPC::apiMaximumSupportedVersion))
194 return nullptr;
195
196 auto const range = table_.equal_range(name);
197 auto const i = std::find_if(range.first, range.second, [version](auto const& entry) {
198 return entry.second.minApiVer_ <= version && version <= entry.second.maxApiVer_;
199 });
200
201 return i == range.second ? nullptr : &i->second;
202 }
203
204 [[nodiscard]] std::set<char const*>
205 getHandlerNames() const
206 {
208 for (auto const& i : table_)
209 ret.insert(i.second.name_);
210
211 return ret;
212 }
213
214private:
215 handler_table_t table_;
216
217 template <class HandlerImpl>
218 void
219 addHandler()
220 {
221 static_assert(HandlerImpl::minApiVer <= HandlerImpl::maxApiVer);
222 static_assert(HandlerImpl::maxApiVer <= RPC::apiMaximumValidVersion);
223 static_assert(RPC::apiMinimumSupportedVersion <= HandlerImpl::minApiVer);
224
225 if (overlappingApiVersion(
226 table_.equal_range(HandlerImpl::name), HandlerImpl::minApiVer, HandlerImpl::maxApiVer))
227 LogicError(std::string("Handler for ") + HandlerImpl::name + " overlaps with an existing handler");
228
229 table_.insert({HandlerImpl::name, handlerFrom<HandlerImpl>()});
230 }
231};
232
233} // namespace
234
235Handler const*
236getHandler(unsigned version, bool betaEnabled, std::string const& name)
237{
238 return HandlerTable::instance().getHandler(version, betaEnabled, name);
239}
240
243{
244 return HandlerTable::instance().getHandlerNames();
245}
246
247} // namespace RPC
248} // namespace xrpl
T any_of(T... args)
Represents a JSON value.
Definition json_value.h:131
T equal_range(T... args)
T find_if(T... args)
T insert(T... args)
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:27
Status
Return codes from Backend operations.
Json::Value makeObjectValue(Value const &value, Json::StaticString const &field=jss::message)
Return a Json::objectValue with a single entry.
Definition Handler.h:47
static constexpr auto apiBetaVersion
Definition ApiVersion.h:46
@ NEEDS_NETWORK_CONNECTION
Definition Handler.h:22
@ NO_CONDITION
Definition Handler.h:21
@ NEEDS_CLOSED_LEDGER
Definition Handler.h:24
@ NEEDS_CURRENT_LEDGER
Definition Handler.h:23
std::set< char const * > getHandlerNames()
Return names of all methods.
Definition Handler.cpp:242
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition Handler.cpp:236
static constexpr auto apiMinimumSupportedVersion
Definition ApiVersion.h:42
static constexpr auto apiMaximumValidVersion
Definition ApiVersion.h:47
static constexpr auto apiMaximumSupportedVersion
Definition ApiVersion.h:43
Json::Value entry(jtx::Env &env, jtx::Account const &account, jtx::Account const &authorize)
Definition delegate.cpp:34
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
Json::Value doDepositAuthorized(RPC::JsonContext &context)
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition AMMInfo.cpp:40
Json::Value doOwnerInfo(RPC::JsonContext &)
Definition OwnerInfo.cpp:16
Json::Value doSignFor(RPC::JsonContext &)
Definition SignFor.cpp:16
Json::Value doLedgerData(RPC::JsonContext &)
Json::Value doValidatorListSites(RPC::JsonContext &)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Json::Value doLedgerAccept(RPC::JsonContext &)
Json::Value doValidationCreate(RPC::JsonContext &)
Json::Value doAccountChannels(RPC::JsonContext &context)
Json::Value doNFTSellOffers(RPC::JsonContext &)
Json::Value doServerInfo(RPC::JsonContext &)
Json::Value doRipplePathFind(RPC::JsonContext &)
Json::Value doConsensusInfo(RPC::JsonContext &context)
Json::Value doVaultInfo(RPC::JsonContext &)
Definition VaultInfo.cpp:59
Json::Value doFetchInfo(RPC::JsonContext &context)
Definition FetchInfo.cpp:11
Json::Value doRandom(RPC::JsonContext &)
Definition Random.cpp:20
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:35
Json::Value doTxHistory(RPC::JsonContext &)
Definition TxHistory.cpp:20
Json::Value doTxJson(RPC::JsonContext &)
Definition Tx.cpp:242
Json::Value doPeerReservationsList(RPC::JsonContext &)
Json::Value doAccountOffers(RPC::JsonContext &context)
Json::Value doSubscribe(RPC::JsonContext &)
Definition Subscribe.cpp:19
Json::Value doLogLevel(RPC::JsonContext &)
Definition LogLevel.cpp:15
Json::Value doValidators(RPC::JsonContext &)
Json::Value doAccountNFTs(RPC::JsonContext &context)
General RPC command that can retrieve objects in the account root.
Json::Value doLedgerHeader(RPC::JsonContext &)
Json::Value doChannelAuthorize(RPC::JsonContext &)
Json::Value doPing(RPC::JsonContext &)
Definition Ping.cpp:14
Json::Value doLedgerRequest(RPC::JsonContext &)
Json::Value doSign(RPC::JsonContext &)
Json::Value doLedgerCurrent(RPC::JsonContext &)
Json::Value doStop(RPC::JsonContext &)
Definition Stop.cpp:13
Json::Value doPeers(RPC::JsonContext &)
Definition Peers.cpp:14
Json::Value doLogRotate(RPC::JsonContext &)
Definition LogRotate.cpp:10
Json::Value doServerDefinitions(RPC::JsonContext &)
Json::Value doPathFind(RPC::JsonContext &)
Definition PathFind.cpp:14
Json::Value doUnlList(RPC::JsonContext &)
Definition UnlList.cpp:11
Json::Value doFee(RPC::JsonContext &context)
Definition Fee1.cpp:11
Json::Value doPeerReservationsDel(RPC::JsonContext &)
Json::Value doAccountCurrencies(RPC::JsonContext &context)
Json::Value doSubmitMultiSigned(RPC::JsonContext &)
Json::Value doBookChanges(RPC::JsonContext &context)
Json::Value doAccountTxJson(RPC::JsonContext &context)
Json::Value doTransactionEntry(RPC::JsonContext &)
Json::Value doManifest(RPC::JsonContext &context)
Json::Value doBookOffers(RPC::JsonContext &context)
Json::Value doGetCounts(RPC::JsonContext &context)
Json::Value doPrint(RPC::JsonContext &)
Definition Print.cpp:11
Json::Value doChannelVerify(RPC::JsonContext &)
Json::Value doUnsubscribe(RPC::JsonContext &)
Json::Value doAccountLines(RPC::JsonContext &context)
Json::Value doCanDelete(RPC::JsonContext &context)
Definition CanDelete.cpp:16
Json::Value doAccountObjects(RPC::JsonContext &context)
Json::Value doLedgerCleaner(RPC::JsonContext &)
Json::Value doPeerReservationsAdd(RPC::JsonContext &)
Json::Value doConnect(RPC::JsonContext &context)
Definition Connect.cpp:20
Json::Value doGetAggregatePrice(RPC::JsonContext &context)
oracles: array of {account, oracle_document_id} base_asset: is the asset to be priced quote_asset: is...
Json::Value doNFTBuyOffers(RPC::JsonContext &)
Json::Value doValidatorInfo(RPC::JsonContext &)
Json::Value doFeature(RPC::JsonContext &context)
Definition Feature1.cpp:17
Json::Value doSimulate(RPC::JsonContext &)
Definition Simulate.cpp:271
Json::Value doAccountInfo(RPC::JsonContext &context)
Json::Value doWalletPropose(RPC::JsonContext &)
Json::Value doLedgerClosed(RPC::JsonContext &)
Json::Value doSubmit(RPC::JsonContext &)
Definition Submit.cpp:24
Json::Value doBlackList(RPC::JsonContext &context)
Definition BlackList.cpp:10
Json::Value doTxReduceRelay(RPC::JsonContext &)
Json::Value doNoRippleCheck(RPC::JsonContext &)
Json::Value doServerState(RPC::JsonContext &)
Json::Value doGatewayBalances(RPC::JsonContext &context)
Json::Value doLedgerEntry(RPC::JsonContext &)