Browse Source

State integration test.

Fixes to the FatTrie.
cl-refactor
Gav Wood 10 years ago
parent
commit
bae383f617
  1. 43
      CMakeLists.txt
  2. 6
      libdevcore/FixedHash.h
  3. 2
      libdevcore/vector_ref.h
  4. 8
      libdevcrypto/MemoryDB.h
  5. 13
      libdevcrypto/OverlayDB.cpp
  6. 2
      libdevcrypto/OverlayDB.h
  7. 2
      libdevcrypto/TrieDB.h
  8. 2
      libethcore/CommonEth.cpp
  9. 36
      libethereum/Account.h
  10. 15
      libethereum/BlockChain.cpp
  11. 8
      libethereum/State.cpp
  12. 63
      libethereum/State.h
  13. 2
      test/CMakeLists.txt
  14. 36
      test/stateOriginal.cpp
  15. 20
      test/trie.cpp

43
CMakeLists.txt

@ -20,6 +20,7 @@ function(createDefaultCacheConfig)
set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on") set(JSONRPC ON CACHE BOOL "Build with jsonprc. default on")
set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)") set(EVMJIT OFF CACHE BOOL "Build a just-in-time compiler for EVM code (requires LLVM)")
set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.") set(FATDB OFF CACHE BOOL "Build with ability to list entries in the Trie. Doubles DB size, slows everything down, but good for looking at state diffs and trie contents.")
set(JUSTTESTS OFF CACHE BOOL "Build only for tests.")
endfunction() endfunction()
@ -49,7 +50,7 @@ function(configureProject)
add_definitions(-DETH_FATDB) add_definitions(-DETH_FATDB)
endif() endif()
if (HEADLESS) if (HEADLESS OR JUSTTESTS)
add_definitions(-DETH_HEADLESS) add_definitions(-DETH_HEADLESS)
endif() endif()
endfunction() endfunction()
@ -153,8 +154,11 @@ if (NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
endif () endif ()
add_subdirectory(libsolidity) add_subdirectory(libsolidity)
add_subdirectory(lllc)
add_subdirectory(solc) if (NOT JUSTTESTS)
add_subdirectory(lllc)
add_subdirectory(solc)
endif()
if (JSONRPC) if (JSONRPC)
add_subdirectory(libweb3jsonrpc) add_subdirectory(libweb3jsonrpc)
@ -171,24 +175,29 @@ add_subdirectory(libethereum)
add_subdirectory(libwebthree) add_subdirectory(libwebthree)
add_subdirectory(test) add_subdirectory(test)
add_subdirectory(eth)
if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug") if (NOT JUSTTESTS)
add_subdirectory(exp)
endif ()
# TODO check msvc add_subdirectory(eth)
if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
add_subdirectory(neth) if("x${CMAKE_BUILD_TYPE}" STREQUAL "xDebug")
endif () add_subdirectory(exp)
endif ()
# TODO check msvc
if(NOT ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"))
add_subdirectory(neth)
endif ()
if (NOT HEADLESS) if (NOT HEADLESS)
add_subdirectory(libnatspec) add_subdirectory(libnatspec)
add_subdirectory(libjsqrc) add_subdirectory(libjsqrc)
add_subdirectory(alethzero) add_subdirectory(alethzero)
add_subdirectory(third) add_subdirectory(third)
add_subdirectory(mix) add_subdirectory(mix)
endif()
endif() endif()

6
libdevcore/FixedHash.h

@ -65,16 +65,16 @@ public:
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); } FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
/// Explicitly construct, copying from a byte array. /// Explicitly construct, copying from a byte array.
explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
/// Explicitly construct, copying from a byte array. /// Explicitly construct, copying from a byte array.
explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else if (_t != FailIfDifferent) { m_data.fill(0); auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
/// Explicitly construct, copying from a bytes in memory with given pointer. /// Explicitly construct, copying from a bytes in memory with given pointer.
explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); } explicit FixedHash(byte const* _bs, ConstructFromPointerType) { memcpy(m_data.data(), _bs, N); }
/// Explicitly construct, copying from a string. /// Explicitly construct, copying from a string.
explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex): FixedHash(_t == FromHex ? fromHex(_s) : dev::asBytes(_s)) {} explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s) : dev::asBytes(_s), _ht) {}
/// Convert to arithmetic type. /// Convert to arithmetic type.
operator Arith() const { return fromBigEndian<Arith>(m_data); } operator Arith() const { return fromBigEndian<Arith>(m_data); }

