/* This file is part of cpp-ethereum. cpp-ethereum is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. cpp-ethereum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with cpp-ethereum. If not, see . */ /** @file CanonBlockChain.cpp * @author Gav Wood * @date 2014 */ #include "CanonBlockChain.h" #include #include #include #include #include #include #include #include #include #include "GenesisInfo.h" #include "State.h" #include "Defaults.h" using namespace std; using namespace dev; using namespace dev::eth; namespace js = json_spirit; unique_ptr CanonBlockChain::s_genesis; boost::shared_mutex CanonBlockChain::x_genesis; Nonce CanonBlockChain::s_nonce(u64(42)); string CanonBlockChain::s_genesisStateJSON; bytes CanonBlockChain::s_genesisExtraData; u256 CanonBlockChain::s_genesisDifficulty; u256 CanonBlockChain::s_genesisGasLimit; CanonBlockChain::CanonBlockChain(std::string const& _path, WithExisting _we, ProgressCallback const& _pc): FullBlockChain(createGenesisBlock(), createGenesisState(), _path) { BlockChain::openDatabase(_path, _we, _pc); } void CanonBlockChain::reopen(WithExisting _we, ProgressCallback const& _pc) { close(); open(createGenesisBlock(), createGenesisState(), m_dbPath); openDatabase(m_dbPath, _we, _pc); } bytes CanonBlockChain::createGenesisBlock() { RLPStream block(3); h256 stateRoot; { MemoryDB db; SecureTrieDB state(&db); state.init(); dev::eth::commit(createGenesisState(), state); stateRoot = state.root(); } js::mValue val; json_spirit::read_string(s_genesisStateJSON.empty() ? c_network == Network::Frontier ? c_genesisInfoFrontier : c_genesisInfoOlympic : s_genesisStateJSON, val); js::mObject genesis = val.get_obj(); h256 mixHash(genesis["mixhash"].get_str()); h256 parentHash(genesis["parentHash"].get_str()); h160 beneficiary(genesis["coinbase"].get_str()); u256 difficulty = fromBigEndian(fromHex(genesis["difficulty"].get_str())); u256 gasLimit = fromBigEndian(fromHex(genesis["gasLimit"].get_str())); u256 timestamp = fromBigEndian(fromHex(genesis["timestamp"].get_str())); bytes extraData = fromHex(genesis["extraData"].get_str()); h64 nonce(genesis["nonce"].get_str()); block.appendList(15) << parentHash << EmptyListSHA3 // sha3(uncles) << beneficiary << stateRoot << EmptyTrie // transactions << EmptyTrie // receipts << LogBloom() << (s_genesisDifficulty ? s_genesisDifficulty : difficulty) << 0 // number << (s_genesisGasLimit ? s_genesisGasLimit : gasLimit) << 0 // gasUsed << timestamp << (s_genesisExtraData.empty() ? extraData : s_genesisExtraData) << mixHash << nonce; block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList); return block.out(); } AccountMap const& CanonBlockChain::createGenesisState() { static AccountMap s_ret; if (s_ret.empty()) s_ret = jsonToAccountMap(s_genesisStateJSON.empty() ? c_network == Network::Frontier ? c_genesisInfoFrontier : c_genesisInfoOlympic : s_genesisStateJSON); return s_ret; } void CanonBlockChain::setGenesis(std::string const& _json) { WriteGuard l(x_genesis); s_genesisStateJSON = _json; s_genesis.reset(); } void CanonBlockChain::forceGenesisExtraData(bytes const& _genesisExtraData) { WriteGuard l(x_genesis); s_genesisExtraData = _genesisExtraData; s_genesis.reset(); } void CanonBlockChain::forceGenesisDifficulty(u256 const& _genesisDifficulty) { WriteGuard l(x_genesis); s_genesisDifficulty = _genesisDifficulty; s_genesis.reset(); } void CanonBlockChain::forceGenesisGasLimit(u256 const& _genesisGasLimit) { WriteGuard l(x_genesis); s_genesisGasLimit = _genesisGasLimit; s_genesis.reset(); } Ethash::BlockHeader const& CanonBlockChain::genesis() { UpgradableGuard l(x_genesis); if (!s_genesis) { auto gb = createGenesisBlock(); UpgradeGuard ul(l); s_genesis.reset(new Ethash::BlockHeader); s_genesis->populate(&gb, CheckEverything); } return *s_genesis; }