rippled
Loading...
Searching...
No Matches
LedgerEntryHelpers.h
1#include <xrpld/rpc/detail/RPCHelpers.h>
2
3#include <xrpl/basics/StringUtilities.h>
4#include <xrpl/basics/strHex.h>
5#include <xrpl/beast/core/LexicalCast.h>
6#include <xrpl/json/json_errors.h>
7#include <xrpl/protocol/ErrorCodes.h>
8#include <xrpl/protocol/Indexes.h>
9#include <xrpl/protocol/RPCErr.h>
10#include <xrpl/protocol/STXChainBridge.h>
11#include <xrpl/protocol/jss.h>
12
13#include <functional>
14
15namespace xrpl {
16
17namespace LedgerEntryHelpers {
18
21{
23 json[jss::error] = err.value_or("malformedRequest");
24 json[jss::error_code] = rpcINVALID_PARAMS;
25 json[jss::error_message] = RPC::missing_field_message(std::string(field.c_str()));
26 return Unexpected(json);
27}
28
30invalidFieldError(std::string const& err, Json::StaticString const field, std::string const& type)
31{
33 json[jss::error] = err;
34 json[jss::error_code] = rpcINVALID_PARAMS;
35 json[jss::error_message] = RPC::expected_field_message(field, type);
36 return Unexpected(json);
37}
38
40malformedError(std::string const& err, std::string const& message)
41{
43 json[jss::error] = err;
44 json[jss::error_code] = rpcINVALID_PARAMS;
45 json[jss::error_message] = message;
46 return Unexpected(json);
47}
48
51 Json::Value const& params,
54{
55 for (auto const field : fields)
56 {
57 if (!params.isMember(field) || params[field].isNull())
58 {
59 return missingFieldError(field, err);
60 }
61 }
62 return true;
63}
64
65template <class T>
67parse(Json::Value const& param);
68
69template <class T>
72 Json::Value const& params,
73 Json::StaticString const fieldName,
74 std::string const& err,
75 std::string const& expectedType)
76{
77 if (!params.isMember(fieldName) || params[fieldName].isNull())
78 {
79 return missingFieldError(fieldName);
80 }
81 if (auto obj = parse<T>(params[fieldName]))
82 {
83 return *obj;
84 }
85 return invalidFieldError(err, fieldName, expectedType);
86}
87
88template <>
90parse(Json::Value const& param)
91{
92 if (!param.isString())
93 return std::nullopt;
94
95 auto const account = parseBase58<AccountID>(param.asString());
96 if (!account || account->isZero())
97 {
98 return std::nullopt;
99 }
100
101 return account;
102}
103
106 Json::Value const& params,
107 Json::StaticString const fieldName,
108 std::string const& err)
109{
110 return required<AccountID>(params, fieldName, err, "AccountID");
111}
112
114parseHexBlob(Json::Value const& param, std::size_t maxLength)
115{
116 if (!param.isString())
117 return std::nullopt;
118
119 auto blob = strUnHex(param.asString());
120 if (!blob || blob->empty() || blob->size() > maxLength)
121 return std::nullopt;
122
123 return blob;
124}
125
128 Json::Value const& params,
129 Json::StaticString const fieldName,
130 std::size_t maxLength,
131 std::string const& err)
132{
133 if (!params.isMember(fieldName) || params[fieldName].isNull())
134 {
135 return missingFieldError(fieldName);
136 }
137 if (auto blob = parseHexBlob(params[fieldName], maxLength))
138 {
139 return *blob;
140 }
141 return invalidFieldError(err, fieldName, "hex string");
142}
143
144template <>
146parse(Json::Value const& param)
147{
148 if (param.isUInt() || (param.isInt() && param.asInt() >= 0))
149 return param.asUInt();
150
151 if (param.isString())
152 {
153 std::uint32_t v = 0;
154 if (beast::lexicalCastChecked(v, param.asString()))
155 return v;
156 }
157
158 return std::nullopt;
159}
160
163 Json::Value const& params,
164 Json::StaticString const fieldName,
165 std::string const& err)
166{
167 return required<std::uint32_t>(params, fieldName, err, "number");
168}
169
170template <>
172parse(Json::Value const& param)
173{
174 uint256 uNodeIndex;
175 if (!param.isString() || !uNodeIndex.parseHex(param.asString()))
176 {
177 return std::nullopt;
178 }
179
180 return uNodeIndex;
181}
182
185 Json::Value const& params,
186 Json::StaticString const fieldName,
187 std::string const& err)
188{
189 return required<uint256>(params, fieldName, err, "Hash256");
190}
191
192template <>
194parse(Json::Value const& param)
195{
196 uint192 field;
197 if (!param.isString() || !field.parseHex(param.asString()))
198 {
199 return std::nullopt;
200 }
201
202 return field;
203}
204
207 Json::Value const& params,
208 Json::StaticString const fieldName,
209 std::string const& err)
210{
211 return required<uint192>(params, fieldName, err, "Hash192");
212}
213
214template <>
216parse(Json::Value const& param)
217{
218 try
219 {
220 return issueFromJson(param);
221 }
222 catch (std::runtime_error const&)
223 {
224 return std::nullopt;
225 }
226}
227
229requiredIssue(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
230{
231 return required<Issue>(params, fieldName, err, "Issue");
232}
233
236{
237 if (auto const value = hasRequired(
238 params,
239 {jss::LockingChainDoor,
240 jss::LockingChainIssue,
241 jss::IssuingChainDoor,
242 jss::IssuingChainIssue});
243 !value)
244 {
245 return Unexpected(value.error());
246 }
247
248 auto const lockingChainDoor =
249 requiredAccountID(params, jss::LockingChainDoor, "malformedLockingChainDoor");
250 if (!lockingChainDoor)
251 {
252 return Unexpected(lockingChainDoor.error());
253 }
254
255 auto const issuingChainDoor =
256 requiredAccountID(params, jss::IssuingChainDoor, "malformedIssuingChainDoor");
257 if (!issuingChainDoor)
258 {
259 return Unexpected(issuingChainDoor.error());
260 }
261
262 Issue lockingChainIssue;
263 try
264 {
265 lockingChainIssue = issueFromJson(params[jss::LockingChainIssue]);
266 }
267 catch (std::runtime_error const& ex)
268 {
269 return invalidFieldError("malformedIssue", jss::LockingChainIssue, "Issue");
270 }
271
272 Issue issuingChainIssue;
273 try
274 {
275 issuingChainIssue = issueFromJson(params[jss::IssuingChainIssue]);
276 }
277 catch (std::runtime_error const& ex)
278 {
279 return invalidFieldError("malformedIssue", jss::IssuingChainIssue, "Issue");
280 }
281
282 return STXChainBridge(
283 *lockingChainDoor, lockingChainIssue, *issuingChainDoor, issuingChainIssue);
284}
285
286} // namespace LedgerEntryHelpers
287
288} // namespace xrpl
Lightweight wrapper to tag static string.
Definition json_value.h:44
Represents a JSON value.
Definition json_value.h:130
Int asInt() const
bool isString() const
UInt asUInt() const
std::string asString() const
Returns the unquoted string value.
bool isUInt() const
bool isNull() const
isNull() tests to see if this field is null.
bool isMember(char const *key) const
Return true if the object has a member named key.
bool isInt() const
A currency issued by an account.
Definition Issue.h:13
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:476
T is_same_v
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:26
bool lexicalCastChecked(Out &out, In in)
Intelligently convert from one type to another.
Expected< std::uint32_t, Json::Value > requiredUInt32(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< AccountID, Json::Value > requiredAccountID(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > missingFieldError(Json::StaticString const field, std::optional< std::string > err=std::nullopt)
std::optional< Blob > parseHexBlob(Json::Value const &param, std::size_t maxLength)
Expected< uint192, Json::Value > requiredUInt192(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< T, Json::Value > required(Json::Value const &params, Json::StaticString const fieldName, std::string const &err, std::string const &expectedType)
Expected< bool, Json::Value > hasRequired(Json::Value const &params, std::initializer_list< Json::StaticString > fields, std::optional< std::string > err=std::nullopt)
Expected< Blob, Json::Value > requiredHexBlob(Json::Value const &params, Json::StaticString const fieldName, std::size_t maxLength, std::string const &err)
Expected< Issue, Json::Value > requiredIssue(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Expected< STXChainBridge, Json::Value > parseBridgeFields(Json::Value const &params)
Unexpected< Json::Value > malformedError(std::string const &err, std::string const &message)
std::optional< T > parse(Json::Value const &param)
Expected< uint256, Json::Value > requiredUInt256(Json::Value const &params, Json::StaticString const fieldName, std::string const &err)
Unexpected< Json::Value > invalidFieldError(std::string const &err, Json::StaticString const field, std::string const &type)
std::string expected_field_message(std::string const &name, std::string const &type)
Definition ErrorCodes.h:285
std::string missing_field_message(std::string const &name)
Definition ErrorCodes.h:225
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Issue issueFromJson(Json::Value const &v)
Definition Issue.cpp:88
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:64