Browse Source

Merge branch 'whizz' of https://github.com/ethereum/cpp-ethereum into client_ref

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
adbb3f011c
  1. 2
      CMakeLists.txt
  2. 4
      libethcore/BlockInfo.h
  3. 12
      libethcore/Ethash.cpp
  4. 2
      libethereum/BlockChain.cpp
  5. 7
      libethereum/BlockChain.h
  6. 2
      libethereum/Client.h
  7. 49
      libp2p/Host.cpp
  8. 2
      libp2p/Host.h
  9. 109
      test/TestHelper.cpp
  10. 21
      test/TestHelper.h
  11. 2
      test/fuzzTesting/checkRandomStateTest.cpp
  12. 2
      test/fuzzTesting/createRandomStateTest.cpp
  13. 2
      test/libethcore/dagger.cpp
  14. 3
      test/libethereum/ClientBase.cpp
  15. 205
      test/libethereum/blockchain.cpp
  16. 2
      test/libethereum/genesis.cpp
  17. 2
      test/libethereum/state.cpp
  18. 27
      test/libevm/vm.cpp

2
CMakeLists.txt

@ -43,7 +43,7 @@ option(GUI "Build GUI components (AlethZero, Mix)" ON)
option(TESTS "Build the tests." ON)
option(NOBOOST "No use of boost macros in test functions" OFF)
option(EVMJIT "Build just-in-time compiler for EVM code (requires LLVM)" OFF)
option(ETHASHCL "Build in support for GPU mining via OpenCL" OFF)
option(ETHASHCL "Build in support for GPU mining via OpenCL" ON)
option(JSCONSOLE "Build in javascript console" ON)
# propagates CMake configuration options to the compiler

4
libethcore/BlockInfo.h

