rippled
Loading...
Searching...
No Matches
Serializer.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <xrpl/basics/Buffer.h>
21#include <xrpl/basics/Slice.h>
22#include <xrpl/basics/base_uint.h>
23#include <xrpl/basics/contract.h>
24#include <xrpl/basics/safe_cast.h>
25#include <xrpl/beast/utility/instrumentation.h>
26#include <xrpl/protocol/HashPrefix.h>
27#include <xrpl/protocol/Serializer.h>
28#include <xrpl/protocol/digest.h>
29
30#include <boost/endian/conversion.hpp>
31
32#include <array>
33#include <cstddef>
34#include <cstdint>
35#include <cstring>
36#include <stdexcept>
37#include <string>
38#include <type_traits>
39
40namespace ripple {
41
42int
44{
45 int ret = mData.size();
46 mData.push_back(static_cast<unsigned char>(i >> 8));
47 mData.push_back(static_cast<unsigned char>(i & 0xff));
48 return ret;
49}
50
51int
53{
54 // This should never trigger; the size & type of a hash prefix are
55 // integral parts of the protocol and unlikely to ever change.
56 static_assert(
58
59 return add32(safe_cast<std::uint32_t>(p));
60}
61
62template <>
63int
64Serializer::addInteger(unsigned char i)
65{
66 return add8(i);
67}
68template <>
69int
74template <>
75int
80template <>
81int
86template <>
87int
89{
90 return add32(i);
91}
92
93int
95{
96 int ret = mData.size();
97 mData.insert(mData.end(), vector.begin(), vector.end());
98 return ret;
99}
100
101int
103{
104 int ret = mData.size();
106 return ret;
107}
108
109int
111{
112 int ret = mData.size();
113 mData.insert(mData.end(), s.begin(), s.end());
114 return ret;
115}
116
117int
118Serializer::addRaw(void const* ptr, int len)
119{
120 int ret = mData.size();
121 mData.insert(mData.end(), (char const*)ptr, ((char const*)ptr) + len);
122 return ret;
123}
124
125int
126Serializer::addFieldID(int type, int name)
127{
128 int ret = mData.size();
129 XRPL_ASSERT(
130 (type > 0) && (type < 256) && (name > 0) && (name < 256),
131 "ripple::Serializer::addFieldID : inputs inside range");
132
133 if (type < 16)
134 {
135 if (name < 16) // common type, common name
136 mData.push_back(static_cast<unsigned char>((type << 4) | name));
137 else
138 {
139 // common type, uncommon name
140 mData.push_back(static_cast<unsigned char>(type << 4));
141 mData.push_back(static_cast<unsigned char>(name));
142 }
143 }
144 else if (name < 16)
145 {
146 // uncommon type, common name
147 mData.push_back(static_cast<unsigned char>(name));
148 mData.push_back(static_cast<unsigned char>(type));
149 }
150 else
151 {
152 // uncommon type, uncommon name
153 mData.push_back(static_cast<unsigned char>(0));
154 mData.push_back(static_cast<unsigned char>(type));
155 mData.push_back(static_cast<unsigned char>(name));
156 }
157
158 return ret;
159}
160
161int
162Serializer::add8(unsigned char byte)
163{
164 int ret = mData.size();
165 mData.push_back(byte);
166 return ret;
167}
168
169bool
170Serializer::get8(int& byte, int offset) const
171{
172 if (offset >= mData.size())
173 return false;
174
175 byte = mData[offset];
176 return true;
177}
178
179bool
181{
182 if (bytes > mData.size())
183 return false;
184
185 mData.resize(mData.size() - bytes);
186 return true;
187}
188
191{
192 return sha512Half(makeSlice(mData));
193}
194
195int
197{
198 int ret = addEncoded(vector.size());
199 addRaw(vector);
200 XRPL_ASSERT(
201 mData.size() ==
202 (ret + vector.size() + encodeLengthLength(vector.size())),
203 "ripple::Serializer::addVL : size matches expected");
204 return ret;
205}
206
207int
209{
210 int ret = addEncoded(slice.size());
211 if (slice.size())
212 addRaw(slice.data(), slice.size());
213 return ret;
214}
215
216int
217Serializer::addVL(void const* ptr, int len)
218{
219 int ret = addEncoded(len);
220
221 if (len)
222 addRaw(ptr, len);
223
224 return ret;
225}
226
227int
229{
231 int numBytes = 0;
232
233 if (length <= 192)
234 {
235 bytes[0] = static_cast<unsigned char>(length);
236 numBytes = 1;
237 }
238 else if (length <= 12480)
239 {
240 length -= 193;
241 bytes[0] = 193 + static_cast<unsigned char>(length >> 8);
242 bytes[1] = static_cast<unsigned char>(length & 0xff);
243 numBytes = 2;
244 }
245 else if (length <= 918744)
246 {
247 length -= 12481;
248 bytes[0] = 241 + static_cast<unsigned char>(length >> 16);
249 bytes[1] = static_cast<unsigned char>((length >> 8) & 0xff);
250 bytes[2] = static_cast<unsigned char>(length & 0xff);
251 numBytes = 3;
252 }
253 else
254 Throw<std::overflow_error>("lenlen");
255
256 return addRaw(&bytes[0], numBytes);
257}
258
259int
261{
262 if (length < 0)
263 Throw<std::overflow_error>("len<0");
264
265 if (length <= 192)
266 return 1;
267
268 if (length <= 12480)
269 return 2;
270
271 if (length <= 918744)
272 return 3;
273
274 Throw<std::overflow_error>("len>918744");
275 return 0; // Silence compiler warning.
276}
277
278int
280{
281 if (b1 < 0)
282 Throw<std::overflow_error>("b1<0");
283
284 if (b1 <= 192)
285 return 1;
286
287 if (b1 <= 240)
288 return 2;
289
290 if (b1 <= 254)
291 return 3;
292
293 Throw<std::overflow_error>("b1>254");
294 return 0; // Silence compiler warning.
295}
296
297int
299{
300 if (b1 < 0)
301 Throw<std::overflow_error>("b1<0");
302
303 if (b1 > 254)
304 Throw<std::overflow_error>("b1>254");
305
306 return b1;
307}
308
309int
311{
312 if (b1 < 193)
313 Throw<std::overflow_error>("b1<193");
314
315 if (b1 > 240)
316 Throw<std::overflow_error>("b1>240");
317
318 return 193 + (b1 - 193) * 256 + b2;
319}
320
321int
322Serializer::decodeVLLength(int b1, int b2, int b3)
323{
324 if (b1 < 241)
325 Throw<std::overflow_error>("b1<241");
326
327 if (b1 > 254)
328 Throw<std::overflow_error>("b1>254");
329
330 return 12481 + (b1 - 241) * 65536 + b2 * 256 + b3;
331}
332
333//------------------------------------------------------------------------------
334
335SerialIter::SerialIter(void const* data, std::size_t size) noexcept
336 : p_(reinterpret_cast<std::uint8_t const*>(data)), remain_(size)
337{
338}
339
340void
342{
343 p_ -= used_;
344 remain_ += used_;
345 used_ = 0;
346}
347
348void
350{
351 if (remain_ < length)
352 Throw<std::runtime_error>("invalid SerialIter skip");
353 p_ += length;
354 used_ += length;
355 remain_ -= length;
356}
357
358unsigned char
360{
361 if (remain_ < 1)
362 Throw<std::runtime_error>("invalid SerialIter get8");
363 unsigned char t = *p_;
364 ++p_;
365 ++used_;
366 --remain_;
367 return t;
368}
369
372{
373 if (remain_ < 2)
374 Throw<std::runtime_error>("invalid SerialIter get16");
375 auto t = p_;
376 p_ += 2;
377 used_ += 2;
378 remain_ -= 2;
379 return (std::uint64_t(t[0]) << 8) + std::uint64_t(t[1]);
380}
381
384{
385 if (remain_ < 4)
386 Throw<std::runtime_error>("invalid SerialIter get32");
387 auto t = p_;
388 p_ += 4;
389 used_ += 4;
390 remain_ -= 4;
391 return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) +
392 (std::uint64_t(t[2]) << 8) + std::uint64_t(t[3]);
393}
394
397{
398 if (remain_ < 8)
399 Throw<std::runtime_error>("invalid SerialIter get64");
400 auto t = p_;
401 p_ += 8;
402 used_ += 8;
403 remain_ -= 8;
404 return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) +
405 (std::uint64_t(t[2]) << 40) + (std::uint64_t(t[3]) << 32) +
406 (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) +
407 (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]);
408}
409
412{
413 if (remain_ < 4)
414 Throw<std::runtime_error>("invalid SerialIter geti32");
415 auto t = p_;
416 p_ += 4;
417 used_ += 4;
418 remain_ -= 4;
419 return boost::endian::load_big_s32(t);
420}
421
424{
425 if (remain_ < 8)
426 Throw<std::runtime_error>("invalid SerialIter geti64");
427 auto t = p_;
428 p_ += 8;
429 used_ += 8;
430 remain_ -= 8;
431 return boost::endian::load_big_s64(t);
432}
433
434void
435SerialIter::getFieldID(int& type, int& name)
436{
437 type = get8();
438 name = type & 15;
439 type >>= 4;
440
441 if (type == 0)
442 {
443 // uncommon type
444 type = get8();
445 if (type < 16)
446 Throw<std::runtime_error>(
447 "gFID: uncommon type out of range " + std::to_string(type));
448 }
449
450 if (name == 0)
451 {
452 // uncommon name
453 name = get8();
454 if (name < 16)
455 Throw<std::runtime_error>(
456 "gFID: uncommon name out of range " + std::to_string(name));
457 }
458}
459
460// getRaw for blob or buffer
461template <class T>
462T
464{
465 static_assert(
467 if (remain_ < size)
468 Throw<std::runtime_error>("invalid SerialIter getRaw");
469 T result(size);
470 if (size != 0)
471 {
472 // It's normally safe to call memcpy with size set to 0 (see the
473 // C99 standard 7.21.1/2). However, here this could mean that
474 // result.data would be null, which would trigger undefined behavior.
475 std::memcpy(result.data(), p_, size);
476 p_ += size;
477 used_ += size;
478 remain_ -= size;
479 }
480 return result;
481}
482
483// VFALCO DEPRECATED Returns a copy
484Blob
486{
487 return getRawHelper<Blob>(size);
488}
489
490int
492{
493 int b1 = get8();
494 int datLen;
495 int lenLen = Serializer::decodeLengthLength(b1);
496 if (lenLen == 1)
497 {
498 datLen = Serializer::decodeVLLength(b1);
499 }
500 else if (lenLen == 2)
501 {
502 int b2 = get8();
503 datLen = Serializer::decodeVLLength(b1, b2);
504 }
505 else
506 {
507 XRPL_ASSERT(
508 lenLen == 3, "ripple::SerialIter::getVLDataLength : lenLen is 3");
509 int b2 = get8();
510 int b3 = get8();
511 datLen = Serializer::decodeVLLength(b1, b2, b3);
512 }
513 return datLen;
514}
515
516Slice
518{
519 if (bytes > remain_)
520 Throw<std::runtime_error>("invalid SerialIter getSlice");
521 Slice s(p_, bytes);
522 p_ += bytes;
523 used_ += bytes;
524 remain_ -= bytes;
525 return s;
526}
527
528// VFALCO DEPRECATED Returns a copy
529Blob
531{
532 return getRaw(getVLDataLength());
533}
534
535Buffer
537{
538 return getRawHelper<Buffer>(getVLDataLength());
539}
540
541} // namespace ripple
T begin(T... args)
Like std::vector<char> but better.
Definition Buffer.h:36
std::size_t remain_
Definition Serializer.h:349
SerialIter(void const *data, std::size_t size) noexcept
Slice getSlice(std::size_t bytes)
void skip(int num)
std::int64_t geti64()
std::uint8_t const * p_
Definition Serializer.h:348
std::int32_t geti32()
void getFieldID(int &type, int &name)
T getRawHelper(int size)
Blob getRaw(int size)
void reset() noexcept
std::size_t used_
Definition Serializer.h:350
std::uint16_t get16()
std::uint32_t get32()
unsigned char get8()
std::uint64_t get64()
Blob::iterator begin()
Definition Serializer.h:252
int addFieldID(int type, int name)
Slice slice() const noexcept
Definition Serializer.h:66
bool get8(int &, int offset) const
uint256 getSHA512Half() const
static int encodeLengthLength(int length)
int addEncoded(int length)
int addInteger(Integer)
int addRaw(Blob const &vector)
int addVL(Blob const &vector)
bool chop(int num)
static int decodeLengthLength(int b1)
int add16(std::uint16_t i)
int add8(unsigned char i)
Blob::iterator end()
Definition Serializer.h:257
static int decodeVLLength(int b1)
An immutable linear range of bytes.
Definition Slice.h:46
const_iterator begin() const noexcept
Definition Slice.h:149
const_iterator end() const noexcept
Definition Slice.h:161
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition Slice.h:98
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition Slice.h:81
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:25
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:244
HashPrefix
Prefix for hashing functions.
Definition HashPrefix.h:55
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:224
T push_back(T... args)
T resize(T... args)
T size(T... args)
T to_string(T... args)