diff --git a/libethereum/BlockInfo.cpp b/libethereum/BlockInfo.cpp index ea28a2971..60fbc092c 100644 --- a/libethereum/BlockInfo.cpp +++ b/libethereum/BlockInfo.cpp @@ -71,8 +71,7 @@ h256 BlockInfo::headerHashWithoutNonce() const void BlockInfo::fillStream(RLPStream& _s, bool _nonce) const { - _s.appendList(_nonce ? 9 : 8) << parentHash << sha3Uncles << coinbaseAddress << stateRoot << sha3Transactions << difficulty << timestamp; - _s.appendString(extraData); + _s.appendList(_nonce ? 9 : 8) << parentHash << sha3Uncles << coinbaseAddress << stateRoot << sha3Transactions << difficulty << timestamp << extraData; if (_nonce) _s << nonce; } diff --git a/libethereum/Common.h b/libethereum/Common.h index 83e0197a2..817fba800 100644 --- a/libethereum/Common.h +++ b/libethereum/Common.h @@ -96,6 +96,9 @@ public: byte& operator[](unsigned _i) { return m_data[_i]; } byte operator[](unsigned _i) const { return m_data[_i]; } + bytesRef ref() { return bytesRef(m_data.data(), N); } + bytesConstRef ref() const { return bytesConstRef(m_data.data(), N); } + byte* data() { return m_data.data(); } byte const* data() const { return m_data.data(); } diff --git a/libethereum/MemTrie.cpp b/libethereum/MemTrie.cpp index b920b5a21..4e80113ae 100644 --- a/libethereum/MemTrie.cpp +++ b/libethereum/MemTrie.cpp @@ -31,7 +31,7 @@ namespace eth #define ENABLE_DEBUG_PRINT 0 /*/ -#define APPEND_CHILD appendString +#define APPEND_CHILD appendData /*/ #define APPEND_CHILD appendRaw /**/ diff --git a/libethereum/RLP.cpp b/libethereum/RLP.cpp index 6b198a119..d84e6d66f 100644 --- a/libethereum/RLP.cpp +++ b/libethereum/RLP.cpp @@ -96,9 +96,9 @@ eth::uint RLP::actualSize() const { if (isNull()) return 0; - if (isInt()) - return 1 + intSize(); - if (isString()) + if (isSingleByte()) + return 1; + if (isData()) return payload().data() - m_data.data() + items(); if (isList()) { @@ -110,39 +110,37 @@ eth::uint RLP::actualSize() const return 0; } -eth::uint RLP::items() const -{ - auto n = (m_data[0] & 0x3f); - if (n < 0x38) - return n; - uint ret = 0; - for (int i = 0; i < n - 0x37; ++i) - ret = (ret << 8) | m_data[i + 1]; - return ret; -} - -RLPStream& RLPStream::appendString(bytesConstRef _s) +bool RLP::isInt() const { - if (_s.size() < 0x38) - m_out.push_back((byte)(_s.size() | 0x40)); + byte n = m_data[0]; + if (n < c_rlpDataImmLenStart) + return !!n; + else if (n <= c_rlpDataImmLenStart + c_rlpDataImmLenCount) + return m_data[1]; + else if (n < c_rlpListStart) + return m_data[1 + n - c_rlpDataIndLenZero]; else - pushCount(_s.size(), 0x40); - uint os = m_out.size(); - m_out.resize(os + _s.size()); - memcpy(m_out.data() + os, _s.data(), _s.size()); - return *this; + return false; + return false; } -RLPStream& RLPStream::appendString(string const& _s) +eth::uint RLP::items() const { - if (_s.size() < 0x38) - m_out.push_back((byte)(_s.size() | 0x40)); + uint ret = 0; + byte n = m_data[0]; + if (n < c_rlpDataImmLenStart) + return 1; + else if (n <= c_rlpDataImmLenStart + c_rlpDataImmLenCount) + return n - c_rlpDataImmLenStart; + else if (n < c_rlpListStart) + for (int i = 0; i < n - c_rlpDataIndLenZero; ++i) + ret = (ret << 8) | m_data[i + 1]; + else if (n <= c_rlpListStart + c_rlpDataImmLenCount) + return n - c_rlpListStart; else - pushCount(_s.size(), 0x40); - uint os = m_out.size(); - m_out.resize(os + _s.size()); - memcpy(m_out.data() + os, _s.data(), _s.size()); - return *this; + for (int i = 0; i < n - c_rlpListIndLenZero; ++i) + ret = (ret << 8) | m_data[i + 1]; + return ret; } RLPStream& RLPStream::appendRaw(bytesConstRef _s) @@ -155,65 +153,48 @@ RLPStream& RLPStream::appendRaw(bytesConstRef _s) RLPStream& RLPStream::appendList(uint _count) { - if (_count < 0x38) - m_out.push_back((byte)(_count | 0x80)); + if (_count < c_rlpListImmLenCount) + m_out.push_back((byte)(_count + c_rlpListStart)); else - pushCount(_count, 0x80); + pushCount(_count, c_rlpListIndLenZero); return *this; } -RLPStream& RLPStream::append(uint _i) +RLPStream& RLPStream::append(bytesConstRef _s, bool _compact) { - if (_i < 0x18) - m_out.push_back((byte)_i); - else - { - auto br = bytesRequired(_i); - m_out.push_back((byte)(br + 0x17)); // max 8 bytes. - pushInt(_i, br); - } - return *this; -} - -RLPStream& RLPStream::append(u160 _i) -{ - if (_i < 0x18) - m_out.push_back((byte)_i); - else - { - auto br = bytesRequired(_i); - m_out.push_back((byte)(br + 0x17)); // max 8 bytes. - pushInt(_i, br); - } - return *this; -} + uint s = _s.size(); + byte const* d = _s.data(); + if (_compact) + for (unsigned i = 0; i < _s.size() && !*d; ++i, --s, ++d) {} -RLPStream& RLPStream::append(u256 _i) -{ - if (_i < 0x18) - m_out.push_back((byte)_i); + if (s == 1 && *d < c_rlpDataImmLenStart) + m_out.push_back(*d); else { - auto br = bytesRequired(_i); - m_out.push_back((byte)(br + 0x17)); // max 8 bytes. - pushInt(_i, br); + if (s < c_rlpDataImmLenCount) + m_out.push_back((byte)(s + c_rlpDataImmLenStart)); + else + pushCount(s, c_rlpDataIndLenZero); + appendRaw(bytesConstRef(d, s)); } return *this; } RLPStream& RLPStream::append(bigint _i) { - if (_i < 0x18) + if (!_i) + m_out.push_back(c_rlpDataImmLenStart); + else if (_i < c_rlpDataImmLenStart) m_out.push_back((byte)_i); else { uint br = bytesRequired(_i); - if (br <= 32) - m_out.push_back((byte)(bytesRequired(_i) + 0x17)); // max 32 bytes. + if (br < c_rlpDataImmLenCount) + m_out.push_back((byte)(br + c_rlpDataImmLenStart)); else { auto brbr = bytesRequired(br); - m_out.push_back((byte)(0x37 + brbr)); + m_out.push_back((byte)(c_rlpDataIndLenZero + brbr)); pushInt(br, brbr); } pushInt(_i, br); @@ -224,7 +205,7 @@ RLPStream& RLPStream::append(bigint _i) void RLPStream::pushCount(uint _count, byte _base) { auto br = bytesRequired(_count); - m_out.push_back((byte)(br + 0x37 + _base)); // max 8 bytes. + m_out.push_back((byte)(br + _base)); // max 8 bytes. pushInt(_count, br); } @@ -233,8 +214,8 @@ std::ostream& eth::operator<<(std::ostream& _out, eth::RLP const& _d) if (_d.isNull()) _out << "null"; else if (_d.isInt()) - _out << std::showbase << std::hex << std::nouppercase << _d.toBigInt(RLP::LaisezFaire) << dec; - else if (_d.isString()) + _out << std::showbase << std::hex << std::nouppercase << _d.toInt(RLP::LaisezFaire) << dec; + else if (_d.isData()) _out << eth::escaped(_d.toString(), false); else if (_d.isList()) { diff --git a/libethereum/RLP.h b/libethereum/RLP.h index 9b563ed4e..1ce6fcf9d 100644 --- a/libethereum/RLP.h +++ b/libethereum/RLP.h @@ -42,6 +42,15 @@ template <> struct intTraits { static const uint maxSize = 20; }; template <> struct intTraits { static const uint maxSize = 32; }; template <> struct intTraits { static const uint maxSize = ~(uint)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; + /** * @brief Class for interpreting Recursive Linear-Prefix Data. * @by Gav Wood, 2013 @@ -68,6 +77,7 @@ public: /// Construct a node to read RLP data in the string. explicit RLP(std::string const& _s): m_data(bytesConstRef((byte const*)_s.data(), _s.size())) {} + /// The bare data of the RLP. bytesConstRef data() const { return m_data; } /// @returns true if the RLP is non-null. @@ -77,49 +87,38 @@ public: 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] == 0x40 || m_data[0] == 0x80); } + bool isEmpty() const { return !isNull() && (m_data[0] == c_rlpDataImmLenStart || m_data[0] == c_rlpListStart); } /// String value. - bool isString() const { return !isNull() && m_data[0] >= 0x40 && m_data[0] < 0x80; } + bool isData() const { return !isNull() && m_data[0] < c_rlpListStart; } /// List value. - bool isList() const { return !isNull() && m_data[0] >= 0x80 && m_data[0] < 0xc0; } - - /// Integer value. Either isSlimInt(), isFatInt() or isBigInt(). - bool isInt() const { return !isNull() && m_data[0] < 0x40; } - - /// Fits into eth::uint type. Can use toSlimInt() to read (as well as toFatInt() or toBigInt() ). - bool isSlimInt() const { return !isNull() && m_data[0] < 0x20; } - - /// Fits into eth::u256 or eth::bigint type. Use only toFatInt() or toBigInt() to read. - bool isFatInt() const { return !isNull() && m_data[0] >= 0x20 && m_data[0] < 0x38; } - - /// Fits into eth::u256 type, though might fit into eth::uint type. - bool isFixedInt() const { return !isNull() && m_data[0] < 0x38; } + bool isList() const { return !isNull() && m_data[0] >= c_rlpListStart; } - /// Fits only into eth::bigint type. Use only toBigInt() to read. - bool isBigInt() const { return !isNull() && m_data[0] >= 0x38 && m_data[0] < 0x40; } + /// 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. uint itemCount() const { return isList() ? items() : 0; } uint itemCountStrict() const { if (!isList()) throw BadCast(); return items(); } - /// @returns the number of characters in the string, or zero if it isn't a string. - uint stringSize() const { return isString() ? items() : 0; } + /// @returns the number of bytes in the data, or zero if it isn't data. + uint size() const { return isData() ? items() : 0; } + uint sizeStrict() const { if (!isData()) throw BadCast(); return items(); } /// Equality operators; does best-effort conversion and checks for equality. - bool operator==(char const* _s) const { return isString() && toString() == _s; } - bool operator!=(char const* _s) const { return isString() && toString() != _s; } - bool operator==(std::string const& _s) const { return isString() && toString() == _s; } - bool operator!=(std::string const& _s) const { return isString() && toString() != _s; } - template bool operator==(FixedHash<_N> const& _h) const { return isString() && toHash<_N>() == _h; } - template bool operator!=(FixedHash<_N> const& _s) const { return isString() && toHash<_N>() != _s; } - bool operator==(uint const& _i) const { return (isInt() || isString()) && toSlimInt() == _i; } - bool operator!=(uint const& _i) const { return (isInt() || isString()) && toSlimInt() != _i; } - bool operator==(u256 const& _i) const { return (isInt() || isString()) && toFatInt() == _i; } - bool operator!=(u256 const& _i) const { return (isInt() || isString()) && toFatInt() != _i; } - bool operator==(bigint const& _i) const { return (isInt() || isString()) && toBigInt() == _i; } - bool operator!=(bigint const& _i) const { return (isInt() || isString()) && toBigInt() != _i; } + 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==(uint const& _i) const { return isInt() && toInt() == _i; } + bool operator!=(uint 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. @@ -167,13 +166,13 @@ public: template explicit operator FixedHash<_N>() const { return toHash>(); } /// Converts to bytearray. @returns the empty byte array if not a string. - bytes toBytes() const { if (!isString()) return bytes(); return bytes(payload().data(), payload().data() + items()); } + bytes toBytes() const { if (!isData()) return bytes(); return bytes(payload().data(), payload().data() + items()); } /// Converts to bytearray. @returns the empty byte array if not a string. - bytesConstRef toBytesConstRef() const { if (!isString()) return bytesConstRef(); return payload().cropped(0, items()); } + bytesConstRef toBytesConstRef() const { if (!isData()) return bytesConstRef(); return payload().cropped(0, items()); } /// Converts to string. @returns the empty string if not a string. - std::string toString() const { if (!isString()) return std::string(); return payload().cropped(0, items()).toString(); } + std::string toString() const { if (!isData()) return std::string(); return payload().cropped(0, items()).toString(); } /// Converts to string. @throws BadCast if not a string. - std::string toStringStrict() const { if (!isString()) throw BadCast(); return payload().cropped(0, items()).toString(); } + std::string toStringStrict() const { if (!isData()) throw BadCast(); return payload().cropped(0, items()).toString(); } template std::vector toVector() const { std::vector ret; if (isList()) { ret.reserve(itemCount()); for (auto const& i: *this) ret.push_back((T)i); } return ret; } template std::array toArray() const { std::array ret; if (itemCount() != N) throw BadCast(); if (isList()) for (uint i = 0; i < N; ++i) ret[i] = (T)operator[](i); return ret; } @@ -181,47 +180,37 @@ public: /// Int conversion flags enum { - AllowString = 1, - AllowInt = 2, + AllowNonCanon = 1, ThrowOnFail = 4, FailIfTooBig = 8, - Strict = AllowString | AllowInt | ThrowOnFail | FailIfTooBig, - StrictlyString = AllowString | ThrowOnFail | FailIfTooBig, - StrictlyInt = AllowInt | ThrowOnFail | FailIfTooBig, - LaisezFaire = AllowString | AllowInt + Strict = ThrowOnFail | FailIfTooBig, + LaisezFaire = AllowNonCanon }; /// Converts to int of type given; if isString(), decodes as big-endian bytestream. @returns 0 if not an int or string. template _T toInt(int _flags = Strict) const { - if ((isString() && !(_flags & AllowString)) || (isInt() && !(_flags & AllowInt)) || isList() || isNull()) + if ((!isInt() && !(_flags & AllowNonCanon)) || isList() || isNull()) if (_flags & ThrowOnFail) throw BadCast(); else return 0; else {} - if (isDirectValueInt()) - return m_data[0]; - - auto s = isInt() ? intSize() - lengthSize() : isString() ? items() : 0; - if (s > intTraits<_T>::maxSize && (_flags & FailIfTooBig)) + auto p = payload(); + if (p.size() > intTraits<_T>::maxSize && (_flags & FailIfTooBig)) if (_flags & ThrowOnFail) throw BadCast(); else return 0; else {} - _T ret = 0; - uint o = lengthSize() + 1; - for (uint i = 0; i < s; ++i) - ret = (ret << 8) | m_data[i + o]; - return ret; + return fromBigEndian<_T>(p); } template _N toHash(int _flags = Strict) const { - if (!isString() || (items() > _N::size && (_flags & FailIfTooBig))) + if (!isData() || (items() > _N::size && (_flags & FailIfTooBig))) if (_flags & ThrowOnFail) throw BadCast(); else @@ -234,46 +223,22 @@ public: return ret; } - /// Converts to eth::uint. @see toInt() - uint toSlimInt(int _flags = Strict) const { return toInt(_flags); } - - /// Converts to eth::u256. @see toInt() - u256 toFatInt(int _flags = Strict) const { return toInt(_flags); } - - /// Converts to eth::bigint. @see toInt() - bigint toBigInt(int _flags = Strict) const { return toInt(_flags); } - /// Converts to RLPs collection object. Useful if you need random access to sub items or will iterate over multiple times. RLPs toList() const; /// @returns the data payload. Valid for all types. - bytesConstRef payload() const { auto n = (m_data[0] & 0x3f); return m_data.cropped(1 + (n < 0x38 ? 0 : (n - 0x37))); } + bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize(), items()); } private: - /// Direct value integer. - bool isDirectValueInt() const { assert(!isNull()); return m_data[0] < 0x18; } - - /// Indirect-value integer. - bool isIndirectValueInt() const { assert(!isNull()); return m_data[0] >= 0x18 && m_data[0] < 0x38; } - - /// Indirect addressed integer. - bool isIndirectAddressedInt() const { assert(!isNull()); return m_data[0] < 0x40 && m_data[0] >= 0x38; } - - /// Direct-length string. - bool isSmallString() const { assert(!isNull()); return m_data[0] >= 0x40 && m_data[0] < 0x78; } - - /// Direct-length list. - bool isSmallList() const { assert(!isNull()); return m_data[0] >= 0x80 && m_data[0] < 0xb8; } + /// Single-byte data payload. + bool isSingleByte() const { assert(!isNull()); return m_data[0] < c_rlpDataImmLenStart; } /// @returns the theoretical size of this item; if it's a list, will require a deep traversal which could take a while. /// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work. uint actualSize() const; - /// @returns the total additional bytes used to encode the integer. Includes the data-size and potentially the length-size. Returns 0 if not isInt(). - uint intSize() const { return (!isInt() || isDirectValueInt()) ? 0 : isIndirectAddressedInt() ? lengthSize() + items() : (m_data[0] - 0x17); } - /// @returns the bytes used to encode the length of the data. Valid for all types. - uint lengthSize() const { auto n = (m_data[0] & 0x3f); return n > 0x37 ? n - 0x37 : 0; } + uint 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 number of data items (bytes in the case of strings & ints, items in the case of lists). Valid for all types. uint items() const; @@ -299,45 +264,48 @@ public: /// Initializes the RLPStream as a list of @a _listItems items. explicit RLPStream(uint _listItems) { appendList(_listItems); } - /// Append given data to the byte stream. - RLPStream& append(uint _s); - RLPStream& append(u160 _s); - RLPStream& append(u256 _s); - RLPStream& append(h160 _s, bool _compact = true) { return appendFixed(_s, _compact); } - RLPStream& append(h256 _s, bool _compact = true) { return appendFixed(_s, _compact); } + /// Append given datum to the byte stream. + RLPStream& append(uint _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)); } + RLPStream& append(h160 _s, bool _compact = false) { return append(_s.ref(), _compact); } + RLPStream& append(h256 _s, bool _compact = false) { return append(_s.ref(), _compact); } + + /// Appends an arbitrary RLP fragment. + RLPStream& append(RLP const& _rlp) { return appendRaw(_rlp.data()); } + + /// Appends a sequence of data to the stream as a list. + template RLPStream& append(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; } + + /// Appends a list. RLPStream& appendList(uint _count); - RLPStream& appendString(bytesConstRef _s); - RLPStream& appendString(bytes const& _s) { return appendString(bytesConstRef(&_s)); } - RLPStream& appendString(std::string const& _s); + + /// Appends raw (pre-serialised) RLP data. Use with caution. RLPStream& appendRaw(bytesConstRef _rlp); RLPStream& appendRaw(bytes const& _rlp) { return appendRaw(&_rlp); } - RLPStream& appendRaw(RLP const& _rlp) { return appendRaw(_rlp.data()); } /// Shift operators for appending data items. - RLPStream& operator<<(uint _i) { return append(_i); } - RLPStream& operator<<(u160 _i) { return append(_i); } - RLPStream& operator<<(u256 _i) { return append(_i); } - RLPStream& operator<<(h160 _i) { return append(_i); } - RLPStream& operator<<(h256 _i) { return append(_i); } - RLPStream& operator<<(bigint _i) { return append(_i); } - RLPStream& operator<<(char const* _s) { return appendString(std::string(_s)); } - RLPStream& operator<<(std::string const& _s) { return appendString(_s); } - RLPStream& operator<<(RLP const& _i) { return appendRaw(_i); } - template RLPStream& operator<<(std::vector<_T> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } - template RLPStream& operator<<(std::array<_T, S> const& _s) { appendList(_s.size()); for (auto const& i: _s) append(i); return *this; } + template RLPStream& operator<<(T _data) { return append(_data); } + /// Clear the output stream so far. void clear() { m_out.clear(); } /// Read the byte stream. bytes const& out() const { return m_out; } + /// Swap the contents of the output stream out for some other byte array. void swapOut(bytes& _dest) { swap(m_out, _dest); } private: /// 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(uint _count, byte _base); + void pushCount(uint _count, byte _offset); /// Push an integer as a raw big-endian byte-stream. template void pushInt(_T _i, uint _br) @@ -348,29 +316,10 @@ private: *(b--) = (byte)_i; } - template - RLPStream& appendFixed(FixedHash<_N> const& _s, bool _compact) - { - uint s = _N; - byte const* d = _s.data(); - if (_compact) - for (unsigned i = 0; i < _N && !*d; ++i, --s, ++d) {} - - if (s < 0x38) - m_out.push_back((byte)(s | 0x40)); - else - pushCount(s, 0x40); - uint os = m_out.size(); - m_out.resize(os + s); - memcpy(m_out.data() + os, d, s); - return *this; - } - /// Determine bytes required to encode the given integer value. @returns 0 if @a _i is zero. template static uint bytesRequired(_T _i) { - _i >>= 8; - uint i = 1; + uint i = 0; for (; _i != 0; ++i, _i >>= 8) {} return i; } diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index 9fc5bf048..d1cc8174d 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -29,14 +29,14 @@ using namespace eth; Transaction::Transaction(bytesConstRef _rlpData) { RLP rlp(_rlpData); - nonce = rlp[0].toInt(RLP::StrictlyInt); + nonce = rlp[0].toInt(); receiveAddress = rlp[1].toHash
(); - value = rlp[2].toInt(RLP::StrictlyInt); - fee = rlp[3].toInt(RLP::StrictlyInt); + value = rlp[2].toInt(); + fee = rlp[3].toInt(); data.reserve(rlp[4].itemCountStrict()); for (auto const& i: rlp[4]) - data.push_back(i.toInt(RLP::StrictlyInt)); - vrs = Signature{ rlp[5].toInt(RLP::StrictlyInt), rlp[6].toInt(RLP::StrictlyInt), rlp[7].toInt(RLP::StrictlyInt) }; + data.push_back(i.toInt()); + vrs = Signature{ rlp[5].toInt(), rlp[6].toInt(), rlp[7].toInt() }; } Address Transaction::sender() const diff --git a/libethereum/TrieDB.h b/libethereum/TrieDB.h index 0a30fcfda..3d327074b 100644 --- a/libethereum/TrieDB.h +++ b/libethereum/TrieDB.h @@ -477,7 +477,7 @@ template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSli { killNode(sha3(_orig.data())); RLPStream s(2); - s.appendRaw(_orig[0]); + s.append(_orig[0]); mergeAtAux(s, _orig[1], _k.mid(k.size()), _v); return s.out(); } @@ -509,7 +509,7 @@ template bytes GenericTrieDB::mergeAt(RLP const& _orig, NibbleSli if (i == n) mergeAtAux(r, _orig[i], _k.mid(1), _v); else - r.appendRaw(_orig[i]); + r.append(_orig[i]); return r.out(); } @@ -547,7 +547,7 @@ template void GenericTrieDB::remove(bytesConstRef _key) template bool GenericTrieDB::isTwoItemNode(RLP const& _n) const { - return (_n.isString() && RLP(node(_n.toHash())).itemCount() == 2) + return (_n.isData() && RLP(node(_n.toHash())).itemCount() == 2) || (_n.isList() && _n.itemCount() == 2); } @@ -669,16 +669,16 @@ template bytes GenericTrieDB::place(RLP const& _orig, NibbleSlice killNode(_orig); if (_orig.isEmpty()) - return RLPStream(2).appendString(hexPrefixEncode(_k, true)).appendString(_s).out(); + return (RLPStream(2) << hexPrefixEncode(_k, true) << _s).out(); assert(_orig.isList() && (_orig.itemCount() == 2 || _orig.itemCount() == 17)); if (_orig.itemCount() == 2) - return RLPStream(2).appendRaw(_orig[0]).appendString(_s).out(); + return (RLPStream(2) << _orig[0] << _s).out(); auto s = RLPStream(17); for (uint i = 0; i < 16; ++i) - s.appendRaw(_orig[i]); - s.appendString(_s); + s << _orig[i]; + s << _s; return s.out(); } @@ -695,8 +695,8 @@ template bytes GenericTrieDB::remove(RLP const& _orig) return RLPNull; RLPStream r(17); for (uint i = 0; i < 16; ++i) - r.appendRaw(_orig[i]); - r.appendString(""); + r << _orig[i]; + r << ""; return r.out(); } @@ -719,11 +719,10 @@ template bytes GenericTrieDB::cleve(RLP const& _orig, uint _s) assert(_s && _s <= k.size()); RLPStream bottom(2); - bottom.appendString(hexPrefixEncode(k, isLeaf(_orig), _s)); - bottom.appendRaw(_orig[1]); + bottom << hexPrefixEncode(k, isLeaf(_orig), _s) << _orig[1]; RLPStream top(2); - top.appendString(hexPrefixEncode(k, false, 0, _s)); + top << hexPrefixEncode(k, false, 0, _s); streamNode(top, bottom.out()); return top.out(); @@ -790,8 +789,7 @@ template bytes GenericTrieDB::branch(RLP const& _orig) if (isLeaf(_orig) || k.size() > 1) { RLPStream bottom(2); - bottom.appendString(hexPrefixEncode(k.mid(1), isLeaf(_orig))); - bottom.appendRaw(_orig[1]); + bottom << hexPrefixEncode(k.mid(1), isLeaf(_orig)) << _orig[1]; streamNode(r, bottom.out()); } else diff --git a/libethereum/TrieHash.cpp b/libethereum/TrieHash.cpp index e4e0cefb3..153e84e17 100644 --- a/libethereum/TrieHash.cpp +++ b/libethereum/TrieHash.cpp @@ -29,7 +29,7 @@ namespace eth { /*/ -#define APPEND_CHILD appendString +#define APPEND_CHILD appendData /*/ #define APPEND_CHILD appendRaw /**/ diff --git a/test/rlp.cpp b/test/rlp.cpp index 4491c27d4..931d5fe46 100644 --- a/test/rlp.cpp +++ b/test/rlp.cpp @@ -31,36 +31,36 @@ int rlpTest() assert(asString(rlp(15)) == "\x0f"); // 3-character string - assert(RLP("\x43""dog") == "dog"); - assert(asString(rlp("dog")) == "\x43""dog"); + assert(RLP("\x83""dog") == "dog"); + assert(asString(rlp("dog")) == "\x83""dog"); // 2-item list - string twoItemListString = "\x82\x0f\x43""dog"; + string twoItemListString = "\xc2\x0f\x83""dog"; RLP twoItemList(twoItemListString); assert(twoItemList.itemCount() == 2); assert(twoItemList[0] == 15); assert(twoItemList[1] == "dog"); - assert(asString(rlpList(15, "dog")) == "\x82\x0f\x43""dog"); + assert(asString(rlpList(15, "dog")) == "\xc2\x0f\x83""dog"); + + // null + assert(RLP("\x80") == ""); + assert(asString(rlp("")) == "\x80"); // 1-byte (8-bit) int - assert(RLP("\x18\x45") == 69); - assert(asString(rlp(69)) == "\x18\x45"); + assert(RLP("\x81\x80") == 128); + assert(asString(rlp(128)) == "\x81\x80"); // 2-byte (16-bit) int - assert(RLP("\x19\x01\x01") == 257); - assert(asString(rlp(257)) == "\x19\x01\x01"); + assert(RLP("\x82\x01\x01") == 257); + assert(asString(rlp(257)) == "\x82\x01\x01"); // 32-byte (256-bit) int - assert(RLP("\x37\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")); + assert(RLP("\xa0\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")); assert(asString(rlp(bigint("0x100102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"))) == "\x37\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"); - // 33-byte (264-bit) int - assert(RLP("\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f") == bigint("0x20100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F")); - assert(asString(rlp(bigint("0x20100102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"))) == "\x38\x21\x20\x10\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"); - // 56-character string. - assert(RLP("\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit") == "Lorem ipsum dolor sit amet, consectetur adipisicing elit"); - assert(asString(rlp("Lorem ipsum dolor sit amet, consectetur adipisicing elit")) == "\x78\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit"); + assert(RLP("\xb8\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit") == "Lorem ipsum dolor sit amet, consectetur adipisicing elit"); + assert(asString(rlp("Lorem ipsum dolor sit amet, consectetur adipisicing elit")) == "\xb8\x38""Lorem ipsum dolor sit amet, consectetur adipisicing elit"); return 0; }