Browse Source

Tests updated.

Fixes to executive logging.
Trie testing made considerably more rigourous.
cl-refactor
Gav Wood 11 years ago
parent
commit
ea660501d7
  1. 72
      libethereum/Executive.cpp
  2. 7
      libethereum/Executive.h
  3. 9
      libethsupport/TrieDB.cpp
  4. 44
      libethsupport/TrieDB.h
  5. 9
      lllc/main.cpp
  6. 9
      test/main.cpp

72
libethereum/Executive.cpp

@ -26,6 +26,37 @@
using namespace std;
using namespace eth;
string eth::memDump(bytes const& _b, unsigned _w, bool _html)
{
stringstream ret;
if (_html)
ret << "<pre style=\"font-family: Monospace, sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 128)
if ((char)_b[j] == '<' && _html)
ret << "&lt;";
else if ((char)_b[j] == '&' && _html)
ret << "&amp;";
else
ret << (char)_b[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
ret << "\n";
}
if (_html)
ret << "</pre>";
return ret.str();
}
Executive::~Executive()
{
// TODO: Make safe.
@ -49,14 +80,14 @@ void Executive::setup(bytesConstRef _rlp)
auto nonceReq = m_s.transactionsFrom(m_sender);
if (m_t.nonce != nonceReq)
{
clog(StateChat) << "Invalid Nonce.";
clog(StateChat) << "Invalid Nonce: Require" << nonceReq << " Got" << m_t.nonce;
throw InvalidNonce(nonceReq, m_t.nonce);
}
// Don't like transactions whose gas price is too low. NOTE: this won't stay here forever - it's just until we get a proper gas price discovery protocol going.
if (m_t.gasPrice < m_s.m_currentBlock.minGasPrice)
{
clog(StateChat) << "Offered gas-price is too low.";
clog(StateChat) << "Offered gas-price is too low: Require >" << m_s.m_currentBlock.minGasPrice << " Got" << m_t.gasPrice;
throw GasPriceTooLow();
}
@ -65,7 +96,7 @@ void Executive::setup(bytesConstRef _rlp)
if (m_t.gas < gasCost)
{
clog(StateChat) << "Not enough gas to pay for the transaction.";
clog(StateChat) << "Not enough gas to pay for the transaction: Require >" << gasCost << " Got" << m_t.gas;
throw OutOfGas();
}
@ -74,7 +105,7 @@ void Executive::setup(bytesConstRef _rlp)
// Avoid unaffordable transactions.
if (m_s.balance(m_sender) < cost)
{
clog(StateChat) << "Not enough cash.";
clog(StateChat) << "Not enough cash: Require >" << cost << " Got" << m_s.balance(m_sender);
throw NotEnoughCash();
}
@ -120,39 +151,6 @@ void Executive::create(Address _sender, u256 _endowment, u256 _gasPrice, u256 _g
m_ext = new ExtVM(m_s, m_newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _init);
}
struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; };
string memDump(bytes const& _b, unsigned _w = 8, bool _html = false)
{
stringstream ret;
if (_html)
ret << "<pre style=\"font-family: Monospace, sans-serif; font-size: small\">";
for (unsigned i = 0; i < _b.size(); i += _w)
{
ret << hex << setw(4) << setfill('0') << i << " ";
for (unsigned j = i; j < i + _w; ++j)
if (j < _b.size())
if (_b[j] >= 32 && _b[j] < 128)
if ((char)_b[j] == '<' && _html)
ret << "&lt;";
else if ((char)_b[j] == '&' && _html)
ret << "&amp;";
else
ret << (char)_b[j];
else
ret << '?';
else
ret << ' ';
ret << " ";
for (unsigned j = i; j < i + _w && j < _b.size(); ++j)
ret << setfill('0') << setw(2) << hex << (unsigned)_b[j] << " ";
ret << "\n";
}
if (_html)
ret << "</pre>";
return ret.str();
}
bool Executive::go(uint64_t _steps)
{
if (m_vm)

7
libethereum/Executive.h

@ -21,6 +21,7 @@
#pragma once
#include <libethsupport/Log.h>
#include <libethcore/CommonEth.h>
#include "Transaction.h"
@ -31,6 +32,10 @@ class VM;
class ExtVM;
class State;
struct VMTraceChannel: public LogChannel { static const char* name() { return "EVM"; } static const int verbosity = 11; };
std::string memDump(bytes const& _b, unsigned _w = 8, bool _html = false);
class Executive
{
public:
@ -40,7 +45,7 @@ public:
void setup(bytesConstRef _transaction);
void create(Address _txSender, u256 _endowment, u256 _gasPrice, u256 _gas, bytesConstRef _code, Address _originAddress);
void call(Address _myAddress, Address _txSender, u256 _txValue, u256 _gasPrice, bytesConstRef _txData, u256 _gas, Address _originAddress);
bool go(uint64_t _steps = (unsigned)-1);
bool go(uint64_t _steps = (uint64_t)-1);
void finalize();
u256 gasUsed() const;

9
libethsupport/TrieDB.cpp

@ -94,6 +94,15 @@ void BasicMap::purge()
m_over.erase(i.first);
}
set<h256> BasicMap::keys() const
{
set<h256> ret;
for (auto const& i: m_refCount)
if (i.second)
ret.insert(i.first);
return ret;
}
Overlay::~Overlay()
{
if (m_db.use_count() == 1 && m_db.get())

44
libethsupport/TrieDB.h

@ -51,6 +51,8 @@ public:
bool kill(h256 _h);
void purge();
std::set<h256> keys() const;
protected:
std::map<h256, std::string> m_over;
std::map<h256, uint> m_refCount;
@ -158,6 +160,48 @@ public:
void debugPrint() {}
void descendKey(h256 _k, std::set<h256>& _keyMask) const
{
_keyMask.erase(_k);
if (_k == m_root && _k == EmptySHA3) // root allowed to be empty
return;
descend(RLP(node(_k)), _keyMask);
}
void descendEntry(RLP const& _r, std::set<h256>& _keyMask) const
{
if (_r.isData() && _r.size() == 32)
descendKey(_r.toHash<h256>(), _keyMask);
else if (_r.isList())
descend(_r, _keyMask);
else
throw InvalidTrie();
}
void descend(RLP const& _r, std::set<h256>& _keyMask) const
{
if (_r.isList() && _r.size() == 2)
{
if (!isLeaf(_r)) // don't go down leaves
descendEntry(_r[1], _keyMask);
}
else if (_r.isList() && _r.size() == 17)
{
for (unsigned i = 0; i < 16; ++i)
if (!_r[i].isEmpty()) // 16 branches are allowed to be empty
descendEntry(_r[i], _keyMask);
}
else
throw InvalidTrie();
}
std::set<h256> check() const
{
std::set<h256> k = m_db->keys();
descendKey(m_root, k);
return k;
}
std::string at(bytesConstRef _key) const;
void insert(bytesConstRef _key, bytesConstRef _value);
void remove(bytesConstRef _key);

9
lllc/main.cpp

@ -25,6 +25,7 @@
#include <liblll/Compiler.h>
#include <libethsupport/CommonIO.h>
#include <libethsupport/CommonData.h>
#include <libethcore/Instruction.h>
#include "BuildInfo.h"
using namespace std;
using namespace eth;
@ -51,7 +52,7 @@ void version()
exit(0);
}
enum Mode { Binary, Hex, Assembly, ParseTree };
enum Mode { Binary, Hex, Assembly, ParseTree, Disassemble };
int main(int argc, char** argv)
{
@ -74,6 +75,8 @@ int main(int argc, char** argv)
mode = ParseTree;
else if ((arg == "-o" || arg == "--optimise") && argc > i + 1)
optimise = atoi(argv[++i]);
else if (arg == "-d" || arg == "--disassemble")
mode = Disassemble;
else if (arg == "-V" || arg == "--version")
version();
else
@ -96,6 +99,10 @@ int main(int argc, char** argv)
vector<string> errors;
if (src.empty())
cerr << "Empty file." << endl;
else if (mode == Disassemble)
{
cout << disassemble(fromHex(src)) << endl;
}
else if (mode == Binary || mode == Hex)
{
auto bs = compileLLL(src, optimise ? true : false, &errors);

9
test/main.cpp

@ -42,15 +42,18 @@ using namespace eth;
BOOST_AUTO_TEST_CASE(basic_tests)
{
cdebug << "Stress-testing Trie...";
{
BasicMap m;
EnforceRefs e(m, true);
GenericTrieDB<BasicMap> d(&m);
d.init(); // initialise as empty tree.
MemTrie t;
for (int a = 0; a < 20; ++a)
assert(d.check().empty());
for (int a = 0; a < 100; ++a)
{
StringMap m;
for (int i = 0; i < 20; ++i)
for (int i = 0; i < 100; ++i)
{
auto k = randomWord();
auto v = toString(i);
@ -59,6 +62,7 @@ BOOST_AUTO_TEST_CASE(basic_tests)
d.insert(k, v);
assert(hash256(m) == t.hash256());
assert(hash256(m) == d.root());
assert(d.check().empty());
}
while (!m.empty())
{
@ -68,6 +72,7 @@ BOOST_AUTO_TEST_CASE(basic_tests)
m.erase(k);
assert(hash256(m) == t.hash256());
assert(hash256(m) == d.root());
assert(d.check().empty());
}
}
}

Loading…
Cancel
Save