diff --git a/libethereum/BlockInfo.cpp b/libethereum/BlockInfo.cpp index a1a9781d1..1ebc5eb58 100644 --- a/libethereum/BlockInfo.cpp +++ b/libethereum/BlockInfo.cpp @@ -36,13 +36,13 @@ void BlockInfo::populateAndVerify(bytesConstRef _block, u256 _number) { RLP header = root[0]; hash = eth::sha256(_block); - parentHash = header[0].toFatInt(); - sha256Uncles = header[1].toFatInt(); - coinbaseAddress = header[2].toFatInt(); - sha256Transactions = header[3].toFatInt(); - difficulty = header[4].toFatInt(); - timestamp = header[5].toFatInt(); - nonce = header[6].toFatInt(); + parentHash = header[0].toInt(); + sha256Uncles = header[1].toInt(); + coinbaseAddress = header[2].toInt(); + sha256Transactions = header[3].toInt(); + difficulty = header[4].toInt(); + timestamp = header[5].toInt(); + nonce = header[6].toInt(); } catch (RLP::BadCast) { diff --git a/libethereum/RLP.cpp b/libethereum/RLP.cpp index e56b68c50..7cf0dd41c 100644 --- a/libethereum/RLP.cpp +++ b/libethereum/RLP.cpp @@ -191,7 +191,7 @@ std::ostream& operator<<(std::ostream& _out, eth::RLP _d) if (_d.isNull()) _out << "null"; else if (_d.isInt()) - _out << std::showbase << std::hex << std::nouppercase << _d.toBigInt(); + _out << std::showbase << std::hex << std::nouppercase << _d.toBigInt(RLP::LaisezFaire); else if (_d.isString()) _out << eth::escaped(_d.toString(), true); else if (_d.isList()) diff --git a/libethereum/RLP.h b/libethereum/RLP.h index b01fbccdc..5d103b5fb 100644 --- a/libethereum/RLP.h +++ b/libethereum/RLP.h @@ -35,6 +35,11 @@ namespace eth class RLP; typedef std::vector RLPs; +template struct intTraits { static const uint maxSize = sizeof(_T); }; +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; }; + /** * @brief Class for interpreting Recursive Linear-Prefix Data. * @by Gav Wood, 2013 @@ -160,15 +165,41 @@ public: /// Converts to string. @throws BadCast if not a string. std::string toStringStrict() const { if (!isString()) throw BadCast(); return payload().cropped(0, items()).toString(); } + /// Int conversion flags + enum + { + AllowString = 1, + AllowInt = 2, + ThrowOnFail = 4, + FailIfTooBig = 8, + Strict = AllowString | AllowInt | ThrowOnFail | FailIfTooBig, + StrictlyString = AllowString | ThrowOnFail | FailIfTooBig, + StrictlyInt = AllowInt | ThrowOnFail | FailIfTooBig, + LaisezFaire = AllowString | AllowInt + }; + /// Converts to int of type given; if isString(), decodes as big-endian bytestream. @returns 0 if not an int or string. - template _T toInt() const + template _T toInt(int _flags = Strict) const { - if (!isString() && !isInt()) - return 0; + if ((isString() && !(_flags & AllowString)) || (isInt() && !(_flags & AllowInt)) || isList() || isNull()) + if (_flags & ThrowOnFail) + throw BadCast(); + else + return 0; + else {} + if (isDirectValueInt()) return m_data[0]; - _T ret = 0; + auto s = isInt() ? intSize() - lengthSize() : isString() ? items() : 0; + if (s > 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]; @@ -176,25 +207,13 @@ public: } /// Converts to eth::uint. @see toInt() - uint toSlimInt() const { return toInt(); } + uint toSlimInt(int _flags = Strict) const { return toInt(_flags); } + /// Converts to eth::u256. @see toInt() - u256 toFatInt() const { return toInt(); } + u256 toFatInt(int _flags = Strict) const { return toInt(_flags); } + /// Converts to eth::bigint. @see toInt() - bigint toBigInt() const { return toInt(); } - - /// Converts to eth::uint. @throws BadCast if not isInt(). @see toInt() - uint toSlimIntStrict() const { if (!isSlimInt()) throw BadCast(); return toInt(); } - /// Converts to eth::u256. @throws BadCast if not isInt(). @see toInt() - u256 toFatIntStrict() const { if (!isFatInt() && !isSlimInt()) throw BadCast(); return toInt(); } - /// Converts to eth::bigint. @throws BadCast if not isInt(). @see toInt() - bigint toBigIntStrict() const { if (!isInt()) throw BadCast(); return toInt(); } - - /// Converts to eth::uint using the toString() as a big-endian bytestream. @throws BadCast if not isString(). @see toInt() - uint toSlimIntFromString() const { if (!isString()) throw BadCast(); return toInt(); } - /// Converts to eth::u256 using the toString() as a big-endian bytestream. @throws BadCast if not isString(). @see toInt() - u256 toFatIntFromString() const { if (!isString()) throw BadCast(); return toInt(); } - /// Converts to eth::bigint using the toString() as a big-endian bytestream. @throws BadCast if not isString(). @see toInt() - bigint toBigIntFromString() const { if (!isString()) throw BadCast(); return 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; diff --git a/libethereum/State.cpp b/libethereum/State.cpp index ee93f2cdf..e4f54869b 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -93,8 +93,17 @@ u256 State::contractMemory(Address _contract, u256 _memory) const return i == m->second.memory().end() ? 0 : i->second; } -bool State::verify(bytes const& _block) +bool State::verify(bytes const& _block, uint _number) { + BlockInfo bi; + try + { + bi.populateAndVerify(bytesConstRef((bytes*)&_block), _number); + } + catch (...) + { + return false; + } return true; } diff --git a/libethereum/State.h b/libethereum/State.h index 3c9b828ae..2c6cea961 100644 --- a/libethereum/State.h +++ b/libethereum/State.h @@ -39,7 +39,7 @@ class State public: explicit State(Address _minerAddress); - bool verify(bytes const& _block); + bool verify(bytes const& _block, uint _number = 0); bool execute(bytes const& _rlp) { try { Transaction t(_rlp); execute(t, t.sender()); } catch (...) { return false; } } bool isNormalAddress(Address _address) const; diff --git a/libethereum/Transaction.cpp b/libethereum/Transaction.cpp index b78ec6ee0..5f30141b2 100644 --- a/libethereum/Transaction.cpp +++ b/libethereum/Transaction.cpp @@ -28,14 +28,14 @@ using namespace eth; Transaction::Transaction(bytes const& _rlpData) { RLP rlp(_rlpData); - nonce = rlp[0].toFatIntStrict(); - receiveAddress = as160(rlp[1].toFatIntFromString()); - value = rlp[2].toFatIntStrict(); - fee = rlp[3].toFatIntStrict(); + nonce = rlp[0].toInt(RLP::StrictlyInt); + receiveAddress = rlp[1].toInt(RLP::StrictlyString); + value = rlp[2].toInt(RLP::StrictlyInt); + fee = rlp[3].toInt(RLP::StrictlyInt); data.reserve(rlp[4].itemCountStrict()); for (auto const& i: rlp[4]) - data.push_back(i.toFatIntStrict()); - vrs = Signature{ (byte)rlp[5].toSlimIntStrict(), rlp[6].toFatIntStrict(), rlp[7].toFatIntStrict() }; + data.push_back(i.toInt(RLP::StrictlyInt)); + vrs = Signature{ rlp[5].toInt(RLP::StrictlyInt), rlp[6].toInt(RLP::StrictlyInt), rlp[7].toInt(RLP::StrictlyInt) }; } Address Transaction::sender() const