Browse Source

Merge remote-tracking branch 'upstream/develop' into NewStateTests

cl-refactor
CJentzsch 10 years ago
parent
commit
4a7d141452
  1. 89
      exp/main.cpp
  2. 19
      libethcore/BlockInfo.cpp
  3. 2
      libethcore/BlockInfo.h
  4. 1
      libethereum/ExtVM.h
  5. 39
      libethereum/State.cpp
  6. 23
      libethereum/State.h
  7. 2
      test/solidityEndToEndTest.cpp

89
exp/main.cpp

@ -28,6 +28,8 @@
#include <libp2p/All.h>
#include <libdevcore/RangeMask.h>
#include <libethereum/DownloadMan.h>
#include <libethereum/All.h>
#include <liblll/All.h>
#include <libwhisper/WhisperPeer.h>
#include <libwhisper/WhisperHost.h>
using namespace std;
@ -36,7 +38,7 @@ using namespace dev::eth;
using namespace dev::p2p;
using namespace dev::shh;
#if 1
#if 0
int main()
{
DownloadMan man;
@ -72,72 +74,25 @@ int main()
cnote << i;*/
return 0;
}
#endif
/*int other(bool& o_started)
#else
int main()
{
setThreadName("other");
short listenPort = 30300;
Host ph("Test", NetworkPreferences(listenPort, "", false, true));
auto wh = ph.registerCapability(new WhisperHost());
ph.start();
o_started = true;
/// Only interested in odd packets
auto w = wh->installWatch(BuildTopicMask()("odd"));
unsigned last = 0;
unsigned total = 0;
for (int i = 0; i < 100 && last < 81; ++i)
{
for (auto i: wh->checkWatch(w))
{
Message msg = wh->envelope(i).open();
last = RLP(msg.payload()).toInt<unsigned>();
cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt<unsigned>();
total += last;
}
this_thread::sleep_for(chrono::milliseconds(50));
}
return total;
KeyPair u = KeyPair::create();
KeyPair cb = KeyPair::create();
OverlayDB db;
State s(cb.address(), db, BaseState::Empty);
cnote << s.rootHash();
s.addBalance(u.address(), 1 * ether);
Address c = s.newContract(1000 * ether, compileLLL("(suicide (caller))"));
s.commit();
State before = s;
cnote << "State before transaction: " << before;
Transaction t(0, 10000, 10000, c, bytes(), 0, u.secret());
cnote << "Transaction: " << t;
cnote << s.balance(c);
s.execute(t.rlp());
cnote << "State after transaction: " << s;
cnote << before.diff(s);
}
#endif
int main(int, char**)
{
g_logVerbosity = 0;
bool started = false;
unsigned result;
std::thread listener([&](){ return (result = other(started)); });
while (!started)
this_thread::sleep_for(chrono::milliseconds(50));
short listenPort = 30303;
string remoteHost = "127.0.0.1";
short remotePort = 30300;
Host ph("Test", NetworkPreferences(listenPort, "", false, true));
auto wh = ph.registerCapability(new WhisperHost());
ph.start();
if (!remoteHost.empty())
ph.connect(remoteHost, remotePort);
KeyPair us = KeyPair::create();
for (int i = 0; i < 10; ++i)
{
wh->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even"));
this_thread::sleep_for(chrono::milliseconds(250));
}
listener.join();
assert(result == 1 + 9 + 25 + 49 + 81);
return 0;
}*/

19
libethcore/BlockInfo.cpp

@ -40,6 +40,25 @@ BlockInfo::BlockInfo(bytesConstRef _block, bool _checkNonce)
populate(_block, _checkNonce);
}
void BlockInfo::setEmpty()
{
parentHash = h256();
sha3Uncles = EmptyListSHA3;
coinbaseAddress = Address();
stateRoot = EmptyTrie;
transactionsRoot = EmptyTrie;
receiptsRoot = EmptyTrie;
logBloom = LogBloom();
difficulty = 0;
number = 0;
gasLimit = 0;
gasUsed = 0;
timestamp = 0;
extraData.clear();
nonce = h256();
hash = headerHash(WithNonce);
}
BlockInfo BlockInfo::fromHeader(bytesConstRef _block)
{
BlockInfo ret;

2
libethcore/BlockInfo.h

@ -108,6 +108,8 @@ public:
}
bool operator!=(BlockInfo const& _cmp) const { return !operator==(_cmp); }
void setEmpty();
void populateFromHeader(RLP const& _header, bool _checkNonce = true);
void populate(bytesConstRef _block, bool _checkNonce = true);
void populate(bytes const& _block, bool _checkNonce = true) { populate(&_block, _checkNonce); }

1
libethereum/ExtVM.h

@ -73,6 +73,7 @@ public:
virtual void suicide(Address _a) override final
{
m_s.addBalance(_a, m_s.balance(myAddress));
m_s.subBalance(myAddress, m_s.balance(myAddress));
ExtVMFace::suicide(_a);
}

39
libethereum/State.cpp

