Browse Source

Allow arbitrary state in genesis block.

cl-refactor
Gav Wood 11 years ago
parent
commit
bfd10936fb
  1. 16
      libethereum/BlockInfo.cpp
  2. 25
      libethereum/Common.cpp
  3. 80
      libethereum/Common.h
  4. 49
      libethereum/State.cpp
  5. 33
      libethereum/State.h

16
libethereum/BlockInfo.cpp

@ -23,6 +23,7 @@
#include "Dagger.h"
#include "Exceptions.h"
#include "RLP.h"
#include "State.h"
#include "BlockInfo.h"
using namespace std;
using namespace eth;
@ -42,7 +43,20 @@ bytes BlockInfo::createGenesisBlock()
{
RLPStream block(3);
auto sha3EmptyList = sha3(RLPEmptyList);
block.appendList(9) << h256() << sha3EmptyList << h160() << h256() << sha3EmptyList << c_genesisDifficulty << (uint)0 << string() << (uint)0;
h256 stateRoot;
{
BasicMap db;
TrieDB<Address, BasicMap> state(&db);
state.init();
eth::commit(genesisState(), db, state);
stateRoot = state.root();
cout << "--- Genesis state_root=" << stateRoot << endl;
clog << state;
clog << db;
}
block.appendList(9) << h256() << sha3EmptyList << h160() << stateRoot << sha3EmptyList << c_genesisDifficulty << (uint)0 << string() << (uint)0;
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();

25
libethereum/Common.cpp

@ -36,11 +36,26 @@
using namespace std;
using namespace eth;
#if NDEBUG
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#else
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#endif
// Logging
bool eth::g_debugEnabled[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, true, true, true, true, true};
char const* g_debugName[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ">>>", "<<<", "LOG", "---", "***", "!!!"};
void eth::simpleDebugOut(std::string const& _s, unsigned char _id)
{
// TODO: Time & thread.
if (g_debugEnabled[_id])
std::cout << (g_debugName[_id] ? g_debugName[_id] : " ") << " " << _s << std::endl << std::flush;
}
std::function<void(std::string const&, unsigned char)> eth::g_debugPost = simpleDebugOut;
std::function<void(char, std::string const&)> eth::g_syslogPost =
[](char _c, string const& _s)
{
if (_c == 'C')
simpleDebugOut(_s, LogChannel);
else
simpleDebugOut("<binary>", LogChannel);
};
std::string eth::escaped(std::string const& _s, bool _all)
{

80
libethereum/Common.h

@ -61,8 +61,6 @@ using u160s = std::vector<u160>;
using u256Set = std::set<u256>;
using u160Set = std::set<u160>;
extern const u256 c_genesisDifficulty;
template <class T, class Out> inline void toBigEndian(T _val, Out& o_out);
template <class T, class In> inline T fromBigEndian(In const& _bytes);
@ -139,6 +137,84 @@ using HexMap = std::map<bytes, std::string>;
static const u256 Invalid256 = ~(u256)0;
static const bytes NullBytes;
/// Logging
class NullOutputStream
{
public:
template <class T> NullOutputStream& operator<<(T const&) { return *this; }
};
extern bool g_debugEnabled[256];
static const uint8_t WarnChannel = 255;
static const uint8_t NoteChannel = 254;
static const uint8_t DebugChannel = 253;
static const uint8_t LogChannel = 252;
static const uint8_t LeftChannel = 251;
static const uint8_t RightChannel = 250;
// Unused for now.
/*template <uint8_t _Channel> struct LogName { static const char constexpr* name = " "; };
template <> struct LogName<LeftChannel> { static const char constexpr* name = "<<<"; };
template <> struct LogName<RightChannel> { static const char constexpr* name = ">>>"; };
template <> struct LogName<WarnChannel> { static const char constexpr* name = "!!!"; };
template <> struct LogName<NoteChannel> { static const char constexpr* name = "***"; };
template <> struct LogName<DebugChannel> { static const char constexpr* name = "---"; };
template <> struct LogName<LogChannel> { static const char constexpr* name = "LOG"; };*/
extern std::function<void(std::string const&, unsigned char)> g_debugPost;
extern std::function<void(char, std::string const&)> g_syslogPost;
void simpleDebugOut(std::string const&, unsigned char);
template <unsigned char _Id = 0, bool _AutoSpacing = true>
class DebugOutputStream
{
public:
DebugOutputStream(char const* _start = " ") { sstr << _start; }
~DebugOutputStream() { g_debugPost(sstr.str(), _Id); }
template <class T> DebugOutputStream& operator<<(T const& _t) { if (_AutoSpacing && sstr.str().size() && sstr.str().back() != ' ') sstr << " "; sstr << _t; return *this; }
std::stringstream sstr;
};
template <bool _AutoSpacing = true>
class SysLogOutputStream
{
public:
SysLogOutputStream() {}
~SysLogOutputStream() { if (sstr.str().size()) g_syslogPost('C', sstr.str()); }
template <class T> SysLogOutputStream& operator<<(T const& _t) { if (_AutoSpacing && sstr.str().size() && sstr.str().back() != ' ') sstr << " "; sstr << _t; return *this; }
static void write(char _type, std::string const& _s) { g_syslogPost(_type, _s); }
template <class _T> static void writePod(char _type, _T const& _s) { char const* begin = (char const*)&_s; char const* end = (char const*)&_s + sizeof(_T); g_syslogPost(_type, std::string(begin, end)); }
std::stringstream sstr;
};
// Dirties the global namespace, but oh so convenient...
#define cnote eth::DebugOutputStream<eth::NoteChannel, true>()
#define cwarn eth::DebugOutputStream<eth::WarnChannel, true>()
#define nbug(X) if (true) {} else eth::NullOutputStream()
#define nsbug(X) if (true) {} else eth::NullOutputStream()
#define ndebug if (true) {} else eth::NullOutputStream()
#if NDEBUG
#define cbug(X) nbug(X)
#define csbug(X) nsbug(X)
#define cdebug ndebug
#else
#define cbug(X) eth::DebugOutputStream<X>()
#define csbug(X) eth::DebugOutputStream<X, false>()
#define cdebug eth::DebugOutputStream<lb::DebugChannel, true>()
#endif
#define clog eth::SysLogOutputStream<true>()
/// Converts arbitrary value to string representation using std::stringstream.
template <class _T>
std::string toString(_T const& _t)

49
libethereum/State.cpp

@ -53,6 +53,24 @@ u256 const State::c_newContractFee = 60000;
u256 const State::c_txFee = 0;
u256 const State::c_blockReward = 1000000000;
#if NDEBUG
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#else
u256 const eth::c_genesisDifficulty = (u256)1 << 22;
#endif
std::map<Address, AddressState> const& eth::genesisState()
{
static std::map<Address, AddressState> s_ret;
if (s_ret.empty())
{
// Initialise.
s_ret[Address(fromUserHex("812413ae7e515a3bcaf7b3444116527bce958c02"))] = AddressState(u256(1) << 200, 0);
s_ret[Address(fromUserHex("93658b04240e4bd4046fd2d6d417d20f146f4b43"))] = AddressState(u256(1) << 200, 0);
}
return s_ret;
}
Overlay State::openDB(std::string _path, bool _killExisting)
{
if (_path.empty())
@ -71,9 +89,16 @@ Overlay State::openDB(std::string _path, bool _killExisting)
State::State(Address _coinbaseAddress, Overlay const& _db): m_db(_db), m_state(&m_db), m_ourAddress(_coinbaseAddress)
{
secp256k1_start();
// Initialise to the state entailed by the genesis block; this guarantees the trie is built correctly.
m_state.init();
eth::commit(genesisState(), m_db, m_state);
cout << "State::State: state root initialised to " << m_state.root() << endl;
m_previousBlock = BlockInfo::genesis();
resetCurrent();
assert(m_state.root() == m_previousBlock.stateRoot);
}
void State::ensureCached(Address _a, bool _requireMemory, bool _forceCreate) const
@ -112,29 +137,7 @@ void State::ensureCached(Address _a, bool _requireMemory, bool _forceCreate) con
void State::commit()
{
for (auto const& i: m_cache)
if (i.second.type() == AddressType::Dead)
m_state.remove(i.first);
else
{
RLPStream s(i.second.type() == AddressType::Contract ? 3 : 2);
s << i.second.balance() << i.second.nonce();
if (i.second.type() == AddressType::Contract)
{
if (i.second.haveMemory())
{
TrieDB<u256, Overlay> memdb(&m_db);
memdb.init();
for (auto const& j: i.second.memory())
if (j.second)
memdb.insert(j.first, rlp(j.second));
s << memdb.root();
}
else
s << i.second.oldRoot();
}
m_state.insert(i.first, &s.out());
}
eth::commit(m_cache, m_db, m_state);
m_cache.clear();
}

33
libethereum/State.h

@ -39,6 +39,9 @@ namespace eth
class BlockChain;
extern const u256 c_genesisDifficulty;
std::map<Address, AddressState> const& genesisState();
/**
* @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).
@ -158,7 +161,7 @@ private:
/// exist in the DB.
void ensureCached(Address _a, bool _requireMemory, bool _forceCreate) const;
/// Commit all changes waiting in the address cache.
/// Commit all changes waiting in the address cache to the DB.
void commit();
/// Execute the given block on our previous block. This will set up m_currentBlock first, then call the other playback().
@ -235,6 +238,34 @@ inline std::ostream& operator<<(std::ostream& _out, State const& _s)
return _out;
}
template <class DB>
void commit(std::map<Address, AddressState> const& _cache, DB& _db, TrieDB<Address, DB>& _state)
{
for (auto const& i: _cache)
if (i.second.type() == AddressType::Dead)
_state.remove(i.first);
else
{
RLPStream s(i.second.type() == AddressType::Contract ? 3 : 2);
s << i.second.balance() << i.second.nonce();
if (i.second.type() == AddressType::Contract)
{
if (i.second.haveMemory())
{
TrieDB<u256, DB> memdb(&_db);
memdb.init();
for (auto const& j: i.second.memory())
if (j.second)
memdb.insert(j.first, rlp(j.second));
s << memdb.root();
}
else
s << i.second.oldRoot();
}
_state.insert(i.first, &s.out());
}
}
}

Loading…
Cancel
Save