@ -75,7 +75,7 @@ DEV_SIMPLE_EXCEPTION(NoHashRecorded);
* The default constructor creates an empty object, which can be tested against with the boolean
* conversion operator.
*/
struct BlockInfo
class BlockInfo
{
friend class BlockChain;
public:
@ -209,7 +209,7 @@ public:
void populateFromParent(BlockHeaderPolished const& _parent)
{
noteDirty();
BlockInfo::parentHash = _parent.hash();
BlockInfo::m_parentHash = _parent.hash();
BlockInfo::populateFromParent(_parent);
BlockInfoSub::populateFromParent(_parent);
}

12
libethcore/Ethash.cpp

@ -196,7 +196,7 @@ public:
static unsigned instances() { return s_numInstances > 0 ? s_numInstances : std::thread::hardware_concurrency(); }
static std::string platformInfo();
static void listDevices() {}
static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, boost::optional<uint64_t>) { return false; }
static bool configureGPU(unsigned, unsigned, unsigned, unsigned, unsigned, bool, unsigned, uint64_t) { return false; }
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, std::thread::hardware_concurrency()); }
protected:
@ -234,7 +234,7 @@ public:
unsigned _deviceId,
bool _allowCPU,
unsigned _extraGPUMemory,
boost::optional<uint64_t> _currentBlock
uint64_t _currentBlock
);
static void setNumInstances(unsigned _instances) { s_numInstances = std::min<unsigned>(_instances, getNumDevices()); }
@ -246,7 +246,7 @@ private:
void workLoop() override;
bool report(uint64_t _nonce);
using Miner::accumulateHashes;
using GenericMiner<EthashProofOfWork>::accumulateHashes;
EthashCLHook* m_hook = nullptr;
ethash_cl_miner* m_miner = nullptr;
@ -448,7 +448,7 @@ std::string EthashCPUMiner::platformInfo()
class EthashCLHook: public ethash_cl_miner::search_hook
{
public:
EthashCLHook(Ethash::GPUMiner* _owner): m_owner(_owner) {}
EthashCLHook(EthashGPUMiner* _owner): m_owner(_owner) {}
EthashCLHook(EthashCLHook const&) = delete;
void abort()
@ -511,7 +511,7 @@ unsigned EthashGPUMiner::s_deviceId = 0;
unsigned EthashGPUMiner::s_numInstances = 0;
EthashGPUMiner::EthashGPUMiner(ConstructionInfo const& _ci):
Miner(_ci),
GenericMiner<EthashProofOfWork>(_ci),
Worker("gpuminer" + toString(index())),
m_hook(new EthashCLHook(this))
{
@ -527,7 +527,7 @@ EthashGPUMiner::~EthashGPUMiner()
bool EthashGPUMiner::report(uint64_t _nonce)
{
Nonce n = (Nonce)(u64)_nonce;
Result r = EthashAux::eval(work().seedHash, work().headerHash, n);
EthashProofOfWork::Result r = EthashAux::eval(work().seedHash, work().headerHash, n);
if (r.value < work().boundary)
return submitProof(Solution{n, r.mixHash});
return false;

2
libethereum/BlockChain.cpp

@ -849,7 +849,7 @@ void BlockChain::rescue(OverlayDB& _db)
u = m;
}
cout << " lowest is " << l << endl;
for (;; --l)
for (; l > 0; --l)
{
h256 h = numberHash(l);
cout << "Checking validity of " << l << " (" << h << ")..." << flush;

7
libethereum/BlockChain.h

@ -395,7 +395,12 @@ public:
BlockHeader h(_block, (_ir & ImportRequirements::ValidSeal) ? Strictness::CheckEverything : Strictness::QuickNonce);
h.verifyInternals(_block);
if ((_ir & ImportRequirements::Parent) != 0)
h.verifyParent(header(h.parentHash()));
{
bytes parentHeader(headerData(h.parentHash()));
if (parentHeader.empty())
BOOST_THROW_EXCEPTION(InvalidParentHash());
h.verifyParent(typename Sealer::BlockHeader(parentHeader, IgnoreSeal, h.parentHash(), HeaderData));
}
res.info = static_cast<BlockInfo&>(h);
}
catch (Exception& ex)

2
libethereum/Client.h

@ -346,7 +346,7 @@ public:
{
m_sealEngine = std::shared_ptr<SealEngineFace>(Ethash::createSealEngine());
m_sealEngine->onSealGenerated([=](bytes const& header){
return this->submitSealed(header);
this->submitSealed(header);
});
init(_host, _dbPath, _forceAction, _networkId);
}

49
libp2p/Host.cpp

@ -399,43 +399,42 @@ void Host::runAcceptor()
auto socket = make_shared<RLPXSocket>(new bi::tcp::socket(m_ioService));
m_tcp4Acceptor.async_accept(socket->ref(), [=](boost::system::error_code ec)
{
if (peerCount() > 9 * m_idealPeerCount)
m_accepting = false;
if (ec || !m_run)
{
socket->close();
return;
}
if (peerCount() > Ingress * m_idealPeerCount)
{
clog(NetConnect) << "Dropping incoming connect due to maximum peer count (9 * ideal peer count): " << socket->remoteEndpoint();
clog(NetConnect) << "Dropping incoming connect due to maximum peer count (" << Ingress << " * ideal peer count): " << socket->remoteEndpoint();
socket->close();
if (ec.value() < 1)
runAcceptor();
return;
}
// if no error code
bool success = false;
if (!ec)
try
{
try
{
// incoming connection; we don't yet know nodeid
auto handshake = make_shared<RLPXHandshake>(this, socket);
m_connecting.push_back(handshake);
handshake->start();
success = true;
}
catch (Exception const& _e)
{
clog(NetWarn) << "ERROR: " << diagnostic_information(_e);
}
catch (std::exception const& _e)
{
clog(NetWarn) << "ERROR: " << _e.what();
}
// incoming connection; we don't yet know nodeid
auto handshake = make_shared<RLPXHandshake>(this, socket);
m_connecting.push_back(handshake);
handshake->start();
success = true;
}
catch (Exception const& _e)
{
clog(NetWarn) << "ERROR: " << diagnostic_information(_e);
}
catch (std::exception const& _e)
{
clog(NetWarn) << "ERROR: " << _e.what();
}
if (!success)
socket->ref().close();
m_accepting = false;
if (ec.value() < 1)
runAcceptor();
runAcceptor();
});
}
}
@ -627,7 +626,7 @@ void Host::run(boost::system::error_code const&)
m_nodeTable->processEvents();
// cleanup zombies
DEV_GUARDED(x_connecting);
DEV_GUARDED(x_connecting)
m_connecting.remove_if([](std::weak_ptr<RLPXHandshake> h){ return h.expired(); });
DEV_GUARDED(x_timers)
m_timers.remove_if([](std::shared_ptr<boost::asio::deadline_timer> t)

2
libp2p/Host.h

@ -212,7 +212,7 @@ protected:
void restoreNetwork(bytesConstRef _b);
private:
enum PeerSlotRatio { Egress = 2, Ingress = 9 };
enum PeerSlotRatio { Egress = 1, Ingress = 4 };
bool havePeerSession(NodeId const& _id) { return !!peerSession(_id); }

109
test/TestHelper.cpp

@ -63,38 +63,23 @@ void connectClients(Client& c1, Client& c2)
void mine(State& s, BlockChain const& _bc)
{
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
s.commitToMine(_bc);
GenericFarm<EthashProofOfWork> f;
bool completed = false;
Ethash::BlockHeader header(s.info);
f.onSolutionFound([&](EthashProofOfWork::Solution sol)
{
header.m_mixHash = sol.mixHash;
header.m_nonce = sol.nonce;
RLPStream ret;
header.streamRLP(ret);
s.sealBlock(ret);
return true;
});
f.setWork(s.info());
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
}
void mine(BlockInfo& _bi)
{
GenericFarm<EthashProofOfWork> f;
bool completed = false;
f.onSolutionFound([&](EthashProofOfWork::Solution sol)
{
_bi.proof = sol;
return completed = true;
});
f.setWork(_bi);
f.startCPU();
while (!completed)
this_thread::sleep_for(chrono::milliseconds(20));
Notified<bytes> sealed;
sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
sealer->generateSeal(s.info());
sealed.waitNot({});
s.sealBlock(sealed);
}
void mine(Ethash::BlockHeader& _bi)
{
std::unique_ptr<SealEngineFace> sealer(Ethash::createSealEngine());
Notified<bytes> sealed;
sealer->onSealGenerated([&](bytes const& sealedHeader){ sealed = sealedHeader; });
sealer->generateSeal(_bi);
sealed.waitNot({});
_bi = Ethash::BlockHeader(sealed);
}
}
@ -158,13 +143,24 @@ void ImportTest::importEnv(json_spirit::mObject& _o)
assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0);
m_environment.currentBlock.parentHash() = h256(_o["previousHash"].get_str());
m_environment.currentBlock.number = toInt(_o["currentNumber"]);
m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]);
m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]);
m_environment.currentBlock.timestamp() = toInt(_o["currentTimestamp"]);
m_environment.currentBlock.coinbaseAddress() = Address(_o["currentCoinbase"].get_str());
RLPStream rlpStream;
rlpStream.appendList(BlockInfo::BasicFields);
rlpStream << h256(_o["previousHash"].get_str());
rlpStream << EmptyListSHA3;
rlpStream << Address(_o["currentCoinbase"].get_str());
rlpStream << h256(); // stateRoot
rlpStream << EmptyTrie; // transactionTrie
rlpStream << EmptyTrie; // receiptTrie
rlpStream << LogBloom(); // bloom
rlpStream << toInt(_o["currentDifficulty"]);
rlpStream << toInt(_o["currentNumber"]);
rlpStream << toInt(_o["currentGasLimit"]);
rlpStream << 0; //gasUsed
rlpStream << toInt(_o["currentTimestamp"]);
rlpStream << std::string(); //extra data
m_environment.currentBlock = BlockInfo(rlpStream.out(), CheckEverything, h256{}, HeaderData);
m_statePre.m_previousBlock = m_environment.previousBlock;
m_statePre.m_currentBlock = m_environment.currentBlock;
}
@ -824,6 +820,43 @@ LastHashes lastHashes(u256 _currentBlockNumber)
return ret;
}
dev::eth::Ethash::BlockHeader constructHeader(
h256 const& _parentHash,
h256 const& _sha3Uncles,
Address const& _coinbaseAddress,
h256 const& _stateRoot,
h256 const& _transactionsRoot,
h256 const& _receiptsRoot,
dev::eth::LogBloom const& _logBloom,
u256 const& _difficulty,
u256 const& _number,
u256 const& _gasLimit,
u256 const& _gasUsed,
u256 const& _timestamp,
bytes const& _extraData)
{
RLPStream rlpStream;
rlpStream.appendList(Ethash::BlockHeader::Fields);
rlpStream << _parentHash << _sha3Uncles << _coinbaseAddress << _stateRoot << _transactionsRoot << _receiptsRoot << _logBloom
<< _difficulty << _number << _gasLimit << _gasUsed << _timestamp << _extraData << h256{} << Nonce{};
return Ethash::BlockHeader(rlpStream.out());
}
void updateEthashSeal(dev::eth::Ethash::BlockHeader& _header, h256 const& _mixHash, dev::eth::Nonce const& _nonce)
{
RLPStream source;
_header.streamRLP(source);
RLP sourceRlp(source.out());
RLPStream header;
header.appendList(Ethash::BlockHeader::Fields);
for (size_t i = 0; i < BlockInfo::BasicFields; i++)
header << sourceRlp[i];
header << _mixHash << _nonce;
_header = Ethash::BlockHeader(header.out());
}
namespace
{

21
test/TestHelper.h

@ -27,6 +27,7 @@
#include <boost/filesystem.hpp>
#include "JsonSpiritHeaders.h"
#include <libethcore/Ethash.h>
#include <libethereum/State.h>
#include <libevm/ExtVMFace.h>
#include <libtestutils/Common.h>
@ -62,7 +63,7 @@ class State;
void mine(Client& c, int numBlocks);
void connectClients(Client& c1, Client& c2);
void mine(State& _s, BlockChain const& _bc);
void mine(BlockInfo& _bi);
void mine(Ethash::BlockHeader& _bi);
}
@ -175,7 +176,21 @@ void checkOutput(bytes const& _output, json_spirit::mObject& _o);
void checkStorage(std::map<u256, u256> _expectedStore, std::map<u256, u256> _resultStore, Address _expectedAddr);
void checkLog(eth::LogEntries _resultLogs, eth::LogEntries _expectedLogs);
void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _expectedCallCreates);
dev::eth::Ethash::BlockHeader constructHeader(
h256 const& _parentHash,
h256 const& _sha3Uncles,
Address const& _coinbaseAddress,
h256 const& _stateRoot,
h256 const& _transactionsRoot,
h256 const& _receiptsRoot,
dev::eth::LogBloom const& _logBloom,
u256 const& _difficulty,
u256 const& _number,
u256 const& _gasLimit,
u256 const& _gasUsed,
u256 const& _timestamp,
bytes const& _extraData);
void updateEthashSeal(dev::eth::Ethash::BlockHeader& _header, h256 const& _mixHash, dev::eth::Nonce const& _nonce);
void executeTests(const std::string& _name, const std::string& _testPathAppendix, const boost::filesystem::path _pathToFiller, std::function<void(json_spirit::mValue&, bool)> doTests);
void userDefinedTest(std::function<void(json_spirit::mValue&, bool)> doTests);
RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj);
@ -224,7 +239,7 @@ public:
bool inputLimits = false;
bool bigData = false;
bool wallet = false;
bool nonetwork = true;
bool nonetwork = false;
bool nodag = true;
/// @}

