aboutsummaryrefslogtreecommitdiffstats
path: root/vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vm.cpp')
-rw-r--r--vm.cpp121
1 files changed, 76 insertions, 45 deletions
diff --git a/vm.cpp b/vm.cpp
index c056abf5..56fe104e 100644
--- a/vm.cpp
+++ b/vm.cpp
@@ -20,11 +20,9 @@
* vm test functions.
*/
-#include "vm.h"
-#include <libdevcore/CommonIO.h>
-#include <libevmjit/VM.h>
-#include <boost/filesystem/path.hpp>
#include <chrono>
+#include <boost/filesystem/path.hpp>
+#include "vm.h"
//#define FILL_TESTS
using namespace std;
@@ -46,7 +44,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1);
- auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
+ auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
@@ -57,14 +55,13 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
get<3>(addresses[ret]) = m_s.code(ret);
}
- t.receiveAddress = ret;
+ t.type = eth::Transaction::ContractCreation;
callcreates.push_back(t);
return ret;
}
-bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride = Address(), Address _codeAddressOverride = Address())
+bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride)
{
-
u256 contractgas = 0xffff;
Transaction t;
@@ -72,6 +69,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
t.gasPrice = gasPrice;
t.gas = *_gas;
t.data = _data.toVector();
+ t.type = eth::Transaction::MessageCall;
t.receiveAddress = _receiveAddress;
callcreates.push_back(t);
@@ -92,7 +90,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
if (!m_s.addresses().count(myAddress))
{
m_ms.internal.resize(m_ms.internal.size() + 1);
- auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
+ auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
if (na != myAddress)
@@ -117,7 +115,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{
m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1);
- auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &suicides, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1);
+ auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
@@ -132,7 +130,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
m_ms.internal.resize(m_ms.internal.size() + 1);
- auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &suicides, &(m_ms.internal.back()), OnOpFunc(), 1);
+ auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), simpleTrace<ExtVM>(), 1);
if (!m_ms.internal.back().from)
m_ms.internal.pop_back();
@@ -147,12 +145,15 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
if (!ret)
return false;
+ // TODO: @CJentzsch refund SSTORE stuff.
+ // TODO: @CJentzsch test logs.
+
// do suicides
- for (auto const& f: suicides)
+ for (auto const& f: sub.suicides)
addresses.erase(f);
// get storage
- if ((get<0>(addresses[myAddress]) >= _value) && (suicides.find(_receiveAddress) == suicides.end()))
+ if ((get<0>(addresses[myAddress]) >= _value) && (sub.suicides.find(_receiveAddress) == sub.suicides.end()))
{
for (auto const& j: m_s.storage(_receiveAddress))
{
@@ -357,10 +358,10 @@ void FakeExtVM::importExec(mObject& _o)
thisTxCode.clear();
code = &thisTxCode;
if (_o["code"].type() == str_type)
- if (_o["code"].get_str().find_first_of("0x") != 0)
- thisTxCode = compileLLL(_o["code"].get_str());
- else
+ if (_o["code"].get_str().find_first_of("0x") == 0)
thisTxCode = fromHex(_o["code"].get_str().substr(2));
+ else
+ thisTxCode = compileLLL(_o["code"].get_str());
else if (_o["code"].type() == array_type)
for (auto const& j: _o["code"].get_array())
thisTxCode.push_back(toByte(j));
@@ -385,7 +386,7 @@ mArray FakeExtVM::exportCallCreates()
for (Transaction const& tx: callcreates)
{
mObject o;
- o["destination"] = toString(tx.receiveAddress);
+ o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress);
push(o, "gasLimit", tx.gas);
push(o, "value", tx.value);
o["data"] = "0x" + toHex(tx.data);
@@ -404,6 +405,7 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
BOOST_REQUIRE(tx.count("destination") > 0);
BOOST_REQUIRE(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"]);
@@ -419,8 +421,11 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
}
}
-h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, std::set<Address>* o_suicides, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
+// THIS IS BROKEN AND NEEDS TO BE REMOVED.
+h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _origin, SubState* o_sub, Manifest* o_ms, OnOpFunc const& _onOp, unsigned _level)
{
+ (void)o_sub;
+
if (!_origin)
_origin = _sender;
@@ -436,8 +441,8 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256());
// Execute init code.
- auto vmObj = VMFace::create(VMFace::Interpreter, *_gas);
- VMFace& vm = *vmObj;
+ auto vmObj = VMFace::create(getVMKind(), *_gas);
+ auto& vm = *vmObj;
ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level);
bool revert = false;
bytesConstRef out;
@@ -447,9 +452,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
out = vm.go(evm, _onOp);
if (o_ms)
o_ms->output = out.toBytes();
- if (o_suicides)
- for (auto i: evm.suicides)
- o_suicides->insert(i);
+ // TODO: deal with evm.sub
}
catch (OutOfGas const& /*_e*/)
{
@@ -484,8 +487,6 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
return _newAddress;
}
-
-
namespace dev { namespace test {
void doTests(json_spirit::mValue& v, bool _fillin)
@@ -499,7 +500,14 @@ void doTests(json_spirit::mValue& v, bool _fillin)
BOOST_REQUIRE(o.count("pre") > 0);
BOOST_REQUIRE(o.count("exec") > 0);
+ auto argc = boost::unit_test::framework::master_test_suite().argc;
+ auto argv = boost::unit_test::framework::master_test_suite().argv;
+ auto useJit = argc >= 2 && std::string(argv[1]) == "--jit";
+ auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter;
+
dev::test::FakeExtVM fev;
+ fev.setVMKind(vmKind);
+
fev.importEnv(o["env"].get_obj());
fev.importState(o["pre"].get_obj());
@@ -512,25 +520,15 @@ void doTests(json_spirit::mValue& v, bool _fillin)
fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress));
fev.code = &fev.thisTxCode;
}
-
-
- auto argc = boost::unit_test::framework::master_test_suite().argc;
- auto argv = boost::unit_test::framework::master_test_suite().argv;
- auto useJit = argc >= 2 && std::string(argv[1]) == "--jit";
- auto showTimes = false;
- for (auto i = 0; i < argc; ++i)
- showTimes |= std::string(argv[i]) == "--show-times";
-
- auto vmKind = useJit ? VMFace::JIT : VMFace::Interpreter;
- auto vm = VMFace::create(vmKind, fev.gas);
+ auto vm = VMFace::create(fev.getVMKind(), fev.gas);
bytes output;
auto outOfGas = false;
auto startTime = std::chrono::high_resolution_clock::now();
try
{
- output = vm->go(fev).toVector();
+ output = vm->go(fev, fev.simpleTrace<FakeExtVM>()).toVector();
}
catch (OutOfGas const&)
{
@@ -546,12 +544,16 @@ void doTests(json_spirit::mValue& v, bool _fillin)
}
auto endTime = std::chrono::high_resolution_clock::now();
- if (showTimes)
- {
- auto testDuration = endTime - startTime;
- cnote << "Execution time: "
- << std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
- << " ms";
+ for (auto i = 0; i < argc; ++i)
+ {
+ if (std::string(argv[i]) == "--show-times")
+ {
+ auto testDuration = endTime - startTime;
+ cnote << "Execution time: "
+ << std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
+ << " ms";
+ }
+ break;
}
auto gas = vm->gas();
@@ -686,11 +688,13 @@ void executeTests(const string& _name)
if (ptestPath == NULL)
{
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
- testPath = "../../../tests/vmtests";
+ testPath = "../../../tests";
}
else
testPath = ptestPath;
+ testPath += "/vmtests";
+
#ifdef FILL_TESTS
try
{
@@ -719,7 +723,7 @@ void executeTests(const string& _name)
cnote << "Testing VM..." << _name;
json_spirit::mValue v;
string s = asString(contents(testPath + "/" + _name + ".json"));
- BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
+ BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?");
json_spirit::read_string(s, v);
dev::test::doTests(v, false);
}
@@ -786,4 +790,31 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest)
dev::test::executeTests("vmSystemOperationsTest");
}
+BOOST_AUTO_TEST_CASE(userDefinedFile)
+{
+ if (boost::unit_test::framework::master_test_suite().argc == 2)
+ {
+ string filename = boost::unit_test::framework::master_test_suite().argv[1];
+ int currentVerbosity = g_logVerbosity;
+ g_logVerbosity = 12;
+ try
+ {
+ cnote << "Testing VM..." << "user defined test";
+ json_spirit::mValue v;
+ string s = asString(contents(filename));
+ BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. ");
+ json_spirit::read_string(s, v);
+ dev::test::doTests(v, false);
+ }
+ catch (Exception const& _e)
+ {
+ BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e));
+ }
+ catch (std::exception const& _e)
+ {
+ BOOST_ERROR("Failed VM Test with Exception: " << _e.what());
+ }
+ g_logVerbosity = currentVerbosity;
+ }
+}