Browse Source

More flexible and stricter RLP int handling.

cl-refactor
Gav Wood 11 years ago
parent
commit
19481bbaee
  1. 14
      libethereum/BlockInfo.cpp
  2. 2
      libethereum/RLP.cpp
  3. 61
      libethereum/RLP.h
  4. 11
      libethereum/State.cpp
  5. 2
      libethereum/State.h
  6. 12
      libethereum/Transaction.cpp

14
libethereum/BlockInfo.cpp

@ -36,13 +36,13 @@ void BlockInfo::populateAndVerify(bytesConstRef _block, u256 _number)
{ {
RLP header = root[0]; RLP header = root[0];
hash = eth::sha256(_block); hash = eth::sha256(_block);
parentHash = header[0].toFatInt(); parentHash = header[0].toInt<u256>();
sha256Uncles = header[1].toFatInt(); sha256Uncles = header[1].toInt<u256>();
coinbaseAddress = header[2].toFatInt(); coinbaseAddress = header[2].toInt<u160>();
sha256Transactions = header[3].toFatInt(); sha256Transactions = header[3].toInt<u256>();
difficulty = header[4].toFatInt(); difficulty = header[4].toInt<uint>();
timestamp = header[5].toFatInt(); timestamp = header[5].toInt<u256>();
nonce = header[6].toFatInt(); nonce = header[6].toInt<u256>();
} }
catch (RLP::BadCast) catch (RLP::BadCast)
{ {

2
libethereum/RLP.cpp

@ -191,7 +191,7 @@ std::ostream& operator<<(std::ostream& _out, eth::RLP _d)
if (_d.isNull()) if (_d.isNull())
_out << "null"; _out << "null";
else if (_d.isInt()) 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()) else if (_d.isString())
_out << eth::escaped(_d.toString(), true); _out << eth::escaped(_d.toString(), true);
else if (_d.isList()) else if (_d.isList())

61
libethereum/RLP.h

@ -35,6 +35,11 @@ namespace eth
class RLP; class RLP;
typedef std::vector<RLP> RLPs; typedef std::vector<RLP> RLPs;
template <class _T> struct intTraits { static const uint maxSize = sizeof(_T); };
template <> struct intTraits<u160> { static const uint maxSize = 20; };
template <> struct intTraits<u256> { static const uint maxSize = 32; };
template <> struct intTraits<bigint> { static const uint maxSize = ~(uint)0; };
/** /**
* @brief Class for interpreting Recursive Linear-Prefix Data. * @brief Class for interpreting Recursive Linear-Prefix Data.
* @by Gav Wood, 2013 * @by Gav Wood, 2013
@ -160,15 +165,41 @@ public:
/// Converts to string. @throws BadCast if not a string. /// 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 (!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. /// Converts to int of type given; if isString(), decodes as big-endian bytestream. @returns 0 if not an int or string.
template <class _T = uint> _T toInt() const template <class _T = uint> _T toInt(int _flags = Strict) const
{ {
if (!isString() && !isInt()) if ((isString() && !(_flags & AllowString)) || (isInt() && !(_flags & AllowInt)) || isList() || isNull())
return 0; if (_flags & ThrowOnFail)
throw BadCast();
else
return 0;
else {}
if (isDirectValueInt()) if (isDirectValueInt())
return m_data[0]; return m_data[0];
_T ret = 0;
auto s = isInt() ? intSize() - lengthSize() : isString() ? items() : 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; uint o = lengthSize() + 1;
for (uint i = 0; i < s; ++i) for (uint i = 0; i < s; ++i)
ret = (ret << 8) | m_data[i + o]; ret = (ret << 8) | m_data[i + o];
@ -176,25 +207,13 @@ public:
} }
/// Converts to eth::uint. @see toInt() /// Converts to eth::uint. @see toInt()
uint toSlimInt() const { return toInt<uint>(); } uint toSlimInt(int _flags = Strict) const { return toInt<uint>(_flags); }
/// Converts to eth::u256. @see toInt() /// Converts to eth::u256. @see toInt()
u256 toFatInt() const { return toInt<u256>(); } u256 toFatInt(int _flags = Strict) const { return toInt<u256>(_flags); }
/// Converts to eth::bigint. @see toInt() /// Converts to eth::bigint. @see toInt()
bigint toBigInt() const { return toInt<bigint>(); } bigint toBigInt(int _flags = Strict) const { return toInt<bigint>(_flags); }
/// Converts to eth::uint. @throws BadCast if not isInt(). @see toInt()
uint toSlimIntStrict() const { if (!isSlimInt()) throw BadCast(); return toInt<uint>(); }
/// Converts to eth::u256. @throws BadCast if not isInt(). @see toInt()
u256 toFatIntStrict() const { if (!isFatInt() && !isSlimInt()) throw BadCast(); return toInt<u256>(); }
/// Converts to eth::bigint. @throws BadCast if not isInt(). @see toInt()
bigint toBigIntStrict() const { if (!isInt()) throw BadCast(); return toInt<bigint>(); }
/// 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<uint>(); }
/// 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<u256>(); }
/// 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>(); }
/// Converts to RLPs collection object. Useful if you need random access to sub items or will iterate over multiple times. /// Converts to RLPs collection object. Useful if you need random access to sub items or will iterate over multiple times.
RLPs toList() const; RLPs toList() const;

11
libethereum/State.cpp

@ -93,8 +93,17 @@ u256 State::contractMemory(Address _contract, u256 _memory) const
return i == m->second.memory().end() ? 0 : i->second; 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; return true;
} }

2
libethereum/State.h

@ -39,7 +39,7 @@ class State
public: public:
explicit State(Address _minerAddress); 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 execute(bytes const& _rlp) { try { Transaction t(_rlp); execute(t, t.sender()); } catch (...) { return false; } }
bool isNormalAddress(Address _address) const; bool isNormalAddress(Address _address) const;

12
libethereum/Transaction.cpp

@ -28,14 +28,14 @@ using namespace eth;
Transaction::Transaction(bytes const& _rlpData) Transaction::Transaction(bytes const& _rlpData)
{ {
RLP rlp(_rlpData); RLP rlp(_rlpData);
nonce = rlp[0].toFatIntStrict(); nonce = rlp[0].toInt<u256>(RLP::StrictlyInt);
receiveAddress = as160(rlp[1].toFatIntFromString()); receiveAddress = rlp[1].toInt<u160>(RLP::StrictlyString);
value = rlp[2].toFatIntStrict(); value = rlp[2].toInt<u256>(RLP::StrictlyInt);
fee = rlp[3].toFatIntStrict(); fee = rlp[3].toInt<u256>(RLP::StrictlyInt);
data.reserve(rlp[4].itemCountStrict()); data.reserve(rlp[4].itemCountStrict());
for (auto const& i: rlp[4]) for (auto const& i: rlp[4])
data.push_back(i.toFatIntStrict()); data.push_back(i.toInt<u256>(RLP::StrictlyInt));
vrs = Signature{ (byte)rlp[5].toSlimIntStrict(), rlp[6].toFatIntStrict(), rlp[7].toFatIntStrict() }; vrs = Signature{ rlp[5].toInt<byte>(RLP::StrictlyInt), rlp[6].toInt<u256>(RLP::StrictlyInt), rlp[7].toInt<u256>(RLP::StrictlyInt) };
} }
Address Transaction::sender() const Address Transaction::sender() const

Loading…
Cancel
Save