rippled
Loading...
Searching...
No Matches
ServerDefinitions.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2023 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/Context.h>
21#include <xrpld/rpc/Role.h>
22
23#include <xrpl/json/json_value.h>
24#include <xrpl/json/json_writer.h>
25#include <xrpl/protocol/LedgerFormats.h>
26#include <xrpl/protocol/SField.h>
27#include <xrpl/protocol/TER.h>
28#include <xrpl/protocol/TxFormats.h>
29#include <xrpl/protocol/digest.h>
30#include <xrpl/protocol/jss.h>
31
32#include <boost/algorithm/string.hpp>
33
34#include <unordered_map>
35
36namespace ripple {
37
38namespace detail {
39
41{
42private:
44 // translate e.g. STI_LEDGERENTRY to LedgerEntry
45 translate(std::string const& inp);
46
49
50public:
52
53 bool
54 hashMatches(uint256 hash) const
55 {
56 return defsHash_ == hash;
57 }
58
59 Json::Value const&
60 get() const
61 {
62 return defs_;
63 }
64};
65
68{
69 auto replace = [&](char const* oldStr, char const* newStr) -> std::string {
70 std::string out = inp;
71 boost::replace_all(out, oldStr, newStr);
72 return out;
73 };
74
75 auto contains = [&](char const* s) -> bool {
76 return inp.find(s) != std::string::npos;
77 };
78
79 if (contains("UINT"))
80 {
81 if (contains("512") || contains("384") || contains("256") ||
82 contains("192") || contains("160") || contains("128"))
83 return replace("UINT", "Hash");
84 else
85 return replace("UINT", "UInt");
86 }
87
89 {"OBJECT", "STObject"},
90 {"ARRAY", "STArray"},
91 {"ACCOUNT", "AccountID"},
92 {"LEDGERENTRY", "LedgerEntry"},
93 {"NOTPRESENT", "NotPresent"},
94 {"PATHSET", "PathSet"},
95 {"VL", "Blob"},
96 {"XCHAIN_BRIDGE", "XChainBridge"},
97 };
98
99 if (auto const& it = replacements.find(inp); it != replacements.end())
100 {
101 return it->second;
102 }
103
105 size_t pos = 0;
106 std::string inpToProcess = inp;
107
108 // convert snake_case to CamelCase
109 for (;;)
110 {
111 pos = inpToProcess.find("_");
112 if (pos == std::string::npos)
113 pos = inpToProcess.size();
114 std::string token = inpToProcess.substr(0, pos);
115 if (token.size() > 1)
116 {
117 boost::algorithm::to_lower(token);
118 token.data()[0] -= ('a' - 'A');
119 out += token;
120 }
121 else
122 out += token;
123 if (pos == inpToProcess.size())
124 break;
125 inpToProcess = inpToProcess.substr(pos + 1);
126 }
127 return out;
128};
129
131{
132 // populate SerializedTypeID names and values
133 defs_[jss::TYPES] = Json::objectValue;
134
135 defs_[jss::TYPES]["Done"] = -1;
136 std::map<int32_t, std::string> typeMap{{-1, "Done"}};
137 for (auto const& [rawName, typeValue] : sTypeMap)
138 {
139 std::string typeName =
140 translate(std::string(rawName).substr(4) /* remove STI_ */);
141 defs_[jss::TYPES][typeName] = typeValue;
142 typeMap[typeValue] = typeName;
143 }
144
145 // populate LedgerEntryType names and values
146 defs_[jss::LEDGER_ENTRY_TYPES] = Json::objectValue;
147 defs_[jss::LEDGER_ENTRY_TYPES][jss::Invalid] = -1;
148
149 for (auto const& f : LedgerFormats::getInstance())
150 {
151 defs_[jss::LEDGER_ENTRY_TYPES][f.getName()] = f.getType();
152 }
153
154 // populate SField serialization data
155 defs_[jss::FIELDS] = Json::arrayValue;
156
157 uint32_t i = 0;
158 {
160 a[0U] = "Generic";
162 v[jss::nth] = 0;
163 v[jss::isVLEncoded] = false;
164 v[jss::isSerialized] = false;
165 v[jss::isSigningField] = false;
166 v[jss::type] = "Unknown";
167 a[1U] = v;
168 defs_[jss::FIELDS][i++] = a;
169 }
170
171 {
173 a[0U] = "Invalid";
175 v[jss::nth] = -1;
176 v[jss::isVLEncoded] = false;
177 v[jss::isSerialized] = false;
178 v[jss::isSigningField] = false;
179 v[jss::type] = "Unknown";
180 a[1U] = v;
181 defs_[jss::FIELDS][i++] = a;
182 }
183
184 {
186 a[0U] = "ObjectEndMarker";
188 v[jss::nth] = 1;
189 v[jss::isVLEncoded] = false;
190 v[jss::isSerialized] = true;
191 v[jss::isSigningField] = true;
192 v[jss::type] = "STObject";
193 a[1U] = v;
194 defs_[jss::FIELDS][i++] = a;
195 }
196
197 {
199 a[0U] = "ArrayEndMarker";
201 v[jss::nth] = 1;
202 v[jss::isVLEncoded] = false;
203 v[jss::isSerialized] = true;
204 v[jss::isSigningField] = true;
205 v[jss::type] = "STArray";
206 a[1U] = v;
207 defs_[jss::FIELDS][i++] = a;
208 }
209
210 {
212 a[0U] = "taker_gets_funded";
214 v[jss::nth] = 258;
215 v[jss::isVLEncoded] = false;
216 v[jss::isSerialized] = false;
217 v[jss::isSigningField] = false;
218 v[jss::type] = "Amount";
219 a[1U] = v;
220 defs_[jss::FIELDS][i++] = a;
221 }
222
223 {
225 a[0U] = "taker_pays_funded";
227 v[jss::nth] = 259;
228 v[jss::isVLEncoded] = false;
229 v[jss::isSerialized] = false;
230 v[jss::isSigningField] = false;
231 v[jss::type] = "Amount";
232 a[1U] = v;
233 defs_[jss::FIELDS][i++] = a;
234 }
235
236 for (auto const& [code, f] : ripple::SField::getKnownCodeToField())
237 {
238 if (f->fieldName == "")
239 continue;
240
242
243 uint32_t type = f->fieldType;
244
245 innerObj[jss::nth] = f->fieldValue;
246
247 // whether the field is variable-length encoded
248 // this means that the length is included before the content
249 innerObj[jss::isVLEncoded] =
250 (type == 7U /* Blob */ || type == 8U /* AccountID */ ||
251 type == 19U /* Vector256 */);
252
253 // whether the field is included in serialization
254 innerObj[jss::isSerialized] =
255 (type < 10000 && f->fieldName != "hash" &&
256 f->fieldName != "index"); /* hash, index, TRANSACTION,
257 LEDGER_ENTRY, VALIDATION, METADATA */
258
259 // whether the field is included in serialization when signing
260 innerObj[jss::isSigningField] = f->shouldInclude(false);
261
262 innerObj[jss::type] = typeMap[type];
263
264 Json::Value innerArray = Json::arrayValue;
265 innerArray[0U] = f->fieldName;
266 innerArray[1U] = innerObj;
267
268 defs_[jss::FIELDS][i++] = innerArray;
269 }
270
271 // populate TER code names and values
272 defs_[jss::TRANSACTION_RESULTS] = Json::objectValue;
273
274 for (auto const& [code, terInfo] : transResults())
275 {
276 defs_[jss::TRANSACTION_RESULTS][terInfo.first] = code;
277 }
278
279 // populate TxType names and values
280 defs_[jss::TRANSACTION_TYPES] = Json::objectValue;
281 defs_[jss::TRANSACTION_TYPES][jss::Invalid] = -1;
282 for (auto const& f : TxFormats::getInstance())
283 {
284 defs_[jss::TRANSACTION_TYPES][f.getName()] = f.getType();
285 }
286
287 // generate hash
288 {
291 defs_[jss::hash] = to_string(defsHash_);
292 }
293}
294
295} // namespace detail
296
299{
300 auto& params = context.params;
301
302 uint256 hash;
303 if (params.isMember(jss::hash))
304 {
305 if (!params[jss::hash].isString() ||
306 !hash.parseHex(params[jss::hash].asString()))
307 return RPC::invalid_field_error(jss::hash);
308 }
309
310 static detail::ServerDefinitions const defs{};
311 if (defs.hashMatches(hash))
312 {
314 jv[jss::hash] = to_string(hash);
315 return jv;
316 }
317 return defs.get();
318}
319
320} // namespace ripple
Outputs a Value in JSON format without formatting (not human friendly).
Definition json_writer.h:54
std::string write(Value const &root) override
Represents a JSON value.
Definition json_value.h:149
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
static LedgerFormats const & getInstance()
static std::unordered_map< int, SField const * > const & getKnownCodeToField()
Definition SField.h:306
An immutable linear range of bytes.
Definition Slice.h:46
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Slice.h:98
static TxFormats const & getInstance()
Definition TxFormats.cpp:71
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:503
std::string translate(std::string const &inp)
bool hashMatches(uint256 hash) const
Json::Value const & get() const
T data(T... args)
T find(T... args)
JSON (JavaScript Object Notation).
Definition json_errors.h:25
@ arrayValue
array value (ordered list)
Definition json_value.h:44
@ objectValue
object value (collection of name/value pairs).
Definition json_value.h:45
Json::Value invalid_field_error(std::string const &name)
Definition ErrorCodes.h:325
static std::string to_string(TableType type)
to_string Returns the name of a table according to its TableType.
Definition Node.cpp:47
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
static std::map< std::string, int > const sTypeMap
Definition SField.h:112
Json::Value doServerDefinitions(RPC::JsonContext &)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:630
std::unordered_map< TERUnderlyingType, std::pair< char const *const, char const *const > > const & transResults()
Definition TER.cpp:35
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:224
T size(T... args)
T substr(T... args)