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];
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<u256>();
sha256Uncles = header[1].toInt<u256>();
coinbaseAddress = header[2].toInt<u160>();
sha256Transactions = header[3].toInt<u256>();
difficulty = header[4].toInt<uint>();
timestamp = header[5].toInt<u256>();
nonce = header[6].toInt<u256>();
}
catch (RLP::BadCast)
{

2
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())

61
libethereum/RLP.h

@ -35,6 +35,11 @@ namespace eth
class RLP;
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.
* @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 <class _T = uint> _T toInt() const
template <class _T = uint> _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>(); }
uint toSlimInt(int _flags = Strict) const { return toInt<uint>(_flags); }
/// 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()
bigint toBigInt() const { return toInt<bigint>(); }
/// 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>(); }
bigint toBigInt(int _flags = Strict) const { return toInt<bigint>(_flags); }
/// Converts to RLPs collection object. Useful if you need random access to sub items or will iterate over multiple times.
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;
}
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;
}

2
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;

12
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<u256>(RLP::StrictlyInt);
receiveAddress = rlp[1].toInt<u160>(RLP::StrictlyString);
value = rlp[2].toInt<u256>(RLP::StrictlyInt);
fee = rlp[3].toInt<u256>(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<u256>(RLP::StrictlyInt));
vrs = Signature{ rlp[5].toInt<byte>(RLP::StrictlyInt), rlp[6].toInt<u256>(RLP::StrictlyInt), rlp[7].toInt<u256>(RLP::StrictlyInt) };
}
Address Transaction::sender() const

Loading…
Cancel
Save