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
7#include <map>
8
9namespace ripple {
10namespace RPC {
11namespace {
12
14template <typename Function>
15Handler::Method<Json::Value>
16byRef(Function const& f)
17{
18 return [f](JsonContext& context, Json::Value& result) {
19 result = f(context);
20 if (result.type() != Json::objectValue)
21 {
22 // LCOV_EXCL_START
23 UNREACHABLE("ripple::RPC::byRef : result is object");
24 result = RPC::makeObjectValue(result);
25 // LCOV_EXCL_STOP
26 }
27
28 return Status();
29 };
30}
31
32template <class Object, class HandlerImpl>
34handle(JsonContext& context, Object& object)
35{
36 XRPL_ASSERT(
37 context.apiVersion >= HandlerImpl::minApiVer &&
38 context.apiVersion <= HandlerImpl::maxApiVer,
39 "ripple::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",
68 byRef(&doAccountCurrencies),
71 {"account_lines", byRef(&doAccountLines), Role::USER, NO_CONDITION},
72 {"account_channels", byRef(&doAccountChannels), Role::USER, NO_CONDITION},
73 {"account_nfts", byRef(&doAccountNFTs), Role::USER, NO_CONDITION},
74 {"account_objects", byRef(&doAccountObjects), Role::USER, NO_CONDITION},
75 {"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
76 {"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
77 {"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
78 {"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
79 {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
80 {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
81 {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION},
82 {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION},
83 {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION},
84 {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION},
85 {"consensus_info", byRef(&doConsensusInfo), Role::ADMIN, NO_CONDITION},
86 {"deposit_authorized",
87 byRef(&doDepositAuthorized),
90 {"feature", byRef(&doFeature), Role::USER, NO_CONDITION},
91 {"fee", byRef(&doFee), Role::USER, NEEDS_CURRENT_LEDGER},
92 {"fetch_info", byRef(&doFetchInfo), Role::ADMIN, NO_CONDITION},
93 {"gateway_balances", byRef(&doGatewayBalances), Role::USER, NO_CONDITION},
94 {"get_counts", byRef(&doGetCounts), Role::ADMIN, NO_CONDITION},
95 {"get_aggregate_price",
96 byRef(&doGetAggregatePrice),
99 {"ledger_accept",
100 byRef(&doLedgerAccept),
103 {"ledger_cleaner",
104 byRef(&doLedgerCleaner),
107 {"ledger_closed", byRef(&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER},
108 {"ledger_current",
109 byRef(&doLedgerCurrent),
112 {"ledger_data", byRef(&doLedgerData), Role::USER, NO_CONDITION},
113 {"ledger_entry", byRef(&doLedgerEntry), Role::USER, NO_CONDITION},
114 {"ledger_header", byRef(&doLedgerHeader), Role::USER, NO_CONDITION, 1, 1},
115 {"ledger_request", byRef(&doLedgerRequest), Role::ADMIN, NO_CONDITION},
116 {"log_level", byRef(&doLogLevel), Role::ADMIN, NO_CONDITION},
117 {"logrotate", byRef(&doLogRotate), Role::ADMIN, NO_CONDITION},
118 {"manifest", byRef(&doManifest), Role::USER, NO_CONDITION},
119 {"nft_buy_offers", byRef(&doNFTBuyOffers), Role::USER, NO_CONDITION},
120 {"nft_sell_offers", byRef(&doNFTSellOffers), Role::USER, NO_CONDITION},
121 {"noripple_check", byRef(&doNoRippleCheck), Role::USER, NO_CONDITION},
122 {"owner_info", byRef(&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER},
123 {"peers", byRef(&doPeers), Role::ADMIN, NO_CONDITION},
124 {"path_find", byRef(&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER},
125 {"ping", byRef(&doPing), Role::USER, NO_CONDITION},
126 {"print", byRef(&doPrint), Role::ADMIN, NO_CONDITION},
127 // { "profile", byRef (&doProfile), Role::USER,
128 // NEEDS_CURRENT_LEDGER },
129 {"random", byRef(&doRandom), Role::USER, NO_CONDITION},
130 {"peer_reservations_add",
131 byRef(&doPeerReservationsAdd),
134 {"peer_reservations_del",
135 byRef(&doPeerReservationsDel),
138 {"peer_reservations_list",
142 {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION},
143 {"server_definitions",
144 byRef(&doServerDefinitions),
147 {"server_info", byRef(&doServerInfo), Role::USER, NO_CONDITION},
148 {"server_state", byRef(&doServerState), Role::USER, NO_CONDITION},
149 {"sign", byRef(&doSign), Role::USER, NO_CONDITION},
150 {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION},
151 {"simulate", byRef(&doSimulate), Role::USER, NEEDS_CURRENT_LEDGER},
152 {"stop", byRef(&doStop), Role::ADMIN, NO_CONDITION},
153 {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER},
154 {"submit_multisigned",
155 byRef(&doSubmitMultiSigned),
158 {"transaction_entry", byRef(&doTransactionEntry), Role::USER, NO_CONDITION},
160 {"tx_history", byRef(&doTxHistory), Role::USER, NO_CONDITION, 1, 1},
161 {"tx_reduce_relay", byRef(&doTxReduceRelay), Role::USER, NO_CONDITION},
162 {"unl_list", byRef(&doUnlList), Role::ADMIN, NO_CONDITION},
163 {"validation_create",
164 byRef(&doValidationCreate),
167 {"validators", byRef(&doValidators), Role::ADMIN, NO_CONDITION},
168 {"validator_list_sites",
169 byRef(&doValidatorListSites),
172 {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION},
173 {"vault_info", byRef(&doVaultInfo), Role::USER, NO_CONDITION},
174 {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION},
175 // Evented methods
176 {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION},
177 {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION},
178};
179
180class HandlerTable
181{
182private:
183 using handler_table_t = std::multimap<std::string, Handler>;
184
185 // Use with equal_range to enforce that API range of a newly added handler
186 // does not overlap with API range of an existing handler with same name
187 [[nodiscard]] bool
188 overlappingApiVersion(
190 unsigned minVer,
191 unsigned maxVer)
192 {
193 XRPL_ASSERT(
194 minVer <= maxVer,
195 "ripple::RPC::HandlerTable : valid API version range");
196 XRPL_ASSERT(
198 "ripple::RPC::HandlerTable : valid max API version");
199
200 return std::any_of(
201 range.first,
202 range.second, //
203 [minVer, maxVer](auto const& item) {
204 return item.second.minApiVer_ <= maxVer &&
205 item.second.maxApiVer_ >= minVer;
206 });
207 }
208
209 template <std::size_t N>
210 explicit HandlerTable(Handler const (&entries)[N])
211 {
212 for (auto const& entry : entries)
213 {
214 if (overlappingApiVersion(
215 table_.equal_range(entry.name_),
216 entry.minApiVer_,
217 entry.maxApiVer_))
219 std::string("Handler for ") + entry.name_ +
220 " overlaps with an existing handler");
221
222 table_.insert({entry.name_, entry});
223 }
224
225 // This is where the new-style handlers are added.
226 addHandler<LedgerHandler>();
227 addHandler<VersionHandler>();
228 }
229
230public:
231 static HandlerTable const&
232 instance()
233 {
234 static HandlerTable const handlerTable(handlerArray);
235 return handlerTable;
236 }
237
238 [[nodiscard]] Handler const*
239 getHandler(unsigned version, bool betaEnabled, std::string const& name)
240 const
241 {
242 if (version < RPC::apiMinimumSupportedVersion ||
243 version > (betaEnabled ? RPC::apiBetaVersion
245 return nullptr;
246
247 auto const range = table_.equal_range(name);
248 auto const i = std::find_if(
249 range.first, range.second, [version](auto const& entry) {
250 return entry.second.minApiVer_ <= version &&
251 version <= entry.second.maxApiVer_;
252 });
253
254 return i == range.second ? nullptr : &i->second;
255 }
256
257 [[nodiscard]] std::set<char const*>
258 getHandlerNames() const
259 {
261 for (auto const& i : table_)
262 ret.insert(i.second.name_);
263
264 return ret;
265 }
266
267private:
268 handler_table_t table_;
269
270 template <class HandlerImpl>
271 void
272 addHandler()
273 {
274 static_assert(HandlerImpl::minApiVer <= HandlerImpl::maxApiVer);
275 static_assert(HandlerImpl::maxApiVer <= RPC::apiMaximumValidVersion);
276 static_assert(
277 RPC::apiMinimumSupportedVersion <= HandlerImpl::minApiVer);
278
279 if (overlappingApiVersion(
280 table_.equal_range(HandlerImpl::name),
281 HandlerImpl::minApiVer,
282 HandlerImpl::maxApiVer))
284 std::string("Handler for ") + HandlerImpl::name +
285 " overlaps with an existing handler");
286
287 table_.insert({HandlerImpl::name, handlerFrom<HandlerImpl>()});
288 }
289};
290
291} // namespace
292
293Handler const*
294getHandler(unsigned version, bool betaEnabled, std::string const& name)
295{
296 return HandlerTable::instance().getHandler(version, betaEnabled, name);
297}
298
301{
302 return HandlerTable::instance().getHandlerNames();
303}
304
305} // namespace RPC
306} // namespace ripple
T any_of(T... args)
Represents a JSON value.
Definition json_value.h:130
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:26
Status
Return codes from Backend operations.
@ NEEDS_CURRENT_LEDGER
Definition Handler.h:23
@ NEEDS_NETWORK_CONNECTION
Definition Handler.h:22
@ NO_CONDITION
Definition Handler.h:21
@ NEEDS_CLOSED_LEDGER
Definition Handler.h:24
static constexpr auto apiMaximumSupportedVersion
Definition ApiVersion.h:43
std::set< char const * > getHandlerNames()
Return names of all methods.
Definition Handler.cpp:300
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 apiMaximumValidVersion
Definition ApiVersion.h:48
static constexpr auto apiBetaVersion
Definition ApiVersion.h:47
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition Handler.cpp:294
static constexpr auto apiMinimumSupportedVersion
Definition ApiVersion.h:42
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 doPeers(RPC::JsonContext &)
Definition Peers.cpp:14
Json::Value doTxHistory(RPC::JsonContext &)
Definition TxHistory.cpp:20
Json::Value doLedgerAccept(RPC::JsonContext &)
Json::Value doUnsubscribe(RPC::JsonContext &)
Json::Value doTxReduceRelay(RPC::JsonContext &)
Json::Value doServerState(RPC::JsonContext &)
Json::Value doChannelVerify(RPC::JsonContext &)
Json::Value doValidationCreate(RPC::JsonContext &)
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 doSubmitMultiSigned(RPC::JsonContext &)
Json::Value doLedgerEntry(RPC::JsonContext &)
Json::Value doNFTBuyOffers(RPC::JsonContext &)
Json::Value doChannelAuthorize(RPC::JsonContext &)
Json::Value doNoRippleCheck(RPC::JsonContext &)
Json::Value doTransactionEntry(RPC::JsonContext &)
Json::Value doConsensusInfo(RPC::JsonContext &context)
Json::Value doBookChanges(RPC::JsonContext &context)
Json::Value doLedgerRequest(RPC::JsonContext &)
Json::Value doSimulate(RPC::JsonContext &)
Definition Simulate.cpp:301
Json::Value doPeerReservationsAdd(RPC::JsonContext &)
Json::Value doLedgerCleaner(RPC::JsonContext &)
Json::Value doSign(RPC::JsonContext &)
Json::Value doAccountTxJson(RPC::JsonContext &context)
Json::Value doAccountLines(RPC::JsonContext &context)
Json::Value doTxJson(RPC::JsonContext &)
Definition Tx.cpp:266
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition AMMInfo.cpp:57
Json::Value doPeerReservationsList(RPC::JsonContext &)
Json::Value doServerInfo(RPC::JsonContext &)
Json::Value doFee(RPC::JsonContext &context)
Definition Fee1.cpp:11
Json::Value doConnect(RPC::JsonContext &context)
Definition Connect.cpp:20
Json::Value doNFTSellOffers(RPC::JsonContext &)
Json::Value doDepositAuthorized(RPC::JsonContext &context)
Json::Value doStop(RPC::JsonContext &)
Definition Stop.cpp:13
Json::Value doLedgerClosed(RPC::JsonContext &)
Json::Value doLogLevel(RPC::JsonContext &)
Definition LogLevel.cpp:15
Json::Value doSubmit(RPC::JsonContext &)
Definition Submit.cpp:26
Json::Value doServerDefinitions(RPC::JsonContext &)
Json::Value doSubscribe(RPC::JsonContext &)
Definition Subscribe.cpp:19
Json::Value doAccountObjects(RPC::JsonContext &context)
Json::Value doFeature(RPC::JsonContext &context)
Definition Feature1.cpp:17
Json::Value doAccountNFTs(RPC::JsonContext &context)
General RPC command that can retrieve objects in the account root.
Json::Value doFetchInfo(RPC::JsonContext &context)
Definition FetchInfo.cpp:11
Json::Value doLedgerHeader(RPC::JsonContext &)
Json::Value doRandom(RPC::JsonContext &)
Definition Random.cpp:20
Json::Value doGetCounts(RPC::JsonContext &context)
Json::Value doManifest(RPC::JsonContext &context)
Json::Value doPing(RPC::JsonContext &)
Definition Ping.cpp:14
Json::Value doBlackList(RPC::JsonContext &context)
Definition BlackList.cpp:10
Json::Value doLedgerData(RPC::JsonContext &)
Json::Value doValidatorListSites(RPC::JsonContext &)
Json::Value doSignFor(RPC::JsonContext &)
Definition SignFor.cpp:16
Json::Value doLedgerCurrent(RPC::JsonContext &)
Json::Value doAccountOffers(RPC::JsonContext &context)
Json::Value doValidatorInfo(RPC::JsonContext &)
Json::Value doGatewayBalances(RPC::JsonContext &context)
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition RangeSet.h:35
Json::Value doRipplePathFind(RPC::JsonContext &)
Json::Value doBookOffers(RPC::JsonContext &context)
Json::Value doAccountCurrencies(RPC::JsonContext &context)
Json::Value doAccountInfo(RPC::JsonContext &context)
Json::Value doLogRotate(RPC::JsonContext &)
Definition LogRotate.cpp:10
Json::Value doCanDelete(RPC::JsonContext &context)
Definition CanDelete.cpp:16
Json::Value doWalletPropose(RPC::JsonContext &)
Json::Value doVaultInfo(RPC::JsonContext &)
Definition VaultInfo.cpp:60
Json::Value doAccountChannels(RPC::JsonContext &context)
Json::Value doPeerReservationsDel(RPC::JsonContext &)
Json::Value doValidators(RPC::JsonContext &)
Json::Value doOwnerInfo(RPC::JsonContext &)
Definition OwnerInfo.cpp:16
Json::Value doPrint(RPC::JsonContext &)
Definition Print.cpp:11
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Json::Value doUnlList(RPC::JsonContext &)
Definition UnlList.cpp:11
Json::Value doPathFind(RPC::JsonContext &)
Definition PathFind.cpp:14