diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/RLP.h b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/RLP.h deleted file mode 100644 index 99a77023..00000000 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/RLP.h +++ /dev/null @@ -1,472 +0,0 @@ -// Aleth: Ethereum C++ client, tools and libraries. -// Copyright 2013-2019 Aleth Authors. -// Licensed under the GNU General Public License, Version 3. - -/// @file -/// Recursive Linear-Prefix serialization / deserialization. -#pragma once - -#include "Exceptions.h" -#include "FixedHash.h" -#include "vector_ref.h" - -#include -#include -#include -#include -#include - -namespace dev -{ - -class RLP; - -template struct intTraits { static const unsigned maxSize = sizeof(_T); }; -template <> struct intTraits { static const unsigned maxSize = 20; }; -template <> struct intTraits { static const unsigned maxSize = 32; }; -template <> struct intTraits { static const unsigned maxSize = ~(unsigned)0; }; - -static const byte c_rlpMaxLengthBytes = 8; -static const byte c_rlpDataImmLenStart = 0x80; -static const byte c_rlpListStart = 0xc0; - -static const byte c_rlpDataImmLenCount = c_rlpListStart - c_rlpDataImmLenStart - c_rlpMaxLengthBytes; -static const byte c_rlpDataIndLenZero = c_rlpDataImmLenStart + c_rlpDataImmLenCount - 1; -static const byte c_rlpListImmLenCount = 256 - c_rlpListStart - c_rlpMaxLengthBytes; -static const byte c_rlpListIndLenZero = c_rlpListStart + c_rlpListImmLenCount - 1; - -template struct Converter { static T convert(RLP const&, int) { BOOST_THROW_EXCEPTION(BadCast()); } }; - -/** - * Class for interpreting Recursive Linear-Prefix Data. - */ -class RLP -{ -public: - /// Conversion flags - enum - { - AllowNonCanon = 1, - ThrowOnFail = 4, - FailIfTooBig = 8, - FailIfTooSmall = 16, - Strict = ThrowOnFail | FailIfTooBig, - VeryStrict = ThrowOnFail | FailIfTooBig | FailIfTooSmall, - LaissezFaire = AllowNonCanon - }; - - using Strictness = int; - - /// Construct a null node. - RLP() {} - - /// Construct a node of value given in the bytes. - explicit RLP(bytesConstRef _d, Strictness _s = VeryStrict); - - /// Construct a node of value given in the bytes. - explicit RLP(bytes const& _d, Strictness _s = VeryStrict): RLP(&_d, _s) {} - - /// Construct a node to read RLP data in the bytes given. - RLP(byte const* _b, unsigned _s, Strictness _st = VeryStrict): RLP(bytesConstRef(_b, _s), _st) {} - - /// Construct a node to read RLP data in the string. - explicit RLP(std::string const& _s, Strictness _st = VeryStrict): RLP(bytesConstRef((byte const*)_s.data(), _s.size()), _st) {} - - /// The bare data of the RLP. - bytesConstRef data() const { return m_data; } - - /// @returns true if the RLP is non-null. - explicit operator bool() const { return !isNull(); } - - /// No value. - bool isNull() const { return m_data.size() == 0; } - - /// Contains a zero-length string or zero-length list. - bool isEmpty() const { return !isNull() && (m_data[0] == c_rlpDataImmLenStart || m_data[0] == c_rlpListStart); } - - /// String value. - bool isData() const { return !isNull() && m_data[0] < c_rlpListStart; } - - /// List value. - bool isList() const { return !isNull() && m_data[0] >= c_rlpListStart; } - - /// Integer value. Must not have a leading zero. - bool isInt() const; - - /// @returns the number of items in the list, or zero if it isn't a list. - size_t itemCount() const { return isList() ? items() : 0; } - size_t itemCountStrict() const { if (!isList()) BOOST_THROW_EXCEPTION(BadCast()); return items(); } - - /// @returns the number of bytes in the data, or zero if it isn't data. - size_t size() const { return isData() ? length() : 0; } - size_t sizeStrict() const { if (!isData()) BOOST_THROW_EXCEPTION(BadCast()); return length(); } - - /// Equality operators; does best-effort conversion and checks for equality. - bool operator==(char const* _s) const { return isData() && toString() == _s; } - bool operator!=(char const* _s) const { return isData() && toString() != _s; } - bool operator==(std::string const& _s) const { return isData() && toString() == _s; } - bool operator!=(std::string const& _s) const { return isData() && toString() != _s; } - template bool operator==(FixedHash<_N> const& _h) const { return isData() && toHash<_N>() == _h; } - template bool operator!=(FixedHash<_N> const& _s) const { return isData() && toHash<_N>() != _s; } - bool operator==(unsigned const& _i) const { return isInt() && toInt() == _i; } - bool operator!=(unsigned const& _i) const { return isInt() && toInt() != _i; } - bool operator==(u256 const& _i) const { return isInt() && toInt() == _i; } - bool operator!=(u256 const& _i) const { return isInt() && toInt() != _i; } - bool operator==(bigint const& _i) const { return isInt() && toInt() == _i; } - bool operator!=(bigint const& _i) const { return isInt() && toInt() != _i; } - - /// Subscript operator. - /// @returns the list item @a _i if isList() and @a _i < listItems(), or RLP() otherwise. - /// @note if used to access items in ascending order, this is efficient. - RLP operator[](size_t _i) const; - - using element_type = RLP; - - /// @brief Iterator class for iterating through items of RLP list. - class iterator - { - friend class RLP; - - public: - using value_type = RLP; - using element_type = RLP; - - iterator& operator++(); - iterator operator++(int) { auto ret = *this; operator++(); return ret; } - RLP operator*() const { return RLP(m_currentItem); } - bool operator==(iterator const& _cmp) const { return m_currentItem == _cmp.m_currentItem; } - bool operator!=(iterator const& _cmp) const { return !operator==(_cmp); } - - private: - iterator() {} - iterator(RLP const& _parent, bool _begin); - - size_t m_remaining = 0; - bytesConstRef m_currentItem; - }; - - /// @brief Iterator into beginning of sub-item list (valid only if we are a list). - iterator begin() const { return iterator(*this, true); } - - /// @brief Iterator into end of sub-item list (valid only if we are a list). - iterator end() const { return iterator(*this, false); } - - template inline T convert(int _flags) const; - - /// Best-effort conversion operators. - explicit operator std::string() const { return toString(); } - explicit operator bytes() const { return toBytes(); } - explicit operator uint8_t() const { return toInt(); } - explicit operator uint16_t() const { return toInt(); } - explicit operator uint32_t() const { return toInt(); } - explicit operator uint64_t() const { return toInt(); } - explicit operator u160() const { return toInt(); } - explicit operator u256() const { return toInt(); } - explicit operator bigint() const { return toInt(); } - template explicit operator FixedHash() const { return toHash>(); } - template explicit operator std::pair() const { return toPair(); } - template explicit operator std::vector() const { return toVector(); } - template explicit operator std::set() const { return toSet(); } - template explicit operator std::array() const { return toArray(); } - - /// Converts to bytearray. @returns the empty byte array if not a string. - bytes toBytes(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return bytes(); } return bytes(payload().data(), payload().data() + length()); } - /// Converts to bytearray. @returns the empty byte array if not a string. - bytesConstRef toBytesConstRef(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return bytesConstRef(); } return payload().cropped(0, length()); } - /// Converts to string. @returns the empty string if not a string. - std::string toString(int _flags = LaissezFaire) const { if (!isData()) { if (_flags & ThrowOnFail) BOOST_THROW_EXCEPTION(BadCast()); else return std::string(); } return payload().cropped(0, length()).toString(); } - /// Converts to string. @throws BadCast if not a string. - std::string toStringStrict() const { return toString(Strict); } - - template - std::vector toVector(int _flags = LaissezFaire) const - { - std::vector ret; - if (isList()) - { - ret.reserve(itemCount()); - for (auto const& i: *this) - ret.push_back(i.convert(_flags)); - } - else if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - return ret; - } - - template - std::set toSet(int _flags = LaissezFaire) const - { - std::set ret; - if (isList()) - for (auto const& i: *this) - ret.insert(i.convert(_flags)); - else if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - return ret; - } - - template - std::unordered_set toUnorderedSet(int _flags = LaissezFaire) const - { - std::unordered_set ret; - if (isList()) - for (auto const& i: *this) - ret.insert(i.convert(_flags)); - else if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - return ret; - } - - template - std::pair toPair(int _flags = Strict) const - { - std::pair ret; - if (itemCountStrict() != 2) - { - if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - else - return ret; - } - ret.first = (*this)[0].convert(_flags); - ret.second = (*this)[1].convert(_flags); - return ret; - } - - template - std::array toArray(int _flags = LaissezFaire) const - { - if (itemCount() != N) - { - if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - else - return std::array(); - } - std::array ret; - for (size_t i = 0; i < N; ++i) - ret[i] = operator[](i).convert(_flags); - return ret; - } - - /// Converts to int of type given; if isData(), decodes as big-endian bytestream. @returns 0 if not an int or data. - template _T toInt(int _flags = Strict) const - { - requireGood(); - if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull()) - { - if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - else - return 0; - } - - auto p = payload(); - if (p.size() > intTraits<_T>::maxSize && (_flags & FailIfTooBig)) - { - if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - else - return 0; - } - - return fromBigEndian<_T>(p); - } - - int64_t toPositiveInt64(int _flags = Strict) const - { - int64_t i = toInt(_flags); - if ((_flags & ThrowOnFail) && i < 0) - BOOST_THROW_EXCEPTION(BadCast()); - return i; - } - - template _N toHash(int _flags = Strict) const - { - requireGood(); - auto p = payload(); - auto l = p.size(); - if (!isData() || (l > _N::size && (_flags & FailIfTooBig)) || (l < _N::size && (_flags & FailIfTooSmall))) - { - if (_flags & ThrowOnFail) - BOOST_THROW_EXCEPTION(BadCast()); - else - return _N(); - } - - _N ret; - size_t s = std::min(_N::size, l); - memcpy(ret.data() + _N::size - s, p.data(), s); - return ret; - } - - /// @returns the data payload. Valid for all types. - bytesConstRef payload() const { auto l = length(); if (l > m_data.size()) BOOST_THROW_EXCEPTION(BadRLP()); return m_data.cropped(payloadOffset(), l); } - - /// @returns the theoretical size of this item as encoded in the data. - /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. - size_t actualSize() const; - -private: - /// Disable construction from rvalue - explicit RLP(bytes const&&) {} - - /// Throws if is non-canonical data (i.e. single byte done in two bytes that could be done in one). - void requireGood() const; - - /// Single-byte data payload. - bool isSingleByte() const { return !isNull() && m_data[0] < c_rlpDataImmLenStart; } - - /// @returns the amount of bytes used to encode the length of the data. Valid for all types. - unsigned lengthSize() const { if (isData() && m_data[0] > c_rlpDataIndLenZero) return m_data[0] - c_rlpDataIndLenZero; if (isList() && m_data[0] > c_rlpListIndLenZero) return m_data[0] - c_rlpListIndLenZero; return 0; } - - /// @returns the size in bytes of the payload, as given by the RLP as opposed to as inferred from m_data. - size_t length() const; - - /// @returns the number of bytes into the data that the payload starts. - size_t payloadOffset() const { return isSingleByte() ? 0 : (1 + lengthSize()); } - - /// @returns the number of data items. - size_t items() const; - - /// @returns the size encoded into the RLP in @a _data and throws if _data is too short. - static size_t sizeAsEncoded(bytesConstRef _data) { return RLP(_data, ThrowOnFail | FailIfTooSmall).actualSize(); } - - /// Our byte data. - bytesConstRef m_data; - - /// The list-indexing cache. - // Index of the last item accessed with operator[] - mutable size_t m_lastIndex = (size_t)-1; - // Offset of the next byte after last byte of m_lastItem - mutable size_t m_lastEnd = 0; - // Data of the last item accessed with operator[] - mutable bytesConstRef m_lastItem; -}; - -template <> struct Converter { static std::string convert(RLP const& _r, int _flags) { return _r.toString(_flags); } }; -template <> struct Converter { static bytes convert(RLP const& _r, int _flags) { return _r.toBytes(_flags); } }; -template <> struct Converter { static uint8_t convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static uint16_t convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static uint32_t convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static uint64_t convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static u160 convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static u256 convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template <> struct Converter { static bigint convert(RLP const& _r, int _flags) { return _r.toInt(_flags); } }; -template struct Converter> { static FixedHash convert(RLP const& _r, int _flags) { return _r.toHash>(_flags); } }; -template struct Converter> { static std::pair convert(RLP const& _r, int _flags) { return _r.toPair(_flags); } }; -template struct Converter> { static std::vector convert(RLP const& _r, int _flags) { return _r.toVector(_flags); } }; -template struct Converter> { static std::set convert(RLP const& _r, int _flags) { return _r.toSet(_flags); } }; -template struct Converter> { static std::unordered_set convert(RLP const& _r, int _flags) { return _r.toUnorderedSet(_flags); } }; -template struct Converter> { static std::array convert(RLP const& _r, int _flags) { return _r.toArray(_flags); } }; - -template inline T RLP::convert(int _flags) const { return Converter::convert(*this, _flags); } - -/** - * @brief Class for writing to an RLP bytestream. - */ -class RLPStream -{ -public: - /// Initializes empty RLPStream. - RLPStream() {} - - /// Initializes the RLPStream as a list of @a _listItems items. - explicit RLPStream(size_t _listItems) { appendList(_listItems); } - - ~RLPStream() {} - - /// Append given datum to the byte stream. - RLPStream& append(unsigned _s) { return append(bigint(_s)); } - RLPStream& append(u160 _s) { return append(bigint(_s)); } - RLPStream& append(u256 _s) { return append(bigint(_s)); } - RLPStream& append(bigint _s); - RLPStream& append(bytesConstRef _s, bool _compact = false); - RLPStream& append(bytes const& _s) { return append(bytesConstRef(&_s)); } - RLPStream& append(std::string const& _s) { return append(bytesConstRef(_s)); } - RLPStream& append(char const* _s) { return append(std::string(_s)); } - template RLPStream& append(FixedHash _s, bool _compact = false, bool _allOrNothing = false) { return _allOrNothing && !_s ? append(bytesConstRef()) : append(_s.ref(), _compact); } - - /// Appends an arbitrary RLP fragment - this *must* be a single item unless @a _itemCount is given. - RLPStream& append(RLP const& _rlp, size_t _itemCount = 1) { return appendRaw(_rlp.data(), _itemCount); } - - /// Appends a sequence of data to the stream as a list. - template RLPStream& append(std::vector<_T> const& _s) { return appendVector(_s); } - template RLPStream& appendVector(std::vector<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } - template RLPStream& append(std::array<_T, S> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } - template RLPStream& append(std::set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } - template RLPStream& append(std::unordered_set<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } - template RLPStream& append(std::pair const& _s) { appendList(2); append(_s.first); append(_s.second); return *this; } - - /// Appends a list. - RLPStream& appendList(size_t _items); - RLPStream& appendList(bytesConstRef _rlp); - RLPStream& appendList(bytes const& _rlp) { return appendList(&_rlp); } - RLPStream& appendList(RLPStream const& _s) { return appendList(&_s.out()); } - - /// Appends raw (pre-serialised) RLP data. Use with caution. - RLPStream& appendRaw(bytesConstRef _rlp, size_t _itemCount = 1); - RLPStream& appendRaw(bytes const& _rlp, size_t _itemCount = 1) { return appendRaw(&_rlp, _itemCount); } - - /// Shift operators for appending data items. - template RLPStream& operator<<(T _data) { return append(_data); } - - /// Clear the output stream so far. - void clear() { m_out.clear(); m_listStack.clear(); } - - /// Read the byte stream. - bytes const& out() const { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return m_out; } - - /// Invalidate the object and steal the output byte stream. - bytes&& invalidate() { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); return std::move(m_out); } - - /// Swap the contents of the output stream out for some other byte array. - void swapOut(bytes& _dest) { if(!m_listStack.empty()) BOOST_THROW_EXCEPTION(RLPException() << errinfo_comment("listStack is not empty")); swap(m_out, _dest); } - -private: - void noteAppended(size_t _itemCount = 1); - - /// Push the node-type byte (using @a _base) along with the item count @a _count. - /// @arg _count is number of characters for strings, data-bytes for ints, or items for lists. - void pushCount(size_t _count, byte _offset); - - /// Push an integer as a raw big-endian byte-stream. - template void pushInt(_T _i, size_t _br) - { - m_out.resize(m_out.size() + _br); - byte* b = &m_out.back(); - for (; _i; _i >>= 8) - *(b--) = (byte)(_i & 0xff); - } - - /// Our output byte stream. - bytes m_out; - - std::vector> m_listStack; -}; - -template void rlpListAux(RLPStream& _out, _T _t) { _out << _t; } -template void rlpListAux(RLPStream& _out, _T _t, _Ts ... _ts) { rlpListAux(_out << _t, _ts...); } - -/// Export a single item in RLP format, returning a byte array. -template bytes rlp(_T _t) { return (RLPStream() << _t).out(); } - -/// Export a list of items in RLP format, returning a byte array. -inline bytes rlpList() { return RLPStream(0).out(); } -template bytes rlpList(_Ts ... _ts) -{ - RLPStream out(sizeof ...(_Ts)); - rlpListAux(out, _ts...); - return out.out(); -} - -/// The empty string in RLP format. -extern bytes RLPNull; - -/// The empty list in RLP format. -extern bytes RLPEmptyList; - -/// Human readable version of RLP. -std::ostream& operator<<(std::ostream& _out, dev::RLP const& _d); - -}