Merge remote-tracking branch 'upstream/develop' into newTests

Conflicts:
	libevm/VM.h
	libevmface/Instruction.h
	test/vm.cpp
This commit is contained in:
Christoph Jentzsch 2014-10-27 18:29:30 +01:00
commit 88cb7f5c8b
6 changed files with 28 additions and 66 deletions

View File

@ -437,12 +437,12 @@ MemTrie::~MemTrie()
h256 MemTrie::hash256() const h256 MemTrie::hash256() const
{ {
return m_root ? m_root->hash256() : h256(); return m_root ? m_root->hash256() : sha3(dev::rlp(bytesConstRef()));
} }
bytes MemTrie::rlp() const bytes MemTrie::rlp() const
{ {
return m_root ? m_root->rlp() : bytes(); return m_root ? m_root->rlp() : dev::rlp(bytesConstRef());
} }
void MemTrie::debugPrint() void MemTrie::debugPrint()

View File

@ -162,7 +162,7 @@ h256 hash256(StringMap const& _s)
{ {
// build patricia tree. // build patricia tree.
if (_s.empty()) if (_s.empty())
return h256(); return sha3(rlp(""));
HexMap hexMap; HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i) for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(i->first)] = i->second; hexMap[asNibbles(i->first)] = i->second;
@ -175,7 +175,7 @@ bytes rlp256(StringMap const& _s)
{ {
// build patricia tree. // build patricia tree.
if (_s.empty()) if (_s.empty())
return bytes(); return rlp("");
HexMap hexMap; HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i) for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(i->first)] = i->second; hexMap[asNibbles(i->first)] = i->second;
@ -188,7 +188,7 @@ h256 hash256(u256Map const& _s)
{ {
// build patricia tree. // build patricia tree.
if (_s.empty()) if (_s.empty())
return h256(); return sha3(rlp(""));
HexMap hexMap; HexMap hexMap;
for (auto i = _s.rbegin(); i != _s.rend(); ++i) for (auto i = _s.rbegin(); i != _s.rend(); ++i)
hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second)); hexMap[asNibbles(toBigEndianString(i->first))] = asString(rlp(i->second));

View File

