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