2
libdevcore/vector_ref.h

@ -23,7 +23,7 @@ public:
vector_ref(typename std::conditional<std::is_const<_T>::value, std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data): m_data(_data->data()), m_count(_data->size()) {} vector_ref(typename std::conditional<std::is_const<_T>::value, std::vector<typename std::remove_const<_T>::type> const*, std::vector<_T>*>::type _data): m_data(_data->data()), m_count(_data->size()) {}
vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type _data): m_data((_T*)_data.data()), m_count(_data.size() / sizeof(_T)) {} vector_ref(typename std::conditional<std::is_const<_T>::value, std::string const&, std::string&>::type _data): m_data((_T*)_data.data()), m_count(_data.size() / sizeof(_T)) {}
#ifdef STORAGE_LEVELDB_INCLUDE_DB_H_ #ifdef STORAGE_LEVELDB_INCLUDE_DB_H_
vector_ref(leveldb::Slice const& _s): m_data(_s.data()), m_count(_s.size() / sizeof(_T)) {} vector_ref(leveldb::Slice const& _s): m_data(reinterpret_cast<_T*>(_s.data())), m_count(_s.size() / sizeof(_T)) {}
#endif #endif
explicit operator bool() const { return m_data && m_count; } explicit operator bool() const { return m_data && m_count; }

8
libdevcrypto/MemoryDB.h

@ -51,14 +51,18 @@ public:
bool kill(h256 _h); bool kill(h256 _h);
void purge(); void purge();
bytes lookupAux(h256 _h) const { return asBytes(lookup(h256(sha3(_h).ref().cropped(16), h256::AlignRight))); } bytes lookupAux(h256 _h) const { auto h = aux(_h); return m_aux.count(h) ? m_aux.at(h) : bytes(); }
void insertAux(h256 _h, bytesConstRef _v) { return insert(h256(sha3(_h).ref().cropped(16), h256::AlignRight), _v); } void insertAux(h256 _h, bytesConstRef _v) { m_auxKey = aux(_h); m_aux[m_auxKey] = _v.toBytes(); }
std::set<h256> keys() const; std::set<h256> keys() const;
protected: protected:
static h256 aux(h256 _k) { return h256(sha3(_k).ref().cropped(0, 24), h256::AlignLeft); }
std::map<h256, std::string> m_over; std::map<h256, std::string> m_over;
std::map<h256, unsigned> m_refCount; std::map<h256, unsigned> m_refCount;
h256 m_auxKey;
std::map<h256, bytes> m_aux;
mutable bool m_enforceRefs = false; mutable bool m_enforceRefs = false;
}; };

13
libdevcrypto/OverlayDB.cpp

@ -19,6 +19,7 @@
* @date 2014 * @date 2014
*/ */
#include <leveldb/db.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include "OverlayDB.h" #include "OverlayDB.h"
using namespace std; using namespace std;
@ -51,11 +52,23 @@ void OverlayDB::commit()
if (m_refCount[i.first]) if (m_refCount[i.first])
m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size())); m_db->Put(m_writeOptions, ldb::Slice((char const*)i.first.data(), i.first.size), ldb::Slice(i.second.data(), i.second.size()));
} }
if (m_auxKey && m_aux.count(m_auxKey))
m_db->Put(m_writeOptions, m_auxKey.ref(), bytesConstRef(&m_aux[m_auxKey]));
m_over.clear(); m_over.clear();
m_refCount.clear(); m_refCount.clear();
} }
} }
bytes OverlayDB::lookupAux(h256 _h) const
{
bytes ret = MemoryDB::lookupAux(_h);
if (!ret.empty())
return ret;
std::string v;
m_db->Get(m_readOptions, _h.ref(), &v);
return asBytes(v);
}
void OverlayDB::rollback() void OverlayDB::rollback()
{ {
m_over.clear(); m_over.clear();

2
libdevcrypto/OverlayDB.h

@ -51,6 +51,8 @@ public:
bool exists(h256 _h) const; bool exists(h256 _h) const;
void kill(h256 _h); void kill(h256 _h);
bytes lookupAux(h256 _h) const;
private: private:
using MemoryDB::clear; using MemoryDB::clear;

2
libdevcrypto/TrieDB.h

@ -408,7 +408,7 @@ public:
Super::setRoot(h256(Super::db()->lookupAux(m_secure.root()))); Super::setRoot(h256(Super::db()->lookupAux(m_secure.root())));
} }
h256 root() const { return m_secure.root(); } h256 root() const { const_cast<FatGenericTrieDB*>(this)->syncRoot(); return m_secure.root(); }
void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); } void insert(bytesConstRef _key, bytesConstRef _value) { Super::insert(_key, _value); m_secure.insert(_key, _value); syncRoot(); }
void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); } void remove(bytesConstRef _key) { Super::remove(_key); m_secure.remove(_key); syncRoot(); }

