xrpld
Loading...
Searching...
No Matches
libxrpl/protocol/Serializer.cpp
1#include <xrpl/protocol/Serializer.h>
2
3#include <xrpl/basics/Buffer.h>
4#include <xrpl/basics/Slice.h>
5#include <xrpl/basics/base_uint.h>
6#include <xrpl/basics/contract.h>
7#include <xrpl/basics/safe_cast.h>
8#include <xrpl/beast/utility/instrumentation.h>
9#include <xrpl/protocol/HashPrefix.h>
10#include <xrpl/protocol/digest.h>
11
12#include <boost/endian/conversion.hpp>
13
14#include <array>
15#include <cstddef>
16#include <cstdint>
17#include <cstring>
18#include <format>
19#include <stdexcept>
20#include <type_traits>
21
22namespace xrpl {
23
24int
26{
27 int const ret = data_.size();
28 data_.push_back(static_cast<unsigned char>(i >> 8));
29 data_.push_back(static_cast<unsigned char>(i & 0xff));
30 return ret;
31}
32
33int
35{
36 // This should never trigger; the size & type of a hash prefix are
37 // integral parts of the protocol and unlikely to ever change.
38 static_assert(std::is_same_v<std::uint32_t, std::underlying_type_t<decltype(p)>>);
39
41}
42
43template <>
44int
45Serializer::addInteger(unsigned char i)
46{
47 return add8(i);
48}
49template <>
50int
55template <>
56int
61template <>
62int
67template <>
68int
70{
71 return add32(i);
72}
73
74int
76{
77 int const ret = data_.size();
78 data_.insert(data_.end(), vector.begin(), vector.end());
79 return ret;
80}
81
82int
84{
85 int const ret = data_.size();
86 data_.insert(data_.end(), slice.begin(), slice.end());
87 return ret;
88}
89
90int
92{
93 int const ret = data_.size();
94 data_.insert(data_.end(), s.begin(), s.end());
95 return ret;
96}
97
98int
99Serializer::addRaw(void const* ptr, int len)
100{
101 int const ret = data_.size();
102 data_.insert(data_.end(), static_cast<char const*>(ptr), static_cast<char const*>(ptr) + len);
103 return ret;
104}
105
106int
107Serializer::addFieldID(int type, int name)
108{
109 int const ret = data_.size();
110 XRPL_ASSERT(
111 (type > 0) && (type < 256) && (name > 0) && (name < 256),
112 "xrpl::Serializer::addFieldID : inputs inside range");
113
114 if (type < 16)
115 {
116 if (name < 16)
117 {
118 // common type, common name
119 data_.push_back(static_cast<unsigned char>((type << 4) | name));
120 }
121 else
122 {
123 // common type, uncommon name
124 data_.push_back(static_cast<unsigned char>(type << 4));
125 data_.push_back(static_cast<unsigned char>(name));
126 }
127 }
128 else if (name < 16)
129 {
130 // uncommon type, common name
131 data_.push_back(static_cast<unsigned char>(name));
132 data_.push_back(static_cast<unsigned char>(type));
133 }
134 else
135 {
136 // uncommon type, uncommon name
137 data_.push_back(static_cast<unsigned char>(0));
138 data_.push_back(static_cast<unsigned char>(type));
139 data_.push_back(static_cast<unsigned char>(name));
140 }
141
142 return ret;
143}
144
145int
146Serializer::add8(unsigned char byteValue)
147{
148 int const ret = data_.size();
149 data_.push_back(byteValue);
150 return ret;
151}
152
153bool
154Serializer::get8(int& byte, int offset) const
155{
156 if (offset >= data_.size())
157 return false;
158
159 byte = data_[offset];
160 return true;
161}
162
163bool
165{
166 if (bytes > data_.size())
167 return false;
168
169 data_.resize(data_.size() - bytes);
170 return true;
171}
172
175{
176 return sha512Half(makeSlice(data_));
177}
178
179int
181{
182 int const ret = addEncoded(vector.size());
183 addRaw(vector);
184 XRPL_ASSERT(
185 data_.size() == (ret + vector.size() + encodeLengthLength(vector.size())),
186 "xrpl::Serializer::addVL : size matches expected");
187 return ret;
188}
189
190int
192{
193 int const ret = addEncoded(slice.size());
194 if (!slice.empty())
195 addRaw(slice.data(), slice.size());
196 return ret;
197}
198
199int
200Serializer::addVL(void const* ptr, int len)
201{
202 int const ret = addEncoded(len);
203
204 if (len != 0)
205 addRaw(ptr, len);
206
207 return ret;
208}
209
210int
212{
213 // Without this, a negative length would fall into the 1 byte case below and
214 // be cast to a first byte no header uses. A size too big for int arrives
215 // here negative as well, since callers pass sizes through this parameter.
217 Throw<std::overflow_error>("addEncoded: length is negative or did not fit in an int");
218
220 int numBytes = 0;
221
223 {
224 bytes[0] = static_cast<std::byte>(length);
225 numBytes = 1;
226 }
227 else if (length <= kMaxValueOfLengthFor2ByteHeader)
228 {
229 // Count from the smallest length a 2 byte header covers.
230 int const offset = length - kMinValueOfLengthFor2ByteHeader;
231 bytes[0] = static_cast<std::byte>(
233 bytes[1] = static_cast<std::byte>(offset % kNumberOfValuesInOneByte);
234 numBytes = 2;
235 }
236 else if (length <= kMaxValueOfLengthFor3ByteHeader)
237 {
238 int const offset = length - kMinValueOfLengthFor3ByteHeader;
239 bytes[0] = static_cast<std::byte>(
241 bytes[1] =
243 bytes[2] = static_cast<std::byte>(offset % kNumberOfValuesInOneByte);
244 numBytes = 3;
245 }
246 else
247 {
248 Throw<std::overflow_error>("addEncoded: length is too large to encode");
249 }
250
251 return addRaw(bytes.data(), numBytes);
252}
253
254int
256{
258 {
260 "encodeLengthLength: length is negative or did not fit in an int");
261 }
262
264 return 1;
265
267 return 2;
268
270 return 3;
271
272 Throw<std::overflow_error>("encodeLengthLength: length is too large to encode");
273}
274
275int
277{
278 int const firstByteValue = std::to_integer<int>(firstByte);
279
280 if (firstByteValue <= kMaxValueOfFirstByteFor1ByteHeader)
281 return 1;
282
283 if (firstByteValue <= kMaxValueOfFirstByteFor2ByteHeader)
284 return 2;
285
286 if (firstByteValue <= kMaxValueOfFirstByteFor3ByteHeader)
287 return 3;
288
289 Throw<std::overflow_error>("decodeLengthLength: first byte does not start any header");
290}
291
292int
294{
295 int const length = std::to_integer<int>(firstByte);
296
297 // A bigger value means a longer header, so it is not a length by itself.
299 Throw<std::overflow_error>("decodeVLLength 1 byte: first byte is not a length");
300
301 return length;
302}
303
304int
306{
307 int const firstByteValue = std::to_integer<int>(firstByte);
308
309 if (firstByteValue < kMinValueOfFirstByteFor2ByteHeader)
310 Throw<std::overflow_error>("decodeVLLength 2 byte: first byte is below the range");
311
312 if (firstByteValue > kMaxValueOfFirstByteFor2ByteHeader)
313 Throw<std::overflow_error>("decodeVLLength 2 byte: first byte is above the range");
314
315 // Both bytes are bounded by their own type, and the first one is bounded to
316 // the 2 byte range above, so this cannot leave the range the header covers.
319 std::to_integer<int>(secondByte);
320}
321
322int
324{
325 int const firstByteValue = std::to_integer<int>(firstByte);
326
327 if (firstByteValue < kMinValueOfFirstByteFor3ByteHeader)
328 Throw<std::overflow_error>("decodeVLLength 3 byte: first byte is below the range");
329
330 if (firstByteValue > kMaxValueOfFirstByteFor3ByteHeader)
331 Throw<std::overflow_error>("decodeVLLength 3 byte: first byte is above the range");
332
333 int const length = kMinValueOfLengthFor3ByteHeader +
335 (std::to_integer<int>(secondByte) * kNumberOfValuesInOneByte) +
336 std::to_integer<int>(thirdByte);
337
338 // A 3 byte header reaches further than kMaxValueOfLengthFor3ByteHeader, which
339 // is as far as the encoder goes. Refuse the rest, so every length accepted
340 // here is one that can be written back.
342 Throw<std::overflow_error>("decodeVLLength 3 byte: length is too large to re-encode");
343
344 return length;
345}
346
347//------------------------------------------------------------------------------
348
349SerialIter::SerialIter(void const* data, std::size_t size) noexcept
350 : p_(reinterpret_cast<std::uint8_t const*>(data)), remain_(size)
351{
352}
353
354void
356{
357 p_ -= used_;
358 remain_ += used_;
359 used_ = 0;
360}
361
362void
364{
365 if (remain_ < length)
366 Throw<std::runtime_error>("invalid SerialIter skip");
367 p_ += length;
368 used_ += length;
369 remain_ -= length;
370}
371
372unsigned char
374{
375 if (remain_ < 1)
376 Throw<std::runtime_error>("invalid SerialIter get8");
377 unsigned char const t = *p_;
378 ++p_;
379 ++used_;
380 --remain_;
381 return t;
382}
383
386{
387 if (remain_ < 2)
388 Throw<std::runtime_error>("invalid SerialIter get16");
389 auto t = p_;
390 p_ += 2;
391 used_ += 2;
392 remain_ -= 2;
393 return (std::uint64_t(t[0]) << 8) + std::uint64_t(t[1]);
394}
395
398{
399 if (remain_ < 4)
400 Throw<std::runtime_error>("invalid SerialIter get32");
401 auto t = p_;
402 p_ += 4;
403 used_ += 4;
404 remain_ -= 4;
405 return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + (std::uint64_t(t[2]) << 8) +
406 std::uint64_t(t[3]);
407}
408
411{
412 if (remain_ < 8)
413 Throw<std::runtime_error>("invalid SerialIter get64");
414 auto t = p_;
415 p_ += 8;
416 used_ += 8;
417 remain_ -= 8;
418 return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + (std::uint64_t(t[2]) << 40) +
419 (std::uint64_t(t[3]) << 32) + (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) +
420 (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]);
421}
422
425{
426 if (remain_ < 4)
427 Throw<std::runtime_error>("invalid SerialIter geti32");
428 auto t = p_;
429 p_ += 4;
430 used_ += 4;
431 remain_ -= 4;
432 return boost::endian::load_big_s32(t);
433}
434
437{
438 if (remain_ < 8)
439 Throw<std::runtime_error>("invalid SerialIter geti64");
440 auto t = p_;
441 p_ += 8;
442 used_ += 8;
443 remain_ -= 8;
444 return boost::endian::load_big_s64(t);
445}
446
447void
448SerialIter::getFieldID(int& type, int& name)
449{
450 type = get8();
451 name = type & 15;
452 type >>= 4;
453
454 if (type == 0)
455 {
456 // uncommon type
457 type = get8();
458 if (type < 16)
459 Throw<std::runtime_error>(std::format("gFID: uncommon type out of range {}", type));
460 }
461
462 if (name == 0)
463 {
464 // uncommon name
465 name = get8();
466 if (name < 16)
467 Throw<std::runtime_error>(std::format("gFID: uncommon name out of range {}", name));
468 }
469}
470
471// getRaw for blob or buffer
472template <class T>
473T
475{
477 if (remain_ < size)
478 Throw<std::runtime_error>("invalid SerialIter getRaw");
479 T result(size);
480 if (size != 0)
481 {
482 // It's normally safe to call memcpy with size set to 0 (see the
483 // C99 standard 7.21.1/2). However, here this could mean that
484 // result.data would be null, which would trigger undefined behavior.
485 std::memcpy(result.data(), p_, size);
486 p_ += size;
487 used_ += size;
488 remain_ -= size;
489 }
490 return result;
491}
492
493// VFALCO DEPRECATED Returns a copy
494Blob
496{
497 return getRawHelper<Blob>(size);
498}
499
500int
502{
503 std::byte const firstByte{get8()};
504 int datLen = 0;
505 int const lenLen = Serializer::decodeLengthLength(firstByte);
506 if (lenLen == 1)
507 {
508 datLen = Serializer::decodeVLLength(firstByte);
509 }
510 else if (lenLen == 2)
511 {
512 std::byte const secondByte{get8()};
513 datLen = Serializer::decodeVLLength(firstByte, secondByte);
514 }
515 else
516 {
517 XRPL_ASSERT(lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3");
518 std::byte const secondByte{get8()};
519 std::byte const thirdByte{get8()};
520 datLen = Serializer::decodeVLLength(firstByte, secondByte, thirdByte);
521 }
522 return datLen;
523}
524
525Slice
527{
528 if (bytes > remain_)
529 Throw<std::runtime_error>("invalid SerialIter getSlice");
530 Slice const s(p_, bytes);
531 p_ += bytes;
532 used_ += bytes;
533 remain_ -= bytes;
534 return s;
535}
536
537// VFALCO DEPRECATED Returns a copy
538Blob
540{
541 return getRaw(getVLDataLength());
542}
543
544Buffer
549
550} // namespace xrpl
T begin(T... args)
Like std::vector<char> but better.
Definition Buffer.h:19
int getVLDataLength()
Reads the length header at the read position and steps past it.
Slice getSlice(std::size_t bytes)
void getFieldID(int &type, int &name)
std::size_t remain_
Definition Serializer.h:481
SerialIter(void const *data, std::size_t size) noexcept
std::uint8_t const * p_
Definition Serializer.h:480
std::size_t used_
Definition Serializer.h:482
int addFieldID(int type, int name)
static int decodeLengthLength(std::byte firstByte)
Works out how long a header is, from its first byte.
int addInteger(Integer)
static constexpr int kMaxValueOfFirstByteFor1ByteHeader
Definition Serializer.h:48
Blob::iterator begin()
Definition Serializer.h:323
static constexpr int kMaxValueOfFirstByteFor2ByteHeader
Definition Serializer.h:52
static constexpr int kMinValueOfLengthFor2ByteHeader
Definition Serializer.h:86
static constexpr int kMaxValueOfLengthFor1ByteHeader
Definition Serializer.h:84
static constexpr int kMinValueOfLengthFor1ByteHeader
A 1 byte header holds the length in the byte itself, so both ends of this range are the same numbers ...
Definition Serializer.h:83
static constexpr int kMaxValueOfLengthFor3ByteHeader
The largest length the encoder will write.
Definition Serializer.h:118
static constexpr int kMaxValueOfLengthFor2ByteHeader
48 values of the first byte mean a 2 byte header, and each of them covers 256 lengths.
Definition Serializer.h:93
static constexpr int kNumberOfValuesInOneByte
Definition Serializer.h:67
int addVL(Blob const &vector)
Blob::iterator end()
Definition Serializer.h:328
int add8(unsigned char byteValue)
static constexpr int kMinValueOfFirstByteFor2ByteHeader
Definition Serializer.h:50
int addEncoded(int length)
Appends the length header for a field of the given length.
int addRaw(Blob const &vector)
Slice slice() const noexcept
Definition Serializer.h:141
static constexpr int kNumberOfValuesInTwoBytes
Definition Serializer.h:68
static int decodeVLLength(std::byte firstByte)
Reads the field length out of a 1 byte header.
static constexpr int kMaxValueOfFirstByteFor3ByteHeader
Definition Serializer.h:57
bool get8(int &, int offset) const
static int encodeLengthLength(int length)
Works out how many bytes the header needs for the given length.
Serializer(int n=256)
Definition Serializer.h:124
static constexpr int kMinValueOfFirstByteFor3ByteHeader
Definition Serializer.h:54
static constexpr int kMinValueOfLengthFor3ByteHeader
Definition Serializer.h:98
An immutable linear range of bytes.
Definition Slice.h:28
T data(T... args)
T end(T... args)
T format(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
constexpr Dest safeCast(Src s) noexcept
Definition safe_cast.h:21
Slice makeSlice(std::array< T, N > const &a)
Definition Slice.h:228
BaseUInt< 256 > UInt256
Definition base_uint.h:580
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:35
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:11
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:52
Sha512HalfHasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:215
T size(T... args)