#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl { int Serializer::add16(std::uint16_t i) { int const ret = data_.size(); data_.push_back(static_cast(i >> 8)); data_.push_back(static_cast(i & 0xff)); return ret; } int Serializer::add32(HashPrefix p) { // This should never trigger; the size & type of a hash prefix are // integral parts of the protocol and unlikely to ever change. static_assert(std::is_same_v>); return add32(safeCast(p)); } template <> int Serializer::addInteger(unsigned char i) { return add8(i); } template <> int Serializer::addInteger(std::uint16_t i) { return add16(i); } template <> int Serializer::addInteger(std::uint32_t i) { return add32(i); } template <> int Serializer::addInteger(std::uint64_t i) { return add64(i); } template <> int Serializer::addInteger(std::int32_t i) { return add32(i); } int Serializer::addRaw(Blob const& vector) { int const ret = data_.size(); data_.insert(data_.end(), vector.begin(), vector.end()); return ret; } int Serializer::addRaw(Slice slice) { int const ret = data_.size(); data_.insert(data_.end(), slice.begin(), slice.end()); return ret; } int Serializer::addRaw(Serializer const& s) { int const ret = data_.size(); data_.insert(data_.end(), s.begin(), s.end()); return ret; } int Serializer::addRaw(void const* ptr, int len) { int const ret = data_.size(); data_.insert(data_.end(), static_cast(ptr), static_cast(ptr) + len); return ret; } int Serializer::addFieldID(int type, int name) { int const ret = data_.size(); XRPL_ASSERT( (type > 0) && (type < 256) && (name > 0) && (name < 256), "xrpl::Serializer::addFieldID : inputs inside range"); if (type < 16) { if (name < 16) { // common type, common name data_.push_back(static_cast((type << 4) | name)); } else { // common type, uncommon name data_.push_back(static_cast(type << 4)); data_.push_back(static_cast(name)); } } else if (name < 16) { // uncommon type, common name data_.push_back(static_cast(name)); data_.push_back(static_cast(type)); } else { // uncommon type, uncommon name data_.push_back(static_cast(0)); data_.push_back(static_cast(type)); data_.push_back(static_cast(name)); } return ret; } int Serializer::add8(unsigned char byteValue) { int const ret = data_.size(); data_.push_back(byteValue); return ret; } bool Serializer::get8(int& byte, int offset) const { if (offset >= data_.size()) return false; byte = data_[offset]; return true; } bool Serializer::chop(int bytes) { if (bytes > data_.size()) return false; data_.resize(data_.size() - bytes); return true; } uint256 Serializer::getSHA512Half() const { return sha512Half(makeSlice(data_)); } int Serializer::addVL(Blob const& vector) { int const ret = addEncoded(vector.size()); addRaw(vector); XRPL_ASSERT( data_.size() == (ret + vector.size() + encodeLengthLength(vector.size())), "xrpl::Serializer::addVL : size matches expected"); return ret; } int Serializer::addVL(Slice const& slice) { int const ret = addEncoded(slice.size()); if (!slice.empty()) addRaw(slice.data(), slice.size()); return ret; } int Serializer::addVL(void const* ptr, int len) { int const ret = addEncoded(len); if (len != 0) addRaw(ptr, len); return ret; } int Serializer::addEncoded(int length) { // Without this, a negative length would fall into the 1 byte case below and // be cast to a first byte no header uses. A size too big for int arrives // here negative as well, since callers pass sizes through this parameter. if (length < kMinValueOfLengthFor1ByteHeader) Throw("addEncoded: length is negative or did not fit in an int"); std::array bytes{}; int numBytes = 0; if (length <= kMaxValueOfLengthFor1ByteHeader) { bytes[0] = static_cast(length); numBytes = 1; } else if (length <= kMaxValueOfLengthFor2ByteHeader) { // Count from the smallest length a 2 byte header covers. int const offset = length - kMinValueOfLengthFor2ByteHeader; bytes[0] = static_cast( kMinValueOfFirstByteFor2ByteHeader + (offset / kNumberOfValuesInOneByte)); bytes[1] = static_cast(offset % kNumberOfValuesInOneByte); numBytes = 2; } else if (length <= kMaxValueOfLengthFor3ByteHeader) { int const offset = length - kMinValueOfLengthFor3ByteHeader; bytes[0] = static_cast( kMinValueOfFirstByteFor3ByteHeader + (offset / kNumberOfValuesInTwoBytes)); bytes[1] = static_cast((offset / kNumberOfValuesInOneByte) % kNumberOfValuesInOneByte); bytes[2] = static_cast(offset % kNumberOfValuesInOneByte); numBytes = 3; } else { Throw("addEncoded: length is too large to encode"); } return addRaw(bytes.data(), numBytes); } int Serializer::encodeLengthLength(int length) { if (length < kMinValueOfLengthFor1ByteHeader) { Throw( "encodeLengthLength: length is negative or did not fit in an int"); } if (length <= kMaxValueOfLengthFor1ByteHeader) return 1; if (length <= kMaxValueOfLengthFor2ByteHeader) return 2; if (length <= kMaxValueOfLengthFor3ByteHeader) return 3; Throw("encodeLengthLength: length is too large to encode"); } int Serializer::decodeLengthLength(std::byte firstByte) { int const firstByteValue = std::to_integer(firstByte); if (firstByteValue <= kMaxValueOfFirstByteFor1ByteHeader) return 1; if (firstByteValue <= kMaxValueOfFirstByteFor2ByteHeader) return 2; if (firstByteValue <= kMaxValueOfFirstByteFor3ByteHeader) return 3; Throw("decodeLengthLength: first byte does not start any header"); } int Serializer::decodeVLLength(std::byte firstByte) { int const length = std::to_integer(firstByte); // A bigger value means a longer header, so it is not a length by itself. if (length > kMaxValueOfLengthFor1ByteHeader) Throw("decodeVLLength 1 byte: first byte is not a length"); return length; } int Serializer::decodeVLLength(std::byte firstByte, std::byte secondByte) { int const firstByteValue = std::to_integer(firstByte); if (firstByteValue < kMinValueOfFirstByteFor2ByteHeader) Throw("decodeVLLength 2 byte: first byte is below the range"); if (firstByteValue > kMaxValueOfFirstByteFor2ByteHeader) Throw("decodeVLLength 2 byte: first byte is above the range"); // Both bytes are bounded by their own type, and the first one is bounded to // the 2 byte range above, so this cannot leave the range the header covers. return kMinValueOfLengthFor2ByteHeader + ((firstByteValue - kMinValueOfFirstByteFor2ByteHeader) * kNumberOfValuesInOneByte) + std::to_integer(secondByte); } int Serializer::decodeVLLength(std::byte firstByte, std::byte secondByte, std::byte thirdByte) { int const firstByteValue = std::to_integer(firstByte); if (firstByteValue < kMinValueOfFirstByteFor3ByteHeader) Throw("decodeVLLength 3 byte: first byte is below the range"); if (firstByteValue > kMaxValueOfFirstByteFor3ByteHeader) Throw("decodeVLLength 3 byte: first byte is above the range"); int const length = kMinValueOfLengthFor3ByteHeader + ((firstByteValue - kMinValueOfFirstByteFor3ByteHeader) * kNumberOfValuesInTwoBytes) + (std::to_integer(secondByte) * kNumberOfValuesInOneByte) + std::to_integer(thirdByte); // A 3 byte header reaches further than kMaxValueOfLengthFor3ByteHeader, which // is as far as the encoder goes. Refuse the rest, so every length accepted // here is one that can be written back. if (length > kMaxValueOfLengthFor3ByteHeader) Throw("decodeVLLength 3 byte: length is too large to re-encode"); return length; } //------------------------------------------------------------------------------ SerialIter::SerialIter(void const* data, std::size_t size) noexcept : p_(reinterpret_cast(data)), remain_(size) { } void SerialIter::reset() noexcept { p_ -= used_; remain_ += used_; used_ = 0; } void SerialIter::skip(int length) { if (remain_ < length) Throw("invalid SerialIter skip"); p_ += length; used_ += length; remain_ -= length; } unsigned char SerialIter::get8() { if (remain_ < 1) Throw("invalid SerialIter get8"); unsigned char const t = *p_; ++p_; ++used_; --remain_; return t; } std::uint16_t SerialIter::get16() { if (remain_ < 2) Throw("invalid SerialIter get16"); auto t = p_; p_ += 2; used_ += 2; remain_ -= 2; return (std::uint64_t(t[0]) << 8) + std::uint64_t(t[1]); } std::uint32_t SerialIter::get32() { if (remain_ < 4) Throw("invalid SerialIter get32"); auto t = p_; p_ += 4; used_ += 4; remain_ -= 4; return (std::uint64_t(t[0]) << 24) + (std::uint64_t(t[1]) << 16) + (std::uint64_t(t[2]) << 8) + std::uint64_t(t[3]); } std::uint64_t SerialIter::get64() { if (remain_ < 8) Throw("invalid SerialIter get64"); auto t = p_; p_ += 8; used_ += 8; remain_ -= 8; return (std::uint64_t(t[0]) << 56) + (std::uint64_t(t[1]) << 48) + (std::uint64_t(t[2]) << 40) + (std::uint64_t(t[3]) << 32) + (std::uint64_t(t[4]) << 24) + (std::uint64_t(t[5]) << 16) + (std::uint64_t(t[6]) << 8) + std::uint64_t(t[7]); } std::int32_t SerialIter::geti32() { if (remain_ < 4) Throw("invalid SerialIter geti32"); auto t = p_; p_ += 4; used_ += 4; remain_ -= 4; return boost::endian::load_big_s32(t); } std::int64_t SerialIter::geti64() { if (remain_ < 8) Throw("invalid SerialIter geti64"); auto t = p_; p_ += 8; used_ += 8; remain_ -= 8; return boost::endian::load_big_s64(t); } void SerialIter::getFieldID(int& type, int& name) { type = get8(); name = type & 15; type >>= 4; if (type == 0) { // uncommon type type = get8(); if (type < 16) Throw("gFID: uncommon type out of range " + std::to_string(type)); } if (name == 0) { // uncommon name name = get8(); if (name < 16) Throw("gFID: uncommon name out of range " + std::to_string(name)); } } // getRaw for blob or buffer template T SerialIter::getRawHelper(int size) { static_assert(std::is_same_v || std::is_same_v); if (remain_ < size) Throw("invalid SerialIter getRaw"); T result(size); if (size != 0) { // It's normally safe to call memcpy with size set to 0 (see the // C99 standard 7.21.1/2). However, here this could mean that // result.data would be null, which would trigger undefined behavior. std::memcpy(result.data(), p_, size); p_ += size; used_ += size; remain_ -= size; } return result; } // VFALCO DEPRECATED Returns a copy Blob SerialIter::getRaw(int size) { return getRawHelper(size); } int SerialIter::getVLDataLength() { std::byte const firstByte{get8()}; int datLen = 0; int const lenLen = Serializer::decodeLengthLength(firstByte); if (lenLen == 1) { datLen = Serializer::decodeVLLength(firstByte); } else if (lenLen == 2) { std::byte const secondByte{get8()}; datLen = Serializer::decodeVLLength(firstByte, secondByte); } else { XRPL_ASSERT(lenLen == 3, "xrpl::SerialIter::getVLDataLength : lenLen is 3"); std::byte const secondByte{get8()}; std::byte const thirdByte{get8()}; datLen = Serializer::decodeVLLength(firstByte, secondByte, thirdByte); } return datLen; } Slice SerialIter::getSlice(std::size_t bytes) { if (bytes > remain_) Throw("invalid SerialIter getSlice"); Slice const s(p_, bytes); p_ += bytes; used_ += bytes; remain_ -= bytes; return s; } // VFALCO DEPRECATED Returns a copy Blob SerialIter::getVL() { return getRaw(getVLDataLength()); } Buffer SerialIter::getVLBuffer() { return getRawHelper(getVLDataLength()); } } // namespace xrpl