diff --git a/mix/MixClient.cpp b/mix/MixClient.cpp index 2db5ecf5b..17e369a4e 100644 --- a/mix/MixClient.cpp +++ b/mix/MixClient.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "Exceptions.h" @@ -34,15 +35,37 @@ using namespace dev; using namespace dev::eth; -using namespace dev::mix; + +namespace dev +{ +namespace mix +{ const Secret c_userAccountSecret = Secret("cb73d9408c4720e230387d956eb0f829d8a4dd2c1055f96257167e14e7169074"); +const u256 c_mixGenesisDifficulty = (u256) 1 << 4; + +class MixBlockChain: public dev::eth::BlockChain +{ +public: + MixBlockChain(std::string const& _path, h256 _stateRoot): BlockChain(createGenesisBlock(_stateRoot), _path, true) + { + } + + static bytes createGenesisBlock(h256 _stateRoot) + { + RLPStream block(3); + block.appendList(14) + << h256() << EmptyListSHA3 << h160() << _stateRoot << EmptyTrie << EmptyTrie << LogBloom() << c_mixGenesisDifficulty << 0 << 1000000 << 0 << (unsigned)0 << std::string() << sha3(bytes(1, 42)); + block.appendRaw(RLPEmptyList); + block.appendRaw(RLPEmptyList); + return block.out(); + } +}; MixClient::MixClient(std::string const& _dbPath): - m_userAccount(c_userAccountSecret), m_bc(_dbPath, true), m_dbPath(_dbPath), m_minigThreads(0) + m_userAccount(c_userAccountSecret), m_dbPath(_dbPath), m_minigThreads(0) { - //TODO: put this into genesis block somehow - //resetState(10000000 * ether); + resetState(10000000 * ether); } MixClient::~MixClient() @@ -51,21 +74,23 @@ MixClient::~MixClient() void MixClient::resetState(u256 _balance) { - (void) _balance; - { - WriteGuard l(x_state); - Guard fl(m_filterLock); - m_filters.clear(); - m_watches.clear(); - m_bc.reopen(m_dbPath, true); - m_state = eth::State(); - m_stateDB = OverlayDB(); - m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::CanonGenesis); - m_state.sync(m_bc); - m_startState = m_state; - m_pendingExecutions.clear(); - } - mine(); + WriteGuard l(x_state); + Guard fl(m_filterLock); + m_filters.clear(); + m_watches.clear(); + + m_stateDB = OverlayDB(); + TrieDB accountState(&m_stateDB); + accountState.init(); + std::map genesisState = { std::make_pair(KeyPair(c_userAccountSecret).address(), Account(_balance, Account::NormalCreation)) }; + dev::eth::commit(genesisState, static_cast(m_stateDB), accountState); + h256 stateRoot = accountState.root(); + m_bc.reset(); + m_bc.reset(new MixBlockChain(m_dbPath, stateRoot)); + m_state = eth::State(m_userAccount.address(), m_stateDB, BaseState::Empty); + m_state.sync(bc()); + m_startState = m_state; + m_pendingExecutions.clear(); } void MixClient::executeTransaction(Transaction const& _t, State& _state) @@ -74,9 +99,9 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) // do debugging run first LastHashes lastHashes(256); - lastHashes[0] = m_bc.numberHash(m_bc.number()); + lastHashes[0] = bc().numberHash(bc().number()); for (unsigned i = 1; i < 256; ++i) - lastHashes[i] = lastHashes[i - 1] ? m_bc.details(lastHashes[i - 1]).parent : h256(); + lastHashes[i] = lastHashes[i - 1] ? bc().details(lastHashes[i - 1]).parent : h256(); State execState = _state; Executive execution(execState, lastHashes, 0); @@ -155,7 +180,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) h256Set changed; Guard l(m_filterLock); for (std::pair& i: m_filters) - if ((unsigned)i.second.filter.latest() > m_bc.number()) + if ((unsigned)i.second.filter.latest() > bc().number()) { // acceptable number. auto m = i.second.filter.matches(_state.receipt(_state.pending().size() - 1)); @@ -163,7 +188,7 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) { // filter catches them for (LogEntry const& l: m) - i.second.changes.push_back(LocalisedLogEntry(l, m_bc.number() + 1)); + i.second.changes.push_back(LocalisedLogEntry(l, bc().number() + 1)); changed.insert(i.first); } } @@ -174,11 +199,11 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state) void MixClient::mine() { WriteGuard l(x_state); - m_state.commitToMine(m_bc); + m_state.commitToMine(bc()); while (!m_state.mine(100, true).completed) {} m_state.completeMine(); - m_bc.import(m_state.blockData(), m_stateDB); - m_state.sync(m_bc); + bc().import(m_state.blockData(), m_stateDB); + m_state.sync(bc()); //m_state.cleanup(true); m_startState = m_state; m_executions.emplace_back(std::move(m_pendingExecutions)); @@ -188,7 +213,7 @@ void MixClient::mine() ExecutionResult const& MixClient::execution(unsigned _block, unsigned _transaction) const { - if (_block == m_bc.number() + 1) + if (_block == bc().number() + 1) return m_pendingExecutions.at(_transaction); return m_executions.at(_block).at(_transaction); } @@ -213,14 +238,13 @@ State MixClient::asOf(int _block) const else if (_block == -1) return m_startState; else - return State(m_stateDB, m_bc, m_bc.numberHash(_block)); + return State(m_stateDB, bc(), bc().numberHash(_block)); } void MixClient::transact(Secret _secret, u256 _value, Address _dest, bytes const& _data, u256 _gas, u256 _gasPrice) { WriteGuard l(x_state); u256 n = m_state.transactionsFrom(toAddress(_secret)); - _gasPrice = 0; //TODO: remove after fixing setBalance Transaction t(_value, _gasPrice, _gas, _dest, _data, n, _secret); executeTransaction(t, m_state); } @@ -229,7 +253,6 @@ Address MixClient::transact(Secret _secret, u256 _endowment, bytes const& _init, { WriteGuard l(x_state); u256 n = m_state.transactionsFrom(toAddress(_secret)); - _gasPrice = 0; //TODO: remove after fixing setBalance eth::Transaction t(_endowment, _gasPrice, _gas, _init, n, _secret); executeTransaction(t, m_state); Address address = right160(sha3(rlpList(t.sender(), t.nonce()))); @@ -301,12 +324,12 @@ eth::LocalisedLogEntries MixClient::logs(unsigned _watchId) const eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const { LocalisedLogEntries ret; - unsigned lastBlock = m_bc.number(); + unsigned lastBlock = bc().number(); unsigned block = std::min(lastBlock, (unsigned)_f.latest()); unsigned end = std::min(lastBlock, std::min(block, (unsigned)_f.earliest())); unsigned skip = _f.skip(); // Pending transactions - if (block > m_bc.number()) + if (block > bc().number()) { ReadGuard l(x_state); for (unsigned i = 0; i < m_state.pending().size(); ++i) @@ -318,15 +341,15 @@ eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block)); skip -= std::min(skip, static_cast(logEntries.size())); } - block = m_bc.number(); + block = bc().number(); } // The rest - auto h = m_bc.numberHash(block); + auto h = bc().numberHash(block); for (; ret.size() != block && block != end; block--) { - if (_f.matches(m_bc.info(h).logBloom)) - for (TransactionReceipt receipt: m_bc.receipts(h).receipts) + if (_f.matches(bc().info(h).logBloom)) + for (TransactionReceipt receipt: bc().receipts(h).receipts) if (_f.matches(receipt.bloom())) { LogEntries logEntries = _f.matches(receipt); @@ -334,7 +357,7 @@ eth::LocalisedLogEntries MixClient::logs(eth::LogFilter const& _f) const ret.insert(ret.begin(), LocalisedLogEntry(logEntries[entry], block)); skip -= std::min(skip, static_cast(logEntries.size())); } - h = m_bc.details(h).parent; + h = bc().details(h).parent; } return ret; } @@ -416,22 +439,22 @@ LocalisedLogEntries MixClient::checkWatch(unsigned _watchId) h256 MixClient::hashFromNumber(unsigned _number) const { - return m_bc.numberHash(_number); + return bc().numberHash(_number); } eth::BlockInfo MixClient::blockInfo(h256 _hash) const { - return BlockInfo(m_bc.block(_hash)); + return BlockInfo(bc().block(_hash)); } eth::BlockDetails MixClient::blockDetails(h256 _hash) const { - return m_bc.details(_hash); + return bc().details(_hash); } eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const { - auto bl = m_bc.block(_blockHash); + auto bl = bc().block(_blockHash); RLP b(bl); if (_i < b[1].itemCount()) return Transaction(b[1][_i].data(), CheckSignature::Range); @@ -441,7 +464,7 @@ eth::Transaction MixClient::transaction(h256 _blockHash, unsigned _i) const eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const { - auto bl = m_bc.block(_blockHash); + auto bl = bc().block(_blockHash); RLP b(bl); if (_i < b[2].itemCount()) return BlockInfo::fromHeader(b[2][_i].data()); @@ -451,7 +474,7 @@ eth::BlockInfo MixClient::uncle(h256 _blockHash, unsigned _i) const unsigned MixClient::number() const { - return m_bc.number(); + return bc().number(); } eth::Transactions MixClient::pending() const @@ -461,7 +484,7 @@ eth::Transactions MixClient::pending() const eth::StateDiff MixClient::diff(unsigned _txi, h256 _block) const { - State st(m_stateDB, m_bc, _block); + State st(m_stateDB, bc(), _block); return st.fromPending(_txi).diff(st.fromPending(_txi + 1)); } @@ -526,3 +549,6 @@ eth::MineProgress MixClient::miningProgress() const { return eth::MineProgress(); } + +} +} diff --git a/mix/MixClient.h b/mix/MixClient.h index bd1002527..323a6b7e6 100644 --- a/mix/MixClient.h +++ b/mix/MixClient.h @@ -27,7 +27,6 @@ #include #include #include -#include #include "MachineStates.h" namespace dev @@ -35,6 +34,8 @@ namespace dev namespace mix { +class MixBlockChain; + class MixClient: public dev::eth::Interface { public: @@ -90,12 +91,14 @@ private: void executeTransaction(dev::eth::Transaction const& _t, eth::State& _state); void noteChanged(h256Set const& _filters); dev::eth::State asOf(int _block) const; + MixBlockChain& bc() { return *m_bc; } + MixBlockChain const& bc() const { return *m_bc; } KeyPair m_userAccount; eth::State m_state; eth::State m_startState; OverlayDB m_stateDB; - eth::CanonBlockChain m_bc; + std::auto_ptr m_bc; mutable boost::shared_mutex x_state; mutable std::mutex m_filterLock; std::map m_filters;