rippled
Loading...
Searching...
No Matches
Handler.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpld/rpc/detail/Handler.h>
21#include <xrpld/rpc/detail/RPCHelpers.h>
22#include <xrpld/rpc/handlers/Handlers.h>
23#include <xrpld/rpc/handlers/Version.h>
24
25#include <xrpl/basics/contract.h>
26
27#include <map>
28
29namespace ripple {
30namespace RPC {
31namespace {
32
34template <typename Function>
35Handler::Method<Json::Value>
36byRef(Function const& f)
37{
38 return [f](JsonContext& context, Json::Value& result) {
39 result = f(context);
40 if (result.type() != Json::objectValue)
41 {
42 UNREACHABLE("ripple::RPC::byRef : result is object");
43 result = RPC::makeObjectValue(result);
44 }
45
46 return Status();
47 };
48}
49
50template <class Object, class HandlerImpl>
52handle(JsonContext& context, Object& object)
53{
54 XRPL_ASSERT(
55 context.apiVersion >= HandlerImpl::minApiVer &&
56 context.apiVersion <= HandlerImpl::maxApiVer,
57 "ripple::RPC::handle : valid API version");
58 HandlerImpl handler(context);
59
60 auto status = handler.check();
61 if (status)
62 status.inject(object);
63 else
64 handler.writeResult(object);
65 return status;
66}
67
68template <typename HandlerImpl>
69Handler
70handlerFrom()
71{
72 return {
73 HandlerImpl::name,
74 &handle<Json::Value, HandlerImpl>,
75 HandlerImpl::role,
76 HandlerImpl::condition,
77 HandlerImpl::minApiVer,
78 HandlerImpl::maxApiVer};
79}
80
81Handler const handlerArray[]{
82 // Some handlers not specified here are added to the table via addHandler()
83 // Request-response methods
84 {"account_info", byRef(&doAccountInfo), Role::USER, NO_CONDITION},
85 {"account_currencies",
86 byRef(&doAccountCurrencies),
89 {"account_lines", byRef(&doAccountLines), Role::USER, NO_CONDITION},
90 {"account_channels", byRef(&doAccountChannels), Role::USER, NO_CONDITION},
91 {"account_nfts", byRef(&doAccountNFTs), Role::USER, NO_CONDITION},
92 {"account_objects", byRef(&doAccountObjects), Role::USER, NO_CONDITION},
93 {"account_offers", byRef(&doAccountOffers), Role::USER, NO_CONDITION},
94 {"account_tx", byRef(&doAccountTxJson), Role::USER, NO_CONDITION},
95 {"amm_info", byRef(&doAMMInfo), Role::USER, NO_CONDITION},
96 {"blacklist", byRef(&doBlackList), Role::ADMIN, NO_CONDITION},
97 {"book_changes", byRef(&doBookChanges), Role::USER, NO_CONDITION},
98 {"book_offers", byRef(&doBookOffers), Role::USER, NO_CONDITION},
99 {"can_delete", byRef(&doCanDelete), Role::ADMIN, NO_CONDITION},
100 {"channel_authorize", byRef(&doChannelAuthorize), Role::USER, NO_CONDITION},
101 {"channel_verify", byRef(&doChannelVerify), Role::USER, NO_CONDITION},
102 {"connect", byRef(&doConnect), Role::ADMIN, NO_CONDITION},
103 {"consensus_info", byRef(&doConsensusInfo), Role::ADMIN, NO_CONDITION},
104 {"deposit_authorized",
105 byRef(&doDepositAuthorized),
108 {"feature", byRef(&doFeature), Role::USER, NO_CONDITION},
109 {"fee", byRef(&doFee), Role::USER, NEEDS_CURRENT_LEDGER},
110 {"fetch_info", byRef(&doFetchInfo), Role::ADMIN, NO_CONDITION},
111 {"gateway_balances", byRef(&doGatewayBalances), Role::USER, NO_CONDITION},
112 {"get_counts", byRef(&doGetCounts), Role::ADMIN, NO_CONDITION},
113 {"get_aggregate_price",
114 byRef(&doGetAggregatePrice),
117 {"ledger_accept",
118 byRef(&doLedgerAccept),
121 {"ledger_cleaner",
122 byRef(&doLedgerCleaner),
125 {"ledger_closed", byRef(&doLedgerClosed), Role::USER, NEEDS_CLOSED_LEDGER},
126 {"ledger_current",
127 byRef(&doLedgerCurrent),
130 {"ledger_data", byRef(&doLedgerData), Role::USER, NO_CONDITION},
131 {"ledger_entry", byRef(&doLedgerEntry), Role::USER, NO_CONDITION},
132 {"ledger_header", byRef(&doLedgerHeader), Role::USER, NO_CONDITION, 1, 1},
133 {"ledger_request", byRef(&doLedgerRequest), Role::ADMIN, NO_CONDITION},
134 {"log_level", byRef(&doLogLevel), Role::ADMIN, NO_CONDITION},
135 {"logrotate", byRef(&doLogRotate), Role::ADMIN, NO_CONDITION},
136 {"manifest", byRef(&doManifest), Role::USER, NO_CONDITION},
137 {"nft_buy_offers", byRef(&doNFTBuyOffers), Role::USER, NO_CONDITION},
138 {"nft_sell_offers", byRef(&doNFTSellOffers), Role::USER, NO_CONDITION},
139 {"noripple_check", byRef(&doNoRippleCheck), Role::USER, NO_CONDITION},
140 {"owner_info", byRef(&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER},
141 {"peers", byRef(&doPeers), Role::ADMIN, NO_CONDITION},
142 {"path_find", byRef(&doPathFind), Role::USER, NEEDS_CURRENT_LEDGER},
143 {"ping", byRef(&doPing), Role::USER, NO_CONDITION},
144 {"print", byRef(&doPrint), Role::ADMIN, NO_CONDITION},
145 // { "profile", byRef (&doProfile), Role::USER,
146 // NEEDS_CURRENT_LEDGER },
147 {"random", byRef(&doRandom), Role::USER, NO_CONDITION},
148 {"peer_reservations_add",
149 byRef(&doPeerReservationsAdd),
152 {"peer_reservations_del",
153 byRef(&doPeerReservationsDel),
156 {"peer_reservations_list",
160 {"ripple_path_find", byRef(&doRipplePathFind), Role::USER, NO_CONDITION},
161 {"server_definitions",
162 byRef(&doServerDefinitions),
165 {"server_info", byRef(&doServerInfo), Role::USER, NO_CONDITION},
166 {"server_state", byRef(&doServerState), Role::USER, NO_CONDITION},
167 {"sign", byRef(&doSign), Role::USER, NO_CONDITION},
168 {"sign_for", byRef(&doSignFor), Role::USER, NO_CONDITION},
169 {"simulate", byRef(&doSimulate), Role::USER, NEEDS_CURRENT_LEDGER},
170 {"stop", byRef(&doStop), Role::ADMIN, NO_CONDITION},
171 {"submit", byRef(&doSubmit), Role::USER, NEEDS_CURRENT_LEDGER},
172 {"submit_multisigned",
173 byRef(&doSubmitMultiSigned),
176 {"transaction_entry", byRef(&doTransactionEntry), Role::USER, NO_CONDITION},
178 {"tx_history", byRef(&doTxHistory), Role::USER, NO_CONDITION, 1, 1},
179 {"tx_reduce_relay", byRef(&doTxReduceRelay), Role::USER, NO_CONDITION},
180 {"unl_list", byRef(&doUnlList), Role::ADMIN, NO_CONDITION},
181 {"validation_create",
182 byRef(&doValidationCreate),
185 {"validators", byRef(&doValidators), Role::ADMIN, NO_CONDITION},
186 {"validator_list_sites",
187 byRef(&doValidatorListSites),
190 {"validator_info", byRef(&doValidatorInfo), Role::ADMIN, NO_CONDITION},
191 {"wallet_propose", byRef(&doWalletPropose), Role::ADMIN, NO_CONDITION},
192 // Evented methods
193 {"subscribe", byRef(&doSubscribe), Role::USER, NO_CONDITION},
194 {"unsubscribe", byRef(&doUnsubscribe), Role::USER, NO_CONDITION},
195};
196
197class HandlerTable
198{
199private:
200 using handler_table_t = std::multimap<std::string, Handler>;
201
202 // Use with equal_range to enforce that API range of a newly added handler
203 // does not overlap with API range of an existing handler with same name
204 [[nodiscard]] bool
205 overlappingApiVersion(
207 unsigned minVer,
208 unsigned maxVer)
209 {
210 XRPL_ASSERT(
211 minVer <= maxVer,
212 "ripple::RPC::HandlerTable : valid API version range");
213 XRPL_ASSERT(
215 "ripple::RPC::HandlerTable : valid max API version");
216
217 return std::any_of(
218 range.first,
219 range.second, //
220 [minVer, maxVer](auto const& item) {
221 return item.second.minApiVer_ <= maxVer &&
222 item.second.maxApiVer_ >= minVer;
223 });
224 }
225
226 template <std::size_t N>
227 explicit HandlerTable(const Handler (&entries)[N])
228 {
229 for (auto const& entry : entries)
230 {
231 if (overlappingApiVersion(
232 table_.equal_range(entry.name_),
233 entry.minApiVer_,
234 entry.maxApiVer_))
236 std::string("Handler for ") + entry.name_ +
237 " overlaps with an existing handler");
238
239 table_.insert({entry.name_, entry});
240 }
241
242 // This is where the new-style handlers are added.
243 addHandler<LedgerHandler>();
244 addHandler<VersionHandler>();
245 }
246
247public:
248 static HandlerTable const&
249 instance()
250 {
251 static HandlerTable const handlerTable(handlerArray);
252 return handlerTable;
253 }
254
255 [[nodiscard]] Handler const*
256 getHandler(unsigned version, bool betaEnabled, std::string const& name)
257 const
258 {
259 if (version < RPC::apiMinimumSupportedVersion ||
260 version > (betaEnabled ? RPC::apiBetaVersion
262 return nullptr;
263
264 auto const range = table_.equal_range(name);
265 auto const i = std::find_if(
266 range.first, range.second, [version](auto const& entry) {
267 return entry.second.minApiVer_ <= version &&
268 version <= entry.second.maxApiVer_;
269 });
270
271 return i == range.second ? nullptr : &i->second;
272 }
273
274 [[nodiscard]] std::set<char const*>
275 getHandlerNames() const
276 {
278 for (auto const& i : table_)
279 ret.insert(i.second.name_);
280
281 return ret;
282 }
283
284private:
285 handler_table_t table_;
286
287 template <class HandlerImpl>
288 void
289 addHandler()
290 {
291 static_assert(HandlerImpl::minApiVer <= HandlerImpl::maxApiVer);
292 static_assert(HandlerImpl::maxApiVer <= RPC::apiMaximumValidVersion);
293 static_assert(
294 RPC::apiMinimumSupportedVersion <= HandlerImpl::minApiVer);
295
296 if (overlappingApiVersion(
297 table_.equal_range(HandlerImpl::name),
298 HandlerImpl::minApiVer,
299 HandlerImpl::maxApiVer))
301 std::string("Handler for ") + HandlerImpl::name +
302 " overlaps with an existing handler");
303
304 table_.insert({HandlerImpl::name, handlerFrom<HandlerImpl>()});
305 }
306};
307
308} // namespace
309
310Handler const*
311getHandler(unsigned version, bool betaEnabled, std::string const& name)
312{
313 return HandlerTable::instance().getHandler(version, betaEnabled, name);
314}
315
318{
319 return HandlerTable::instance().getHandlerNames();
320}
321
322} // namespace RPC
323} // namespace ripple
T any_of(T... args)
Represents a JSON value.
Definition: json_value.h:148
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:44
Status
Return codes from Backend operations.
@ NEEDS_CURRENT_LEDGER
Definition: Handler.h:41
@ NEEDS_NETWORK_CONNECTION
Definition: Handler.h:40
@ NO_CONDITION
Definition: Handler.h:39
@ NEEDS_CLOSED_LEDGER
Definition: Handler.h:42
static constexpr auto apiMaximumSupportedVersion
Definition: ApiVersion.h:58
std::set< char const * > getHandlerNames()
Return names of all methods.
Definition: Handler.cpp:317
Json::Value makeObjectValue(Value const &value, Json::StaticString const &field=jss::message)
Return a Json::objectValue with a single entry.
Definition: Handler.h:65
static constexpr auto apiMaximumValidVersion
Definition: ApiVersion.h:63
static constexpr auto apiBetaVersion
Definition: ApiVersion.h:62
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition: Handler.cpp:311
static constexpr auto apiMinimumSupportedVersion
Definition: ApiVersion.h:57
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
Json::Value doPeers(RPC::JsonContext &)
Definition: Peers.cpp:33
Json::Value doTxHistory(RPC::JsonContext &)
Definition: TxHistory.cpp:39
Json::Value doLedgerAccept(RPC::JsonContext &)
Json::Value doUnsubscribe(RPC::JsonContext &)
Definition: Unsubscribe.cpp:33
Json::Value doTxReduceRelay(RPC::JsonContext &)
Json::Value doServerState(RPC::JsonContext &)
Definition: ServerState.cpp:30
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 &)
Definition: NFTOffers.cpp:165
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)
Definition: BookOffers.cpp:206
Json::Value doLedgerRequest(RPC::JsonContext &)
Json::Value doSimulate(RPC::JsonContext &)
Definition: Simulate.cpp:297
Json::Value doPeerReservationsAdd(RPC::JsonContext &)
Json::Value doLedgerCleaner(RPC::JsonContext &)
Json::Value doSign(RPC::JsonContext &)
Definition: SignHandler.cpp:34
Json::Value doAccountTxJson(RPC::JsonContext &context)
Definition: AccountTx.cpp:404
Json::Value doAccountLines(RPC::JsonContext &context)
Json::Value doTxJson(RPC::JsonContext &)
Definition: Tx.cpp:282
Json::Value doAMMInfo(RPC::JsonContext &context)
Definition: AMMInfo.cpp:76
Json::Value doPeerReservationsList(RPC::JsonContext &)
Json::Value doServerInfo(RPC::JsonContext &)
Definition: ServerInfo.cpp:322
Json::Value doFee(RPC::JsonContext &context)
Definition: Fee1.cpp:30
Json::Value doConnect(RPC::JsonContext &context)
Definition: Connect.cpp:39
Json::Value doNFTSellOffers(RPC::JsonContext &)
Definition: NFTOffers.cpp:151
Json::Value doDepositAuthorized(RPC::JsonContext &context)
Json::Value doStop(RPC::JsonContext &)
Definition: Stop.cpp:32
Json::Value doLedgerClosed(RPC::JsonContext &)
Json::Value doLogLevel(RPC::JsonContext &)
Definition: LogLevel.cpp:34
Json::Value doSubmit(RPC::JsonContext &)
Definition: Submit.cpp:45
Json::Value doServerDefinitions(RPC::JsonContext &)
Definition: ServerInfo.cpp:299
Json::Value doSubscribe(RPC::JsonContext &)
Definition: Subscribe.cpp:38
Json::Value doAccountObjects(RPC::JsonContext &context)
Json::Value doFeature(RPC::JsonContext &context)
Definition: Feature1.cpp:36
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:30
Json::Value doLedgerHeader(RPC::JsonContext &)
Json::Value doRandom(RPC::JsonContext &)
Definition: Random.cpp:39
Json::Value doManifest(RPC::JsonContext &)
Json::Value doGetCounts(RPC::JsonContext &context)
Definition: GetCounts.cpp:138
Json::Value doPing(RPC::JsonContext &)
Definition: Ping.cpp:33
Json::Value doBlackList(RPC::JsonContext &context)
Definition: BlackList.cpp:29
Json::Value doLedgerData(RPC::JsonContext &)
Definition: LedgerData.cpp:46
Json::Value doValidatorListSites(RPC::JsonContext &)
Json::Value doSignFor(RPC::JsonContext &)
Definition: SignFor.cpp:35
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:54
Json::Value doRipplePathFind(RPC::JsonContext &)
Json::Value doBookOffers(RPC::JsonContext &context)
Definition: BookOffers.cpp:37
Json::Value doAccountCurrencies(RPC::JsonContext &context)
Json::Value doAccountInfo(RPC::JsonContext &context)
Definition: AccountInfo.cpp:50
Json::Value doLogRotate(RPC::JsonContext &)
Definition: LogRotate.cpp:29
Json::Value doCanDelete(RPC::JsonContext &context)
Definition: CanDelete.cpp:35
Json::Value doWalletPropose(RPC::JsonContext &)
Json::Value doAccountChannels(RPC::JsonContext &context)
Json::Value doPeerReservationsDel(RPC::JsonContext &)
Json::Value doValidators(RPC::JsonContext &)
Definition: Validators.cpp:29
Json::Value doOwnerInfo(RPC::JsonContext &)
Definition: OwnerInfo.cpp:35
Json::Value doPrint(RPC::JsonContext &)
Definition: Print.cpp:30
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:37
Json::Value doUnlList(RPC::JsonContext &)
Definition: UnlList.cpp:30
Json::Value doPathFind(RPC::JsonContext &)
Definition: PathFind.cpp:33