2
libethcore/CommonEth.cpp

@ -33,7 +33,7 @@ namespace eth
{ {
const unsigned c_protocolVersion = 55; const unsigned c_protocolVersion = 55;
const unsigned c_databaseVersion = 5 + const unsigned c_databaseVersion = 6 +
#if ETH_FATDB #if ETH_FATDB
1000 1000
#else #else

36
libethereum/Account.h

@ -76,28 +76,40 @@ public:
ContractConception ContractConception
}; };
/// Changedness of account to create.
enum Changedness
{
/// Account starts as though it has been changed.
Changed,
/// Account starts as though it has not been changed.
Unchanged
};
/// Construct a dead Account. /// Construct a dead Account.
Account() {} Account() {}
/// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a /// Construct an alive Account, with given endowment, for either a normal (non-contract) account or for a
/// contract account in the /// contract account in the
/// conception phase, where the code is not yet known. /// conception phase, where the code is not yet known.
Account(u256 _balance, NewAccountType _t): m_isAlive(true), m_balance(_balance), m_codeHash(_t == NormalCreation ? EmptySHA3 : c_contractConceptionCodeHash) {} Account(u256 _balance, NewAccountType _t, Changedness _c = Changed): m_isAlive(true), m_isUnchanged(_c == Unchanged), m_balance(_balance), m_codeHash(_t == NormalCreation ? EmptySHA3 : c_contractConceptionCodeHash) {}
/// Explicit constructor for wierd cases of construction of a normal account. /// Explicit constructor for wierd cases of construction of a normal account.
Account(u256 _nonce, u256 _balance): m_isAlive(true), m_nonce(_nonce), m_balance(_balance) {} Account(u256 _nonce, u256 _balance, Changedness _c = Changed): m_isAlive(true), m_isUnchanged(_c == Unchanged), m_nonce(_nonce), m_balance(_balance) {}
/// Explicit constructor for wierd cases of construction or a contract account. /// Explicit constructor for wierd cases of construction or a contract account.
Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash): m_isAlive(true), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); } Account(u256 _nonce, u256 _balance, h256 _contractRoot, h256 _codeHash, Changedness _c): m_isAlive(true), m_isUnchanged(_c == Unchanged), m_nonce(_nonce), m_balance(_balance), m_storageRoot(_contractRoot), m_codeHash(_codeHash) { assert(_contractRoot); }
/// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false. /// Kill this account. Useful for the suicide opcode. Following this call, isAlive() returns false.
void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; } void kill() { m_isAlive = false; m_storageOverlay.clear(); m_codeHash = EmptySHA3; m_storageRoot = EmptyTrie; m_balance = 0; m_nonce = 0; changed(); }
/// @returns true iff this object represents an account in the state. Returns false if this object /// @returns true iff this object represents an account in the state. Returns false if this object
/// represents an account that should no longer exist in the trie (an account that never existed or was /// represents an account that should no longer exist in the trie (an account that never existed or was
/// suicided). /// suicided).
bool isAlive() const { return m_isAlive; } bool isAlive() const { return m_isAlive; }
/// @returns true if the account is unchanged from creation.
bool isDirty() const { return !m_isUnchanged; }
/// @returns the balance of this account. Can be altered in place. /// @returns the balance of this account. Can be altered in place.
u256& balance() { return m_balance; } u256& balance() { return m_balance; }
@ -106,7 +118,7 @@ public:
u256 const& balance() const { return m_balance; } u256 const& balance() const { return m_balance; }
/// Increments the balance of this account by the given amount. It's a bigint, so can be negative. /// Increments the balance of this account by the given amount. It's a bigint, so can be negative.
void addBalance(bigint _i) { m_balance = (u256)((bigint)m_balance + _i); } void addBalance(bigint _i) { if (!_i) return; m_balance = (u256)((bigint)m_balance + _i); changed(); }
/// @returns the nonce of the account. Can be altered in place. /// @returns the nonce of the account. Can be altered in place.
u256& nonce() { return m_nonce; } u256& nonce() { return m_nonce; }
@ -115,7 +127,7 @@ public:
u256 const& nonce() const { return m_nonce; } u256 const& nonce() const { return m_nonce; }
/// Increment the nonce of the account by one. /// Increment the nonce of the account by one.
void incNonce() { m_nonce++; } void incNonce() { m_nonce++; changed(); }
/// @returns the root of the trie (whose nodes are stored in the state db externally to this class) /// @returns the root of the trie (whose nodes are stored in the state db externally to this class)
@ -127,7 +139,7 @@ public:
/// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing /// Set a key/value pair in the account's storage. This actually goes into the overlay, for committing
/// to the trie later. /// to the trie later.
void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; } void setStorage(u256 _p, u256 _v) { m_storageOverlay[_p] = _v; changed(); }
/// @returns true if we are in the contract-conception state and setCode is valid to call. /// @returns true if we are in the contract-conception state and setCode is valid to call.
bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; } bool isFreshCode() const { return m_codeHash == c_contractConceptionCodeHash; }
@ -140,8 +152,8 @@ public:
h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; } h256 codeHash() const { assert(!isFreshCode()); return m_codeHash; }
/// Sets the code of the account. Must only be called when isFreshCode() returns true. /// Sets the code of the account. Must only be called when isFreshCode() returns true.
void setCode(bytes&& _code) { assert(isFreshCode()); m_codeCache = _code; } void setCode(bytes&& _code) { assert(isFreshCode()); m_codeCache = _code; changed(); }
void setCode(bytes const& _code) { assert(isFreshCode()); m_codeCache = _code; } void setCode(bytes const& _code) { assert(isFreshCode()); m_codeCache = _code; changed(); }
/// @returns true if the account's code is available through code(). /// @returns true if the account's code is available through code().
bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); } bool codeCacheValid() const { return m_codeHash == EmptySHA3 || m_codeHash == c_contractConceptionCodeHash || m_codeCache.size(); }
@ -154,9 +166,15 @@ public:
bytes const& code() const { assert(codeCacheValid()); return m_codeCache; } bytes const& code() const { assert(codeCacheValid()); return m_codeCache; }
private: private:
/// Note that we've altered the account.
void changed() { m_isUnchanged = false; }
/// Is this account existant? If not, it represents a deleted account. /// Is this account existant? If not, it represents a deleted account.
bool m_isAlive = false; bool m_isAlive = false;
/// True if we've not made any alteration to the account having been given it's properties directly.
bool m_isUnchanged = false;
/// Account's nonce. /// Account's nonce.
u256 m_nonce = 0; u256 m_nonce = 0;

