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 &&
39 context.apiVersion <= HandlerImpl::maxApiVer,
40 "xrpl::RPC::handle : valid API version");
41 HandlerImpl handler(context);
42
43 auto status = handler.check();
44 if (status)
45 status.inject(object);
46 else
47 handler.writeResult(object);
48 return status;
49}
50
51template <typename HandlerImpl>
52Handler
53handlerFrom()
54{
55 return {
56 HandlerImpl::name,
57 &handle<Json::Value, HandlerImpl>,
58 HandlerImpl::role,
59 HandlerImpl::condition,
60 HandlerImpl::minApiVer,
61 HandlerImpl::maxApiVer};
62}
63
64Handler const handlerArray[]{
65 // Some handlers not specified here are added to the table via addHandler()
66 // Request-response methods
67 {"account_info", byRef(&doAccountInfo), Role::USER, NO_CONDITION},
68 {"account_currencies",
69 byRef(&doAccountCurrencies),
72 {"account_lines", byRef(&doAccountLines), Role::USER, NO_CONDITION},
73 {"account_channels", byRef(&doAccountChannels), Role::USER, NO_CONDITION},
74 {"account_nfts", byRef(&doAccountNFTs), Role::USER, NO_CONDITION},
75 {"account_objects", byRef(&doAccountObjects), Role::USER, NO_CONDITION},
76 {"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
77 {"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
78 {"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
79 {"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
80 {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
81 {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
82 {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION},
83 {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION},
84 {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION},
85 {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION},
86 {"consensus_info", byRef(&doConsensusInfo), Role::ADMIN, NO_CONDITION},
87 {"deposit_authorized",
88 byRef(&doDepositAuthorized),
91 {"feature", byRef(&doFeature), Role::USER, NO_CONDITION},
92 {"fee", byRef(&doFee), Role::USER, NEEDS_CURRENT_LEDGER},
93 {"fetch_info", byRef(&doFetchInfo), Role::ADMIN, NO_CONDITION},
94 {"gateway_balances", byRef(&doGatewayBalances), Role::USER, NO_CONDITION},
95 {"get_counts", byRef(&doGetCounts), Role::ADMIN, NO_CONDITION},
96 {"get_aggregate_price",
97 byRef(&doGetAggregatePrice),
100 {"ledger_accept",
101 byRef(&doLedgerAccept),
104 {"ledger_cleaner",
105 byRef(&doLedgerCleaner),
108 {"ledger_closed", byRef(&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER},
109 {"ledger_current",
110 byRef(&doLedgerCurrent),
113 {"ledger_data", byRef(&doLedgerData), Role::USER, NO_CONDITION},
114 {"ledger_entry", byRef(&doLedgerEntry), Role::USER, NO_CONDITION},
115 {"ledger_header", byRef(&doLedgerHeader), Role::USER, NO_CONDITION, 1, 1},
116 {"ledger_request", byRef(&doLedgerRequest), Role::ADMIN, NO_CONDITION},
117 {"log_level", byRef(&doLogLevel), Role::ADMIN, NO_CONDITION},
118 {"logrotate", byRef(&doLogRotate), Role::ADMIN, NO_CONDITION},
119 {"manifest", byRef(&doManifest), Role::USER, NO_CONDITION},
120 {"nft_buy_offers", byRef(&doNFTBuyOffers), Role::USER, NO_CONDITION},
121 {"nft_sell_offers", byRef(&doNFTSellOffers), Role::USER, NO_CONDITION},
122 {"noripple_check", byRef(&doNoRippleCheck), Role::USER, NO_CONDITION},
123 {"owner_info", byRef(&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER},
124 {"peers", byRef(&doPeers), Role::ADMIN, NO_CONDITION},
125 {"path_find", byRef(&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER},
126 {"ping", byRef(&doPing), Role::USER, NO_CONDITION},
127 {"print", byRef(&doPrint), Role::ADMIN, NO_CONDITION},
128 // { "profile", byRef (&doProfile), Role::USER,
129 // NEEDS_CURRENT_LEDGER },
130 {"random", byRef(&doRandom), Role::USER, NO_CONDITION},
131 {"peer_reservations_add",
132 byRef(&doPeerReservationsAdd),
135 {"peer_reservations_del",
136 byRef(&doPeerReservationsDel),
139 {"peer_reservations_list",
143 {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION},
144 {"server_definitions",
145 byRef(&doServerDefinitions),
148 {"server_info", byRef(&doServerInfo), Role::USER, NO_CONDITION},
149 {"server_state", byRef(&doServerState), Role::USER, NO_CONDITION},
150 {"sign", byRef(&doSign), Role::USER, NO_CONDITION},
151 {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION},
152 {"simulate", byRef(&doSimulate), Role::USER, NEEDS_CURRENT_LEDGER},
153 {"stop", byRef(&doStop), Role::ADMIN, NO_CONDITION},
154 {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER},
155 {"submit_multisigned",
156 byRef(&doSubmitMultiSigned),
159 {"transaction_entry", byRef(&doTransactionEntry), Role::USER, NO_CONDITION},
161 {"tx_history", byRef(&doTxHistory), Role::USER, NO_CONDITION, 1, 1},
162 {"tx_reduce_relay", byRef(&doTxReduceRelay), Role::USER, NO_CONDITION},
163 {"unl_list", byRef(&doUnlList), Role::ADMIN, NO_CONDITION},
164 {"validation_create",
165 byRef(&doValidationCreate),
168 {"validators", byRef(&doValidators), Role::ADMIN, NO_CONDITION},
169 {"validator_list_sites",
170 byRef(&doValidatorListSites),
173 {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION},
174 {"vault_info", byRef(&doVaultInfo), Role::USER, NO_CONDITION},
175 {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION},
176 // Event methods
177 {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION},
178 {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION},
179};
180
181class HandlerTable
182{
183private:
184 using handler_table_t = std::multimap<std::string, Handler>;
185
186 // Use with equal_range to enforce that API range of a newly added handler
187 // does not overlap with API range of an existing handler with same name
188 [[nodiscard]] bool
189 overlappingApiVersion(
191 unsigned minVer,
192 unsigned maxVer)
193 {
194 XRPL_ASSERT(
195 minVer <= maxVer,
196 "xrpl::RPC::HandlerTable : valid API version range");
197 XRPL_ASSERT(
199 "xrpl::RPC::HandlerTable : valid max API version");
200
201 return std::any_of(
202 range.first,
203 range.second, //
204 [minVer, maxVer](auto const& item) {
205 return item.second.minApiVer_ <= maxVer &&
206 item.second.maxApiVer_ >= minVer;
207 });
208 }
209
210 template <std::size_t N>
211 explicit HandlerTable(Handler const (&entries)[N])
212 {
213 for (auto const& entry : entries)
214 {
215 if (overlappingApiVersion(
216 table_.equal_range(entry.name_),
217 entry.minApiVer_,
218 entry.maxApiVer_))
220 std::string("Handler for ") + entry.name_ +
221 " overlaps with an existing handler");
222
223 table_.insert({entry.name_, entry});
224 }
225
226 // This is where the new-style handlers are added.
227 addHandler<LedgerHandler>();
228 addHandler<VersionHandler>();
229 }
230
231public:
232 static HandlerTable const&
233 instance()
234 {
235 static HandlerTable const handlerTable(handlerArray);
236 return handlerTable;
237 }
238
239 [[nodiscard]] Handler const*
240 getHandler(unsigned version, bool betaEnabled, std::string const& name)
241 const
242 {
243 if (version < RPC::apiMinimumSupportedVersion ||
244 version > (betaEnabled ? RPC::apiBetaVersion
246 return nullptr;
247
248 auto const range = table_.equal_range(name);
249 auto const i = std::find_if(
250 range.first, range.second, [version](auto const& entry) {
251 return entry.second.minApiVer_ <= version &&
252 version <= entry.second.maxApiVer_;
253 });
254
255 return i == range.second ? nullptr : &i->second;
256 }
257
258 [[nodiscard]] std::set<char const*>
259 getHandlerNames() const
260 {
262 for (auto const& i : table_)
263 ret.insert(i.second.name_);
264
265 return ret;
266 }
267
268private:
269 handler_table_t table_;
270
271 template <class HandlerImpl>
272 void
273 addHandler()
274 {
275 static_assert(HandlerImpl::minApiVer <= HandlerImpl::maxApiVer);
276 static_assert(HandlerImpl::maxApiVer <= RPC::apiMaximumValidVersion);
277 static_assert(
278 RPC::apiMinimumSupportedVersion <= HandlerImpl::minApiVer);
279
280 if (overlappingApiVersion(
281 table_.equal_range(HandlerImpl::name),
282 HandlerImpl::minApiVer,
283 HandlerImpl::maxApiVer))
285 std::string("Handler for ") + HandlerImpl::name +
286 " overlaps with an existing handler");
287
288 table_.insert({HandlerImpl::name, handlerFrom<HandlerImpl>()});
289 }
290};
291
292} // namespace
293
294Handler const*
295getHandler(unsigned version, bool betaEnabled, std::string const& name)
296{
297 return HandlerTable::instance().getHandler(version, betaEnabled, name);
298}
299
302{
303 return HandlerTable::instance().getHandlerNames();
304}
305
306} // namespace RPC
307} // 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:47
@ 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:301
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition Handler.cpp:295
static constexpr auto apiMinimumSupportedVersion
Definition ApiVersion.h:42
static constexpr auto apiMaximumValidVersion
Definition ApiVersion.h:48
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:36
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:41
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:60
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:266
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:301
Json::Value doAccountInfo(RPC::JsonContext &context)
Json::Value doWalletPropose(RPC::JsonContext &)
Json::Value doLedgerClosed(RPC::JsonContext &)
Json::Value doSubmit(RPC::JsonContext &)
Definition Submit.cpp:26
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 &)