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