rippled
Loading...
Searching...
No Matches
Serializer.cpp
1#include <xrpl/basics/Buffer.h>
2#include <xrpl/basics/Slice.h>
3#include <xrpl/basics/base_uint.h>
4#include <xrpl/basics/contract.h>
5#include <xrpl/basics/safe_cast.h>
6#include <xrpl/beast/utility/instrumentation.h>
7#include <xrpl/protocol/HashPrefix.h>
8#include <xrpl/protocol/Serializer.h>
9#include <xrpl/protocol/digest.h>
10
11#include <boost/endian/conversion.hpp>
12
13#include <array>
14#include <cstddef>
15#include <cstdint>
16#include <cstring>
17#include <stdexcept>
18#include <string>
19#include <type_traits>
20
21namespace xrpl {
22
23int
25{
26 int const ret = mData.size();
27 mData.push_back(static_cast<unsigned char>(i >> 8));
28 mData.push_back(static_cast<unsigned char>(i & 0xff));
29 return ret;
30}
31
32int
34{
35 // This should never trigger; the size & type of a hash prefix are
36 // integral parts of the protocol and unlikely to ever change.
37 static_assert(std::is_same_v<std::uint32_t, std::underlying_type_t<decltype(p)>>);
38
39 return add32(safe_cast<std::uint32_t>(p));
40}
41
42template <>
43int
44Serializer::addInteger(unsigned char i)
45{
46 return add8(i);
47}
48template <>
49int
54template <>
55int
60template <>
61int
66template <>
67int
69{
70 return add32(i);
71}
72
73int
75{
76 int const ret = mData.size();
77 mData.insert(mData.end(), vector.begin(), vector.end());
78 return ret;
79}
80
81int
83{
84 int const ret = mData.size();
86 return ret;
87}
88
89int
91{
92 int const ret = mData.size();
93 mData.insert(mData.end(), s.begin(), s.end());
94 return ret;
95}
96
97int
98Serializer::addRaw(void const* ptr, int len)
99{
100 int const ret = mData.size();
101 mData.insert(mData.end(), (char const*)ptr, ((char const*)ptr) + len);
102 return ret;
103}
104
105int
106Serializer::addFieldID(int type, int name)
107{
108 int const ret = mData.size();
109 XRPL_ASSERT(
110 (type > 0) && (type < 256) && (name > 0) && (name < 256),
111 "xrpl::Serializer::addFieldID : inputs inside range");
112
113 if (type < 16)
114 {
115 if (name < 16)
116 { // common type, common name
117 mData.push_back(static_cast<unsigned char>((type << 4) | name));
118 }
119 else
120 {
121 // common type, uncommon name
122 mData.push_back(static_cast<unsigned char>(type << 4));
123 mData.push_back(static_cast<unsigned char>(name));
124 }
125 }
126 else if (name < 16)
127 {
128 // uncommon type, common name
129 mData.push_back(static_cast<unsigned char>(name));
130 mData.push_back(static_cast<unsigned char>(type));
131 }
132 else
133 {
134 // uncommon type, uncommon name
135 mData.push_back(static_cast<unsigned char>(0));
136 mData.push_back(static_cast<unsigned char>(type));
137 mData.push_back(static_cast<unsigned char>(name));
138 }
139
140 return ret;
141}
142
143int
144Serializer::add8(unsigned char byte)
145{
146 int const ret = mData.size();
147 mData.push_back(byte);
148 return ret;
149}
150
151bool
152Serializer::get8(int& byte, int offset) const
153{
154 if (offset >= mData.size())
155 return false;
156
157 byte = mData[offset];
158 return true;
159}
160
161bool
163{
164 if (bytes > mData.size())
165 return false;
166
167 mData.resize(mData.size() - bytes);
168 return true;
169}
170
173{
174 return sha512Half(makeSlice(mData));
175}
176
177int
179{
180 int const ret = addEncoded(vector.size());
181 addRaw(vector);
182 XRPL_ASSERT(
183 mData.size() == (ret + vector.size() + encodeLengthLength(vector.size())),
184 "xrpl::Serializer::addVL : size matches expected");
185 return ret;
186}
187
188int
190{
191 int const ret = addEncoded(slice.size());
192 if (!slice.empty())
193 addRaw(slice.data(), slice.size());
194 return ret;
195}
196
197int
198Serializer::addVL(void const* ptr, int len)
199{
200 int const ret = addEncoded(len);
201
202 if (len != 0)
203 addRaw(ptr, len);
204
205 return ret;
206}
207
208int
210{
212 int numBytes = 0;
213
214 if (length <= 192)
215 {
216 bytes[0] = static_cast<unsigned char>(length);
217 numBytes = 1;
218 }
219 else if (length <= 12480)
220 {
221 length -= 193;
222 bytes[0] = 193 + static_cast<unsigned char>(length >> 8);
223 bytes[1] = static_cast<unsigned char>(length & 0xff);
224 numBytes = 2;
225 }
226 else if (length <= 918744)
227 {
228 length -= 12481;
229 bytes[0] = 241 + static_cast<unsigned char>(length >> 16);
230 bytes[1] = static_cast<unsigned char>((length >> 8) & 0xff);
231 bytes[2] = static_cast<unsigned char>(length & 0xff);
232 numBytes = 3;
233 }
234 else
235 {
236 Throw<std::overflow_error>("lenlen");
237 }
238
239 return addRaw(&bytes[0], numBytes);
240}
241
242int
244{
245 if (length < 0)
246 Throw<std::overflow_error>("len<0");
247
248 if (length <= 192)
249 return 1;
250
251 if (length <= 12480)
252 return 2;
253
254 if (length <= 918744)
255 return 3;
256
257 Throw<std::overflow_error>("len>918744");
258 return 0; // Silence compiler warning.
259}
260
261int
263{
264 if (b1 < 0)
265 Throw<std::overflow_error>("b1<0");
266
267 if (b1 <= 192)
268 return 1;
269
270 if (b1 <= 240)
271 return 2;
272
273 if (b1 <= 254)
274 return 3;
275
276 Throw<std::overflow_error>("b1>254");
277 return 0; // Silence compiler warning.
278}
279
280int
282{
283 if (b1 < 0)
284 Throw<std::overflow_error>("b1<0");
285
286 if (b1 > 254)
287 Throw<std::overflow_error>("b1>254");
288
289 return b1;
290}
291
292int
294{
295 if (b1 < 193)
296 Throw<std::overflow_error>("b1<193");
297
298 if (b1 > 240)
299 Throw<std::overflow_error>("b1>240");
300
301 return 193 + ((b1 - 193) * 256) + b2;
302}
303
304int
305Serializer::decodeVLLength(int b1, int b2, int b3)
306{
307 if (b1 < 241)
308 Throw<std::overflow_error>("b1<241");
309
310 if (b1 > 254)
311 Throw<std::overflow_error>("b1>254");
312
313 return 12481 + ((b1 - 241) * 65536) + (b2 * 256) + b3;
314}
315
316//------------------------------------------------------------------------------
317
318SerialIter::SerialIter(void const* data, std::size_t size) noexcept
319 : p_(reinterpret_cast<std::uint8_t const*>(data)), remain_(size)
320{
321}
322
323void
325{
326 p_ -= used_;
327 remain_ += used_;
328 used_ = 0;
329}
330
331void
333{
334 if (remain_ < length)
335 Throw<std::runtime_error>("invalid SerialIter skip");
336 p_ += length;
337 used_ += length;
338 remain_ -= length;
339}
340
341unsigned char
343{
344 if (remain_ < 1)
345 Throw<std::runtime_error>("invalid SerialIter get8");
346 unsigned char const t = *p_;
347 ++p_;
348 ++used_;
349 --remain_;
350 return t;
351}
352
355{
356 if (remain_ < 2)
357 Throw<std::runtime_error>("invalid SerialIter get16");
358 auto t = p_;
359 p_ += 2;
360 used_ += 2;
361 remain_ -= 2;
362 return (std::uint64_t(t[0]) << 8) + std::uint64_t(t[1]);
363}
364
367{
368 if (remain_ < 4)
369 Throw<std::runtime_error>("invalid SerialIter get32");
370 auto t = p_;
371 p_ += 4;
372 used_ += 4;
373 remain_ -= 4;
374 return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + (std::uint64_t(t[2]) << 8) +
375 std::uint64_t(t[3]);
376}
377
380{
381 if (remain_ < 8)
382 Throw<std::runtime_error>("invalid SerialIter get64");
383 auto t = p_;
384 p_ += 8;
385 used_ += 8;
386 remain_ -= 8;
387 return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + (std::uint64_t(t[2]) << 40) +
388 (std::uint64_t(t[3]) << 32) + (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) +
389 (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]);
390}
391
394{
395 if (remain_ < 4)
396 Throw<std::runtime_error>("invalid SerialIter geti32");
397 auto t = p_;
398 p_ += 4;
399 used_ += 4;
400 remain_ -= 4;
401 return boost::endian::load_big_s32(t);
402}
403
406{
407 if (remain_ < 8)
408 Throw<std::runtime_error>("invalid SerialIter geti64");
409 auto t = p_;
410 p_ += 8;
411 used_ += 8;
412 remain_ -= 8;
413 return boost::endian::load_big_s64(t);
414}
415
416void
417SerialIter::getFieldID(int& type, int& name)
418{
419 type = get8();
420 name = type & 15;
421 type >>= 4;
422
423 if (type == 0)
424 {
425 // uncommon type
426 type = get8();
427 if (type < 16)
428 Throw<std::runtime_error>("gFID: uncommon type out of range " + std::to_string(type));
429 }
430
431 if (name == 0)
432 {
433 // uncommon name
434 name = get8();
435 if (name < 16)
436 Throw<std::runtime_error>("gFID: uncommon name out of range " + std::to_string(name));
437 }
438}
439
440// getRaw for blob or buffer
441template <class T>
442T
444{
446 if (remain_ < size)
447 Throw<std::runtime_error>("invalid SerialIter getRaw");
448 T result(size);
449 if (size != 0)
450 {
451 // It's normally safe to call memcpy with size set to 0 (see the
452 // C99 standard 7.21.1/2). However, here this could mean that
453 // result.data would be null, which would trigger undefined behavior.
454 std::memcpy(result.data(), p_, size);
455 p_ += size;
456 used_ += size;
457 remain_ -= size;
458 }
459 return result;
460}
461
462// VFALCO DEPRECATED Returns a copy
463Blob
465{
466 return getRawHelper<Blob>(size);
467}
468
469int
471{
472 int const b1 = get8();
473 int datLen = 0;
474 int const lenLen = Serializer::decodeLengthLength(b1);
475 if (lenLen == 1)
476 {
477 datLen = Serializer::decodeVLLength(b1);
478 }
479 else if (lenLen == 2)
480 {
481 int const b2 = get8();
482 datLen = Serializer::decodeVLLength(b1, b2);
483 }
484 else
485 {
486 XRPL_ASSERT(lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3");
487 int const b2 = get8();
488 int const b3 = get8();
489 datLen = Serializer::decodeVLLength(b1, b2, b3);
490 }
491 return datLen;
492}
493
494Slice
496{
497 if (bytes > remain_)
498 Throw<std::runtime_error>("invalid SerialIter getSlice");
499 Slice const s(p_, bytes);
500 p_ += bytes;
501 used_ += bytes;
502 remain_ -= bytes;
503 return s;
504}
505
506// VFALCO DEPRECATED Returns a copy
507Blob
509{
510 return getRaw(getVLDataLength());
511}
512
513Buffer
515{
516 return getRawHelper<Buffer>(getVLDataLength());
517}
518
519} // namespace xrpl
T begin(T... args)
Like std::vector<char> but better.
Definition Buffer.h:16
Blob getRaw(int size)
std::uint16_t get16()
void reset() noexcept
Slice getSlice(std::size_t bytes)
T getRawHelper(int size)
void getFieldID(int &type, int &name)
void skip(int num)
std::size_t remain_
Definition Serializer.h:322
SerialIter(void const *data, std::size_t size) noexcept
std::uint64_t get64()
std::int32_t geti32()
std::int64_t geti64()
unsigned char get8()
std::uint8_t const * p_
Definition Serializer.h:321
std::uint32_t get32()
std::size_t used_
Definition Serializer.h:323
int addFieldID(int type, int name)
static int decodeVLLength(int b1)
int addInteger(Integer)
Blob::iterator begin()
Definition Serializer.h:226
int add16(std::uint16_t i)
uint256 getSHA512Half() const
int addVL(Blob const &vector)
Blob::iterator end()
Definition Serializer.h:231
static int decodeLengthLength(int b1)
bool chop(int num)
int addEncoded(int length)
int addRaw(Blob const &vector)
Slice slice() const noexcept
Definition Serializer.h:44
int add8(unsigned char i)
bool get8(int &, int offset) const
static int encodeLengthLength(int length)
An immutable linear range of bytes.
Definition Slice.h:26
const_iterator begin() const noexcept
Definition Slice.h:127
bool empty() const noexcept
Return true if the byte range is empty.
Definition Slice.h:50
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Slice.h:78
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition Slice.h:61
const_iterator end() const noexcept
Definition Slice.h:139
T end(T... args)
T insert(T... args)
T is_same_v
T memcpy(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:204
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:34
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:215
T push_back(T... args)
T resize(T... args)
T size(T... args)
T to_string(T... args)