@ -63,7 +63,7 @@ OverlayDB State::openDB(std::string _path, bool _killExisting)
return OverlayDB(db);
}
State::State(Address _coinbaseAddress, OverlayDB const& _db):
State::State(Address _coinbaseAddress, OverlayDB const& _db, BaseState _bs):
m_db(_db),
m_state(&m_db),
m_ourAddress(_coinbaseAddress),
@ -74,12 +74,19 @@ State::State(Address _coinbaseAddress, OverlayDB const& _db):
paranoia("beginning of normal construction.", true);
dev::eth::commit(genesisState(), m_db, m_state);
m_db.commit();
if (_bs == BaseState::Genesis)
{
dev::eth::commit(genesisState(), m_db, m_state);
m_db.commit();
paranoia("after DB commit of normal construction.", true);
paranoia("after DB commit of normal construction.", true);
m_previousBlock = BlockChain::genesis();
}
else
{
m_previousBlock.setEmpty();
}
m_previousBlock = BlockChain::genesis();
resetCurrent();
assert(m_state.root() == m_previousBlock.stateRoot);
@ -857,6 +864,23 @@ void State::subBalance(Address _id, bigint _amount)
it->second.addBalance(-_amount);
}
Address State::newContract(u256 _balance, bytes const& _code)
{
auto h = sha3(_code);
m_db.insert(h, &_code);
while (true)
{
Address ret = Address::random();
ensureCached(ret, false, false);
auto it = m_cache.find(ret);
if (it == m_cache.end())
{
m_cache[ret] = Account(0, _balance, EmptyTrie, h);
return ret;
}
}
}
u256 State::transactionsFrom(Address _id) const
{
ensureCached(_id, false, false);
@ -993,8 +1017,11 @@ u256 State::execute(bytesConstRef _rlp, bytes* o_output, bool _commit)
ctrace << "Executing" << e.t() << "on" << h;
ctrace << toHex(e.t().rlp());
#endif
#if ETH_TRACE
e.go(e.simpleTrace());
#else
e.go();
#endif
e.finalize();
#if ETH_PARANOIA

23
libethereum/State.h

@ -53,6 +53,8 @@ struct StateTrace: public LogChannel { static const char* name() { return "=S=";
struct StateDetail: public LogChannel { static const char* name() { return "/S/"; } static const int verbosity = 14; };
struct StateSafeExceptions: public LogChannel { static const char* name() { return "(S)"; } static const int verbosity = 21; };
enum class BaseState { Empty, Genesis };
/**
* @brief Model of the current state of the ledger.
* Maintains current ledger (m_current) as a fast hash-map. This is hashed only when required (i.e. to create or verify a block).
@ -66,7 +68,7 @@ class State
public:
/// Construct state object.
State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB());
State(Address _coinbaseAddress = Address(), OverlayDB const& _db = OverlayDB(), BaseState _bs = BaseState::Genesis);
/// Construct state object from arbitrary point in blockchain.
State(OverlayDB const& _db, BlockChain const& _bc, h256 _hash);
@ -183,6 +185,9 @@ public:
/// Set the value of a storage position of an account.
void setStorage(Address _contract, u256 _location, u256 _value) { m_cache[_contract].setStorage(_location, _value); }
/// Create a new contract.
Address newContract(u256 _balance, bytes const& _code);
/// Get the storage of an account.
/// @note This is expensive. Don't use it unless you need to.
/// @returns std::map<u256, u256> if no account exists at that address.
@ -244,6 +249,12 @@ public:
/// the block since all state changes are ultimately reversed.
void cleanup(bool _fullCommit);
/// Commit all changes waiting in the address cache to the DB.
void commit();
/// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock).
void resetCurrent();
private:
/// Undo the changes to the state for committing to mine.
void uncommitToMine();
@ -257,25 +268,19 @@ private:
/// Retrieve all information about a given address into a cache.
void ensureCached(std::map<Address, Account>& _cache, Address _a, bool _requireCode, bool _forceCreate) const;
/// Commit all changes waiting in the address cache to the DB.
void commit();
/// Execute the given block, assuming it corresponds to m_currentBlock. If _bc is passed, it will be used to check the uncles.
/// Throws on failure.
u256 enact(bytesConstRef _block, BlockChain const* _bc = nullptr, bool _checkNonce = true);
/// Sets m_currentBlock to a clean state, (i.e. no change from m_previousBlock).
void resetCurrent();
/// Finalise the block, applying the earned rewards.
void applyRewards(Addresses const& _uncleAddresses);
void refreshManifest(RLPStream* _txs = nullptr);
/// @returns gas used by transactions thus far executed.
u256 gasUsed() const { return m_receipts.size() ? m_receipts.back().gasUsed() : 0; }
/// Debugging only. Good for checking the Trie is in shape.
bool isTrieGood(bool _enforceRefs, bool _requireNoLeftOvers) const;
/// Debugging only. Good for checking the Trie is in shape.
void paranoia(std::string const& _when, bool _enforceRefs = false) const;
OverlayDB m_db; ///< Our overlay for the state tree.

2
test/solidityEndToEndTest.cpp

@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE(empty_string_on_stack)
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, 0x61/*'a'*/, 0x62/*'b'*/, 0x63/*'c'*/, 0x00}));
BOOST_CHECK(callContractFunction(0, bytes(1, 0x02)) == bytes({0x00, 0x02, 0x61/*'a'*/, 0x62/*'b'*/, 0x63/*'c'*/, 0x00}));
}
BOOST_AUTO_TEST_CASE(state_smoke_test)

Loading…
Cancel
Save