/*
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 state.cpp
* @author Christoph Jentzsch
* @date 2014
* State test functions.
*/
#include
#include
#include "JsonSpiritHeaders.h"
#include
#include
#include
#include
#include
#include
#include "TestHelper.h"
using namespace std;
using namespace json_spirit;
using namespace dev;
using namespace dev::eth;
using namespace dev::eth;
namespace dev { namespace test {
LastHashes lastHashes(u256 _currentBlockNumber)
{
LastHashes ret;
for (u256 i = 1; i <= 256 && i <= _currentBlockNumber; ++i)
ret.push_back(sha3(toString(_currentBlockNumber - i)));
return ret;
}
void doStateTests(json_spirit::mValue& v, bool _fillin)
{
processCommandLineOptions();
for (auto& i: v.get_obj())
{
cerr << i.first << endl;
mObject& o = i.second.get_obj();
BOOST_REQUIRE(o.count("env") > 0);
BOOST_REQUIRE(o.count("pre") > 0);
BOOST_REQUIRE(o.count("transaction") > 0);
ImportTest importer(o, _fillin);
State theState = importer.m_statePre;
bytes tx = importer.m_transaction.rlp();
bytes output;
try
{
theState.execute(lastHashes(importer.m_environment.currentBlock.number), tx, &output);
}
catch (Exception const& _e)
{
cnote << "state execution did throw an exception: " << diagnostic_information(_e);
}
catch (std::exception const& _e)
{
cnote << "state execution did throw an exception: " << _e.what();
}
if (_fillin)
importer.exportTest(output, theState);
else
{
BOOST_REQUIRE(o.count("post") > 0);
BOOST_REQUIRE(o.count("out") > 0);
// check output
checkOutput(output, o);
// check logs
checkLog(theState.pending().size() ? theState.log(0) : LogEntries(), importer.m_environment.sub.logs);
// check addresses
auto expectedAddrs = importer.m_statePost.addresses();
auto resultAddrs = theState.addresses();
for (auto& expectedPair : expectedAddrs)
{
auto& expectedAddr = expectedPair.first;
auto resultAddrIt = resultAddrs.find(expectedAddr);
if (resultAddrIt == resultAddrs.end())
BOOST_ERROR("Missing expected address " << expectedAddr);
else
{
BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) == theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr));
BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) == theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr));
BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code");
checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr);
}
}
checkAddresses