15
libethereum/BlockChain.cpp

@ -19,6 +19,8 @@
* @date 2014 * @date 2014
*/ */
#include <leveldb/db.h>
#include "BlockChain.h" #include "BlockChain.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -43,14 +45,17 @@ namespace js = json_spirit;
std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc) std::ostream& dev::eth::operator<<(std::ostream& _out, BlockChain const& _bc)
{ {
string cmp = toBigEndianString(_bc.currentHash()); string cmp = toBigEndianString(_bc.currentHash());
auto it = _bc.m_extrasDB->NewIterator(_bc.m_readOptions); auto it = _bc.m_db->NewIterator(_bc.m_readOptions);
for (it->SeekToFirst(); it->Valid(); it->Next()) for (it->SeekToFirst(); it->Valid(); it->Next())
if (it->key().ToString() != "best") if (it->key().ToString() != "best")
{ {
string rlpString = it->value().ToString(); try {
RLP r(rlpString); BlockInfo d(bytesConstRef(it->value()));
BlockDetails d(r); _out << toHex(it->key().ToString()) << ": " << d.number << " @ " << d.parentHash << (cmp == it->key().ToString() ? " BEST" : "") << std::endl;
_out << toHex(it->key().ToString()) << ": " << d.number << " @ " << d.parent << (cmp == it->key().ToString() ? " BEST" : "") << std::endl; }
catch (...) {
cwarn << "Invalid DB entry:" << toHex(it->key().ToString()) << " -> " << toHex(bytesConstRef(it->value()));
}
} }
delete it; delete it;
return _out; return _out;

8
libethereum/State.cpp

@ -224,7 +224,7 @@ void State::ensureCached(std::map<Address, Account>& _cache, Address _a, bool _r
if (state.isNull()) if (state.isNull())
s = Account(0, Account::NormalCreation); s = Account(0, Account::NormalCreation);
else else
s = Account(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>()); s = Account(state[0].toInt<u256>(), state[1].toInt<u256>(), state[2].toHash<h256>(), state[3].toHash<h256>(), Account::Unchanged);
bool ok; bool ok;
tie(it, ok) = _cache.insert(make_pair(_a, s)); tie(it, ok) = _cache.insert(make_pair(_a, s));
} }
@ -625,7 +625,7 @@ void State::uncommitToMine()
if (!m_transactions.size()) if (!m_transactions.size())
m_state.setRoot(m_previousBlock.stateRoot); m_state.setRoot(m_previousBlock.stateRoot);
else else
m_state.setRoot(m_receipts[m_receipts.size() - 1].stateRoot()); m_state.setRoot(m_receipts.back().stateRoot());
m_db = m_lastTx; m_db = m_lastTx;
paranoia("Uncommited to mine", true); paranoia("Uncommited to mine", true);
m_currentBlock.sha3Uncles = h256(); m_currentBlock.sha3Uncles = h256();
@ -890,7 +890,7 @@ Address State::newContract(u256 _balance, bytes const& _code)
auto it = m_cache.find(ret); auto it = m_cache.find(ret);
if (it == m_cache.end()) if (it == m_cache.end())
{ {
m_cache[ret] = Account(0, _balance, EmptyTrie, h); m_cache[ret] = Account(0, _balance, EmptyTrie, h, Account::Changed);
return ret; return ret;
} }
} }
@ -1144,7 +1144,7 @@ std::ostream& dev::eth::operator<<(std::ostream& _out, State const& _s)
_out << "--- " << _s.rootHash() << std::endl; _out << "--- " << _s.rootHash() << std::endl;
std::set<Address> d; std::set<Address> d;
std::set<Address> dtr; std::set<Address> dtr;
auto trie = TrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_s.m_db), _s.rootHash()); auto trie = SecureTrieDB<Address, OverlayDB>(const_cast<OverlayDB*>(&_s.m_db), _s.rootHash());
for (auto i: trie) for (auto i: trie)
d.insert(i.first), dtr.insert(i.first); d.insert(i.first), dtr.insert(i.first);
for (auto i: _s.m_cache) for (auto i: _s.m_cache)