2
test/fuzzTesting/checkRandomStateTest.cpp

@ -87,7 +87,7 @@ bool doStateTest(mValue& _v)
try
{
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number()), importer.m_transaction).output;
}
catch (Exception const& _e)
{

2
test/fuzzTesting/createRandomStateTest.cpp

@ -233,7 +233,7 @@ void doStateTests(json_spirit::mValue& _v)
eth::State theState = importer.m_statePre;
try
{
output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
output = theState.execute(test::lastHashes(importer.m_environment.currentBlock.number()), importer.m_transaction).output;
}
catch (Exception const& _e)
{

2
test/libethcore/dagger.cpp

@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE(basic_test)
cnote << i.first;
js::mObject& o = i.second.get_obj();
vector<pair<string, string>> ss;
Ethash::BlockHeader header(fromHex(o["header"].get_str()), CheckNothing);
Ethash::BlockHeader header(fromHex(o["header"].get_str()), CheckNothing, h256{}, HeaderData);
h256 headerHash(o["header_hash"].get_str());
Nonce nonce(o["nonce"].get_str());
BOOST_REQUIRE_EQUAL(headerHash, header.hashWithout());

3
test/libethereum/ClientBase.cpp

@ -21,6 +21,7 @@
#include <boost/test/unit_test.hpp>
#include <libdevcore/CommonJS.h>
#include <libtestutils/FixedClient.h>
#include "../TestUtils.h"
using namespace std;
@ -139,7 +140,7 @@ BOOST_AUTO_TEST_CASE(blocks)
ETH_CHECK_EQUAL(expectedBlockInfoUncldeHash, _blockInfo.sha3Uncles());
};
Ethash::BlockHeader blockInfo(_client.bc().headerData(blockHash));
Ethash::BlockHeader blockInfo((static_cast<FixedClient&>(_client)).bc().headerData(blockHash));
compareBlockInfos(blockHeader, blockInfo);
// blockDetails

205
test/libethereum/blockchain.cpp

@ -37,16 +37,17 @@ namespace dev { namespace test {
typedef std::vector<bytes> uncleList;
typedef std::pair<bytes, uncleList> blockSet;
BlockInfo constructBlock(mObject& _o);
bytes createBlockRLPFromFields(mObject& _tObj);
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList);
using BlockHeader = Ethash::BlockHeader;
BlockHeader constructBlock(mObject& _o, h256 const& _stateRoot = h256{});
bytes createBlockRLPFromFields(mObject& _tObj, h256 const& _stateRoot = h256{});
RLPStream createFullBlockFromHeader(BlockHeader const& _bi, bytes const& _txs = RLPEmptyList, bytes const& _uncles = RLPEmptyList);
mArray writeTransactionsToJson(Transactions const& txs);
mObject writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi);
void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj);
BlockInfo constructBlock(mObject& _o);
void updatePoW(BlockInfo& _bi);
mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector<BlockInfo> const& _vBiBlocks, std::vector<blockSet> _blockSet);
mObject writeBlockHeaderToJson(mObject& _o, BlockHeader const& _bi);
void overwriteBlockHeader(BlockHeader& _current_BlockHeader, mObject& _blObj);
void updatePoW(BlockHeader& _bi);
mArray importUncles(mObject const& _blObj, vector<BlockHeader>& _vBiUncles, vector<BlockHeader> const& _vBiBlocks, std::vector<blockSet> _blockSet);
void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
{
@ -61,12 +62,12 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
cerr << i.first << endl;
TBOOST_REQUIRE(o.count("genesisBlockHeader"));
BlockInfo biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj());
TBOOST_REQUIRE(o.count("pre"));
ImportTest importer(o["pre"].get_obj());
TransientDirectory td_stateDB_tmp;
State trueState(OverlayDB(State::openDB(td_stateDB_tmp.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress());
BlockHeader biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), h256{});
State trueState(OverlayDB(State::openDB(td_stateDB_tmp.path(), h256{}, WithExisting::Kill)), BaseState::Empty, biGenesisBlock.coinbaseAddress());
//Imported blocks from the start
std::vector<blockSet> blockSets;
@ -76,7 +77,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
trueState.commit();
if (_fillin)
biGenesisBlock.stateRoot() = trueState.rootHash();
biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj(), trueState.rootHash());
else
TBOOST_CHECK_MESSAGE((biGenesisBlock.stateRoot() == trueState.rootHash()), "root hash does not match");
@ -96,7 +97,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
// construct true blockchain
TransientDirectory td;
BlockChain trueBc(rlpGenesisBlock.out(), td.path(), WithExisting::Kill);
FullBlockChain<Ethash> trueBc(rlpGenesisBlock.out(), StateDefinition(), td.path(), WithExisting::Kill);
if (_fillin)
{
@ -107,7 +108,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
genesis.first = rlpGenesisBlock.out();
genesis.second = uncleList();
blockSets.push_back(genesis);
vector<BlockInfo> vBiBlocks;
vector<BlockHeader> vBiBlocks;
vBiBlocks.push_back(biGenesisBlock);
size_t importBlockNumber = 0;
@ -124,8 +125,9 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
vBiBlocks.push_back(biGenesisBlock);
TransientDirectory td_stateDB, td_bc;
BlockChain bc(rlpGenesisBlock.out(), td_bc.path(), WithExisting::Kill);
State state(OverlayDB(State::openDB(td_stateDB.path())), BaseState::Empty, biGenesisBlock.coinbaseAddress());
FullBlockChain<Ethash> bc(rlpGenesisBlock.out(), StateDefinition(), td_bc.path(), WithExisting::Kill);
State state(OverlayDB(State::openDB(td_stateDB.path(), h256{}, WithExisting::Kill)), BaseState::Empty);
trueState.setAddress(biGenesisBlock.coinbaseAddress());
importer.importState(o["pre"].get_obj(), state);
state.commit();
@ -134,12 +136,12 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
BlockQueue uncleQueue;
uncleList uncles = blockSets.at(i).second;
for (size_t j = 0; j < uncles.size(); j++)
uncleQueue.import(&uncles.at(j), bc);
uncleQueue.import(&uncles.at(j), false);
const bytes block = blockSets.at(i).first;
bc.sync(uncleQueue, state.db(), 4);
bc.attemptImport(block, state.db());
vBiBlocks.push_back(BlockInfo(block));
vBiBlocks.push_back(BlockHeader(block));
state.sync(bc);
}
@ -156,7 +158,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
}
//get uncles
vector<BlockInfo> vBiUncles;
vector<BlockHeader> vBiUncles;
blObj["uncleHeaders"] = importUncles(blObj, vBiUncles, vBiBlocks, blockSets);
BlockQueue uncleBlockQueue;
@ -167,7 +169,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
RLPStream uncle = createFullBlockFromHeader(vBiUncles.at(i));
try
{
uncleBlockQueue.import(&uncle.out(), bc);
uncleBlockQueue.import(&uncle.out(), false);
uncleBlockQueueList.push_back(uncle.out());
// wait until block is verified
this_thread::sleep_for(chrono::seconds(1));
@ -205,14 +207,14 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
txList.push_back(txi);
blObj["transactions"] = writeTransactionsToJson(txList);
BlockInfo current_BlockHeader = state.info();
BlockHeader current_BlockHeader = state.info();
RLPStream uncleStream;
uncleStream.appendList(vBiUncles.size());
for (unsigned i = 0; i < vBiUncles.size(); ++i)
{
RLPStream uncleRlp;
vBiUncles[i].streamRLP(uncleRlp, WithNonce);
vBiUncles[i].streamRLP(uncleRlp);
uncleStream.appendRaw(uncleRlp.out());
}
@ -225,7 +227,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
if (vBiUncles.size())
{
// update unclehash in case of invalid uncles
current_BlockHeader.sha3Uncles() = sha3(uncleStream.out());
current_BlockHeader.setSha3Uncles(sha3(uncleStream.out()));
updatePoW(current_BlockHeader);
}
@ -330,7 +332,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
blockRLP = importByteArray(blObj["rlp"].get_str());
trueState.sync(trueBc);
trueBc.import(blockRLP, trueState.db());
if (trueBc.info() != BlockInfo(blockRLP))
if (trueBc.info() != BlockHeader(blockRLP))
importedAndBest = false;
trueState.sync(trueBc);
}
@ -363,17 +365,17 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
TBOOST_REQUIRE(blObj.count("blockHeader"));
mObject tObj = blObj["blockHeader"].get_obj();
BlockInfo blockHeaderFromFields;
BlockHeader blockHeaderFromFields;
const bytes c_rlpBytesBlockHeader = createBlockRLPFromFields(tObj);
const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader);
blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, IgnoreNonce);
blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, IgnoreSeal);
BlockInfo blockFromRlp = trueBc.info();
BlockHeader blockFromRlp(trueBc.header());
if (importedAndBest)
{
//Check the fields restored from RLP to original fields
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce)), "hash in given RLP not matching the block hash!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.headerHash(WithProof) == blockFromRlp.headerHash(WithProof)), "hash in given RLP not matching the block hash!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.parentHash() == blockFromRlp.parentHash()), "parentHash in given RLP not matching the block parentHash!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.sha3Uncles() == blockFromRlp.sha3Uncles()), "sha3Uncles in given RLP not matching the block sha3Uncles!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.coinbaseAddress() == blockFromRlp.coinbaseAddress()),"coinbaseAddress in given RLP not matching the block coinbaseAddress!");
@ -381,14 +383,14 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.transactionsRoot() == blockFromRlp.transactionsRoot()), "transactionsRoot in given RLP not matching the block transactionsRoot!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.receiptsRoot() == blockFromRlp.receiptsRoot()), "receiptsRoot in given RLP not matching the block receiptsRoot!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.logBloom() == blockFromRlp.logBloom()), "logBloom in given RLP not matching the block logBloom!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty == blockFromRlp.difficulty), "difficulty in given RLP not matching the block difficulty!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number == blockFromRlp.number), "number in given RLP not matching the block number!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit),"gasLimit in given RLP not matching the block gasLimit!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed), "gasUsed in given RLP not matching the block gasUsed!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.difficulty() == blockFromRlp.difficulty()), "difficulty in given RLP not matching the block difficulty!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.number() == blockFromRlp.number()), "number in given RLP not matching the block number!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasLimit() == blockFromRlp.gasLimit()),"gasLimit in given RLP not matching the block gasLimit!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.gasUsed() == blockFromRlp.gasUsed()), "gasUsed in given RLP not matching the block gasUsed!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.timestamp() == blockFromRlp.timestamp()), "timestamp in given RLP not matching the block timestamp!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.extraData() == blockFromRlp.extraData()), "extraData in given RLP not matching the block extraData!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash == blockFromRlp.mixHash), "mixHash in given RLP not matching the block mixHash!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce == blockFromRlp.nonce), "nonce in given RLP not matching the block nonce!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.mixHash() == blockFromRlp.mixHash()), "mixHash in given RLP not matching the block mixHash!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields.nonce() == blockFromRlp.nonce()), "nonce in given RLP not matching the block nonce!");
TBOOST_CHECK_MESSAGE((blockHeaderFromFields == blockFromRlp), "However, blockHeaderFromFields != blockFromRlp!");
@ -454,7 +456,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
// check uncle list
// uncles from uncle list field
vector<BlockInfo> uBlHsFromField;
vector<BlockHeader> uBlHsFromField;
if (blObj["uncleHeaders"].type() != json_spirit::null_type)
for (auto const& uBlHeaderObj: blObj["uncleHeaders"].get_array())
{
@ -462,7 +464,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
TBOOST_REQUIRE((uBlH.size() == 16));
bytes uncleRLP = createBlockRLPFromFields(uBlH);
const RLP c_uRLP(uncleRLP);
BlockInfo uncleBlockHeader;
BlockHeader uncleBlockHeader;
try
{
uncleBlockHeader.populateFromHeader(c_uRLP);
@ -475,10 +477,10 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
}
// uncles from block RLP
vector<BlockInfo> uBlHsFromRlp;
vector<BlockHeader> uBlHsFromRlp;
for (auto const& uRLP: root[2])
{
BlockInfo uBl;
BlockHeader uBl;
uBl.populateFromHeader(uRLP);
uBlHsFromRlp.push_back(uBl);
}
@ -499,7 +501,7 @@ void doBlockchainTests(json_spirit::mValue& _v, bool _fillin)
// helping functions
mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector<BlockInfo> const& _vBiBlocks, std::vector<blockSet> _blockSet)
mArray importUncles(mObject const& _blObj, vector<BlockHeader>& _vBiUncles, vector<BlockHeader> const& _vBiBlocks, std::vector<blockSet> _blockSet)
{
// write uncle list
mArray aUncleList;
@ -521,7 +523,7 @@ mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector
{
size_t number = (size_t)toInt(uncleHeaderObj["sameAsBlock"]);
uncleHeaderObj.erase("sameAsBlock");
BlockInfo currentUncle = _vBiBlocks[number];
BlockHeader currentUncle = _vBiBlocks[number];
writeBlockHeaderToJson(uncleHeaderObj, currentUncle);
aUncleList.push_back(uncleHeaderObj);
_vBiUncles.push_back(currentUncle);
@ -532,7 +534,7 @@ mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector
if (uncleHeaderObj.count("sameAsPreviousBlockUncle"))
{
bytes uncleRLP = _blockSet[(size_t)toInt(uncleHeaderObj["sameAsPreviousBlockUncle"])].second[0];
BlockInfo uncleHeader(uncleRLP);
BlockHeader uncleHeader(uncleRLP);
writeBlockHeaderToJson(uncleHeaderObj, uncleHeader);
aUncleList.push_back(uncleHeaderObj);
@ -548,15 +550,15 @@ mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector
uncleHeaderObj.erase("overwriteAndRedoPoW");
}
BlockInfo uncleBlockFromFields = constructBlock(uncleHeaderObj);
BlockHeader uncleBlockFromFields = constructBlock(uncleHeaderObj);
// make uncle header valid
uncleBlockFromFields.timestamp() = (u256)time(0);
cnote << "uncle block n = " << toString(uncleBlockFromFields.number);
uncleBlockFromFields.setTimestamp((u256)time(0));
cnote << "uncle block n = " << toString(uncleBlockFromFields.number());
if (_vBiBlocks.size() > 2)
{
if (uncleBlockFromFields.number - 1 < _vBiBlocks.size())
uncleBlockFromFields.populateFromParent(_vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
if (uncleBlockFromFields.number() - 1 < _vBiBlocks.size())
uncleBlockFromFields.populateFromParent(_vBiBlocks[(size_t)uncleBlockFromFields.number() - 1]);
else
uncleBlockFromFields.populateFromParent(_vBiBlocks[_vBiBlocks.size() - 2]);
}
@ -565,29 +567,32 @@ mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector
if (overwrite != "false")
{
uncleBlockFromFields.difficulty = overwrite == "difficulty" ? toInt(uncleHeaderObj["difficulty"]) : uncleBlockFromFields.difficulty;
uncleBlockFromFields.gasLimit = overwrite == "gasLimit" ? toInt(uncleHeaderObj["gasLimit"]) : uncleBlockFromFields.gasLimit;
uncleBlockFromFields.gasUsed = overwrite == "gasUsed" ? toInt(uncleHeaderObj["gasUsed"]) : uncleBlockFromFields.gasUsed;
uncleBlockFromFields.parentHash() = overwrite == "parentHash" ? h256(uncleHeaderObj["parentHash"].get_str()) : uncleBlockFromFields.parentHash();
uncleBlockFromFields.stateRoot() = overwrite == "stateRoot" ? h256(uncleHeaderObj["stateRoot"].get_str()) : uncleBlockFromFields.stateRoot();
uncleBlockFromFields = constructHeader(
overwrite == "parentHash" ? h256(uncleHeaderObj["parentHash"].get_str()) : uncleBlockFromFields.parentHash(),
uncleBlockFromFields.sha3Uncles(),
uncleBlockFromFields.coinbaseAddress(),
overwrite == "stateRoot" ? h256(uncleHeaderObj["stateRoot"].get_str()) : uncleBlockFromFields.stateRoot(),
uncleBlockFromFields.transactionsRoot(),
uncleBlockFromFields.receiptsRoot(),
uncleBlockFromFields.logBloom(),
overwrite == "difficulty" ? toInt(uncleHeaderObj["difficulty"]) : overwrite == "timestamp" ? uncleBlockFromFields.calculateDifficulty(_vBiBlocks[(size_t)uncleBlockFromFields.number() - 1]) : uncleBlockFromFields.difficulty(),
uncleBlockFromFields.number(),
overwrite == "gasLimit" ? toInt(uncleHeaderObj["gasLimit"]) : uncleBlockFromFields.gasLimit(),
overwrite == "gasUsed" ? toInt(uncleHeaderObj["gasUsed"]) : uncleBlockFromFields.gasUsed(),
overwrite == "timestamp" ? toInt(uncleHeaderObj["timestamp"]) : uncleBlockFromFields.timestamp(),
uncleBlockFromFields.extraData());
if (overwrite == "parentHashIsBlocksParent")
uncleBlockFromFields.populateFromParent(_vBiBlocks[_vBiBlocks.size() - 1]);
if (overwrite == "timestamp")
{
uncleBlockFromFields.timestamp() = toInt(uncleHeaderObj["timestamp"]);
uncleBlockFromFields.difficulty = uncleBlockFromFields.calculateDifficulty(_vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
}
}
updatePoW(uncleBlockFromFields);
if (overwrite == "nonce")
uncleBlockFromFields.nonce = Nonce(uncleHeaderObj["nonce"].get_str());
updateEthashSeal(uncleBlockFromFields, uncleBlockFromFields.mixHash(), Nonce(uncleHeaderObj["nonce"].get_str()));
if (overwrite == "mixHash")
uncleBlockFromFields.mixHash = h256(uncleHeaderObj["mixHash"].get_str());
updateEthashSeal(uncleBlockFromFields, h256(uncleHeaderObj["mixHash"].get_str()), uncleBlockFromFields.nonce());
writeBlockHeaderToJson(uncleHeaderObj, uncleBlockFromFields);
@ -600,7 +605,7 @@ mArray importUncles(mObject const& _blObj, vector<BlockInfo>& _vBiUncles, vector
return aUncleList;
}
bytes createBlockRLPFromFields(mObject& _tObj)
bytes createBlockRLPFromFields(mObject& _tObj, h256 const& _stateRoot)
{
RLPStream rlpStream;
rlpStream.appendList(_tObj.count("hash") > 0 ? (_tObj.size() - 1) : _tObj.size());
@ -614,7 +619,9 @@ bytes createBlockRLPFromFields(mObject& _tObj)
if (_tObj.count("coinbase"))
rlpStream << importByteArray(_tObj["coinbase"].get_str());
if (_tObj.count("stateRoot"))
if (_stateRoot)
rlpStream << _stateRoot;
else if (_tObj.count("stateRoot"))
rlpStream << importByteArray(_tObj["stateRoot"].get_str());
if (_tObj.count("transactionsTrie"))
@ -653,47 +660,35 @@ bytes createBlockRLPFromFields(mObject& _tObj)
return rlpStream.out();
}
void overwriteBlockHeader(BlockInfo& _header, mObject& _blObj)
void overwriteBlockHeader(BlockHeader& _header, mObject& _blObj)
{
auto ho = _blObj["blockHeader"].get_obj();
if (ho.size() != 14)
{
BlockInfo tmp = _header;
if (ho.count("parentHash"))
tmp.parentHash() = h256(ho["parentHash"].get_str());
if (ho.count("uncleHash"))
tmp.sha3Uncles() = h256(ho["uncleHash"].get_str());
if (ho.count("coinbase"))
tmp.coinbaseAddress() = Address(ho["coinbase"].get_str());
if (ho.count("stateRoot"))
tmp.stateRoot() = h256(ho["stateRoot"].get_str());
if (ho.count("transactionsTrie"))
tmp.transactionsRoot() = h256(ho["transactionsTrie"].get_str());
if (ho.count("receiptTrie"))
tmp.receiptsRoot() = h256(ho["receiptTrie"].get_str());
if (ho.count("bloom"))
tmp.logBloom() = LogBloom(ho["bloom"].get_str());
if (ho.count("difficulty"))
tmp.difficulty = toInt(ho["difficulty"]);
if (ho.count("number"))
tmp.number = toInt(ho["number"]);
if (ho.count("gasLimit"))
tmp.gasLimit = toInt(ho["gasLimit"]);
if (ho.count("gasUsed"))
tmp.gasUsed = toInt(ho["gasUsed"]);
if (ho.count("timestamp"))
tmp.timestamp() = toInt(ho["timestamp"]);
if (ho.count("extraData"))
tmp.extraData() = importByteArray(ho["extraData"].get_str());
BlockHeader tmp = constructHeader(
ho.count("parentHash") ? h256(ho["parentHash"].get_str()) : h256{},
ho.count("uncleHash") ? h256(ho["uncleHash"].get_str()) : EmptyListSHA3,
ho.count("coinbase") ? Address(ho["coinbase"].get_str()) : Address{},
ho.count("stateRoot") ? h256(ho["stateRoot"].get_str()): h256{},
ho.count("transactionsTrie") ? h256(ho["transactionsTrie"].get_str()) : EmptyTrie,
ho.count("receiptTrie") ? h256(ho["receiptTrie"].get_str()) : EmptyTrie,
ho.count("bloom") ? LogBloom(ho["bloom"].get_str()) : LogBloom{},
ho.count("difficulty") ? toInt(ho["difficulty"]) : u256(0),
ho.count("number") ? toInt(ho["number"]) : u256(0),
ho.count("gasLimit") ? toInt(ho["gasLimit"]) : u256(0),
ho.count("gasUsed") ? toInt(ho["gasUsed"]) : u256(0),
ho.count("timestamp") ? toInt(ho["timestamp"]) : u256(0),
ho.count("extraData") ? importByteArray(ho["extraData"].get_str()) : bytes{});
// find new valid nonce
if (tmp != _header && tmp.difficulty)
if (static_cast<BlockInfo>(tmp) != static_cast<BlockInfo>(_header) && tmp.difficulty())
mine(tmp);
if (ho.count("mixHash"))
tmp.mixHash = h256(ho["mixHash"].get_str());
updateEthashSeal(tmp, h256(ho["mixHash"].get_str()), tmp.nonce());
if (ho.count("nonce"))
tmp.nonce = Nonce(ho["nonce"].get_str());
updateEthashSeal(tmp, tmp.mixHash(), Nonce(ho["nonce"].get_str()));
tmp.noteDirty();
_header = tmp;
@ -703,19 +698,19 @@ void overwriteBlockHeader(BlockInfo& _header, mObject& _blObj)
// take the blockheader as is
const bytes c_blockRLP = createBlockRLPFromFields(ho);
const RLP c_bRLP(c_blockRLP);
_header.populateFromHeader(c_bRLP, IgnoreNonce);
_header.populateFromHeader(c_bRLP, IgnoreSeal);
}
}
BlockInfo constructBlock(mObject& _o)
BlockHeader constructBlock(mObject& _o, h256 const& _stateRoot)
{
BlockInfo ret;
BlockHeader ret;
try
{
// construct genesis block
const bytes c_blockRLP = createBlockRLPFromFields(_o);
const bytes c_blockRLP = createBlockRLPFromFields(_o, _stateRoot);
const RLP c_bRLP(c_blockRLP);
ret.populateFromHeader(c_bRLP, IgnoreNonce);
ret.populateFromHeader(c_bRLP, IgnoreSeal);
}
catch (Exception const& _e)
{
@ -732,7 +727,7 @@ BlockInfo constructBlock(mObject& _o)
return ret;
}
void updatePoW(BlockInfo& _bi)
void updatePoW(BlockHeader& _bi)
{
mine(_bi);
_bi.noteDirty();
@ -749,7 +744,7 @@ mArray writeTransactionsToJson(Transactions const& txs)
return txArray;
}
mObject writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
mObject writeBlockHeaderToJson(mObject& _o, BlockHeader const& _bi)
{
_o["parentHash"] = toString(_bi.parentHash());
_o["uncleHash"] = toString(_bi.sha3Uncles());
@ -758,22 +753,22 @@ mObject writeBlockHeaderToJson(mObject& _o, BlockInfo const& _bi)
_o["transactionsTrie"] = toString(_bi.transactionsRoot());
_o["receiptTrie"] = toString(_bi.receiptsRoot());
_o["bloom"] = toString(_bi.logBloom());
_o["difficulty"] = toCompactHex(_bi.difficulty, HexPrefix::Add, 1);
_o["difficulty"] = toCompactHex(_bi.difficulty(), HexPrefix::Add, 1);
_o["number"] = toCompactHex(_bi.number(), HexPrefix::Add, 1);
_o["gasLimit"] = toCompactHex(_bi.gasLimit, HexPrefix::Add, 1);
_o["gasUsed"] = toCompactHex(_bi.gasUsed, HexPrefix::Add, 1);
_o["gasLimit"] = toCompactHex(_bi.gasLimit(), HexPrefix::Add, 1);
_o["gasUsed"] = toCompactHex(_bi.gasUsed(), HexPrefix::Add, 1);
_o["timestamp"] = toCompactHex(_bi.timestamp(), HexPrefix::Add, 1);
_o["extraData"] = toHex(_bi.extraData(), 2, HexPrefix::Add);
_o["mixHash"] = toString(_bi.mixHash);
_o["nonce"] = toString(_bi.nonce);
_o["mixHash"] = toString(_bi.mixHash());
_o["nonce"] = toString(_bi.nonce());
_o["hash"] = toString(_bi.hash());
return _o;
}
RLPStream createFullBlockFromHeader(BlockInfo const& _bi, bytes const& _txs, bytes const& _uncles)
RLPStream createFullBlockFromHeader(BlockHeader const& _bi, bytes const& _txs, bytes const& _uncles)
{
RLPStream rlpStream;
_bi.streamRLP(rlpStream, WithNonce);
_bi.streamRLP(rlpStream, WithProof);
RLPStream ret(3);
ret.appendRaw(rlpStream.out());

2
test/libethereum/genesis.cpp

@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(genesis_tests)
BOOST_CHECK_EQUAL(CanonBlockChain<Ethash>::genesis().stateRoot(), h256(o["genesis_state_root"].get_str()));
BOOST_CHECK_EQUAL(toHex(CanonBlockChain<Ethash>::createGenesisBlock()), toHex(fromHex(o["genesis_rlp_hex"].get_str())));
BOOST_CHECK_EQUAL(Ethash::BlockHeader(CanonBlockChain<Ethash>::createGenesisBlock()).hashWithout(), h256(o["genesis_hash"].get_str()));
BOOST_CHECK_EQUAL(Ethash::BlockHeader(CanonBlockChain<Ethash>::createGenesisBlock()).hash(), h256(o["genesis_hash"].get_str()));
}
BOOST_AUTO_TEST_SUITE_END()

2
test/libethereum/state.cpp

@ -63,7 +63,7 @@ void doStateTests(json_spirit::mValue& v, bool _fillin)
try
{
Listener::ExecTimeGuard guard{i.first};
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number), importer.m_transaction).output;
output = theState.execute(lastHashes(importer.m_environment.currentBlock.number()), importer.m_transaction).output;
}
catch (Exception const& _e)
{

27
test/libevm/vm.cpp

@ -102,13 +102,26 @@ void FakeExtVM::importEnv(mObject& _o)
assert(_o.count("currentCoinbase") > 0);
assert(_o.count("currentNumber") > 0);
currentBlock.parentHash() = h256(_o["previousHash"].get_str());
currentBlock.number = toInt(_o["currentNumber"]);
lastHashes = test::lastHashes(currentBlock.number);
currentBlock.gasLimit = toInt(_o["currentGasLimit"]);
currentBlock.difficulty = toInt(_o["currentDifficulty"]);
currentBlock.timestamp = toInt(_o["currentTimestamp"]);
currentBlock.coinbaseAddress() = Address(_o["currentCoinbase"].get_str());
RLPStream rlpStream;
rlpStream.appendList(BlockInfo::BasicFields);
rlpStream << h256(_o["previousHash"].get_str());
rlpStream << EmptyListSHA3;
rlpStream << Address(_o["currentCoinbase"].get_str());
rlpStream << h256(); // stateRoot
rlpStream << EmptyTrie; // transactionTrie
rlpStream << EmptyTrie; // receiptTrie
rlpStream << LogBloom(); // bloom
rlpStream << toInt(_o["currentDifficulty"]);
rlpStream << toInt(_o["currentNumber"]);
rlpStream << toInt(_o["currentGasLimit"]);
rlpStream << 0; //gasUsed
rlpStream << toInt(_o["currentTimestamp"]);
rlpStream << std::string(); //extra data
currentBlock = BlockInfo(rlpStream.out(), CheckEverything, h256{}, HeaderData);
lastHashes = test::lastHashes(currentBlock.number());
}
mObject FakeExtVM::exportState()

Loading…
Cancel
Save