mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
Conflicts: test/vm.cpp
This commit is contained in:
commit
ec9330609f
@ -17,6 +17,7 @@ target_link_libraries(testeth ethereum)
|
|||||||
target_link_libraries(testeth ethcore)
|
target_link_libraries(testeth ethcore)
|
||||||
target_link_libraries(testeth secp256k1)
|
target_link_libraries(testeth secp256k1)
|
||||||
target_link_libraries(testeth gmp)
|
target_link_libraries(testeth gmp)
|
||||||
|
target_link_libraries(testeth solidity)
|
||||||
target_link_libraries(testeth ${CRYPTOPP_LS})
|
target_link_libraries(testeth ${CRYPTOPP_LS})
|
||||||
target_link_libraries(testeth evm)
|
target_link_libraries(testeth evm)
|
||||||
target_link_libraries(testeth evmjit)
|
target_link_libraries(testeth evmjit)
|
||||||
|
@ -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()
|
||||||
|
@ -21,23 +21,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//#include <ostream>
|
#include <libdevcrypto/CryptoPP.h>
|
||||||
|
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable:4100 4244)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wconversion"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
||||||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
|
||||||
#pragma GCC diagnostic ignored "-Wextra"
|
|
||||||
#include <eccrypto.h>
|
|
||||||
#include <ecp.h>
|
|
||||||
#include <files.h>
|
|
||||||
#include <osrng.h>
|
|
||||||
#include <oids.h>
|
|
||||||
#pragma warning(pop)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CryptoPP;
|
using namespace CryptoPP;
|
||||||
|
@ -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));
|
||||||
|
@ -42,11 +42,7 @@ void doMyTests(json_spirit::mValue& v);
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
g_logVerbosity = 0;
|
||||||
{
|
|
||||||
cout << "usage: createRandomTest <filename>\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create random code
|
// create random code
|
||||||
|
|
||||||
@ -64,14 +60,48 @@ int main(int argc, char *argv[])
|
|||||||
string randomCode;
|
string randomCode;
|
||||||
|
|
||||||
for (int i = 0; i < lengthOfCode; ++i)
|
for (int i = 0; i < lengthOfCode; ++i)
|
||||||
randomCode += toHex(toCompactBigEndian(randGen()));
|
{
|
||||||
|
uint8_t opcode = randGen();
|
||||||
|
|
||||||
// read template test file
|
// disregard all invalid commands, except of one (0x10)
|
||||||
|
if (dev::eth::isValidInstruction(dev::eth::Instruction(opcode)) || opcode == 0x10)
|
||||||
|
randomCode += toHex(toCompactBigEndian(opcode));
|
||||||
|
else
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string s =\
|
||||||
|
"{\n\
|
||||||
|
\"randomVMtest\": {\n\
|
||||||
|
\"env\" : {\n\
|
||||||
|
\"previousHash\" : \"5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6\",\n\
|
||||||
|
\"currentNumber\" : \"0\",\n\
|
||||||
|
\"currentGasLimit\" : \"1000000\",\n\
|
||||||
|
\"currentDifficulty\" : \"256\",\n\
|
||||||
|
\"currentTimestamp\" : 1,\n\
|
||||||
|
\"currentCoinbase\" : \"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba\"\n\
|
||||||
|
},\n\
|
||||||
|
\"pre\" : {\n\
|
||||||
|
\"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\" : {\n\
|
||||||
|
\"balance\" : \"1000000000000000000\",\n\
|
||||||
|
\"nonce\" : 0,\n\
|
||||||
|
\"code\" : \"random\",\n\
|
||||||
|
\"storage\": {}\n\
|
||||||
|
}\n\
|
||||||
|
},\n\
|
||||||
|
\"exec\" : {\n\
|
||||||
|
\"address\" : \"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6\",\n\
|
||||||
|
\"origin\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
|
||||||
|
\"caller\" : \"cd1722f3947def4cf144679da39c4c32bdc35681\",\n\
|
||||||
|
\"value\" : \"1000000000000000000\",\n\
|
||||||
|
\"data\" : \"\",\n\
|
||||||
|
\"gasPrice\" : \"100000000000000\",\n\
|
||||||
|
\"gas\" : \"10000\"\n\
|
||||||
|
}\n\
|
||||||
|
}\n\
|
||||||
|
}";
|
||||||
|
|
||||||
mValue v;
|
mValue v;
|
||||||
boost::filesystem::path p(__FILE__);
|
|
||||||
boost::filesystem::path dir = p.parent_path();
|
|
||||||
string s = asString(contents(dir.string() + "/randomTestFiller.json"));
|
|
||||||
read_string(s, v);
|
read_string(s, v);
|
||||||
|
|
||||||
// insert new random code
|
// insert new random code
|
||||||
@ -80,9 +110,8 @@ int main(int argc, char *argv[])
|
|||||||
// execute code in vm
|
// execute code in vm
|
||||||
doMyTests(v);
|
doMyTests(v);
|
||||||
|
|
||||||
// write new test
|
// stream to output for further handling by the bash script
|
||||||
string filename = argv[1];
|
cout << json_spirit::write_string(v, true);
|
||||||
writeFile(filename, asBytes(json_spirit::write_string(v, true)));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
349
crypto.cpp
349
crypto.cpp
@ -27,37 +27,163 @@
|
|||||||
#include <libdevcore/Log.h>
|
#include <libdevcore/Log.h>
|
||||||
#include <libethereum/Transaction.h>
|
#include <libethereum/Transaction.h>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <libdevcrypto/EC.h>
|
||||||
#include "TestHelperCrypto.h"
|
#include "TestHelperCrypto.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace dev;
|
using namespace dev;
|
||||||
|
using namespace dev::crypto;
|
||||||
namespace dev
|
|
||||||
{
|
|
||||||
namespace crypto
|
|
||||||
{
|
|
||||||
|
|
||||||
inline CryptoPP::AutoSeededRandomPool& PRNG() {
|
|
||||||
static CryptoPP::AutoSeededRandomPool prng;
|
|
||||||
return prng;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace CryptoPP;
|
using namespace CryptoPP;
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(crypto)
|
BOOST_AUTO_TEST_SUITE(devcrypto)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(common_encrypt_decrypt)
|
||||||
|
{
|
||||||
|
string message("Now is the time for all good persons to come to the aide of humanity.");
|
||||||
|
bytes m = asBytes(message);
|
||||||
|
bytesConstRef bcr(&m);
|
||||||
|
|
||||||
|
KeyPair k = KeyPair::create();
|
||||||
|
bytes cipher;
|
||||||
|
encrypt(k.pub(), bcr, cipher);
|
||||||
|
assert(cipher != asBytes(message) && cipher.size() > 0);
|
||||||
|
|
||||||
|
bytes plain;
|
||||||
|
decrypt(k.sec(), bytesConstRef(&cipher), plain);
|
||||||
|
|
||||||
|
assert(asString(plain) == message);
|
||||||
|
assert(plain == asBytes(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1)
|
||||||
|
{
|
||||||
|
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
|
||||||
|
ECIES<ECP>::Encryptor e(d.GetKey());
|
||||||
|
|
||||||
|
Secret s;
|
||||||
|
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
|
||||||
|
|
||||||
|
Public p;
|
||||||
|
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
|
||||||
|
|
||||||
|
assert(dev::toAddress(s) == right160(dev::sha3(p.ref())));
|
||||||
|
|
||||||
|
Secret previous = s;
|
||||||
|
for (auto i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
|
||||||
|
ECIES<ECP>::Encryptor e(d.GetKey());
|
||||||
|
|
||||||
|
Secret s;
|
||||||
|
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
|
||||||
|
assert(s != previous);
|
||||||
|
|
||||||
|
Public p;
|
||||||
|
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
|
||||||
|
|
||||||
|
assert(dev::toAddress(s) == right160(dev::sha3(p.ref())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(cryptopp_keys_cryptor_sipaseckp256k1)
|
||||||
|
{
|
||||||
|
KeyPair k = KeyPair::create();
|
||||||
|
Secret s = k.sec();
|
||||||
|
|
||||||
|
// Convert secret to exponent used by pp
|
||||||
|
Integer e = pp::ExponentFromSecret(s);
|
||||||
|
|
||||||
|
// Test that exported DL_EC private is same as exponent from Secret
|
||||||
|
CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> privatek;
|
||||||
|
privatek.AccessGroupParameters().Initialize(pp::secp256k1());
|
||||||
|
privatek.SetPrivateExponent(e);
|
||||||
|
assert(e == privatek.GetPrivateExponent());
|
||||||
|
|
||||||
|
// Test that exported secret is same as decryptor(privatek) secret
|
||||||
|
ECIES<ECP>::Decryptor d;
|
||||||
|
d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1());
|
||||||
|
d.AccessKey().SetPrivateExponent(e);
|
||||||
|
assert(d.AccessKey().GetPrivateExponent() == e);
|
||||||
|
|
||||||
|
// Test that decryptor->encryptor->public == private->makepublic->public
|
||||||
|
CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pubk;
|
||||||
|
pubk.AccessGroupParameters().Initialize(pp::secp256k1());
|
||||||
|
privatek.MakePublicKey(pubk);
|
||||||
|
|
||||||
|
ECIES<ECP>::Encryptor enc(d);
|
||||||
|
assert(pubk.GetPublicElement() == enc.AccessKey().GetPublicElement());
|
||||||
|
|
||||||
|
// Test against sipa/seckp256k1
|
||||||
|
Public p;
|
||||||
|
pp::PublicFromExponent(pp::ExponentFromSecret(s), p);
|
||||||
|
assert(toAddress(s) == dev::right160(dev::sha3(p.ref())));
|
||||||
|
assert(k.pub() == p);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(cryptopp_public_export_import)
|
||||||
|
{
|
||||||
|
ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1());
|
||||||
|
ECIES<ECP>::Encryptor e(d.GetKey());
|
||||||
|
|
||||||
|
Secret s;
|
||||||
|
pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s);
|
||||||
|
Public p;
|
||||||
|
pp::PublicFromDL_PublicKey_EC(e.GetKey(), p);
|
||||||
|
Address addr = right160(dev::sha3(p.ref()));
|
||||||
|
assert(toAddress(s) == addr);
|
||||||
|
|
||||||
|
KeyPair l(s);
|
||||||
|
assert(l.address() == addr);
|
||||||
|
|
||||||
|
DL_PublicKey_EC<ECP> pub;
|
||||||
|
pub.Initialize(pp::secp256k1(), pp::PointFromPublic(p));
|
||||||
|
assert(pub.GetPublicElement() == e.GetKey().GetPublicElement());
|
||||||
|
|
||||||
|
KeyPair k = KeyPair::create();
|
||||||
|
Public p2;
|
||||||
|
pp::PublicFromExponent(pp::ExponentFromSecret(k.sec()), p2);
|
||||||
|
assert(k.pub() == p2);
|
||||||
|
|
||||||
|
Address a = k.address();
|
||||||
|
Address a2 = toAddress(k.sec());
|
||||||
|
assert(a2 == a);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ecies_eckeypair)
|
||||||
|
{
|
||||||
|
KeyPair k = KeyPair::create();
|
||||||
|
|
||||||
|
string message("Now is the time for all good persons to come to the aide of humanity.");
|
||||||
|
string original = message;
|
||||||
|
|
||||||
|
bytes b = asBytes(message);
|
||||||
|
encrypt(k.pub(), b);
|
||||||
|
assert(b != asBytes(original));
|
||||||
|
|
||||||
|
decrypt(k.sec(), b);
|
||||||
|
assert(b == asBytes(original));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac)
|
||||||
|
{
|
||||||
|
// New connections require new ECDH keypairs
|
||||||
|
// Every new connection requires a new EC keypair
|
||||||
|
// Every new trust requires a new EC keypair
|
||||||
|
// All connections should share seed for PRF (or PRNG) for nonces
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
|
BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
|
||||||
{
|
{
|
||||||
cnote << "Testing cryptopp_ecies_message...";
|
cnote << "Testing cryptopp_ecies_message...";
|
||||||
|
|
||||||
string const message("Now is the time for all good men to come to the aide of humanity.");
|
string const message("Now is the time for all good persons to come to the aide of humanity.");
|
||||||
|
|
||||||
AutoSeededRandomPool prng;
|
ECIES<ECP>::Decryptor localDecryptor(pp::PRNG(), pp::secp256k1());
|
||||||
|
|
||||||
ECIES<ECP>::Decryptor localDecryptor(prng, ASN1::secp256r1());
|
|
||||||
SavePrivateKey(localDecryptor.GetPrivateKey());
|
SavePrivateKey(localDecryptor.GetPrivateKey());
|
||||||
|
|
||||||
ECIES<ECP>::Encryptor localEncryptor(localDecryptor);
|
ECIES<ECP>::Encryptor localEncryptor(localDecryptor);
|
||||||
@ -65,31 +191,31 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
|
|||||||
|
|
||||||
ECIES<ECP>::Decryptor futureDecryptor;
|
ECIES<ECP>::Decryptor futureDecryptor;
|
||||||
LoadPrivateKey(futureDecryptor.AccessPrivateKey());
|
LoadPrivateKey(futureDecryptor.AccessPrivateKey());
|
||||||
futureDecryptor.GetPrivateKey().ThrowIfInvalid(prng, 3);
|
futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3);
|
||||||
|
|
||||||
ECIES<ECP>::Encryptor futureEncryptor;
|
ECIES<ECP>::Encryptor futureEncryptor;
|
||||||
LoadPublicKey(futureEncryptor.AccessPublicKey());
|
LoadPublicKey(futureEncryptor.AccessPublicKey());
|
||||||
futureEncryptor.GetPublicKey().ThrowIfInvalid(prng, 3);
|
futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3);
|
||||||
|
|
||||||
// encrypt/decrypt with local
|
// encrypt/decrypt with local
|
||||||
string cipherLocal;
|
string cipherLocal;
|
||||||
StringSource ss1 (message, true, new PK_EncryptorFilter(prng, localEncryptor, new StringSink(cipherLocal) ) );
|
StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG(), localEncryptor, new StringSink(cipherLocal) ) );
|
||||||
string plainLocal;
|
string plainLocal;
|
||||||
StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocal) ) );
|
StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocal) ) );
|
||||||
|
|
||||||
// encrypt/decrypt with future
|
// encrypt/decrypt with future
|
||||||
string cipherFuture;
|
string cipherFuture;
|
||||||
StringSource ss3 (message, true, new PK_EncryptorFilter(prng, futureEncryptor, new StringSink(cipherFuture) ) );
|
StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) );
|
||||||
string plainFuture;
|
string plainFuture;
|
||||||
StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFuture) ) );
|
StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFuture) ) );
|
||||||
|
|
||||||
// decrypt local w/future
|
// decrypt local w/future
|
||||||
string plainFutureFromLocal;
|
string plainFutureFromLocal;
|
||||||
StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(prng, futureDecryptor, new StringSink(plainFutureFromLocal) ) );
|
StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) );
|
||||||
|
|
||||||
// decrypt future w/local
|
// decrypt future w/local
|
||||||
string plainLocalFromFuture;
|
string plainLocalFromFuture;
|
||||||
StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(prng, localDecryptor, new StringSink(plainLocalFromFuture) ) );
|
StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) );
|
||||||
|
|
||||||
|
|
||||||
assert(plainLocal == message);
|
assert(plainLocal == message);
|
||||||
@ -98,96 +224,110 @@ BOOST_AUTO_TEST_CASE(cryptopp_ecies_message)
|
|||||||
assert(plainLocalFromFuture == plainLocal);
|
assert(plainLocalFromFuture == plainLocal);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cryptopp_ecdh_prime)
|
BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr)
|
||||||
{
|
{
|
||||||
cnote << "Testing cryptopp_ecdh_prime...";
|
const int aesKeyLen = 16;
|
||||||
|
assert(sizeof(char) == sizeof(byte));
|
||||||
|
|
||||||
using namespace CryptoPP;
|
// generate test key
|
||||||
OID curve = ASN1::secp256r1();
|
AutoSeededRandomPool rng;
|
||||||
|
SecByteBlock key(0x00, aesKeyLen);
|
||||||
|
rng.GenerateBlock(key, key.size());
|
||||||
|
|
||||||
ECDH<ECP>::Domain dhLocal(curve);
|
// cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr
|
||||||
SecByteBlock privLocal(dhLocal.PrivateKeyLength());
|
byte ctr[AES::BLOCKSIZE];
|
||||||
SecByteBlock pubLocal(dhLocal.PublicKeyLength());
|
rng.GenerateBlock(ctr, sizeof(ctr));
|
||||||
dhLocal.GenerateKeyPair(dev::crypto::PRNG(), privLocal, pubLocal);
|
|
||||||
|
|
||||||
ECDH<ECP>::Domain dhRemote(curve);
|
string text = "Now is the time for all good persons to come to the aide of humanity.";
|
||||||
SecByteBlock privRemote(dhRemote.PrivateKeyLength());
|
// c++11 ftw
|
||||||
SecByteBlock pubRemote(dhRemote.PublicKeyLength());
|
unsigned char const* in = (unsigned char*)&text[0];
|
||||||
dhRemote.GenerateKeyPair(dev::crypto::PRNG(), privRemote, pubRemote);
|
unsigned char* out = (unsigned char*)&text[0];
|
||||||
|
string original = text;
|
||||||
|
|
||||||
assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength());
|
string cipherCopy;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CTR_Mode<AES>::Encryption e;
|
||||||
|
e.SetKeyWithIV(key, key.size(), ctr);
|
||||||
|
e.ProcessData(out, in, text.size());
|
||||||
|
assert(text != original);
|
||||||
|
cipherCopy = text;
|
||||||
|
}
|
||||||
|
catch(CryptoPP::Exception& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
// local: send public to remote; remote: send public to local
|
try
|
||||||
|
{
|
||||||
|
CTR_Mode< AES >::Decryption d;
|
||||||
|
d.SetKeyWithIV(key, key.size(), ctr);
|
||||||
|
d.ProcessData(out, in, text.size());
|
||||||
|
assert(text == original);
|
||||||
|
}
|
||||||
|
catch(CryptoPP::Exception& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
// Local
|
|
||||||
SecByteBlock sharedLocal(dhLocal.AgreedValueLength());
|
|
||||||
assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote));
|
|
||||||
|
|
||||||
// Remote
|
// reencrypt ciphertext...
|
||||||
SecByteBlock sharedRemote(dhRemote.AgreedValueLength());
|
try
|
||||||
assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal));
|
{
|
||||||
|
assert(cipherCopy != text);
|
||||||
|
in = (unsigned char*)&cipherCopy[0];
|
||||||
|
out = (unsigned char*)&cipherCopy[0];
|
||||||
|
|
||||||
// Test
|
CTR_Mode<AES>::Encryption e;
|
||||||
Integer ssLocal, ssRemote;
|
e.SetKeyWithIV(key, key.size(), ctr);
|
||||||
ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes());
|
e.ProcessData(out, in, text.size());
|
||||||
ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes());
|
|
||||||
|
|
||||||
assert(ssLocal != 0);
|
|
||||||
assert(ssLocal == ssRemote);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cryptopp_ecdh_aes128_cbc_noauth)
|
|
||||||
{
|
|
||||||
// ECDH gives 256-bit shared while aes uses 128-bits
|
|
||||||
// Use first 128-bits of shared secret as symmetric key
|
|
||||||
// IV is 0
|
|
||||||
// New connections require new ECDH keypairs
|
|
||||||
|
|
||||||
|
// yep, ctr mode.
|
||||||
|
assert(cipherCopy == original);
|
||||||
|
}
|
||||||
|
catch(CryptoPP::Exception& e)
|
||||||
|
{
|
||||||
|
cerr << e.what() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cryptopp_eth_fbba)
|
BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc)
|
||||||
{
|
{
|
||||||
// Initial Authentication:
|
const int aesKeyLen = 16;
|
||||||
//
|
assert(sizeof(char) == sizeof(byte));
|
||||||
// New/Known Peer:
|
|
||||||
// pubkeyL = knownR? ? myKnown : myECDH
|
AutoSeededRandomPool rng;
|
||||||
// pubkeyR = knownR? ? theirKnown : theirECDH
|
SecByteBlock key(0x00, aesKeyLen);
|
||||||
//
|
rng.GenerateBlock(key, key.size());
|
||||||
// Initial message = hmac(k=sha3(shared-secret[128..255]), address(pubkeyL)) || ECIES encrypt(pubkeyR, pubkeyL)
|
|
||||||
//
|
// Generate random IV
|
||||||
// Key Exchange (this could occur after handshake messages):
|
byte iv[AES::BLOCKSIZE];
|
||||||
// If peers do not know each other they will need to exchange public keys.
|
rng.GenerateBlock(iv, AES::BLOCKSIZE);
|
||||||
//
|
|
||||||
// Drop ECDH (this could occur after handshake messages):
|
string string128("AAAAAAAAAAAAAAAA");
|
||||||
// After authentication and/or key exchange, both sides generate shared key
|
string plainOriginal = string128;
|
||||||
// from their 'known' keys and use this to encrypt all future messages.
|
|
||||||
//
|
CryptoPP::CBC_Mode<Rijndael>::Encryption cbcEncryption(key, key.size(), iv);
|
||||||
// v2: If one side doesn't trust the other then a single-use key maybe sent.
|
cbcEncryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size());
|
||||||
// This will need to be tracked for future connections; when non-trusting peer
|
assert(string128 != plainOriginal);
|
||||||
// wants to trust the other, it can request that it's old, 'new', public key be
|
|
||||||
// accepted. And, if the peer *really* doesn't trust the other side, it can request
|
CBC_Mode<Rijndael>::Decryption cbcDecryption(key, key.size(), iv);
|
||||||
// that a new, 'new', public key be accepted.
|
cbcDecryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size());
|
||||||
//
|
assert(plainOriginal == string128);
|
||||||
// Handshake (all or nothing, padded):
|
|
||||||
// All Peers (except blacklisted):
|
|
||||||
//
|
// plaintext whose size isn't divisible by block size must use stream filter for padding
|
||||||
//
|
string string192("AAAAAAAAAAAAAAAABBBBBBBB");
|
||||||
// New Peer:
|
plainOriginal = string192;
|
||||||
//
|
|
||||||
//
|
string cipher;
|
||||||
// Known Untrusted Peer:
|
StreamTransformationFilter* aesStream = new StreamTransformationFilter(cbcEncryption, new StringSink(cipher));
|
||||||
//
|
StringSource source(string192, true, aesStream);
|
||||||
//
|
assert(cipher.size() == 32);
|
||||||
// Known Trusted Peer:
|
|
||||||
//
|
cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size());
|
||||||
//
|
assert(string192 == plainOriginal);
|
||||||
// Blacklisted Peeer:
|
|
||||||
// Already dropped by now.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// MAC:
|
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(eth_keypairs)
|
BOOST_AUTO_TEST_CASE(eth_keypairs)
|
||||||
@ -201,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);
|
||||||
@ -229,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);
|
||||||
@ -257,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);
|
||||||
|
13
genesis.cpp
13
genesis.cpp
@ -35,9 +35,20 @@ namespace js = json_spirit;
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(genesis_tests)
|
BOOST_AUTO_TEST_CASE(genesis_tests)
|
||||||
{
|
{
|
||||||
|
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
|
||||||
|
string testPath;
|
||||||
|
|
||||||
|
if (ptestPath == NULL)
|
||||||
|
{
|
||||||
|
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
||||||
|
testPath = "../../../tests";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
testPath = ptestPath;
|
||||||
|
|
||||||
cnote << "Testing Genesis block...";
|
cnote << "Testing Genesis block...";
|
||||||
js::mValue v;
|
js::mValue v;
|
||||||
string s = asString(contents("../../../tests/genesishashestest.json"));
|
string s = asString(contents(testPath + "/genesishashestest.json"));
|
||||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'genesishashestest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'genesishashestest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
||||||
js::read_string(s, v);
|
js::read_string(s, v);
|
||||||
|
|
||||||
|
@ -33,9 +33,20 @@ namespace js = json_spirit;
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(hexPrefix_test)
|
BOOST_AUTO_TEST_CASE(hexPrefix_test)
|
||||||
{
|
{
|
||||||
|
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
|
||||||
|
string testPath;
|
||||||
|
|
||||||
|
if (ptestPath == NULL)
|
||||||
|
{
|
||||||
|
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
||||||
|
testPath = "../../../tests";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
testPath = ptestPath;
|
||||||
|
|
||||||
cnote << "Testing Hex-Prefix-Encode...";
|
cnote << "Testing Hex-Prefix-Encode...";
|
||||||
js::mValue v;
|
js::mValue v;
|
||||||
string s = asString(contents("../../../tests/hexencodetest.json"));
|
string s = asString(contents(testPath + "/hexencodetest.json"));
|
||||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content from 'hexencodetest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content from 'hexencodetest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
||||||
js::read_string(s, v);
|
js::read_string(s, v);
|
||||||
for (auto& i: v.get_obj())
|
for (auto& i: v.get_obj())
|
||||||
|
2
main.cpp
2
main.cpp
@ -44,7 +44,7 @@ using namespace dev::eth;
|
|||||||
BOOST_AUTO_TEST_CASE(basic_tests)
|
BOOST_AUTO_TEST_CASE(basic_tests)
|
||||||
{
|
{
|
||||||
/* RLPStream s;
|
/* RLPStream s;
|
||||||
BlockInfo::genesis().fillStream(s, false);
|
BlockInfo::genesis().streamRLP(s, false);
|
||||||
std::cout << RLP(s.out()) << std::endl;
|
std::cout << RLP(s.out()) << std::endl;
|
||||||
std::cout << toHex(s.out()) << std::endl;
|
std::cout << toHex(s.out()) << std::endl;
|
||||||
std::cout << sha3(s.out()) << std::endl;*/
|
std::cout << sha3(s.out()) << std::endl;*/
|
||||||
|
13
rlp.cpp
13
rlp.cpp
@ -61,7 +61,18 @@ namespace dev
|
|||||||
|
|
||||||
static void getRLPTestCases(js::mValue& v)
|
static void getRLPTestCases(js::mValue& v)
|
||||||
{
|
{
|
||||||
string s = asString(contents("../../../tests/rlptest.json"));
|
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
|
||||||
|
string testPath;
|
||||||
|
|
||||||
|
if (ptestPath == NULL)
|
||||||
|
{
|
||||||
|
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
||||||
|
testPath = "../../../tests";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
testPath = ptestPath;
|
||||||
|
|
||||||
|
string s = asString(contents(testPath + "/rlptest.json"));
|
||||||
BOOST_REQUIRE_MESSAGE( s.length() > 0,
|
BOOST_REQUIRE_MESSAGE( s.length() > 0,
|
||||||
"Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
"Contents of 'rlptest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
||||||
js::read_string(s, v);
|
js::read_string(s, v);
|
||||||
|
178
solidityNameAndTypeResolution.cpp
Normal file
178
solidityNameAndTypeResolution.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author Christian <c@ethdev.com>
|
||||||
|
* @date 2014
|
||||||
|
* Unit tests for the name and type resolution of the solidity parser.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <libdevcore/Log.h>
|
||||||
|
#include <libsolidity/Scanner.h>
|
||||||
|
#include <libsolidity/Parser.h>
|
||||||
|
#include <libsolidity/NameAndTypeResolver.h>
|
||||||
|
#include <libsolidity/Exceptions.h>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
namespace dev
|
||||||
|
{
|
||||||
|
namespace solidity
|
||||||
|
{
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void parseTextAndResolveNames(const std::string& _source)
|
||||||
|
{
|
||||||
|
Parser parser;
|
||||||
|
ASTPointer<ContractDefinition> contract = parser.parse(
|
||||||
|
std::make_shared<Scanner>(CharStream(_source)));
|
||||||
|
NameAndTypeResolver resolver;
|
||||||
|
resolver.resolveNamesAndTypes(*contract);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(smoke_test)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVariable1;\n"
|
||||||
|
" function fun(uint256 arg1) { var x; uint256 y; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(double_stateVariable_declaration)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 variable;\n"
|
||||||
|
" uint128 variable;\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(double_function_declaration)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun() { var x; }\n"
|
||||||
|
" function fun() { var x; }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(double_variable_declaration)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() { uint256 x; if (true) { uint256 x; } }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(name_shadowing)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 variable;\n"
|
||||||
|
" function f() { uint32 variable ; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(name_references)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 variable;\n"
|
||||||
|
" function f(uint256 arg) returns (uint out) { f(variable); test; out; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(undeclared_name)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 variable;\n"
|
||||||
|
" function f(uint256 arg) { f(notfound); }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), DeclarationError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(reference_to_later_declaration)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function g() { f(); }"
|
||||||
|
" function f() { }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_inference_smoke_test)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_checking_return)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() returns (bool r) { return 1 >= 2; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() returns (bool r1, bool r2) { return 1 >= 2; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() returns (uint256 r) { return 1 >= 2; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_checking_function_call)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() returns (bool r) { return g(12, true) == 3; }\n"
|
||||||
|
" function g(uint256 a, bool b) returns (uint256 r) { }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function f() returns (int256 r) { var x = int256(uint32(2)); return x; }"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end namespaces
|
||||||
|
|
221
solidityParser.cpp
Normal file
221
solidityParser.cpp
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author Christian <c@ethdev.com>
|
||||||
|
* @date 2014
|
||||||
|
* Unit tests for the solidity parser.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <libdevcore/Log.h>
|
||||||
|
#include <libsolidity/Scanner.h>
|
||||||
|
#include <libsolidity/Parser.h>
|
||||||
|
#include <libsolidity/Exceptions.h>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
namespace dev
|
||||||
|
{
|
||||||
|
namespace solidity
|
||||||
|
{
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
ASTPointer<ASTNode> parseText(const std::string& _source)
|
||||||
|
{
|
||||||
|
Parser parser;
|
||||||
|
return parser.parse(std::make_shared<Scanner>(CharStream(_source)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(SolidityParser)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(smoke_test)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVariable1;\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 ;\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_THROW(parseText(text), ParserError);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(empty_function)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVar;\n"
|
||||||
|
" function functionName(hash160 arg1, address addr) const\n"
|
||||||
|
" returns (int id)\n"
|
||||||
|
" { }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(no_function_params)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVar;\n"
|
||||||
|
" function functionName() {}\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(single_function_param)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVar;\n"
|
||||||
|
" function functionName(hash hashin) returns (hash hashout) {}\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(struct_definition)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" uint256 stateVar;\n"
|
||||||
|
" struct MyStructName {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" uint256 count;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mapping)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" mapping(address => string) names;\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mapping_in_struct)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" struct test_struct {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" uint256 count;\n"
|
||||||
|
" mapping(hash => test_struct) self_reference;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" struct test_struct {\n"
|
||||||
|
" address addr;\n"
|
||||||
|
" mapping (uint64 => mapping (hash => uint)) complex_mapping;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(variable_definition)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" var b;\n"
|
||||||
|
" uint256 c;\n"
|
||||||
|
" mapping(address=>hash) d;\n"
|
||||||
|
" customtype varname;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(variable_definition_with_initialization)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" var b = 2;\n"
|
||||||
|
" uint256 c = 0x87;\n"
|
||||||
|
" mapping(address=>hash) d;\n"
|
||||||
|
" string name = \"Solidity\";"
|
||||||
|
" customtype varname;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(operator_expression)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" uint256 x = (1 + 4) || false && (1 - 12) + -9;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(complex_expression)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" uint256 x = (1 + 4).member(++67)[a/=9] || true;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(while_loop)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" uint256 x = (1 + 4).member(++67) || true;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(if_statement)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) {\n"
|
||||||
|
" if (a >= 8) return 2; else { var b = 7; }\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(else_if_statement)
|
||||||
|
{
|
||||||
|
char const* text = "contract test {\n"
|
||||||
|
" function fun(uint256 a) returns (address b) {\n"
|
||||||
|
" if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n";
|
||||||
|
BOOST_CHECK_NO_THROW(parseText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end namespaces
|
||||||
|
|
143
solidityScanner.cpp
Normal file
143
solidityScanner.cpp
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @author Christian <c@ethdev.com>
|
||||||
|
* @date 2014
|
||||||
|
* Unit tests for the solidity scanner.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libsolidity/Scanner.h>
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
namespace dev
|
||||||
|
{
|
||||||
|
namespace solidity
|
||||||
|
{
|
||||||
|
namespace test
|
||||||
|
{
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(SolidityScanner)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_empty)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream(""));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(smoke_test)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream("function break;765 \t \"string1\",'string2'\nidentifier1"));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::FUNCTION);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::BREAK);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "765");
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string1");
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::COMMA);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "string2");
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "identifier1");
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(string_escapes)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream(" { \"a\\x61\""));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "aa");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(string_escapes_with_zero)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream(" { \"a\\x61\\x00abc\""));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LBRACE);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::STRING_LITERAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), std::string("aa\0abc", 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(string_escape_illegal)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream(" bla \"\\x6rf\" (illegalescape)"));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "");
|
||||||
|
// TODO recovery from illegal tokens should be improved
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ILLEGAL);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(hex_numbers)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream("var x = 0x765432536763762734623472346;"));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::VAR);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "0x765432536763762734623472346");
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(locations)
|
||||||
|
{
|
||||||
|
Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment"));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 0);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 19);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 20);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 23);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::SUB);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 27);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 50);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(ambiguities)
|
||||||
|
{
|
||||||
|
// test scanning of some operators which need look-ahead
|
||||||
|
Scanner scanner(CharStream("<=""<""+ +=a++ =>""<<"));
|
||||||
|
BOOST_CHECK_EQUAL(scanner.getCurrentToken(), Token::LTE);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::LT);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ADD);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ASSIGN_ADD);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::INC);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::ARROW);
|
||||||
|
BOOST_CHECK_EQUAL(scanner.next(), Token::SHL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end namespaces
|
@ -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());
|
||||||
|
13
trie.cpp
13
trie.cpp
@ -49,9 +49,20 @@ static unsigned fac(unsigned _i)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(trie_tests)
|
BOOST_AUTO_TEST_CASE(trie_tests)
|
||||||
{
|
{
|
||||||
|
const char* ptestPath = getenv("ETHEREUM_TEST_PATH");
|
||||||
|
string testPath;
|
||||||
|
|
||||||
|
if (ptestPath == NULL)
|
||||||
|
{
|
||||||
|
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
||||||
|
testPath = "../../../tests";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
testPath = ptestPath;
|
||||||
|
|
||||||
cnote << "Testing Trie...";
|
cnote << "Testing Trie...";
|
||||||
js::mValue v;
|
js::mValue v;
|
||||||
string s = asString(contents("../../../tests/trietest.json"));
|
string s = asString(contents(testPath + "/trietest.json"));
|
||||||
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of 'trietest.json' is empty. Have you cloned the 'tests' repo branch develop?");
|
||||||
js::read_string(s, v);
|
js::read_string(s, v);
|
||||||
for (auto& i: v.get_obj())
|
for (auto& i: v.get_obj())
|
||||||
|
111
vm.cpp
111
vm.cpp
@ -20,11 +20,9 @@
|
|||||||
* vm test functions.
|
* vm test functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vm.h"
|
|
||||||
#include <libdevcore/CommonIO.h>
|
|
||||||
#include <libevmjit/VM.h>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include "vm.h"
|
||||||
//#define FILL_TESTS
|
//#define FILL_TESTS
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -46,7 +44,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();
|
||||||
|
|
||||||
@ -57,14 +55,13 @@ 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 = ret;
|
t.type = eth::Transaction::ContractCreation;
|
||||||
callcreates.push_back(t);
|
callcreates.push_back(t);
|
||||||
return ret;
|
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;
|
u256 contractgas = 0xffff;
|
||||||
|
|
||||||
Transaction t;
|
Transaction t;
|
||||||
@ -72,6 +69,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);
|
||||||
|
|
||||||
@ -92,7 +90,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)
|
||||||
@ -117,7 +115,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();
|
||||||
|
|
||||||
@ -132,7 +130,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()), 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)
|
if (!m_ms.internal.back().from)
|
||||||
m_ms.internal.pop_back();
|
m_ms.internal.pop_back();
|
||||||
@ -147,12 +145,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))
|
||||||
{
|
{
|
||||||
@ -357,10 +358,10 @@ void FakeExtVM::importExec(mObject& _o)
|
|||||||
thisTxCode.clear();
|
thisTxCode.clear();
|
||||||
code = &thisTxCode;
|
code = &thisTxCode;
|
||||||
if (_o["code"].type() == str_type)
|
if (_o["code"].type() == str_type)
|
||||||
if (_o["code"].get_str().find_first_of("0x") != 0)
|
if (_o["code"].get_str().find_first_of("0x") == 0)
|
||||||
thisTxCode = compileLLL(_o["code"].get_str());
|
|
||||||
else
|
|
||||||
thisTxCode = fromHex(_o["code"].get_str().substr(2));
|
thisTxCode = fromHex(_o["code"].get_str().substr(2));
|
||||||
|
else
|
||||||
|
thisTxCode = compileLLL(_o["code"].get_str());
|
||||||
else if (_o["code"].type() == array_type)
|
else if (_o["code"].type() == array_type)
|
||||||
for (auto const& j: _o["code"].get_array())
|
for (auto const& j: _o["code"].get_array())
|
||||||
thisTxCode.push_back(toByte(j));
|
thisTxCode.push_back(toByte(j));
|
||||||
@ -385,7 +386,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);
|
||||||
@ -404,6 +405,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"]);
|
||||||
@ -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)
|
if (!_origin)
|
||||||
_origin = _sender;
|
_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());
|
m_cache[_newAddress] = AddressState(0, balance(_newAddress) + _endowment, h256(), h256());
|
||||||
|
|
||||||
// Execute init code.
|
// Execute init code.
|
||||||
auto vmObj = VMFace::create(VMFace::Interpreter, *_gas);
|
auto vmObj = VMFace::create(getVMKind(), *_gas);
|
||||||
VMFace& vm = *vmObj;
|
auto& vm = *vmObj;
|
||||||
ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level);
|
ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level);
|
||||||
bool revert = false;
|
bool revert = false;
|
||||||
bytesConstRef out;
|
bytesConstRef out;
|
||||||
@ -447,9 +452,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*/)
|
||||||
{
|
{
|
||||||
@ -484,8 +487,6 @@ h160 FakeState::createNewAddress(Address _newAddress, Address _sender, u256 _end
|
|||||||
return _newAddress;
|
return _newAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace dev { namespace test {
|
namespace dev { namespace test {
|
||||||
|
|
||||||
void doTests(json_spirit::mValue& v, bool _fillin)
|
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("pre") > 0);
|
||||||
BOOST_REQUIRE(o.count("exec") > 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;
|
dev::test::FakeExtVM fev;
|
||||||
|
fev.setVMKind(vmKind);
|
||||||
|
|
||||||
fev.importEnv(o["env"].get_obj());
|
fev.importEnv(o["env"].get_obj());
|
||||||
fev.importState(o["pre"].get_obj());
|
fev.importState(o["pre"].get_obj());
|
||||||
|
|
||||||
@ -513,24 +521,14 @@ void doTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
fev.code = &fev.thisTxCode;
|
fev.code = &fev.thisTxCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto vm = VMFace::create(fev.getVMKind(), fev.gas);
|
||||||
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);
|
|
||||||
bytes output;
|
bytes output;
|
||||||
auto outOfGas = false;
|
auto outOfGas = false;
|
||||||
|
|
||||||
auto startTime = std::chrono::high_resolution_clock::now();
|
auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
output = vm->go(fev).toVector();
|
output = vm->go(fev, fev.simpleTrace<FakeExtVM>()).toVector();
|
||||||
}
|
}
|
||||||
catch (OutOfGas const&)
|
catch (OutOfGas const&)
|
||||||
{
|
{
|
||||||
@ -546,13 +544,17 @@ void doTests(json_spirit::mValue& v, bool _fillin)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto endTime = std::chrono::high_resolution_clock::now();
|
auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
if (showTimes)
|
for (auto i = 0; i < argc; ++i)
|
||||||
|
{
|
||||||
|
if (std::string(argv[i]) == "--show-times")
|
||||||
{
|
{
|
||||||
auto testDuration = endTime - startTime;
|
auto testDuration = endTime - startTime;
|
||||||
cnote << "Execution time: "
|
cnote << "Execution time: "
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
|
||||||
<< " ms";
|
<< " ms";
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
auto gas = vm->gas();
|
auto gas = vm->gas();
|
||||||
|
|
||||||
@ -686,11 +688,13 @@ void executeTests(const string& _name)
|
|||||||
if (ptestPath == NULL)
|
if (ptestPath == NULL)
|
||||||
{
|
{
|
||||||
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
cnote << " could not find environment variable ETHEREUM_TEST_PATH \n";
|
||||||
testPath = "../../../tests/vmtests";
|
testPath = "../../../tests";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
testPath = ptestPath;
|
testPath = ptestPath;
|
||||||
|
|
||||||
|
testPath += "/vmtests";
|
||||||
|
|
||||||
#ifdef FILL_TESTS
|
#ifdef FILL_TESTS
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -719,7 +723,7 @@ void executeTests(const string& _name)
|
|||||||
cnote << "Testing VM..." << _name;
|
cnote << "Testing VM..." << _name;
|
||||||
json_spirit::mValue v;
|
json_spirit::mValue v;
|
||||||
string s = asString(contents(testPath + "/" + _name + ".json"));
|
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);
|
json_spirit::read_string(s, v);
|
||||||
dev::test::doTests(v, false);
|
dev::test::doTests(v, false);
|
||||||
}
|
}
|
||||||
@ -786,4 +790,31 @@ 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];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
58
vm.h
58
vm.h
@ -28,6 +28,7 @@ along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
#include "JsonSpiritHeaders.h"
|
#include "JsonSpiritHeaders.h"
|
||||||
#include <libdevcore/Log.h>
|
#include <libdevcore/Log.h>
|
||||||
|
#include <libdevcore/CommonIO.h>
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
#include <libevm/ExtVMFace.h>
|
#include <libevm/ExtVMFace.h>
|
||||||
#include <libevm/VM.h>
|
#include <libevm/VM.h>
|
||||||
@ -44,24 +45,24 @@ 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 = Address(), std::set<Address>* o_suicides = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = eth::OnOpFunc(), unsigned _level = 0);
|
h160 createNewAddress(Address _newAddress, Address _txSender, u256 _endowment, u256 _gasPrice, u256* _gas, bytesConstRef _code, Address _originAddress = {}, eth::SubState* o_sub = nullptr, eth::Manifest* o_ms = nullptr, eth::OnOpFunc const& _onOp = {}, unsigned _level = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FakeExtVM: public eth::ExtVMFace
|
class FakeExtVM: public eth::ExtVMFace
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FakeExtVM() {}
|
FakeExtVM() = default;
|
||||||
FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0);
|
FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth = 0);
|
||||||
|
|
||||||
u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; }
|
virtual u256 store(u256 _n) override { return std::get<2>(addresses[myAddress])[_n]; }
|
||||||
void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; }
|
virtual void setStore(u256 _n, u256 _v) override { std::get<2>(addresses[myAddress])[_n] = _v; }
|
||||||
u256 balance(Address _a) override { return std::get<0>(addresses[_a]); }
|
virtual u256 balance(Address _a) override { return std::get<0>(addresses[_a]); }
|
||||||
void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; }
|
virtual void subBalance(u256 _a) override { std::get<0>(addresses[myAddress]) -= _a; }
|
||||||
u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); }
|
virtual u256 txCount(Address _a) override { return std::get<1>(addresses[_a]); }
|
||||||
void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); }
|
virtual void suicide(Address _a) override { std::get<0>(addresses[_a]) += std::get<0>(addresses[myAddress]); addresses.erase(myAddress); }
|
||||||
bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); }
|
virtual bytes const& codeAt(Address _a) override { return std::get<3>(addresses[_a]); }
|
||||||
h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override;
|
virtual h160 create(u256 _endowment, u256* _gas, bytesConstRef _init, eth::OnOpFunc const&) override;
|
||||||
bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override;
|
virtual bool call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, eth::OnOpFunc const&, Address, Address) override;
|
||||||
void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data);
|
void setTransaction(Address _caller, u256 _value, u256 _gasPrice, bytes const& _data);
|
||||||
void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
|
void setContract(Address _myAddress, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
|
||||||
void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
|
void set(Address _a, u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage, bytes const& _code);
|
||||||
@ -79,6 +80,13 @@ public:
|
|||||||
void importExec(json_spirit::mObject& _o);
|
void importExec(json_spirit::mObject& _o);
|
||||||
json_spirit::mArray exportCallCreates();
|
json_spirit::mArray exportCallCreates();
|
||||||
void importCallCreates(json_spirit::mArray& _callcreates);
|
void importCallCreates(json_spirit::mArray& _callcreates);
|
||||||
|
void setVMKind(eth::VMFace::Kind _kind) { m_s.setVMKind(_kind); }
|
||||||
|
eth::VMFace::Kind getVMKind() const { return m_s.getVMKind(); }
|
||||||
|
|
||||||
|
template<typename ExtVMType>
|
||||||
|
eth::OnOpFunc simpleTrace();
|
||||||
|
|
||||||
|
FakeState state() const { return m_s; }
|
||||||
|
|
||||||
std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes>> addresses;
|
std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes>> addresses;
|
||||||
eth::Transactions callcreates;
|
eth::Transactions callcreates;
|
||||||
@ -91,4 +99,32 @@ private:
|
|||||||
eth::Manifest m_ms;
|
eth::Manifest m_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ExtVMType>
|
||||||
|
eth::OnOpFunc FakeExtVM::simpleTrace()
|
||||||
|
{
|
||||||
|
return [](uint64_t steps, eth::Instruction inst, bigint newMemSize, bigint gasCost, void* voidVM, void const* voidExt)
|
||||||
|
{
|
||||||
|
ExtVMType const& ext = *(ExtVMType const*)voidExt;
|
||||||
|
eth::VM& vm = *(eth::VM*)voidVM;
|
||||||
|
|
||||||
|
std::ostringstream o;
|
||||||
|
o << std::endl << " STACK" << std::endl;
|
||||||
|
for (auto i: vm.stack())
|
||||||
|
o << (h256)i << std::endl;
|
||||||
|
o << " MEMORY" << std::endl << memDump(vm.memory());
|
||||||
|
o << " STORAGE" << std::endl;
|
||||||
|
for (auto const& i: ext.state().storage(ext.myAddress))
|
||||||
|
o << std::showbase << std::hex << i.first << ": " << i.second << std::endl;
|
||||||
|
dev::LogOutputStream<eth::VMTraceChannel, false>(true) << o.str();
|
||||||
|
dev::LogOutputStream<eth::VMTraceChannel, false>(false) << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32" << " ]";
|
||||||
|
|
||||||
|
if (eth::VMTraceChannel::verbosity <= g_logVerbosity)
|
||||||
|
{
|
||||||
|
std::ofstream f;
|
||||||
|
f.open("./vmtrace.log", std::ofstream::app);
|
||||||
|
f << o.str();
|
||||||
|
f << " | " << std::dec << ext.depth << " | " << ext.myAddress << " | #" << steps << " | " << std::hex << std::setw(4) << std::setfill('0') << vm.curPC() << " : " << instructionInfo(inst).name << " | " << std::dec << vm.gas() << " | -" << std::dec << gasCost << " | " << newMemSize << "x32";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
} } // Namespace Close
|
} } // Namespace Close
|
||||||
|
@ -670,6 +670,34 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"jumpi2": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "1000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff596002600357",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"gas" : "10000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"pc0": {
|
"pc0": {
|
||||||
"env" : {
|
"env" : {
|
||||||
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
@ -27,6 +27,34 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"push1_missingStack": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "1000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "0x60",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "1000000000000000000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"gas" : "10000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"push2": {
|
"push2": {
|
||||||
"env" : {
|
"env" : {
|
||||||
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
@ -509,7 +509,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"CallRecursiveBomb": {
|
"CallRecursiveBomb0": {
|
||||||
"env" : {
|
"env" : {
|
||||||
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
"currentNumber" : "0",
|
"currentNumber" : "0",
|
||||||
@ -543,6 +543,90 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"CallRecursiveBomb1": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "10000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "20000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "100000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "1",
|
||||||
|
"gas" : "364723"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"CallRecursiveBomb2": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "10000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "20000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "100000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "1",
|
||||||
|
"gas" : "364724"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"CallRecursiveBomb3": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "10000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "20000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "{ [[ 0 ]] (+ (SLOAD 0) 1) [[ 1 ]] (CALL (- (GAS) 224) (ADDRESS) 0 0 0 0 0) }",
|
||||||
|
"storage": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "100000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "1",
|
||||||
|
"gas" : "1000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"suicide0": {
|
"suicide0": {
|
||||||
"env" : {
|
"env" : {
|
||||||
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
@ -949,6 +1033,77 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"ABAcalls2": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "10000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1000000000000000000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }",
|
||||||
|
"storage": {}
|
||||||
|
},
|
||||||
|
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
|
||||||
|
"balance" : "0",
|
||||||
|
"code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 0 0 0 0 0) } ",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "100000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"gas" : "10000000000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"ABAcalls3": {
|
||||||
|
"env" : {
|
||||||
|
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6",
|
||||||
|
"currentNumber" : "0",
|
||||||
|
"currentGasLimit" : "10000000",
|
||||||
|
"currentDifficulty" : "256",
|
||||||
|
"currentTimestamp" : 1,
|
||||||
|
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba"
|
||||||
|
},
|
||||||
|
"pre" : {
|
||||||
|
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
|
||||||
|
"balance" : "1025000",
|
||||||
|
"nonce" : 0,
|
||||||
|
"code" : "{ [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x945304eb96065b2a98b57a48a06ae28d285a71b5 1 0 0 0 0) }",
|
||||||
|
"storage": {}
|
||||||
|
},
|
||||||
|
"945304eb96065b2a98b57a48a06ae28d285a71b5" : {
|
||||||
|
"balance" : "0",
|
||||||
|
"code" : " { [[ 0 ]] (ADD (SLOAD 0) 1) (CALL (- (GAS) 1000) 0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 0 0 0 0 0) } ",
|
||||||
|
"nonce" : "0",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
"exec" : {
|
||||||
|
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
|
||||||
|
"origin" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"caller" : "cd1722f3947def4cf144679da39c4c32bdc35681",
|
||||||
|
"value" : "100000",
|
||||||
|
"data" : "",
|
||||||
|
"gasPrice" : "100000000000000",
|
||||||
|
"gas" : "1000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"ABAcallsSuicide0": {
|
"ABAcallsSuicide0": {
|
||||||
"env" : {
|
"env" : {
|
||||||
|
Loading…
Reference in New Issue
Block a user