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 ripple {
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 {
57 return inp.find(s) != std::string::npos;
58 };
59
60 if (contains("UINT"))
61 {
62 if (contains("512") || contains("384") || contains("256") ||
63 contains("192") || contains("160") || contains("128"))
64 return replace("UINT", "Hash");
65 else
66 return replace("UINT", "UInt");
67 }
68
70 {"OBJECT", "STObject"},
71 {"ARRAY", "STArray"},
72 {"ACCOUNT", "AccountID"},
73 {"LEDGERENTRY", "LedgerEntry"},
74 {"NOTPRESENT", "NotPresent"},
75 {"PATHSET", "PathSet"},
76 {"VL", "Blob"},
77 {"XCHAIN_BRIDGE", "XChainBridge"},
78 };
79
80 if (auto const& it = replacements.find(inp); it != replacements.end())
81 {
82 return it->second;
83 }
84
86 size_t pos = 0;
87 std::string inpToProcess = inp;
88
89 // convert snake_case to CamelCase
90 for (;;)
91 {
92 pos = inpToProcess.find("_");
93 if (pos == std::string::npos)
94 pos = inpToProcess.size();
95 std::string token = inpToProcess.substr(0, pos);
96 if (token.size() > 1)
97 {
98 boost::algorithm::to_lower(token);
99 token.data()[0] -= ('a' - 'A');
100 out += token;
101 }
102 else
103 out += token;
104 if (pos == inpToProcess.size())
105 break;
106 inpToProcess = inpToProcess.substr(pos + 1);
107 }
108 return out;
109};
110
112{
113 // populate SerializedTypeID names and values
114 defs_[jss::TYPES] = Json::objectValue;
115
116 defs_[jss::TYPES]["Done"] = -1;
117 std::map<int32_t, std::string> typeMap{{-1, "Done"}};
118 for (auto const& [rawName, typeValue] : sTypeMap)
119 {
120 std::string typeName =
121 translate(std::string(rawName).substr(4) /* remove STI_ */);
122 defs_[jss::TYPES][typeName] = typeValue;
123 typeMap[typeValue] = typeName;
124 }
125
126 // populate LedgerEntryType names and values
127 defs_[jss::LEDGER_ENTRY_TYPES] = Json::objectValue;
128 defs_[jss::LEDGER_ENTRY_TYPES][jss::Invalid] = -1;
129
130 for (auto const& f : LedgerFormats::getInstance())
131 {
132 defs_[jss::LEDGER_ENTRY_TYPES][f.getName()] = f.getType();
133 }
134
135 // populate SField serialization data
136 defs_[jss::FIELDS] = Json::arrayValue;
137
138 uint32_t i = 0;
139 {
141 a[0U] = "Generic";
143 v[jss::nth] = 0;
144 v[jss::isVLEncoded] = false;
145 v[jss::isSerialized] = false;
146 v[jss::isSigningField] = false;
147 v[jss::type] = "Unknown";
148 a[1U] = v;
149 defs_[jss::FIELDS][i++] = a;
150 }
151
152 {
154 a[0U] = "Invalid";
156 v[jss::nth] = -1;
157 v[jss::isVLEncoded] = false;
158 v[jss::isSerialized] = false;
159 v[jss::isSigningField] = false;
160 v[jss::type] = "Unknown";
161 a[1U] = v;
162 defs_[jss::FIELDS][i++] = a;
163 }
164
165 {
167 a[0U] = "ObjectEndMarker";
169 v[jss::nth] = 1;
170 v[jss::isVLEncoded] = false;
171 v[jss::isSerialized] = true;
172 v[jss::isSigningField] = true;
173 v[jss::type] = "STObject";
174 a[1U] = v;
175 defs_[jss::FIELDS][i++] = a;
176 }
177
178 {
180 a[0U] = "ArrayEndMarker";
182 v[jss::nth] = 1;
183 v[jss::isVLEncoded] = false;
184 v[jss::isSerialized] = true;
185 v[jss::isSigningField] = true;
186 v[jss::type] = "STArray";
187 a[1U] = v;
188 defs_[jss::FIELDS][i++] = a;
189 }
190
191 {
193 a[0U] = "taker_gets_funded";
195 v[jss::nth] = 258;
196 v[jss::isVLEncoded] = false;
197 v[jss::isSerialized] = false;
198 v[jss::isSigningField] = false;
199 v[jss::type] = "Amount";
200 a[1U] = v;
201 defs_[jss::FIELDS][i++] = a;
202 }
203
204 {
206 a[0U] = "taker_pays_funded";
208 v[jss::nth] = 259;
209 v[jss::isVLEncoded] = false;
210 v[jss::isSerialized] = false;
211 v[jss::isSigningField] = false;
212 v[jss::type] = "Amount";
213 a[1U] = v;
214 defs_[jss::FIELDS][i++] = a;
215 }
216
217 for (auto const& [code, f] : ripple::SField::getKnownCodeToField())
218 {
219 if (f->fieldName == "")
220 continue;
221
223
224 uint32_t type = f->fieldType;
225
226 innerObj[jss::nth] = f->fieldValue;
227
228 // whether the field is variable-length encoded
229 // this means that the length is included before the content
230 innerObj[jss::isVLEncoded] =
231 (type == 7U /* Blob */ || type == 8U /* AccountID */ ||
232 type == 19U /* Vector256 */);
233
234 // whether the field is included in serialization
235 innerObj[jss::isSerialized] =
236 (type < 10000 && f->fieldName != "hash" &&
237 f->fieldName != "index"); /* hash, index, TRANSACTION,
238 LEDGER_ENTRY, VALIDATION, METADATA */
239
240 // whether the field is included in serialization when signing
241 innerObj[jss::isSigningField] = f->shouldInclude(false);
242
243 innerObj[jss::type] = typeMap[type];
244
245 Json::Value innerArray = Json::arrayValue;
246 innerArray[0U] = f->fieldName;
247 innerArray[1U] = innerObj;
248
249 defs_[jss::FIELDS][i++] = innerArray;
250 }
251
252 // populate TER code names and values
253 defs_[jss::TRANSACTION_RESULTS] = Json::objectValue;
254
255 for (auto const& [code, terInfo] : transResults())
256 {
257 defs_[jss::TRANSACTION_RESULTS][terInfo.first] = code;
258 }
259
260 // populate TxType names and values
261 defs_[jss::TRANSACTION_TYPES] = Json::objectValue;
262 defs_[jss::TRANSACTION_TYPES][jss::Invalid] = -1;
263 for (auto const& f : TxFormats::getInstance())
264 {
265 defs_[jss::TRANSACTION_TYPES][f.getName()] = f.getType();
266 }
267
268 // generate hash
269 {
272 defs_[jss::hash] = to_string(defsHash_);
273 }
274}
275
276} // namespace detail
277
280{
281 auto& params = context.params;
282
283 uint256 hash;
284 if (params.isMember(jss::hash))
285 {
286 if (!params[jss::hash].isString() ||
287 !hash.parseHex(params[jss::hash].asString()))
288 return RPC::invalid_field_error(jss::hash);
289 }
290
291 static detail::ServerDefinitions const defs{};
292 if (defs.hashMatches(hash))
293 {
295 jv[jss::hash] = to_string(hash);
296 return jv;
297 }
298 return defs.get();
299}
300
301} // namespace ripple
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:287
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:79
static TxFormats const & getInstance()
Definition TxFormats.cpp:52
constexpr bool parseHex(std::string_view sv)
Parse a hex string into a base_uint.
Definition base_uint.h:484
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: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:306
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
static std::map< std::string, int > const sTypeMap
Definition SField.h:93
Json::Value doServerDefinitions(RPC::JsonContext &)
std::string to_string(base_uint< Bits, Tag > const &a)
Definition base_uint.h:611
std::unordered_map< TERUnderlyingType, std::pair< char const *const, char const *const > > const & transResults()
Definition TER.cpp:16
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:205
T size(T... args)
T substr(T... args)