63
libethereum/State.h

@ -328,40 +328,43 @@ template <class DB>
void commit(std::map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state) void commit(std::map<Address, Account> const& _cache, DB& _db, SecureTrieDB<Address, DB>& _state)
{ {
for (auto const& i: _cache) for (auto const& i: _cache)
if (!i.second.isAlive()) if (i.second.isDirty())
_state.remove(i.first);
else
{ {
RLPStream s(4); if (!i.second.isAlive())
s << i.second.nonce() << i.second.balance(); _state.remove(i.first);
if (i.second.storageOverlay().empty())
{
assert(i.second.baseRoot());
s.append(i.second.baseRoot());
}
else else
{ {
SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot()); RLPStream s(4);
for (auto const& j: i.second.storageOverlay()) s << i.second.nonce() << i.second.balance();
if (j.second)
storageDB.insert(j.first, rlp(j.second)); if (i.second.storageOverlay().empty())
else {
storageDB.remove(j.first); assert(i.second.baseRoot());
assert(storageDB.root()); s.append(i.second.baseRoot());
s.append(storageDB.root()); }
} else
{
if (i.second.isFreshCode()) SecureTrieDB<h256, DB> storageDB(&_db, i.second.baseRoot());
{ for (auto const& j: i.second.storageOverlay())
h256 ch = sha3(i.second.code()); if (j.second)
_db.insert(ch, &i.second.code()); storageDB.insert(j.first, rlp(j.second));
s << ch; else
storageDB.remove(j.first);
assert(storageDB.root());
s.append(storageDB.root());
}
if (i.second.isFreshCode())
{
h256 ch = sha3(i.second.code());
_db.insert(ch, &i.second.code());
s << ch;
}
else
s << i.second.codeHash();
_state.insert(i.first, &s.out());
} }
else
s << i.second.codeHash();
_state.insert(i.first, &s.out());
} }
} }

2
test/CMakeLists.txt

@ -26,7 +26,7 @@ target_link_libraries(testeth ethereum)
target_link_libraries(testeth ethcore) target_link_libraries(testeth ethcore)
target_link_libraries(testeth secp256k1) target_link_libraries(testeth secp256k1)
target_link_libraries(testeth solidity) target_link_libraries(testeth solidity)
if (NOT HEADLESS) if (NOT HEADLESS AND NOT JUSTTESTS)
target_link_libraries(testeth webthree) target_link_libraries(testeth webthree)
target_link_libraries(testeth natspec) target_link_libraries(testeth natspec)
endif() endif()

