xrpld
Loading...
Searching...
No Matches
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 <stdexcept>
19#include <string>
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(), (char const*)ptr, ((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 byte)
147{
148 int const ret = data_.size();
149 data_.push_back(byte);
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{
214 int numBytes = 0;
215
216 if (length <= 192)
217 {
218 bytes[0] = static_cast<unsigned char>(length);
219 numBytes = 1;
220 }
221 else if (length <= 12480)
222 {
223 length -= 193;
224 bytes[0] = 193 + static_cast<unsigned char>(length >> 8);
225 bytes[1] = static_cast<unsigned char>(length & 0xff);
226 numBytes = 2;
227 }
228 else if (length <= 918744)
229 {
230 length -= 12481;
231 bytes[0] = 241 + static_cast<unsigned char>(length >> 16);
232 bytes[1] = static_cast<unsigned char>((length >> 8) & 0xff);
233 bytes[2] = static_cast<unsigned char>(length & 0xff);
234 numBytes = 3;
235 }
236 else
237 {
239 }
240
241 return addRaw(&bytes[0], numBytes);
242}
243
244int
246{
247 if (length < 0)
249
250 if (length <= 192)
251 return 1;
252
253 if (length <= 12480)
254 return 2;
255
256 if (length <= 918744)
257 return 3;
258
259 Throw<std::overflow_error>("len>918744");
260 return 0; // Silence compiler warning.
261}
262
263int
265{
266 if (b1 < 0)
268
269 if (b1 <= 192)
270 return 1;
271
272 if (b1 <= 240)
273 return 2;
274
275 if (b1 <= 254)
276 return 3;
277
279 return 0; // Silence compiler warning.
280}
281
282int
284{
285 if (b1 < 0)
287
288 if (b1 > 254)
290
291 return b1;
292}
293
294int
296{
297 if (b1 < 193)
299
300 if (b1 > 240)
302
303 return 193 + ((b1 - 193) * 256) + b2;
304}
305
306int
307Serializer::decodeVLLength(int b1, int b2, int b3)
308{
309 if (b1 < 241)
311
312 if (b1 > 254)
314
315 return 12481 + ((b1 - 241) * 65536) + (b2 * 256) + b3;
316}
317
318//------------------------------------------------------------------------------
319
320SerialIter::SerialIter(void const* data, std::size_t size) noexcept
321 : p_(reinterpret_cast<std::uint8_t const*>(data)), remain_(size)
322{
323}
324
325void
327{
328 p_ -= used_;
329 remain_ += used_;
330 used_ = 0;
331}
332
333void
335{
336 if (remain_ < length)
337 Throw<std::runtime_error>("invalid SerialIter skip");
338 p_ += length;
339 used_ += length;
340 remain_ -= length;
341}
342
343unsigned char
345{
346 if (remain_ < 1)
347 Throw<std::runtime_error>("invalid SerialIter get8");
348 unsigned char const t = *p_;
349 ++p_;
350 ++used_;
351 --remain_;
352 return t;
353}
354
357{
358 if (remain_ < 2)
359 Throw<std::runtime_error>("invalid SerialIter get16");
360 auto t = p_;
361 p_ += 2;
362 used_ += 2;
363 remain_ -= 2;
364 return (std::uint64_t(t[0]) << 8) + std::uint64_t(t[1]);
365}
366
369{
370 if (remain_ < 4)
371 Throw<std::runtime_error>("invalid SerialIter get32");
372 auto t = p_;
373 p_ += 4;
374 used_ += 4;
375 remain_ -= 4;
376 return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + (std::uint64_t(t[2]) << 8) +
377 std::uint64_t(t[3]);
378}
379
382{
383 if (remain_ < 8)
384 Throw<std::runtime_error>("invalid SerialIter get64");
385 auto t = p_;
386 p_ += 8;
387 used_ += 8;
388 remain_ -= 8;
389 return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + (std::uint64_t(t[2]) << 40) +
390 (std::uint64_t(t[3]) << 32) + (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) +
391 (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]);
392}
393
396{
397 if (remain_ < 4)
398 Throw<std::runtime_error>("invalid SerialIter geti32");
399 auto t = p_;
400 p_ += 4;
401 used_ += 4;
402 remain_ -= 4;
403 return boost::endian::load_big_s32(t);
404}
405
408{
409 if (remain_ < 8)
410 Throw<std::runtime_error>("invalid SerialIter geti64");
411 auto t = p_;
412 p_ += 8;
413 used_ += 8;
414 remain_ -= 8;
415 return boost::endian::load_big_s64(t);
416}
417
418void
419SerialIter::getFieldID(int& type, int& name)
420{
421 type = get8();
422 name = type & 15;
423 type >>= 4;
424
425 if (type == 0)
426 {
427 // uncommon type
428 type = get8();
429 if (type < 16)
430 Throw<std::runtime_error>("gFID: uncommon type out of range " + std::to_string(type));
431 }
432
433 if (name == 0)
434 {
435 // uncommon name
436 name = get8();
437 if (name < 16)
438 Throw<std::runtime_error>("gFID: uncommon name out of range " + std::to_string(name));
439 }
440}
441
442// getRaw for blob or buffer
443template <class T>
444T
446{
448 if (remain_ < size)
449 Throw<std::runtime_error>("invalid SerialIter getRaw");
450 T result(size);
451 if (size != 0)
452 {
453 // It's normally safe to call memcpy with size set to 0 (see the
454 // C99 standard 7.21.1/2). However, here this could mean that
455 // result.data would be null, which would trigger undefined behavior.
456 std::memcpy(result.data(), p_, size);
457 p_ += size;
458 used_ += size;
459 remain_ -= size;
460 }
461 return result;
462}
463
464// VFALCO DEPRECATED Returns a copy
465Blob
467{
468 return getRawHelper<Blob>(size);
469}
470
471int
473{
474 int const b1 = get8();
475 int datLen = 0;
476 int const lenLen = Serializer::decodeLengthLength(b1);
477 if (lenLen == 1)
478 {
479 datLen = Serializer::decodeVLLength(b1);
480 }
481 else if (lenLen == 2)
482 {
483 int const b2 = get8();
484 datLen = Serializer::decodeVLLength(b1, b2);
485 }
486 else
487 {
488 XRPL_ASSERT(lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3");
489 int const b2 = get8();
490 int const b3 = get8();
491 datLen = Serializer::decodeVLLength(b1, b2, b3);
492 }
493 return datLen;
494}
495
496Slice
498{
499 if (bytes > remain_)
500 Throw<std::runtime_error>("invalid SerialIter getSlice");
501 Slice const s(p_, bytes);
502 p_ += bytes;
503 used_ += bytes;
504 remain_ -= bytes;
505 return s;
506}
507
508// VFALCO DEPRECATED Returns a copy
509Blob
511{
512 return getRaw(getVLDataLength());
513}
514
515Buffer
520
521} // 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)
Serializer(int n=256)
Definition Serializer.h:27
An immutable linear range of bytes.
Definition Slice.h:26
T end(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
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
Definition safe_cast.h:21
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:34
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:10
BaseUInt< 256 > uint256
Definition base_uint.h:562
XRPL_NO_SANITIZE_ADDRESS void Throw(Args &&... args)
Definition contract.h:49
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
Definition Slice.h:215
T size(T... args)
T to_string(T... args)