@ -341,6 +341,7 @@ BOOST_AUTO_TEST_CASE(eth_keypairs)
{ {
eth::Transaction t; eth::Transaction t;
t.nonce = 0; t.nonce = 0;
t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000; t.value = 1000;
auto rlp = t.rlp(false); auto rlp = t.rlp(false);
@ -369,6 +370,7 @@ int cryptoTest()
{ {
eth::Transaction t; eth::Transaction t;
t.nonce = 0; t.nonce = 0;
t.type = eth::Transaction::MessageCall;
t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b"));
t.value = 1000; t.value = 1000;
auto rlp = t.rlp(false); auto rlp = t.rlp(false);
@ -397,6 +399,7 @@ int cryptoTest()
Transaction t; Transaction t;
t.nonce = 0; t.nonce = 0;
t.value = 1; // 1 wei. t.value = 1; // 1 wei.
t.type = eth::Transaction::MessageCall;
t.receiveAddress = toAddress(sha3("123")); t.receiveAddress = toAddress(sha3("123"));
bytes sig64 = toBigEndian(t.vrs.r) + toBigEndian(t.vrs.s); bytes sig64 = toBigEndian(t.vrs.r) + toBigEndian(t.vrs.s);

View File

@ -68,6 +68,7 @@ int stateTest()
Transaction t; Transaction t;
t.nonce = s.transactionsFrom(myMiner.address()); t.nonce = s.transactionsFrom(myMiner.address());
t.value = 1000; // 1e3 wei. t.value = 1000; // 1e3 wei.
t.type = eth::Transaction::MessageCall;
t.receiveAddress = me.address(); t.receiveAddress = me.address();
t.sign(myMiner.secret()); t.sign(myMiner.secret());
assert(t.sender() == myMiner.address()); assert(t.sender() == myMiner.address());

78
vm.cpp
View File

@ -45,7 +45,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
m_s.noteSending(myAddress); m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1); 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) if (!m_ms.internal.back().from)
m_ms.internal.pop_back(); m_ms.internal.pop_back();
@ -56,7 +56,7 @@ h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFun
get<3>(addresses[ret]) = m_s.code(ret); get<3>(addresses[ret]) = m_s.code(ret);
} }
t.receiveAddress = Address(); t.type = eth::Transaction::ContractCreation;
callcreates.push_back(t); callcreates.push_back(t);
return ret; return ret;
} }
@ -71,6 +71,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
t.gasPrice = gasPrice; t.gasPrice = gasPrice;
t.gas = *_gas; t.gas = *_gas;
t.data = _data.toVector(); t.data = _data.toVector();
t.type = eth::Transaction::MessageCall;
t.receiveAddress = _receiveAddress; t.receiveAddress = _receiveAddress;
callcreates.push_back(t); callcreates.push_back(t);
@ -91,7 +92,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
if (!m_s.addresses().count(myAddress)) if (!m_s.addresses().count(myAddress))
{ {
m_ms.internal.resize(m_ms.internal.size() + 1); 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) if (!m_ms.internal.back().from)
m_ms.internal.pop_back(); m_ms.internal.pop_back();
if (na != myAddress) if (na != myAddress)
@ -116,7 +117,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
{ {
m_s.noteSending(myAddress); m_s.noteSending(myAddress);
m_ms.internal.resize(m_ms.internal.size() + 1); 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) if (!m_ms.internal.back().from)
m_ms.internal.pop_back(); m_ms.internal.pop_back();
@ -131,7 +132,7 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
m_ms.internal.resize(m_ms.internal.size() + 1); 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()), Executive::simpleTrace(), 1); auto ret = m_s.call(_receiveAddress,_codeAddressOverride ? _codeAddressOverride : _receiveAddress, _myAddressOverride ? _myAddressOverride : myAddress, _value, gasPrice, _data, _gas, _out, origin, &sub, &(m_ms.internal.back()), OnOpFunc(), 1);
if (!m_ms.internal.back().from) if (!m_ms.internal.back().from)
m_ms.internal.pop_back(); m_ms.internal.pop_back();
@ -146,12 +147,15 @@ bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data,
if (!ret) if (!ret)
return false; return false;
// TODO: @CJentzsch refund SSTORE stuff.
// TODO: @CJentzsch test logs.
// do suicides // do suicides
for (auto const& f: suicides) for (auto const& f: sub.suicides)
addresses.erase(f); addresses.erase(f);
// get storage // 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)) for (auto const& j: m_s.storage(_receiveAddress))
{ {
@ -384,7 +388,7 @@ mArray FakeExtVM::exportCallCreates()
for (Transaction const& tx: callcreates) for (Transaction const& tx: callcreates)
{ {
mObject o; mObject o;
o["destination"] = toString(tx.receiveAddress); o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress);
push(o, "gasLimit", tx.gas); push(o, "gasLimit", tx.gas);
push(o, "value", tx.value); push(o, "value", tx.value);
o["data"] = "0x" + toHex(tx.data); o["data"] = "0x" + toHex(tx.data);
@ -403,6 +407,7 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
BOOST_REQUIRE(tx.count("destination") > 0); BOOST_REQUIRE(tx.count("destination") > 0);
BOOST_REQUIRE(tx.count("gasLimit") > 0); BOOST_REQUIRE(tx.count("gasLimit") > 0);
Transaction t; Transaction t;
t.type = tx["destination"].get_str().empty() ? Transaction::ContractCreation : Transaction::MessageCall;
t.receiveAddress = Address(tx["destination"].get_str()); t.receiveAddress = Address(tx["destination"].get_str());
t.value = toInt(tx["value"]); t.value = toInt(tx["value"]);
t.gas = toInt(tx["gasLimit"]); t.gas = toInt(tx["gasLimit"]);
@ -418,28 +423,11 @@ void FakeExtVM::importCallCreates(mArray& _callcreates)
} }
} }
OnOpFunc FakeExtVM::simpleTrace() // 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)
{ {
return [](uint64_t steps, Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt) (void)o_sub;
{
FakeExtVM const& ext = *(FakeExtVM const*)voidExt;
VM& vm = *(VM*)voidVM;
ostringstream o;
o << endl << " STACK" << endl;
for (auto i: vm.stack())
o << (h256)i << endl;
o << " MEMORY" << endl << memDump(vm.memory());
o << " STORAGE" << endl;
for (auto const& i: ext.state().storage(ext.myAddress))
o << showbase << hex << i.first << ": " << i.second << endl;
dev::LogOutputStream<VMTraceChannel, false>(true) << o.str();
dev::LogOutputStream<VMTraceChannel, false>(false) << " | " << dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << hex << setw(4) << setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << dec << vm.gas() << " | -" << dec << gasCost << " | " << newMemSize << "x32" << " ]";
};
}
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)
{
if (!_origin) if (!_origin)
_origin = _sender; _origin = _sender;
@ -465,9 +453,7 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
out = vm.go(evm, _onOp); out = vm.go(evm, _onOp);
if (o_ms) if (o_ms)
o_ms->output = out.toBytes(); o_ms->output = out.toBytes();
if (o_suicides) // TODO: deal with evm.sub
for (auto i: evm.suicides)
o_suicides->insert(i);
} }
catch (OutOfGas const& /*_e*/) catch (OutOfGas const& /*_e*/)
{ {
@ -504,7 +490,6 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
namespace dev { namespace test { namespace dev { namespace test {
void doTests(json_spirit::mValue& v, bool _fillin) void doTests(json_spirit::mValue& v, bool _fillin)
@ -536,7 +521,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
VM vm(fev.gas); VM vm(fev.gas);
try try
{ {
output = vm.go(fev, fev.simpleTrace()).toVector(); output = vm.go(fev).toVector();
} }
catch (Exception const& _e) catch (Exception const& _e)
{ {
@ -772,30 +757,3 @@ BOOST_AUTO_TEST_CASE(vmSystemOperationsTest)
{ {
dev::test::executeTests("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];
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());
}
}
}

2
vm.h
View File

@ -44,7 +44,7 @@ class FakeState: public eth::State
{ {
public: public:
/// Execute a contract-creation transaction. /// Execute a contract-creation transaction.
h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, std::set<Address>* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0); h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, eth::SubState* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0);
}; };
class FakeExtVM: public eth::ExtVMFace class FakeExtVM: public eth::ExtVMFace