36
test/stateOriginal.cpp

@ -20,6 +20,7 @@
* State test functions. * State test functions.
*/ */
#include <boost/test/unit_test.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <secp256k1/secp256k1.h> #include <secp256k1/secp256k1.h>
#include <libethereum/CanonBlockChain.h> #include <libethereum/CanonBlockChain.h>
@ -29,7 +30,21 @@ using namespace std;
using namespace dev; using namespace dev;
using namespace dev::eth; using namespace dev::eth;
int stateTest() namespace dev
{
namespace test
{
int stateTest();
BOOST_AUTO_TEST_SUITE(StateIntegration)
BOOST_AUTO_TEST_CASE(Basic)
{
State s;
}
BOOST_AUTO_TEST_CASE(Complex)
{ {
cnote << "Testing State..."; cnote << "Testing State...";
@ -37,14 +52,15 @@ int stateTest()
KeyPair myMiner = sha3("Gav's Miner"); KeyPair myMiner = sha3("Gav's Miner");
// KeyPair you = sha3("123"); // KeyPair you = sha3("123");
Defaults::setDBPath(boost::filesystem::temp_directory_path().string()); Defaults::setDBPath(boost::filesystem::temp_directory_path().string() + "/" + toString(chrono::system_clock::now().time_since_epoch().count()));
OverlayDB stateDB = State::openDB(); OverlayDB stateDB = State::openDB();
CanonBlockChain bc; CanonBlockChain bc;
State s(myMiner.address(), stateDB);
cout << bc; cout << bc;
State s(myMiner.address(), stateDB);
cout << s;
// Sync up - this won't do much until we use the last state. // Sync up - this won't do much until we use the last state.
s.sync(bc); s.sync(bc);
@ -52,7 +68,7 @@ int stateTest()
// Mine to get some ether! // Mine to get some ether!
s.commitToMine(bc); s.commitToMine(bc);
while (!s.mine(100).completed) {} while (!s.mine(100, true).completed) {}
s.completeMine(); s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);
@ -65,7 +81,7 @@ int stateTest()
// Inject a transaction to transfer funds from miner to me. // Inject a transaction to transfer funds from miner to me.
bytes tx; bytes tx;
{ {
Transaction t(1000, 0, 0, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret()); Transaction t(1000, 10000, 10000, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret());
assert(t.sender() == myMiner.address()); assert(t.sender() == myMiner.address());
tx = t.rlp(); tx = t.rlp();
} }
@ -76,7 +92,7 @@ int stateTest()
// Mine to get some ether and set in stone. // Mine to get some ether and set in stone.
s.commitToMine(bc); s.commitToMine(bc);
s.commitToMine(bc); s.commitToMine(bc);
while (!s.mine(50).completed) { s.commitToMine(bc); } while (!s.mine(100, true).completed) {}
s.completeMine(); s.completeMine();
bc.attemptImport(s.blockData(), stateDB); bc.attemptImport(s.blockData(), stateDB);
@ -85,7 +101,9 @@ int stateTest()
s.sync(bc); s.sync(bc);
cout << s; cout << s;
return 0;
} }
BOOST_AUTO_TEST_SUITE_END()
}
}

20
test/trie.cpp

@ -52,6 +52,26 @@ using dev::operator <<;
BOOST_AUTO_TEST_SUITE(TrieTests) BOOST_AUTO_TEST_SUITE(TrieTests)
BOOST_AUTO_TEST_CASE(fat_trie)
{
h256 r;
MemoryDB fm;
{
FatGenericTrieDB<MemoryDB> ft(&fm);
ft.init();
ft.insert(h256("69", h256::FromHex, h256::AlignRight).ref(), h256("414243", h256::FromHex, h256::AlignRight).ref());
for (auto i: ft)
cnote << i.first << i.second;
r = ft.root();
}
{
FatGenericTrieDB<MemoryDB> ft(&fm);
ft.setRoot(r);
for (auto i: ft)
cnote << i.first << i.second;
}
}
BOOST_AUTO_TEST_CASE(trie_test_anyorder) BOOST_AUTO_TEST_CASE(trie_test_anyorder)
{ {
string testPath = test::getTestPath(); string testPath = test::getTestPath();

Loading…
Cancel
Save