/* 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 TestHelper.cpp * @author Marko Simovic * @date 2014 */ #include "TestHelper.h" #include #include #include #include using namespace std; namespace dev { namespace eth { void mine(Client& c, int numBlocks) { auto startBlock = c.blockChain().details().number; c.startMining(); while(c.blockChain().details().number < startBlock + numBlocks) std::this_thread::sleep_for(std::chrono::milliseconds(100)); c.stopMining(); } void connectClients(Client& c1, Client& c2) { (void)c1; (void)c2; // TODO: Move to WebThree. eth::Client no longer handles networking. #if 0 short c1Port = 20000; short c2Port = 21000; c1.startNetwork(c1Port); c2.startNetwork(c2Port); c2.connect("127.0.0.1", c1Port); #endif } namespace test { ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller) { importEnv(_o["env"].get_obj()); importState(_o["pre"].get_obj(), m_statePre); importExec(_o["exec"].get_obj()); if (!isFiller) { importState(_o["post"].get_obj(), m_statePost); importCallCreates(_o["callcreates"].get_array()); importGas(_o); importOutput(_o); } } void ImportTest::importEnv(json_spirit::mObject& _o) { assert(_o.count("previousHash") > 0); assert(_o.count("currentGasLimit") > 0); assert(_o.count("currentDifficulty") > 0); assert(_o.count("currentTimestamp") > 0); assert(_o.count("currentCoinbase") > 0); assert(_o.count("currentNumber") > 0); m_environment.previousBlock.hash = 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()); } void ImportTest::importState(json_spirit::mObject& _o, State& _state) { for (auto const& i: _o) { json_spirit::mObject o = i.second.get_obj(); assert(o.count("balance") > 0); assert(o.count("nonce") > 0); assert(o.count("storage") > 0); assert(o.count("code") > 0); Address address = Address(i.first); cout << "address: " << address.abridged() << endl; _state.m_cache[address] = AddressState(toInt(o["nonce"]), toInt(o["balance"]), h256(), h256()); cout << "addressInUse: " << _state.addressInUse(address) << endl; cout << "balance: " << _state.balance(address) << endl; for (auto const& j: o["storage"].get_obj()) _state.setStorage(address, toInt(j.first), toInt(j.second)); bytes code; if (o["code"].type() == json_spirit::str_type) if (o["code"].get_str().find_first_of("0x") != 0) code = compileLLL(o["code"].get_str(), false); else code = fromHex(o["code"].get_str().substr(2)); else { code.clear(); for (auto const& j: o["code"].get_array()) code.push_back(toByte(j)); } _state.m_cache[address].setCode(bytesConstRef(&code)); _state.ensureCached(address, true, true); } } void ImportTest::importExec(json_spirit::mObject& _o) { assert(_o.count("address")> 0); assert(_o.count("caller") > 0); assert(_o.count("origin") > 0); assert(_o.count("value") > 0); assert(_o.count("data") > 0); assert(_o.count("gasPrice") > 0); assert(_o.count("gas") > 0); assert(_o.count("code") > 0); m_environment.myAddress = Address(_o["address"].get_str()); m_environment.caller = Address(_o["caller"].get_str()); m_environment.origin = Address(_o["origin"].get_str()); m_environment.value = toInt(_o["value"]); m_environment.gasPrice = toInt(_o["gasPrice"]); gasExec = toInt(_o["gas"]); if (_o["code"].type() == json_spirit::str_type) if (_o["code"].get_str().find_first_of("0x") == 0) code = fromHex(_o["code"].get_str().substr(2)); else code = compileLLL(_o["code"].get_str()); else if (_o["code"].type() == json_spirit::array_type) for (auto const& j: _o["code"].get_array()) code.push_back(toByte(j)); else m_environment.code.reset(); m_environment.code = &code; if (_o["data"].type() == json_spirit::str_type) if (_o["data"].get_str().find_first_of("0x") == 0) data = fromHex(_o["data"].get_str().substr(2)); else data = fromHex(_o["data"].get_str()); else for (auto const& j: _o["data"].get_array()) data.push_back(toByte(j)); m_environment.data = &data; } void ImportTest::importCallCreates(json_spirit::mArray& _callcreates) { for (json_spirit::mValue& v: _callcreates) { auto tx = v.get_obj(); assert(tx.count("data") > 0); assert(tx.count("value") > 0); assert(tx.count("destination") > 0); assert(tx.count("gasLimit") > 0); Transaction t; t.type = tx["destination"].get_str().empty() ? Transaction::ContractCreation : Transaction::MessageCall; t.receiveAddress = Address(tx["destination"].get_str()); t.value = toInt(tx["value"]); t.gas = toInt(tx["gasLimit"]); if (tx["data"].type() == json_spirit::str_type) if (tx["data"].get_str().find_first_of("0x") == 0) t.data = fromHex(tx["data"].get_str().substr(2)); else t.data = fromHex(tx["data"].get_str()); else for (auto const& j: tx["data"].get_array()) t.data.push_back(toByte(j)); callcreates.push_back(t); } } void ImportTest::importGas(json_spirit::mObject& _o) { gas = toInt(_o["gas"]); } void ImportTest::importOutput(json_spirit::mObject& _o) { int i = 0; if (_o["out"].type() == json_spirit::array_type) for (auto const& d: _o["out"].get_array()) { output[i] = uint8_t(toInt(d)); ++i; } else if (_o["out"].get_str().find("0x") == 0) output = fromHex(_o["out"].get_str().substr(2)); else output = fromHex(_o["out"].get_str()); } u256 toInt(json_spirit::mValue const& _v) { switch (_v.type()) { case json_spirit::str_type: return u256(_v.get_str()); case json_spirit::int_type: return (u256)_v.get_uint64(); case json_spirit::bool_type: return (u256)(uint64_t)_v.get_bool(); case json_spirit::real_type: return (u256)(uint64_t)_v.get_real(); default: cwarn << "Bad type for scalar: " << _v.type(); } return 0; } byte toByte(json_spirit::mValue const& _v) { switch (_v.type()) { case json_spirit::str_type: return (byte)stoi(_v.get_str()); case json_spirit::int_type: return (byte)_v.get_uint64(); case json_spirit::bool_type: return (byte)_v.get_bool(); case json_spirit::real_type: return (byte)_v.get_real(); default: cwarn << "Bad type for scalar: " << _v.type(); } return 0; } } } } // namespaces