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 auto error = RPC::missing_field_message(std::string(field.c_str()));
24 json[jss::error] = err.value_or("malformedRequest");
25 json[jss::error_code] = rpcINVALID_PARAMS;
26 json[jss::error_message] = std::move(error);
27 return Unexpected(json);
28}
29
31invalidFieldError(std::string const& err, Json::StaticString const field, std::string const& type)
32{
34 auto error = RPC::expected_field_message(field, type);
35 json[jss::error] = err;
36 json[jss::error_code] = rpcINVALID_PARAMS;
37 json[jss::error_message] = std::move(error);
38 return Unexpected(json);
39}
40
42malformedError(std::string const& err, std::string const& message)
43{
45 json[jss::error] = err;
46 json[jss::error_code] = rpcINVALID_PARAMS;
47 json[jss::error_message] = message;
48 return Unexpected(json);
49}
50
53 Json::Value const& params,
56{
57 for (auto const field : fields)
58 {
59 if (!params.isMember(field) || params[field].isNull())
60 {
61 return missingFieldError(field, err);
62 }
63 }
64 return true;
65}
66
67template <class T>
69parse(Json::Value const& param);
70
71template <class T>
74 Json::Value const& params,
75 Json::StaticString const fieldName,
76 std::string const& err,
77 std::string const& expectedType)
78{
79 if (!params.isMember(fieldName) || params[fieldName].isNull())
80 {
81 return missingFieldError(fieldName);
82 }
83 if (auto obj = parse<T>(params[fieldName]))
84 {
85 return *obj;
86 }
87 return invalidFieldError(err, fieldName, expectedType);
88}
89
90template <>
92parse(Json::Value const& param)
93{
94 if (!param.isString())
95 return std::nullopt;
96
97 auto const account = parseBase58<AccountID>(param.asString());
98 if (!account || account->isZero())
99 {
100 return std::nullopt;
101 }
102
103 return account;
104}
105
107requiredAccountID(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
108{
109 return required<AccountID>(params, fieldName, err, "AccountID");
110}
111
113parseHexBlob(Json::Value const& param, std::size_t maxLength)
114{
115 if (!param.isString())
116 return std::nullopt;
117
118 auto const blob = strUnHex(param.asString());
119 if (!blob || blob->empty() || blob->size() > maxLength)
120 return std::nullopt;
121
122 return blob;
123}
124
127 Json::Value const& params,
128 Json::StaticString const fieldName,
129 std::size_t maxLength,
130 std::string const& err)
131{
132 if (!params.isMember(fieldName) || params[fieldName].isNull())
133 {
134 return missingFieldError(fieldName);
135 }
136 if (auto blob = parseHexBlob(params[fieldName], maxLength))
137 {
138 return *blob;
139 }
140 return invalidFieldError(err, fieldName, "hex string");
141}
142
143template <>
145parse(Json::Value const& param)
146{
147 if (param.isUInt() || (param.isInt() && param.asInt() >= 0))
148 return param.asUInt();
149
150 if (param.isString())
151 {
153 if (beast::lexicalCastChecked(v, param.asString()))
154 return v;
155 }
156
157 return std::nullopt;
158}
159
161requiredUInt32(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
162{
163 return required<std::uint32_t>(params, fieldName, err, "number");
164}
165
166template <>
168parse(Json::Value const& param)
169{
170 uint256 uNodeIndex;
171 if (!param.isString() || !uNodeIndex.parseHex(param.asString()))
172 {
173 return std::nullopt;
174 }
175
176 return uNodeIndex;
177}
178
180requiredUInt256(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
181{
182 return required<uint256>(params, fieldName, err, "Hash256");
183}
184
185template <>
187parse(Json::Value const& param)
188{
189 uint192 field;
190 if (!param.isString() || !field.parseHex(param.asString()))
191 {
192 return std::nullopt;
193 }
194
195 return field;
196}
197
199requiredUInt192(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
200{
201 return required<uint192>(params, fieldName, err, "Hash192");
202}
203
204template <>
206parse(Json::Value const& param)
207{
208 try
209 {
210 return issueFromJson(param);
211 }
212 catch (std::runtime_error const&)
213 {
214 return std::nullopt;
215 }
216}
217
219requiredIssue(Json::Value const& params, Json::StaticString const fieldName, std::string const& err)
220{
221 return required<Issue>(params, fieldName, err, "Issue");
222}
223
226{
227 if (auto const value = hasRequired(
228 params, {jss::LockingChainDoor, jss::LockingChainIssue, jss::IssuingChainDoor, jss::IssuingChainIssue});
229 !value)
230 {
231 return Unexpected(value.error());
232 }
233
234 auto const lockingChainDoor = requiredAccountID(params, jss::LockingChainDoor, "malformedLockingChainDoor");
235 if (!lockingChainDoor)
236 {
237 return Unexpected(lockingChainDoor.error());
238 }
239
240 auto const issuingChainDoor = requiredAccountID(params, jss::IssuingChainDoor, "malformedIssuingChainDoor");
241 if (!issuingChainDoor)
242 {
243 return Unexpected(issuingChainDoor.error());
244 }
245
246 Issue lockingChainIssue;
247 try
248 {
249 lockingChainIssue = issueFromJson(params[jss::LockingChainIssue]);
250 }
251 catch (std::runtime_error const& ex)
252 {
253 return invalidFieldError("malformedIssue", jss::LockingChainIssue, "Issue");
254 }
255
256 Issue issuingChainIssue;
257 try
258 {
259 issuingChainIssue = issueFromJson(params[jss::IssuingChainIssue]);
260 }
261 catch (std::runtime_error const& ex)
262 {
263 return invalidFieldError("malformedIssue", jss::IssuingChainIssue, "Issue");
264 }
265
266 return STXChainBridge(*lockingChainDoor, lockingChainIssue, *issuingChainDoor, issuingChainIssue);
267}
268
269} // namespace LedgerEntryHelpers
270
271} // 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:471
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:280
std::string missing_field_message(std::string const &name)
Definition ErrorCodes.h:220
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:82
@ rpcINVALID_PARAMS
Definition ErrorCodes.h:64