mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge branch 'develop' into mk_jsonrpc_upgrade
Conflicts: alethzero/MainWin.cpp libweb3jsonrpc/WebThreeStubServer.cpp libweb3jsonrpc/abstractwebthreestubserver.h libweb3jsonrpc/spec.json test/jsonrpc.cpp test/webthreestubclient.h
This commit is contained in:
		
						commit
						1d278d2857
					
				| @ -7,7 +7,7 @@ include_directories(..) | |||||||
| 
 | 
 | ||||||
| file(GLOB HEADERS "*.h") | file(GLOB HEADERS "*.h") | ||||||
| add_executable(testeth ${SRC_LIST} ${HEADERS}) | add_executable(testeth ${SRC_LIST} ${HEADERS}) | ||||||
| add_executable(createRandomTest createRandomTest.cpp vm.cpp) | add_executable(createRandomTest createRandomTest.cpp vm.cpp TestHelper.cpp) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(testeth ethereum) | target_link_libraries(testeth ethereum) | ||||||
| target_link_libraries(testeth ethcore) | target_link_libraries(testeth ethcore) | ||||||
|  | |||||||
							
								
								
									
										341
									
								
								TestHelper.cpp
									
									
									
									
									
								
							
							
						
						
									
										341
									
								
								TestHelper.cpp
									
									
									
									
									
								
							| @ -23,7 +23,12 @@ | |||||||
| 
 | 
 | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <chrono> | #include <chrono> | ||||||
|  | #include <boost/filesystem/path.hpp> | ||||||
| #include <libethereum/Client.h> | #include <libethereum/Client.h> | ||||||
|  | #include <liblll/Compiler.h> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev::eth; | ||||||
| 
 | 
 | ||||||
| namespace dev | namespace dev | ||||||
| { | { | ||||||
| @ -53,6 +58,342 @@ void connectClients(Client& c1, Client& c2) | |||||||
| 	c2.connect("127.0.0.1", c1Port); | 	c2.connect("127.0.0.1", c1Port); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | ImportTest::ImportTest(json_spirit::mObject& _o, bool isFiller): m_TestObject(_o) | ||||||
|  | { | ||||||
|  | 	importEnv(_o["env"].get_obj()); | ||||||
|  | 	importState(_o["pre"].get_obj(), m_statePre); | ||||||
|  | 	importTransaction(_o["transaction"].get_obj()); | ||||||
|  | 
 | ||||||
|  | 	if (!isFiller) | ||||||
|  | 	{ | ||||||
|  | 		importState(_o["post"].get_obj(), m_statePost); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ImportTest::importEnv(json_spirit::mObject& _o) | ||||||
|  | { | ||||||
|  | 	BOOST_REQUIRE(_o.count("previousHash") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("currentGasLimit") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("currentDifficulty") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("currentTimestamp") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("currentCoinbase") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("currentNumber") > 0); | ||||||
|  | 
 | ||||||
|  | 	m_environment.previousBlock.hash = h256(_o["previousHash"].get_str()); | ||||||
|  | 	m_environment.currentBlock.number = toInt(_o["currentNumber"]); | ||||||
|  | 	m_environment.currentBlock.gasLimit = toInt(_o["currentGasLimit"]); | ||||||
|  | 	m_environment.currentBlock.difficulty = toInt(_o["currentDifficulty"]); | ||||||
|  | 	m_environment.currentBlock.timestamp = toInt(_o["currentTimestamp"]); | ||||||
|  | 	m_environment.currentBlock.coinbaseAddress = Address(_o["currentCoinbase"].get_str()); | ||||||
|  | 
 | ||||||
|  | 	m_statePre.m_previousBlock = m_environment.previousBlock; | ||||||
|  | 	m_statePre.m_currentBlock = m_environment.currentBlock; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ImportTest::importState(json_spirit::mObject& _o, State& _state) | ||||||
|  | { | ||||||
|  | 	for (auto& i: _o) | ||||||
|  | 	{ | ||||||
|  | 		json_spirit::mObject o = i.second.get_obj(); | ||||||
|  | 
 | ||||||
|  | 		BOOST_REQUIRE(o.count("balance") > 0); | ||||||
|  | 		BOOST_REQUIRE(o.count("nonce") > 0); | ||||||
|  | 		BOOST_REQUIRE(o.count("storage") > 0); | ||||||
|  | 		BOOST_REQUIRE(o.count("code") > 0); | ||||||
|  | 
 | ||||||
|  | 		Address address = Address(i.first); | ||||||
|  | 
 | ||||||
|  | 		for (auto const& j: o["storage"].get_obj()) | ||||||
|  | 			_state.setStorage(address, toInt(j.first), toInt(j.second)); | ||||||
|  | 
 | ||||||
|  | 		bytes code = importCode(o); | ||||||
|  | 
 | ||||||
|  | 		if (code.size()) | ||||||
|  | 		{ | ||||||
|  | 			_state.m_cache[address] = Account(toInt(o["balance"]), Account::ContractConception); | ||||||
|  | 			_state.m_cache[address].setCode(bytesConstRef(&code)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			_state.m_cache[address] = Account(toInt(o["balance"]), Account::NormalCreation); | ||||||
|  | 
 | ||||||
|  | 		for(int i=0; i<toInt(o["nonce"]); ++i) | ||||||
|  | 			_state.noteSending(address); | ||||||
|  | 
 | ||||||
|  | 		_state.ensureCached(address, false, false); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ImportTest::importTransaction(json_spirit::mObject& _o) | ||||||
|  | { | ||||||
|  | 	BOOST_REQUIRE(_o.count("nonce")> 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("gasPrice") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("gasLimit") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("to") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("value") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("secretKey") > 0); | ||||||
|  | 	BOOST_REQUIRE(_o.count("data") > 0); | ||||||
|  | 
 | ||||||
|  | 	m_transaction = _o["to"].get_str().empty() ? | ||||||
|  | 		Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())) : | ||||||
|  | 		Transaction(toInt(_o["value"]), toInt(_o["gasPrice"]), toInt(_o["gasLimit"]), Address(_o["to"].get_str()), importData(_o), toInt(_o["nonce"]), Secret(_o["secretKey"].get_str())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ImportTest::exportTest(bytes _output, State& _statePost) | ||||||
|  | { | ||||||
|  | 	// export output
 | ||||||
|  | 	m_TestObject["out"] = "0x" + toHex(_output); | ||||||
|  | 
 | ||||||
|  | 	// export post state
 | ||||||
|  | 	json_spirit::mObject postState; | ||||||
|  | 
 | ||||||
|  | 	std::map<Address, Account> genesis = genesisState(); | ||||||
|  | 
 | ||||||
|  | 	for (auto const& a: _statePost.addresses()) | ||||||
|  | 	{ | ||||||
|  | 		if (genesis.count(a.first)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		json_spirit::mObject o; | ||||||
|  | 		o["balance"] = toString(_statePost.balance(a.first)); | ||||||
|  | 		o["nonce"] = toString(_statePost.transactionsFrom(a.first)); | ||||||
|  | 		{ | ||||||
|  | 			json_spirit::mObject store; | ||||||
|  | 			for (auto const& s: _statePost.storage(a.first)) | ||||||
|  | 				store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); | ||||||
|  | 			o["storage"] = store; | ||||||
|  | 		} | ||||||
|  | 		o["code"] = "0x" + toHex(_statePost.code(a.first)); | ||||||
|  | 
 | ||||||
|  | 		postState[toString(a.first)] = o; | ||||||
|  | 	} | ||||||
|  | 	m_TestObject["post"] = json_spirit::mValue(postState); | ||||||
|  | 
 | ||||||
|  | 	// export pre state
 | ||||||
|  | 	json_spirit::mObject preState; | ||||||
|  | 
 | ||||||
|  | 	for (auto const& a: m_statePre.addresses()) | ||||||
|  | 	{ | ||||||
|  | 		if (genesis.count(a.first)) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		json_spirit::mObject o; | ||||||
|  | 		o["balance"] = toString(m_statePre.balance(a.first)); | ||||||
|  | 		o["nonce"] = toString(m_statePre.transactionsFrom(a.first)); | ||||||
|  | 		{ | ||||||
|  | 			json_spirit::mObject store; | ||||||
|  | 			for (auto const& s: m_statePre.storage(a.first)) | ||||||
|  | 				store["0x"+toHex(toCompactBigEndian(s.first))] = "0x"+toHex(toCompactBigEndian(s.second)); | ||||||
|  | 			o["storage"] = store; | ||||||
|  | 		} | ||||||
|  | 		o["code"] = "0x" + toHex(m_statePre.code(a.first)); | ||||||
|  | 
 | ||||||
|  | 		preState[toString(a.first)] = o; | ||||||
|  | 	} | ||||||
|  | 	m_TestObject["pre"] = json_spirit::mValue(preState); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | u256 toInt(json_spirit::mValue const& _v) | ||||||
|  | { | ||||||
|  | 	switch (_v.type()) | ||||||
|  | 	{ | ||||||
|  | 	case json_spirit::str_type: return u256(_v.get_str()); | ||||||
|  | 	case json_spirit::int_type: return (u256)_v.get_uint64(); | ||||||
|  | 	case json_spirit::bool_type: return (u256)(uint64_t)_v.get_bool(); | ||||||
|  | 	case json_spirit::real_type: return (u256)(uint64_t)_v.get_real(); | ||||||
|  | 	default: cwarn << "Bad type for scalar: " << _v.type(); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | byte toByte(json_spirit::mValue const& _v) | ||||||
|  | { | ||||||
|  | 	switch (_v.type()) | ||||||
|  | 	{ | ||||||
|  | 	case json_spirit::str_type: return (byte)stoi(_v.get_str()); | ||||||
|  | 	case json_spirit::int_type: return (byte)_v.get_uint64(); | ||||||
|  | 	case json_spirit::bool_type: return (byte)_v.get_bool(); | ||||||
|  | 	case json_spirit::real_type: return (byte)_v.get_real(); | ||||||
|  | 	default: cwarn << "Bad type for scalar: " << _v.type(); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bytes importData(json_spirit::mObject& _o) | ||||||
|  | { | ||||||
|  | 	bytes data; | ||||||
|  | 	if (_o["data"].type() == json_spirit::str_type) | ||||||
|  | 		if (_o["data"].get_str().find_first_of("0x") == 0) | ||||||
|  | 			data = fromHex(_o["data"].get_str().substr(2)); | ||||||
|  | 		else | ||||||
|  | 			data = fromHex(_o["data"].get_str()); | ||||||
|  | 	else | ||||||
|  | 		for (auto const& j: _o["data"].get_array()) | ||||||
|  | 			data.push_back(toByte(j)); | ||||||
|  | 
 | ||||||
|  | 	return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bytes importCode(json_spirit::mObject& _o) | ||||||
|  | { | ||||||
|  | 	bytes code; | ||||||
|  | 	if (_o["code"].type() == json_spirit::str_type) | ||||||
|  | 		if (_o["code"].get_str().find_first_of("0x") != 0) | ||||||
|  | 			code = compileLLL(_o["code"].get_str(), false); | ||||||
|  | 		else | ||||||
|  | 			code = fromHex(_o["code"].get_str().substr(2)); | ||||||
|  | 	else if (_o["code"].type() == json_spirit::array_type) | ||||||
|  | 	{ | ||||||
|  | 		code.clear(); | ||||||
|  | 		for (auto const& j: _o["code"].get_array()) | ||||||
|  | 			code.push_back(toByte(j)); | ||||||
|  | 	} | ||||||
|  | 	return code; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void checkOutput(bytes const& _output, json_spirit::mObject& _o) | ||||||
|  | { | ||||||
|  | 	int j = 0; | ||||||
|  | 	if (_o["out"].type() == json_spirit::array_type) | ||||||
|  | 		for (auto const& d: _o["out"].get_array()) | ||||||
|  | 		{ | ||||||
|  | 			BOOST_CHECK_MESSAGE(_output[j] == toInt(d), "Output byte [" << j << "] different!"); | ||||||
|  | 			++j; | ||||||
|  | 		} | ||||||
|  | 	else if (_o["out"].get_str().find("0x") == 0) | ||||||
|  | 		BOOST_CHECK(_output == fromHex(_o["out"].get_str().substr(2))); | ||||||
|  | 	else | ||||||
|  | 		BOOST_CHECK(_output == fromHex(_o["out"].get_str())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void checkStorage(map<u256, u256> _expectedStore, map<u256, u256> _resultStore, Address _expectedAddr) | ||||||
|  | { | ||||||
|  | 	for (auto&& expectedStorePair : _expectedStore) | ||||||
|  | 	{ | ||||||
|  | 		auto& expectedStoreKey = expectedStorePair.first; | ||||||
|  | 		auto resultStoreIt = _resultStore.find(expectedStoreKey); | ||||||
|  | 		if (resultStoreIt == _resultStore.end()) | ||||||
|  | 			BOOST_ERROR(_expectedAddr << ": missing store key " << expectedStoreKey); | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			auto& expectedStoreValue = expectedStorePair.second; | ||||||
|  | 			auto& resultStoreValue = resultStoreIt->second; | ||||||
|  | 			BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, _expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string getTestPath() | ||||||
|  | { | ||||||
|  | 	string testPath; | ||||||
|  | 	const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); | ||||||
|  | 
 | ||||||
|  | 	if (ptestPath == NULL) | ||||||
|  | 	{ | ||||||
|  | 		cnote << " could not find environment variable ETHEREUM_TEST_PATH \n"; | ||||||
|  | 		testPath = "../../../tests"; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		testPath = ptestPath; | ||||||
|  | 
 | ||||||
|  | 	return testPath; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void userDefinedTest(string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests) | ||||||
|  | { | ||||||
|  | 	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) | ||||||
|  | 	{ | ||||||
|  | 		string arg = boost::unit_test::framework::master_test_suite().argv[i]; | ||||||
|  | 		if (arg == testTypeFlag) | ||||||
|  | 		{ | ||||||
|  | 			if (i + 1 >= boost::unit_test::framework::master_test_suite().argc) | ||||||
|  | 			{ | ||||||
|  | 				cnote << "Missing filename\nUsage: testeth " << testTypeFlag << " <filename>\n"; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			string filename = boost::unit_test::framework::master_test_suite().argv[i + 1]; | ||||||
|  | 			int currentVerbosity = g_logVerbosity; | ||||||
|  | 			g_logVerbosity = 12; | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				cnote << "Testing user defined test: " << filename; | ||||||
|  | 				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); | ||||||
|  | 				doTests(v, false); | ||||||
|  | 			} | ||||||
|  | 			catch (Exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed Test with Exception: " << diagnostic_information(_e)); | ||||||
|  | 				g_logVerbosity = currentVerbosity; | ||||||
|  | 			} | ||||||
|  | 			catch (std::exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed Test with Exception: " << _e.what()); | ||||||
|  | 				g_logVerbosity = currentVerbosity; | ||||||
|  | 			} | ||||||
|  | 			g_logVerbosity = currentVerbosity; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 			continue; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void executeTests(const string& _name, const string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests) | ||||||
|  | { | ||||||
|  | 	string testPath = getTestPath(); | ||||||
|  | 	testPath += _testPathAppendix; | ||||||
|  | 
 | ||||||
|  | 	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) | ||||||
|  | 	{ | ||||||
|  | 		string arg = boost::unit_test::framework::master_test_suite().argv[i]; | ||||||
|  | 		if (arg == "--filltests") | ||||||
|  | 		{ | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				cnote << "Populating tests..."; | ||||||
|  | 				json_spirit::mValue v; | ||||||
|  | 				boost::filesystem::path p(__FILE__); | ||||||
|  | 				boost::filesystem::path dir = p.parent_path(); | ||||||
|  | 				string s = asString(dev::contents(dir.string() + "/" + _name + "Filler.json")); | ||||||
|  | 				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + dir.string() + "/" + _name + "Filler.json is empty."); | ||||||
|  | 				json_spirit::read_string(s, v); | ||||||
|  | 				doTests(v, true); | ||||||
|  | 				writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); | ||||||
|  | 			} | ||||||
|  | 			catch (Exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); | ||||||
|  | 			} | ||||||
|  | 			catch (std::exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed test with Exception: " << _e.what()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	try | ||||||
|  | 	{ | ||||||
|  | 		cnote << "Testing ..." << _name; | ||||||
|  | 		json_spirit::mValue v; | ||||||
|  | 		string s = asString(dev::contents(testPath + "/" + _name + ".json")); | ||||||
|  | 		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); | ||||||
|  | 		doTests(v, false); | ||||||
|  | 	} | ||||||
|  | 	catch (Exception const& _e) | ||||||
|  | 	{ | ||||||
|  | 		BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); | ||||||
|  | 	} | ||||||
|  | 	catch (std::exception const& _e) | ||||||
|  | 	{ | ||||||
|  | 		BOOST_ERROR("Failed test with Exception: " << _e.what()); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } } // namespaces
 | ||||||
|  | |||||||
							
								
								
									
										55
									
								
								TestHelper.h
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								TestHelper.h
									
									
									
									
									
								
							| @ -21,6 +21,11 @@ | |||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <functional> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include "JsonSpiritHeaders.h" | ||||||
|  | #include <libethereum/State.h> | ||||||
|  | 
 | ||||||
| namespace dev | namespace dev | ||||||
| { | { | ||||||
| namespace eth | namespace eth | ||||||
| @ -31,5 +36,55 @@ class Client; | |||||||
| void mine(Client& c, int numBlocks); | void mine(Client& c, int numBlocks); | ||||||
| void connectClients(Client& c1, Client& c2); | void connectClients(Client& c1, Client& c2); | ||||||
| 
 | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class ImportTest | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	ImportTest() = default; | ||||||
|  | 	ImportTest(json_spirit::mObject& _o, bool isFiller); | ||||||
|  | 
 | ||||||
|  | 	// imports
 | ||||||
|  | 	void importEnv(json_spirit::mObject& _o); | ||||||
|  | 	void importState(json_spirit::mObject& _o, eth::State& _state); | ||||||
|  | 	void importTransaction(json_spirit::mObject& _o); | ||||||
|  | 	void exportTest(bytes _output, eth::State& _statePost); | ||||||
|  | 
 | ||||||
|  | 	eth::State m_statePre; | ||||||
|  | 	eth::State m_statePost; | ||||||
|  | 	eth::ExtVMFace m_environment; | ||||||
|  | 	eth::Transaction m_transaction; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	json_spirit::mObject& m_TestObject; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // helping functions
 | ||||||
|  | u256 toInt(json_spirit::mValue const& _v); | ||||||
|  | byte toByte(json_spirit::mValue const& _v); | ||||||
|  | bytes importCode(json_spirit::mObject& _o); | ||||||
|  | bytes importData(json_spirit::mObject& _o); | ||||||
|  | void checkOutput(bytes const& _output, json_spirit::mObject& _o); | ||||||
|  | void checkStorage(std::map<u256, u256> _expectedStore, std::map<u256, u256> _resultStore, Address _expectedAddr); | ||||||
|  | void executeTests(const std::string& _name, const std::string& _testPathAppendix, std::function<void(json_spirit::mValue&, bool)> doTests); | ||||||
|  | std::string getTestPath(); | ||||||
|  | void userDefinedTest(std::string testTypeFlag, std::function<void(json_spirit::mValue&, bool)> doTests); | ||||||
|  | 
 | ||||||
|  | template<typename mapType> | ||||||
|  | void checkAddresses(mapType& _expectedAddrs, mapType& _resultAddrs) | ||||||
|  | { | ||||||
|  | 	for (auto& resultPair : _resultAddrs) | ||||||
|  | 	{ | ||||||
|  | 		auto& resultAddr = resultPair.first; | ||||||
|  | 		auto expectedAddrIt = _expectedAddrs.find(resultAddr); | ||||||
|  | 		if (expectedAddrIt == _expectedAddrs.end()) | ||||||
|  | 			BOOST_ERROR("Missing result address " << resultAddr); | ||||||
|  | 	} | ||||||
|  | 	BOOST_CHECK(_expectedAddrs == _resultAddrs); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,51 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  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/>.
 |  | ||||||
|  */ |  | ||||||
| /** @file TestHelperCrypto.h
 |  | ||||||
|  * @author Alex Leverington <nessence@gmail.com> |  | ||||||
|  * @date 2014 |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <libdevcrypto/CryptoPP.h> |  | ||||||
| 
 |  | ||||||
| using namespace std; |  | ||||||
| using namespace CryptoPP; |  | ||||||
| 
 |  | ||||||
| void SavePrivateKey(const PrivateKey& key, const string& file = "ecies.private.key") |  | ||||||
| { |  | ||||||
| 	FileSink sink(file.c_str()); |  | ||||||
| 	key.Save(sink); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void SavePublicKey(const PublicKey& key, const string& file = "ecies.public.key") |  | ||||||
| { |  | ||||||
| 	FileSink sink(file.c_str()); |  | ||||||
| 	key.Save(sink); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void LoadPrivateKey(PrivateKey& key, const string& file = "ecies.private.key") |  | ||||||
| { |  | ||||||
| 	FileSource source(file.c_str(), true); |  | ||||||
| 	key.Load(source); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void LoadPublicKey(PublicKey& key, const string& file = "ecies.public.key") |  | ||||||
| { |  | ||||||
| 	FileSource source(file.c_str(), true); |  | ||||||
| 	key.Load(source); |  | ||||||
| } |  | ||||||
| @ -31,7 +31,8 @@ | |||||||
| #include <json_spirit/json_spirit_writer_template.h> | #include <json_spirit/json_spirit_writer_template.h> | ||||||
| #include <libdevcore/CommonIO.h> | #include <libdevcore/CommonIO.h> | ||||||
| #include <libdevcore/CommonData.h> | #include <libdevcore/CommonData.h> | ||||||
| #include <libevmface/Instruction.h> | #include <libevmcore/Instruction.h> | ||||||
|  | #include <libevm/VM.h> | ||||||
| #include "vm.h" | #include "vm.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| @ -134,18 +135,24 @@ void doMyTests(json_spirit::mValue& v) | |||||||
| 		o["pre"] = mValue(fev.exportState()); | 		o["pre"] = mValue(fev.exportState()); | ||||||
| 
 | 
 | ||||||
| 		fev.importExec(o["exec"].get_obj()); | 		fev.importExec(o["exec"].get_obj()); | ||||||
| 		if (!fev.code) | 		if (fev.code.empty()) | ||||||
| 		{ | 		{ | ||||||
| 			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); | 			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); | ||||||
| 			fev.code = &fev.thisTxCode; | 			fev.code = fev.thisTxCode; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		vm.reset(fev.gas); | 		vm.reset(fev.gas); | ||||||
| 		bytes output; | 		bytes output; | ||||||
|  | 		u256 gas; | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			output = vm.go(fev).toBytes(); | 			output = vm.go(fev).toBytes(); | ||||||
| 		} | 		} | ||||||
|  | 		catch (eth::VMException const& _e) | ||||||
|  | 		{ | ||||||
|  | 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | ||||||
|  | 			gas = 0; | ||||||
|  | 		} | ||||||
| 		catch (Exception const& _e) | 		catch (Exception const& _e) | ||||||
| 		{ | 		{ | ||||||
| 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | ||||||
| @ -176,6 +183,6 @@ void doMyTests(json_spirit::mValue& v) | |||||||
| 		o["post"] = mValue(fev.exportState()); | 		o["post"] = mValue(fev.exportState()); | ||||||
| 		o["callcreates"] = fev.exportCallCreates(); | 		o["callcreates"] = fev.exportCallCreates(); | ||||||
| 		o["out"] = "0x" + toHex(output); | 		o["out"] = "0x" + toHex(output); | ||||||
| 		fev.push(o, "gas", vm.gas()); | 		fev.push(o, "gas", gas); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										432
									
								
								crypto.cpp
									
									
									
									
									
								
							
							
						
						
									
										432
									
								
								crypto.cpp
									
									
									
									
									
								
							| @ -27,8 +27,9 @@ | |||||||
| #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 <libdevcrypto/SHA3.h> | ||||||
| #include "TestHelperCrypto.h" | #include <libdevcrypto/ECDHE.h> | ||||||
|  | #include <libdevcrypto/CryptoPP.h> | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| @ -37,131 +38,265 @@ using namespace CryptoPP; | |||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_SUITE(devcrypto) | BOOST_AUTO_TEST_SUITE(devcrypto) | ||||||
| 
 | 
 | ||||||
|  | static Secp256k1 s_secp256k1; | ||||||
|  | static CryptoPP::AutoSeededRandomPool s_rng; | ||||||
|  | static CryptoPP::OID s_curveOID(CryptoPP::ASN1::secp256k1()); | ||||||
|  | static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP> s_params(s_curveOID); | ||||||
|  | static CryptoPP::DL_GroupParameters_EC<CryptoPP::ECP>::EllipticCurve s_curve(s_params.GetCurve()); | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(verify_secert) | ||||||
|  | { | ||||||
|  | 	h256 empty; | ||||||
|  | 	KeyPair kNot(empty); | ||||||
|  | 	BOOST_REQUIRE(!kNot.address()); | ||||||
|  | 	KeyPair k(sha3(empty)); | ||||||
|  | 	BOOST_REQUIRE(k.address()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) | BOOST_AUTO_TEST_CASE(common_encrypt_decrypt) | ||||||
| { | { | ||||||
| 	string message("Now is the time for all good persons to come to the aide of humanity."); | 	string message("Now is the time for all good persons to come to the aid of humanity."); | ||||||
| 	bytes m = asBytes(message); | 	bytes m = asBytes(message); | ||||||
| 	bytesConstRef bcr(&m); | 	bytesConstRef bcr(&m); | ||||||
| 
 | 
 | ||||||
| 	KeyPair k = KeyPair::create(); | 	KeyPair k = KeyPair::create(); | ||||||
| 	bytes cipher; | 	bytes cipher; | ||||||
| 	encrypt(k.pub(), bcr, cipher); | 	encrypt(k.pub(), bcr, cipher); | ||||||
| 	assert(cipher != asBytes(message) && cipher.size() > 0); | 	BOOST_REQUIRE(cipher != asBytes(message) && cipher.size() > 0); | ||||||
| 	 | 	 | ||||||
| 	bytes plain; | 	bytes plain; | ||||||
| 	decrypt(k.sec(), bytesConstRef(&cipher), plain); | 	decrypt(k.sec(), bytesConstRef(&cipher), plain); | ||||||
| 	 | 	 | ||||||
| 	assert(asString(plain) == message); | 	BOOST_REQUIRE(asString(plain) == message); | ||||||
| 	assert(plain == asBytes(message)); | 	BOOST_REQUIRE(plain == asBytes(message)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(cryptopp_vs_secp256k1) | BOOST_AUTO_TEST_CASE(cryptopp_cryptopp_secp256k1libport) | ||||||
| { | { | ||||||
| 	ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1()); | 	secp256k1_start(); | ||||||
| 	ECIES<ECP>::Encryptor e(d.GetKey()); |  | ||||||
| 	 | 	 | ||||||
| 	Secret s; | 	// base secret
 | ||||||
| 	pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); | 	Secret secret(sha3("privacy")); | ||||||
| 	 | 	 | ||||||
| 	Public p; | 	// we get ec params from signer
 | ||||||
| 	pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); | 	ECDSA<ECP, SHA3_256>::Signer signer; | ||||||
| 	 | 	 | ||||||
| 	assert(dev::toAddress(s) == right160(dev::sha3(p.ref()))); | 	// e := sha3(msg)
 | ||||||
| 	 | 	bytes e(fromHex("0x01")); | ||||||
| 	Secret previous = s; | 	e.resize(32); | ||||||
| 	for (auto i = 0; i < 30; i++) | 	int tests = 2; | ||||||
|  | 	while (sha3(&e, &e), secret = sha3(secret.asBytes()), tests--) | ||||||
| 	{ | 	{ | ||||||
| 		ECIES<ECP>::Decryptor d(pp::PRNG(), pp::secp256k1()); | 		KeyPair key(secret); | ||||||
| 		ECIES<ECP>::Encryptor e(d.GetKey()); | 		Public pkey = key.pub(); | ||||||
|  | 		signer.AccessKey().Initialize(s_params, secretToExponent(secret)); | ||||||
| 		 | 		 | ||||||
| 		Secret s; | 		h256 he(sha3(e)); | ||||||
| 		pp::SecretFromDL_PrivateKey_EC(d.GetKey(), s); | 		Integer heInt(he.asBytes().data(), 32); | ||||||
| 		assert(s != previous); | 		h256 k(crypto::kdf(secret, he)); | ||||||
|  | 		Integer kInt(k.asBytes().data(), 32); | ||||||
|  | 		kInt %= s_params.GetSubgroupOrder()-1; | ||||||
| 
 | 
 | ||||||
| 		Public p; | 		ECP::Point rp = s_params.ExponentiateBase(kInt); | ||||||
| 		pp::PublicFromDL_PublicKey_EC(e.GetKey(), p); | 		Integer const& q = s_params.GetGroupOrder(); | ||||||
|  | 		Integer r = s_params.ConvertElementToInteger(rp); | ||||||
| 
 | 
 | ||||||
| 		assert(dev::toAddress(s) == right160(dev::sha3(p.ref()))); | 		Integer kInv = kInt.InverseMod(q); | ||||||
|  | 		Integer s = (kInv * (Integer(secret.asBytes().data(), 32)*r + heInt)) % q; | ||||||
|  | 		BOOST_REQUIRE(!!r && !!s); | ||||||
|  | 
 | ||||||
|  | 		Signature sig; | ||||||
|  | 		sig[64] = rp.y.IsOdd() ? 1 : 0; | ||||||
|  | 		r.Encode(sig.data(), 32); | ||||||
|  | 		s.Encode(sig.data() + 32, 32); | ||||||
|  | 
 | ||||||
|  | 		Public p = dev::recover(sig, he); | ||||||
|  | 		BOOST_REQUIRE(p == pkey); | ||||||
|  | 		 | ||||||
|  | 		// verify w/cryptopp
 | ||||||
|  | 		BOOST_REQUIRE(s_secp256k1.verify(pkey, sig, bytesConstRef(&e))); | ||||||
|  | 		 | ||||||
|  | 		// verify with secp256k1lib
 | ||||||
|  | 		byte encpub[65] = {0x04}; | ||||||
|  | 		memcpy(&encpub[1], pkey.data(), 64); | ||||||
|  | 		byte dersig[72]; | ||||||
|  | 		size_t cssz = DSAConvertSignatureFormat(dersig, 72, DSA_DER, sig.data(), 64, DSA_P1363); | ||||||
|  | 		BOOST_CHECK(cssz <= 72); | ||||||
|  | 		BOOST_REQUIRE(1 == secp256k1_ecdsa_verify(he.data(), sizeof(he), dersig, cssz, encpub, 65)); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(cryptopp_keys_cryptor_sipaseckp256k1) | BOOST_AUTO_TEST_CASE(cryptopp_ecdsa_sipaseckp256k1) | ||||||
| { | { | ||||||
| 	KeyPair k = KeyPair::create(); | 	secp256k1_start(); | ||||||
| 	Secret s = k.sec(); |  | ||||||
| 	 | 	 | ||||||
| 	// Convert secret to exponent used by pp
 | 	// cryptopp integer encoding
 | ||||||
| 	Integer e = pp::ExponentFromSecret(s); | 	Integer nHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2H"); | ||||||
|  | 	Integer nB(fromHex("f2ee15ea639b73fa3db9b34a245bdfa015c260c598b211bf05a1ecc4b3e3b4f2").data(), 32); | ||||||
|  | 	BOOST_REQUIRE(nHex == nB); | ||||||
| 	 | 	 | ||||||
| 	// Test that exported DL_EC private is same as exponent from Secret
 | 	bytes sbytes(fromHex("0xFFFF")); | ||||||
| 	CryptoPP::DL_PrivateKey_EC<CryptoPP::ECP> privatek; | 	Secret secret(sha3(sbytes)); | ||||||
| 	privatek.AccessGroupParameters().Initialize(pp::secp256k1()); | 	KeyPair key(secret); | ||||||
| 	privatek.SetPrivateExponent(e); |  | ||||||
| 	assert(e == privatek.GetPrivateExponent()); |  | ||||||
| 	 | 	 | ||||||
| 	// Test that exported secret is same as decryptor(privatek) secret
 | 	bytes m(1, 0xff); | ||||||
| 	ECIES<ECP>::Decryptor d; | 	int tests = 2; | ||||||
| 	d.AccessKey().AccessGroupParameters().Initialize(pp::secp256k1()); | 	while (m[0]++, tests--) | ||||||
| 	d.AccessKey().SetPrivateExponent(e); | 	{ | ||||||
| 	assert(d.AccessKey().GetPrivateExponent() == e); | 		h256 hm(sha3(m)); | ||||||
|  | 		Integer hInt(hm.asBytes().data(), 32); | ||||||
|  | 		h256 k(hm ^ key.sec()); | ||||||
|  | 		Integer kInt(k.asBytes().data(), 32); | ||||||
| 
 | 
 | ||||||
| 	// Test that decryptor->encryptor->public == private->makepublic->public
 | 		// raw sign w/cryptopp (doesn't pass through cryptopp hash filter)
 | ||||||
| 	CryptoPP::DL_PublicKey_EC<CryptoPP::ECP> pubk; | 		ECDSA<ECP, SHA3_256>::Signer signer; | ||||||
| 	pubk.AccessGroupParameters().Initialize(pp::secp256k1()); | 		signer.AccessKey().Initialize(s_params, secretToExponent(key.sec())); | ||||||
| 	privatek.MakePublicKey(pubk); | 		Integer r, s; | ||||||
|  | 		signer.RawSign(kInt, hInt, r, s); | ||||||
| 
 | 
 | ||||||
| 	ECIES<ECP>::Encryptor enc(d); | 		// verify cryptopp raw-signature w/cryptopp
 | ||||||
| 	assert(pubk.GetPublicElement() == enc.AccessKey().GetPublicElement()); | 		ECDSA<ECP, SHA3_256>::Verifier verifier; | ||||||
|  | 		verifier.AccessKey().Initialize(s_params, publicToPoint(key.pub())); | ||||||
|  | 		Signature sigppraw; | ||||||
|  | 		r.Encode(sigppraw.data(), 32); | ||||||
|  | 		s.Encode(sigppraw.data() + 32, 32); | ||||||
|  | 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppraw.data(), 64)); | ||||||
|  | //		BOOST_REQUIRE(crypto::verify(key.pub(), sigppraw, bytesConstRef(&m)));
 | ||||||
|  | 		BOOST_REQUIRE(dev::verify(key.pub(), sigppraw, hm)); | ||||||
| 		 | 		 | ||||||
| 	// Test against sipa/seckp256k1
 | 		// sign with cryptopp, verify, recover w/sec256lib
 | ||||||
| 	Public p; | 		Signature seclibsig(dev::sign(key.sec(), hm)); | ||||||
| 	pp::PublicFromExponent(pp::ExponentFromSecret(s), p); | 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), seclibsig.data(), 64)); | ||||||
| 	assert(toAddress(s) == dev::right160(dev::sha3(p.ref()))); | //		BOOST_REQUIRE(crypto::verify(key.pub(), seclibsig, bytesConstRef(&m)));
 | ||||||
| 	assert(k.pub() == p); | 		BOOST_REQUIRE(dev::verify(key.pub(), seclibsig, hm)); | ||||||
|  | 		BOOST_REQUIRE(dev::recover(seclibsig, hm) == key.pub()); | ||||||
|  | 
 | ||||||
|  | 		// sign with cryptopp (w/hash filter?), verify with cryptopp
 | ||||||
|  | 		bytes sigppb(signer.MaxSignatureLength()); | ||||||
|  | 		size_t ssz = signer.SignMessage(s_rng, m.data(), m.size(), sigppb.data()); | ||||||
|  | 		Signature sigpp; | ||||||
|  | 		memcpy(sigpp.data(), sigppb.data(), 64); | ||||||
|  | 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), sigppb.data(), ssz)); | ||||||
|  | //		BOOST_REQUIRE(crypto::verify(key.pub(), sigpp, bytesConstRef(&m)));
 | ||||||
|  | 		BOOST_REQUIRE(dev::verify(key.pub(), sigpp, hm)); | ||||||
|  | 
 | ||||||
|  | 		// sign with cryptopp and stringsource hash filter
 | ||||||
|  | 		string sigstr; | ||||||
|  | 		StringSource ssrc(asString(m), true, new SignerFilter(s_rng, signer, new StringSink(sigstr))); | ||||||
|  | 		FixedHash<sizeof(Signature)> retsig((byte const*)sigstr.data(), Signature::ConstructFromPointer); | ||||||
|  | 		BOOST_REQUIRE(verifier.VerifyMessage(m.data(), m.size(), retsig.data(), 64)); | ||||||
|  | //		BOOST_REQUIRE(crypto::verify(key.pub(), retsig, bytesConstRef(&m)));
 | ||||||
|  | 		BOOST_REQUIRE(dev::verify(key.pub(), retsig, hm)); | ||||||
|  | 		 | ||||||
|  | 		/// verification w/sec256lib
 | ||||||
|  | 		// requires public key and sig in standard format
 | ||||||
|  | 		byte encpub[65] = {0x04}; | ||||||
|  | 		memcpy(&encpub[1], key.pub().data(), 64); | ||||||
|  | 		byte dersig[72]; | ||||||
|  | 		 | ||||||
|  | 		// verify sec256lib sig w/sec256lib
 | ||||||
|  | 		size_t cssz = DSAConvertSignatureFormat(dersig, 72, DSA_DER, seclibsig.data(), 64, DSA_P1363); | ||||||
|  | 		BOOST_CHECK(cssz <= 72); | ||||||
|  | 		BOOST_REQUIRE(1 == secp256k1_ecdsa_verify(hm.data(), sizeof(hm), dersig, cssz, encpub, 65)); | ||||||
|  | 		 | ||||||
|  | 		// verify cryptopp-raw sig w/sec256lib
 | ||||||
|  | 		cssz = DSAConvertSignatureFormat(dersig, 72, DSA_DER, sigppraw.data(), 64, DSA_P1363); | ||||||
|  | 		BOOST_CHECK(cssz <= 72); | ||||||
|  | 		BOOST_REQUIRE(1 == secp256k1_ecdsa_verify(hm.data(), sizeof(hm), dersig, cssz, encpub, 65)); | ||||||
|  | 
 | ||||||
|  | 		// verify cryptopp sig w/sec256lib
 | ||||||
|  | 		cssz = DSAConvertSignatureFormat(dersig, 72, DSA_DER, sigppb.data(), 64, DSA_P1363); | ||||||
|  | 		BOOST_CHECK(cssz <= 72); | ||||||
|  | 		BOOST_REQUIRE(1 == secp256k1_ecdsa_verify(hm.data(), sizeof(hm), dersig, cssz, encpub, 65)); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 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) | BOOST_AUTO_TEST_CASE(ecies_eckeypair) | ||||||
| { | { | ||||||
| 	KeyPair k = KeyPair::create(); | 	KeyPair k = KeyPair::create(); | ||||||
| 
 | 
 | ||||||
| 	string message("Now is the time for all good persons to come to the aide of humanity."); | 	string message("Now is the time for all good persons to come to the aid of humanity."); | ||||||
| 	string original = message; | 	string original = message; | ||||||
| 	 | 	 | ||||||
| 	bytes b = asBytes(message); | 	bytes b = asBytes(message); | ||||||
| 	encrypt(k.pub(), b); | 	s_secp256k1.encrypt(k.pub(), b); | ||||||
| 	assert(b != asBytes(original)); | 	BOOST_REQUIRE(b != asBytes(original)); | ||||||
| 
 | 
 | ||||||
| 	decrypt(k.sec(), b); | 	s_secp256k1.decrypt(k.sec(), b); | ||||||
| 	assert(b == asBytes(original)); | 	BOOST_REQUIRE(b == asBytes(original)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ecdh) | ||||||
|  | { | ||||||
|  | 	cnote << "Testing ecdh..."; | ||||||
|  | 
 | ||||||
|  | 	ECDH<ECP>::Domain dhLocal(s_curveOID); | ||||||
|  | 	SecByteBlock privLocal(dhLocal.PrivateKeyLength()); | ||||||
|  | 	SecByteBlock pubLocal(dhLocal.PublicKeyLength()); | ||||||
|  | 	dhLocal.GenerateKeyPair(s_rng, privLocal, pubLocal); | ||||||
|  | 	 | ||||||
|  | 	ECDH<ECP>::Domain dhRemote(s_curveOID); | ||||||
|  | 	SecByteBlock privRemote(dhRemote.PrivateKeyLength()); | ||||||
|  | 	SecByteBlock pubRemote(dhRemote.PublicKeyLength()); | ||||||
|  | 	dhRemote.GenerateKeyPair(s_rng, privRemote, pubRemote); | ||||||
|  | 	 | ||||||
|  | 	assert(dhLocal.AgreedValueLength() == dhRemote.AgreedValueLength()); | ||||||
|  | 	 | ||||||
|  | 	// local: send public to remote; remote: send public to local
 | ||||||
|  | 	 | ||||||
|  | 	// Local
 | ||||||
|  | 	SecByteBlock sharedLocal(dhLocal.AgreedValueLength()); | ||||||
|  | 	assert(dhLocal.Agree(sharedLocal, privLocal, pubRemote)); | ||||||
|  | 	 | ||||||
|  | 	// Remote
 | ||||||
|  | 	SecByteBlock sharedRemote(dhRemote.AgreedValueLength()); | ||||||
|  | 	assert(dhRemote.Agree(sharedRemote, privRemote, pubLocal)); | ||||||
|  | 	 | ||||||
|  | 	// Test
 | ||||||
|  | 	Integer ssLocal, ssRemote; | ||||||
|  | 	ssLocal.Decode(sharedLocal.BytePtr(), sharedLocal.SizeInBytes()); | ||||||
|  | 	ssRemote.Decode(sharedRemote.BytePtr(), sharedRemote.SizeInBytes()); | ||||||
|  | 	 | ||||||
|  | 	assert(ssLocal != 0); | ||||||
|  | 	assert(ssLocal == ssRemote); | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
|  | 	// Now use our keys
 | ||||||
|  | 	KeyPair a = KeyPair::create(); | ||||||
|  | 	byte puba[65] = {0x04}; | ||||||
|  | 	memcpy(&puba[1], a.pub().data(), 64); | ||||||
|  | 	 | ||||||
|  | 	KeyPair b = KeyPair::create(); | ||||||
|  | 	byte pubb[65] = {0x04}; | ||||||
|  | 	memcpy(&pubb[1], b.pub().data(), 64); | ||||||
|  | 	 | ||||||
|  | 	ECDH<ECP>::Domain dhA(s_curveOID); | ||||||
|  | 	Secret shared; | ||||||
|  | 	BOOST_REQUIRE(dhA.Agree(shared.data(), a.sec().data(), pubb)); | ||||||
|  | 	BOOST_REQUIRE(shared); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(ecdhe) | ||||||
|  | { | ||||||
|  | 	cnote << "Testing ecdhe..."; | ||||||
|  | 	 | ||||||
|  | 	ECDHE a, b; | ||||||
|  | 	BOOST_CHECK_NE(a.pubkey(), b.pubkey()); | ||||||
|  | 	 | ||||||
|  | 	ECDHE local; | ||||||
|  | 	ECDHE remote; | ||||||
|  | 	 | ||||||
|  | 	// local tx pubkey -> remote
 | ||||||
|  | 	Secret sremote; | ||||||
|  | 	remote.agree(local.pubkey(), sremote); | ||||||
|  | 	 | ||||||
|  | 	// remote tx pbukey -> local
 | ||||||
|  | 	Secret slocal; | ||||||
|  | 	local.agree(remote.pubkey(), slocal); | ||||||
|  | 
 | ||||||
|  | 	BOOST_REQUIRE(sremote); | ||||||
|  | 	BOOST_REQUIRE(slocal); | ||||||
|  | 	BOOST_REQUIRE_EQUAL(sremote, slocal); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) | BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) | ||||||
| @ -172,62 +307,12 @@ BOOST_AUTO_TEST_CASE(ecdhe_aes128_ctr_sha3mac) | |||||||
| 	// All connections should share seed for PRF (or PRNG) for nonces
 | 	// All connections should share seed for PRF (or PRNG) for nonces
 | ||||||
| 	 | 	 | ||||||
| 	 | 	 | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(cryptopp_ecies_message) |  | ||||||
| { |  | ||||||
| 	cnote << "Testing cryptopp_ecies_message..."; |  | ||||||
| 
 |  | ||||||
| 	string const message("Now is the time for all good persons to come to the aide of humanity."); |  | ||||||
| 
 |  | ||||||
| 	ECIES<ECP>::Decryptor localDecryptor(pp::PRNG(), pp::secp256k1()); |  | ||||||
| 	SavePrivateKey(localDecryptor.GetPrivateKey()); |  | ||||||
| 	 |  | ||||||
| 	ECIES<ECP>::Encryptor localEncryptor(localDecryptor); |  | ||||||
| 	SavePublicKey(localEncryptor.GetPublicKey()); |  | ||||||
| 
 |  | ||||||
| 	ECIES<ECP>::Decryptor futureDecryptor; |  | ||||||
| 	LoadPrivateKey(futureDecryptor.AccessPrivateKey()); |  | ||||||
| 	futureDecryptor.GetPrivateKey().ThrowIfInvalid(pp::PRNG(), 3); |  | ||||||
| 	 |  | ||||||
| 	ECIES<ECP>::Encryptor futureEncryptor; |  | ||||||
| 	LoadPublicKey(futureEncryptor.AccessPublicKey()); |  | ||||||
| 	futureEncryptor.GetPublicKey().ThrowIfInvalid(pp::PRNG(), 3); |  | ||||||
| 
 |  | ||||||
| 	// encrypt/decrypt with local
 |  | ||||||
| 	string cipherLocal; |  | ||||||
| 	StringSource ss1 (message, true, new PK_EncryptorFilter(pp::PRNG(), localEncryptor, new StringSink(cipherLocal) ) ); |  | ||||||
| 	string plainLocal; |  | ||||||
| 	StringSource ss2 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocal) ) ); |  | ||||||
| 
 |  | ||||||
| 	// encrypt/decrypt with future
 |  | ||||||
| 	string cipherFuture; |  | ||||||
| 	StringSource ss3 (message, true, new PK_EncryptorFilter(pp::PRNG(), futureEncryptor, new StringSink(cipherFuture) ) ); |  | ||||||
| 	string plainFuture; |  | ||||||
| 	StringSource ss4 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFuture) ) ); |  | ||||||
| 	 |  | ||||||
| 	// decrypt local w/future
 |  | ||||||
| 	string plainFutureFromLocal; |  | ||||||
| 	StringSource ss5 (cipherLocal, true, new PK_DecryptorFilter(pp::PRNG(), futureDecryptor, new StringSink(plainFutureFromLocal) ) ); |  | ||||||
| 	 |  | ||||||
| 	// decrypt future w/local
 |  | ||||||
| 	string plainLocalFromFuture; |  | ||||||
| 	StringSource ss6 (cipherFuture, true, new PK_DecryptorFilter(pp::PRNG(), localDecryptor, new StringSink(plainLocalFromFuture) ) ); |  | ||||||
| 	 |  | ||||||
| 	 |  | ||||||
| 	assert(plainLocal == message); |  | ||||||
| 	assert(plainFuture == plainLocal); |  | ||||||
| 	assert(plainFutureFromLocal == plainLocal); |  | ||||||
| 	assert(plainLocalFromFuture == plainLocal); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | ||||||
| { | { | ||||||
| 	const int aesKeyLen = 16; | 	const int aesKeyLen = 16; | ||||||
| 	assert(sizeof(char) == sizeof(byte)); | 	BOOST_REQUIRE(sizeof(char) == sizeof(byte)); | ||||||
| 	 | 	 | ||||||
| 	// generate test key
 | 	// generate test key
 | ||||||
| 	AutoSeededRandomPool rng; | 	AutoSeededRandomPool rng; | ||||||
| @ -235,22 +320,29 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | |||||||
| 	rng.GenerateBlock(key, key.size()); | 	rng.GenerateBlock(key, key.size()); | ||||||
| 	 | 	 | ||||||
| 	// cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr
 | 	// cryptopp uses IV as nonce/counter which is same as using nonce w/0 ctr
 | ||||||
| 	byte ctr[AES::BLOCKSIZE]; | 	FixedHash<AES::BLOCKSIZE> ctr; | ||||||
| 	rng.GenerateBlock(ctr, sizeof(ctr)); | 	rng.GenerateBlock(ctr.data(), sizeof(ctr)); | ||||||
| 
 | 
 | ||||||
| 	string text = "Now is the time for all good persons to come to the aide of humanity."; | 	// used for decrypt
 | ||||||
| 	// c++11 ftw
 | 	FixedHash<AES::BLOCKSIZE> ctrcopy(ctr); | ||||||
|  | 	 | ||||||
|  | 	string text = "Now is the time for all good persons to come to the aid of humanity."; | ||||||
| 	unsigned char const* in = (unsigned char*)&text[0]; | 	unsigned char const* in = (unsigned char*)&text[0]; | ||||||
| 	unsigned char* out = (unsigned char*)&text[0]; | 	unsigned char* out = (unsigned char*)&text[0]; | ||||||
| 	string original = text; | 	string original = text; | ||||||
|  | 	string doublespeak = text + text; | ||||||
| 	 | 	 | ||||||
| 	string cipherCopy; | 	string cipherCopy; | ||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		CTR_Mode<AES>::Encryption e; | 		CTR_Mode<AES>::Encryption e; | ||||||
| 		e.SetKeyWithIV(key, key.size(), ctr); | 		e.SetKeyWithIV(key, key.size(), ctr.data()); | ||||||
|  | 		 | ||||||
|  | 		// 68 % 255 should be difference of counter
 | ||||||
| 		e.ProcessData(out, in, text.size()); | 		e.ProcessData(out, in, text.size()); | ||||||
| 		assert(text != original); | 		ctr = h128(u128(ctr) + text.size() % 16); | ||||||
|  | 		 | ||||||
|  | 		BOOST_REQUIRE(text != original); | ||||||
| 		cipherCopy = text; | 		cipherCopy = text; | ||||||
| 	} | 	} | ||||||
| 	catch(CryptoPP::Exception& e) | 	catch(CryptoPP::Exception& e) | ||||||
| @ -261,9 +353,9 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | |||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		CTR_Mode< AES >::Decryption d; | 		CTR_Mode< AES >::Decryption d; | ||||||
| 		d.SetKeyWithIV(key, key.size(), ctr); | 		d.SetKeyWithIV(key, key.size(), ctrcopy.data()); | ||||||
| 		d.ProcessData(out, in, text.size()); | 		d.ProcessData(out, in, text.size()); | ||||||
| 		assert(text == original); | 		BOOST_REQUIRE(text == original); | ||||||
| 	} | 	} | ||||||
| 	catch(CryptoPP::Exception& e) | 	catch(CryptoPP::Exception& e) | ||||||
| 	{ | 	{ | ||||||
| @ -274,16 +366,16 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | |||||||
| 	// reencrypt ciphertext...
 | 	// reencrypt ciphertext...
 | ||||||
| 	try | 	try | ||||||
| 	{ | 	{ | ||||||
| 		assert(cipherCopy != text); | 		BOOST_REQUIRE(cipherCopy != text); | ||||||
| 		in = (unsigned char*)&cipherCopy[0]; | 		in = (unsigned char*)&cipherCopy[0]; | ||||||
| 		out = (unsigned char*)&cipherCopy[0]; | 		out = (unsigned char*)&cipherCopy[0]; | ||||||
| 		 | 		 | ||||||
| 		CTR_Mode<AES>::Encryption e; | 		CTR_Mode<AES>::Encryption e; | ||||||
| 		e.SetKeyWithIV(key, key.size(), ctr); | 		e.SetKeyWithIV(key, key.size(), ctrcopy.data()); | ||||||
| 		e.ProcessData(out, in, text.size()); | 		e.ProcessData(out, in, text.size()); | ||||||
| 		 | 		 | ||||||
| 		// yep, ctr mode.
 | 		// yep, ctr mode.
 | ||||||
| 		assert(cipherCopy == original); | 		BOOST_REQUIRE(cipherCopy == original); | ||||||
| 	} | 	} | ||||||
| 	catch(CryptoPP::Exception& e) | 	catch(CryptoPP::Exception& e) | ||||||
| 	{ | 	{ | ||||||
| @ -295,7 +387,7 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_ctr) | |||||||
| BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) | BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) | ||||||
| { | { | ||||||
| 	const int aesKeyLen = 16; | 	const int aesKeyLen = 16; | ||||||
| 	assert(sizeof(char) == sizeof(byte)); | 	BOOST_REQUIRE(sizeof(char) == sizeof(byte)); | ||||||
| 	 | 	 | ||||||
| 	AutoSeededRandomPool rng; | 	AutoSeededRandomPool rng; | ||||||
| 	SecByteBlock key(0x00, aesKeyLen); | 	SecByteBlock key(0x00, aesKeyLen); | ||||||
| @ -310,11 +402,11 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) | |||||||
| 	 | 	 | ||||||
| 	CryptoPP::CBC_Mode<Rijndael>::Encryption cbcEncryption(key, key.size(), iv); | 	CryptoPP::CBC_Mode<Rijndael>::Encryption cbcEncryption(key, key.size(), iv); | ||||||
| 	cbcEncryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); | 	cbcEncryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); | ||||||
| 	assert(string128 != plainOriginal); | 	BOOST_REQUIRE(string128 != plainOriginal); | ||||||
| 	 | 	 | ||||||
| 	CBC_Mode<Rijndael>::Decryption cbcDecryption(key, key.size(), iv); | 	CBC_Mode<Rijndael>::Decryption cbcDecryption(key, key.size(), iv); | ||||||
| 	cbcDecryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); | 	cbcDecryption.ProcessData((byte*)&string128[0], (byte*)&string128[0], string128.size()); | ||||||
| 	assert(plainOriginal == string128); | 	BOOST_REQUIRE(plainOriginal == string128); | ||||||
| 	 | 	 | ||||||
| 	 | 	 | ||||||
| 	// plaintext whose size isn't divisible by block size must use stream filter for padding
 | 	// plaintext whose size isn't divisible by block size must use stream filter for padding
 | ||||||
| @ -324,10 +416,10 @@ BOOST_AUTO_TEST_CASE(cryptopp_aes128_cbc) | |||||||
| 	string cipher; | 	string cipher; | ||||||
| 	StreamTransformationFilter* aesStream = new StreamTransformationFilter(cbcEncryption, new StringSink(cipher)); | 	StreamTransformationFilter* aesStream = new StreamTransformationFilter(cbcEncryption, new StringSink(cipher)); | ||||||
| 	StringSource source(string192, true, aesStream); | 	StringSource source(string192, true, aesStream); | ||||||
| 	assert(cipher.size() == 32); | 	BOOST_REQUIRE(cipher.size() == 32); | ||||||
| 
 | 
 | ||||||
| 	cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size()); | 	cbcDecryption.ProcessData((byte*)&cipher[0], (byte*)&string192[0], cipher.size()); | ||||||
| 	assert(string192 == plainOriginal); | 	BOOST_REQUIRE(string192 == plainOriginal); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(eth_keypairs) | BOOST_AUTO_TEST_CASE(eth_keypairs) | ||||||
| @ -339,20 +431,15 @@ BOOST_AUTO_TEST_CASE(eth_keypairs) | |||||||
| 	BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); | 	BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); | ||||||
| 	BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); | 	BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); | ||||||
| 	{ | 	{ | ||||||
| 		eth::Transaction t; | 		eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret()); | ||||||
| 		t.nonce = 0; | 		auto rlp = t.rlp(eth::WithoutSignature); | ||||||
| 		t.type = eth::Transaction::MessageCall; |  | ||||||
| 		t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); |  | ||||||
| 		t.value = 1000; |  | ||||||
| 		auto rlp = t.rlp(false); |  | ||||||
| 		cnote << RLP(rlp); | 		cnote << RLP(rlp); | ||||||
| 		cnote << toHex(rlp); | 		cnote << toHex(rlp); | ||||||
| 		cnote << t.sha3(false); | 		cnote << t.sha3(eth::WithoutSignature); | ||||||
| 		t.sign(p.secret()); | 		rlp = t.rlp(eth::WithSignature); | ||||||
| 		rlp = t.rlp(true); |  | ||||||
| 		cnote << RLP(rlp); | 		cnote << RLP(rlp); | ||||||
| 		cnote << toHex(rlp); | 		cnote << toHex(rlp); | ||||||
| 		cnote << t.sha3(true); | 		cnote << t.sha3(eth::WithSignature); | ||||||
| 		BOOST_REQUIRE(t.sender() == p.address()); | 		BOOST_REQUIRE(t.sender() == p.address()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -365,23 +452,18 @@ int cryptoTest() | |||||||
| 	secp256k1_start(); | 	secp256k1_start(); | ||||||
| 
 | 
 | ||||||
| 	KeyPair p(Secret(fromHex("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4"))); | 	KeyPair p(Secret(fromHex("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4"))); | ||||||
| 	assert(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); | 	BOOST_REQUIRE(p.pub() == Public(fromHex("97466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f"))); | ||||||
| 	assert(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); | 	BOOST_REQUIRE(p.address() == Address(fromHex("8a40bfaa73256b60764c1bf40675a99083efb075"))); | ||||||
| 	{ | 	{ | ||||||
| 		eth::Transaction t; | 		eth::Transaction t(1000, 0, 0, h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")), bytes(), 0, p.secret()); | ||||||
| 		t.nonce = 0; | 		auto rlp = t.rlp(eth::WithoutSignature); | ||||||
| 		t.type = eth::Transaction::MessageCall; |  | ||||||
| 		t.receiveAddress = h160(fromHex("944400f4b88ac9589a0f17ed4671da26bddb668b")); |  | ||||||
| 		t.value = 1000; |  | ||||||
| 		auto rlp = t.rlp(false); |  | ||||||
| 		cnote << RLP(rlp); | 		cnote << RLP(rlp); | ||||||
| 		cnote << toHex(rlp); | 		cnote << toHex(rlp); | ||||||
| 		cnote << t.sha3(false); | 		cnote << t.sha3(eth::WithoutSignature); | ||||||
| 		t.sign(p.secret()); | 		rlp = t.rlp(eth::WithSignature); | ||||||
| 		rlp = t.rlp(true); |  | ||||||
| 		cnote << RLP(rlp); | 		cnote << RLP(rlp); | ||||||
| 		cnote << toHex(rlp); | 		cnote << toHex(rlp); | ||||||
| 		cnote << t.sha3(true); | 		cnote << t.sha3(eth::WithSignature); | ||||||
| 		assert(t.sender() == p.address()); | 		assert(t.sender() == p.address()); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -407,8 +489,8 @@ int cryptoTest() | |||||||
| 
 | 
 | ||||||
| 	auto msg = t.rlp(false); | 	auto msg = t.rlp(false); | ||||||
| 	cout << "TX w/o SIG: " << RLP(msg) << endl; | 	cout << "TX w/o SIG: " << RLP(msg) << endl; | ||||||
| 	cout << "RLP(TX w/o SIG): " << toHex(t.rlpString(false)) << endl; | 	cout << "RLP(TX w/o SIG): " << toHex(t.rlp(false)) << endl; | ||||||
| 	std::string hmsg = sha3(t.rlpString(false), false); | 	std::string hmsg = sha3(t.rlp(false), false); | ||||||
| 	cout << "SHA256(RLP(TX w/o SIG)): 0x" << toHex(hmsg) << endl; | 	cout << "SHA256(RLP(TX w/o SIG)): 0x" << toHex(hmsg) << endl; | ||||||
| 
 | 
 | ||||||
| 	bytes privkey = sha3Bytes("123"); | 	bytes privkey = sha3Bytes("123"); | ||||||
|  | |||||||
							
								
								
									
										17
									
								
								genesis.cpp
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								genesis.cpp
									
									
									
									
									
								
							| @ -26,6 +26,7 @@ | |||||||
| #include <libdevcore/CommonIO.h> | #include <libdevcore/CommonIO.h> | ||||||
| #include <libethereum/BlockChain.h> | #include <libethereum/BlockChain.h> | ||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
|  | #include "TestHelper.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| @ -33,18 +34,12 @@ using namespace dev::eth; | |||||||
| 
 | 
 | ||||||
| namespace js = json_spirit; | namespace js = json_spirit; | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(BasicTests) | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(genesis_tests) | BOOST_AUTO_TEST_CASE(genesis_tests) | ||||||
| { | { | ||||||
| 	const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); | 	string testPath = test::getTestPath(); | ||||||
| 	string testPath; | 	testPath += "/BasicTests"; | ||||||
| 
 |  | ||||||
| 	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; | ||||||
| @ -59,3 +54,5 @@ BOOST_AUTO_TEST_CASE(genesis_tests) | |||||||
| 	BOOST_CHECK_EQUAL(sha3(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str())); | 	BOOST_CHECK_EQUAL(sha3(BlockChain::createGenesisBlock()), h256(o["genesis_hash"].get_str())); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -26,23 +26,19 @@ | |||||||
| #include <libdevcore/CommonIO.h> | #include <libdevcore/CommonIO.h> | ||||||
| #include <libdevcrypto/TrieCommon.h> | #include <libdevcrypto/TrieCommon.h> | ||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
|  | #include "TestHelper.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| namespace js = json_spirit; | namespace js = json_spirit; | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(BasicTests) | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(hexPrefix_test) | BOOST_AUTO_TEST_CASE(hexPrefix_test) | ||||||
| { | { | ||||||
| 	const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); |  | ||||||
| 	string testPath; |  | ||||||
| 
 | 
 | ||||||
| 	if (ptestPath == NULL) | 	string testPath = test::getTestPath(); | ||||||
| 	{ | 	testPath += "/BasicTests"; | ||||||
| 		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; | ||||||
| @ -62,3 +58,4 @@ BOOST_AUTO_TEST_CASE(hexPrefix_test) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | |||||||
							
								
								
									
										149
									
								
								jsonrpc.cpp
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								jsonrpc.cpp
									
									
									
									
									
								
							| @ -29,8 +29,8 @@ | |||||||
| #include <libwebthree/WebThree.h> | #include <libwebthree/WebThree.h> | ||||||
| #include <libweb3jsonrpc/WebThreeStubServer.h> | #include <libweb3jsonrpc/WebThreeStubServer.h> | ||||||
| #include <libweb3jsonrpc/CorsHttpServer.h> | #include <libweb3jsonrpc/CorsHttpServer.h> | ||||||
| #include <jsonrpccpp/server/connectors/httpserver.h> | #include <jsonrpc/connectors/httpserver.h> | ||||||
| #include <jsonrpccpp/client/connectors/httpclient.h> | #include <jsonrpc/connectors/httpclient.h> | ||||||
| #include <set> | #include <set> | ||||||
| #include "JsonSpiritHeaders.h" | #include "JsonSpiritHeaders.h" | ||||||
| #include "TestHelper.h" | #include "TestHelper.h" | ||||||
| @ -43,53 +43,45 @@ using namespace dev; | |||||||
| using namespace dev::eth; | using namespace dev::eth; | ||||||
| namespace js = json_spirit; | namespace js = json_spirit; | ||||||
| 
 | 
 | ||||||
| namespace jsonrpc_tests | WebThreeDirect *web3; | ||||||
| { |  | ||||||
| 
 |  | ||||||
| string name = "Ethereum(++) tests"; |  | ||||||
| string dbPath; |  | ||||||
| auto s = set<string>{"eth", "shh"}; |  | ||||||
| dev::p2p::NetworkPreferences np(30303, std::string(), false); |  | ||||||
| dev::WebThreeDirect web3(name, dbPath, true, s, np); |  | ||||||
| 
 |  | ||||||
| unique_ptr<WebThreeStubServer> jsonrpcServer; | unique_ptr<WebThreeStubServer> jsonrpcServer; | ||||||
| unique_ptr<WebThreeStubClient> jsonrpcClient; | unique_ptr<WebThreeStubClient> jsonrpcClient; | ||||||
| unique_ptr<jsonrpc::AbstractServerConnector> jsonrpcConnector; |  | ||||||
| jsonrpc::HttpClient httpClient("http://localhost:8080"); |  | ||||||
| 
 | 
 | ||||||
| struct JsonrpcFixture  { | struct Setup | ||||||
| 	JsonrpcFixture() |  | ||||||
| { | { | ||||||
| 		cnote << "setup jsonrpc"; | 	Setup() | ||||||
|  | 	{ | ||||||
|  | 		static bool setup = false; | ||||||
|  | 		if (setup) | ||||||
|  | 			return; | ||||||
|  | 		setup = true; | ||||||
| 
 | 
 | ||||||
| 		web3.setIdealPeerCount(5); | 		dev::p2p::NetworkPreferences nprefs(30303, std::string(), false); | ||||||
| 		web3.ethereum()->setForceMining(true); | 		web3 = new WebThreeDirect("Ethereum(++) tests", "", true, {"eth", "shh"}, nprefs); | ||||||
| 		jsonrpcConnector = unique_ptr<jsonrpc::AbstractServerConnector>(new jsonrpc::CorsHttpServer(8080)); | 		 | ||||||
| 		jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(*jsonrpcConnector.get(), web3, {})); | 		web3->setIdealPeerCount(5); | ||||||
|  | 		web3->ethereum()->setForceMining(true); | ||||||
|  | 		jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(new jsonrpc::CorsHttpServer(8080), *web3, {})); | ||||||
| 		jsonrpcServer->setIdentities({}); | 		jsonrpcServer->setIdentities({}); | ||||||
| 		jsonrpcServer->StartListening(); | 		jsonrpcServer->StartListening(); | ||||||
| 		 | 		 | ||||||
| 		jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(httpClient)); | 		jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(new jsonrpc::HttpClient("http://localhost:8080"))); | ||||||
| 	} |  | ||||||
| 	~JsonrpcFixture() |  | ||||||
| 	{ |  | ||||||
| 		cnote << "teardown jsonrpc"; |  | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| BOOST_GLOBAL_FIXTURE(JsonrpcFixture) | BOOST_FIXTURE_TEST_SUITE(environment, Setup) | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock) | BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc defaultBlock..."; | 	cnote << "Testing jsonrpc defaultBlock..."; | ||||||
| 	int defaultBlock = jsonrpcClient->defaultBlock(); | 	int defaultBlock = jsonrpcClient->eth_defaultBlock(); | ||||||
| 	BOOST_CHECK_EQUAL(defaultBlock, web3.ethereum()->getDefault()); | 	BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice) | BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc gasPrice..."; | 	cnote << "Testing jsonrpc gasPrice..."; | ||||||
| 	string gasPrice = jsonrpcClient->gasPrice(); | 	string gasPrice = jsonrpcClient->eth_gasPrice(); | ||||||
| 	BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo)); | 	BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -97,26 +89,26 @@ BOOST_AUTO_TEST_CASE(jsonrpc_isListening) | |||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc isListening..."; | 	cnote << "Testing jsonrpc isListening..."; | ||||||
| 
 | 
 | ||||||
| 	web3.startNetwork(); | 	web3->startNetwork(); | ||||||
| 	bool listeningOn = jsonrpcClient->listening(); | 	bool listeningOn = jsonrpcClient->eth_listening(); | ||||||
| 	BOOST_CHECK_EQUAL(listeningOn, web3.isNetworkStarted()); | 	BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted()); | ||||||
| 	 | 	 | ||||||
| 	web3.stopNetwork(); | 	web3->stopNetwork(); | ||||||
| 	bool listeningOff = jsonrpcClient->listening(); | 	bool listeningOff = jsonrpcClient->eth_listening(); | ||||||
| 	BOOST_CHECK_EQUAL(listeningOff, web3.isNetworkStarted()); | 	BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_isMining) | BOOST_AUTO_TEST_CASE(jsonrpc_isMining) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc isMining..."; | 	cnote << "Testing jsonrpc isMining..."; | ||||||
| 
 | 
 | ||||||
| 	web3.ethereum()->startMining(); | 	web3->ethereum()->startMining(); | ||||||
| 	bool miningOn = jsonrpcClient->mining(); | 	bool miningOn = jsonrpcClient->eth_mining(); | ||||||
| 	BOOST_CHECK_EQUAL(miningOn, web3.ethereum()->isMining()); | 	BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining()); | ||||||
| 
 | 
 | ||||||
| 	web3.ethereum()->stopMining(); | 	web3->ethereum()->stopMining(); | ||||||
| 	bool miningOff = jsonrpcClient->mining(); | 	bool miningOff = jsonrpcClient->eth_mining(); | ||||||
| 	BOOST_CHECK_EQUAL(miningOff, web3.ethereum()->isMining()); | 	BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_accounts) | BOOST_AUTO_TEST_CASE(jsonrpc_accounts) | ||||||
| @ -124,7 +116,7 @@ BOOST_AUTO_TEST_CASE(jsonrpc_accounts) | |||||||
| 	cnote << "Testing jsonrpc accounts..."; | 	cnote << "Testing jsonrpc accounts..."; | ||||||
| 	std::vector <dev::KeyPair> keys = {KeyPair::create(), KeyPair::create()}; | 	std::vector <dev::KeyPair> keys = {KeyPair::create(), KeyPair::create()}; | ||||||
| 	jsonrpcServer->setAccounts(keys); | 	jsonrpcServer->setAccounts(keys); | ||||||
| 	Json::Value k = jsonrpcClient->accounts(); | 	Json::Value k = jsonrpcClient->eth_accounts(); | ||||||
| 	jsonrpcServer->setAccounts({}); | 	jsonrpcServer->setAccounts({}); | ||||||
| 	BOOST_CHECK_EQUAL(k.isArray(), true); | 	BOOST_CHECK_EQUAL(k.isArray(), true); | ||||||
| 	BOOST_CHECK_EQUAL(k.size(),  keys.size()); | 	BOOST_CHECK_EQUAL(k.size(),  keys.size()); | ||||||
| @ -141,41 +133,41 @@ BOOST_AUTO_TEST_CASE(jsonrpc_accounts) | |||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_number) | BOOST_AUTO_TEST_CASE(jsonrpc_number) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc number2..."; | 	cnote << "Testing jsonrpc number2..."; | ||||||
| 	int number = jsonrpcClient->number(); | 	int number = jsonrpcClient->eth_number(); | ||||||
| 	BOOST_CHECK_EQUAL(number, web3.ethereum()->number() + 1); | 	BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1); | ||||||
| 	dev::eth::mine(*(web3.ethereum()), 1); | 	dev::eth::mine(*(web3->ethereum()), 1); | ||||||
| 	int numberAfter = jsonrpcClient->number(); | 	int numberAfter = jsonrpcClient->eth_number(); | ||||||
| 	BOOST_CHECK_EQUAL(number + 1, numberAfter); | 	BOOST_CHECK_EQUAL(number + 1, numberAfter); | ||||||
| 	BOOST_CHECK_EQUAL(numberAfter, web3.ethereum()->number() + 1); | 	BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_peerCount) | BOOST_AUTO_TEST_CASE(jsonrpc_peerCount) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc peerCount..."; | 	cnote << "Testing jsonrpc peerCount..."; | ||||||
| 	int peerCount = jsonrpcClient->peerCount(); | 	int peerCount = jsonrpcClient->eth_peerCount(); | ||||||
| 	BOOST_CHECK_EQUAL(web3.peerCount(), peerCount); | 	BOOST_CHECK_EQUAL(web3->peerCount(), peerCount); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_setListening) | BOOST_AUTO_TEST_CASE(jsonrpc_setListening) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc setListening..."; | 	cnote << "Testing jsonrpc setListening..."; | ||||||
| 
 | 
 | ||||||
| 	jsonrpcClient->setListening(true); | 	jsonrpcClient->eth_setListening(true); | ||||||
| 	BOOST_CHECK_EQUAL(web3.isNetworkStarted(), true); | 	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true); | ||||||
| 	 | 	 | ||||||
| 	jsonrpcClient->setListening(false); | 	jsonrpcClient->eth_setListening(false); | ||||||
| 	BOOST_CHECK_EQUAL(web3.isNetworkStarted(), false); | 	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_setMining) | BOOST_AUTO_TEST_CASE(jsonrpc_setMining) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc setMining..."; | 	cnote << "Testing jsonrpc setMining..."; | ||||||
| 
 | 
 | ||||||
| 	jsonrpcClient->setMining(true); | 	jsonrpcClient->eth_setMining(true); | ||||||
| 	BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), true); | 	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true); | ||||||
| 
 | 
 | ||||||
| 	jsonrpcClient->setMining(false); | 	jsonrpcClient->eth_setMining(false); | ||||||
| 	BOOST_CHECK_EQUAL(web3.ethereum()->isMining(), false); | 	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_stateAt) | BOOST_AUTO_TEST_CASE(jsonrpc_stateAt) | ||||||
| @ -183,38 +175,38 @@ BOOST_AUTO_TEST_CASE(jsonrpc_stateAt) | |||||||
| 	cnote << "Testing jsonrpc stateAt..."; | 	cnote << "Testing jsonrpc stateAt..."; | ||||||
| 	dev::KeyPair key = KeyPair::create(); | 	dev::KeyPair key = KeyPair::create(); | ||||||
| 	auto address = key.address(); | 	auto address = key.address(); | ||||||
| 	string stateAt = jsonrpcClient->stateAt(toJS(address), "0"); | 	string stateAt = jsonrpcClient->eth_stateAt(toJS(address), "0"); | ||||||
| 	BOOST_CHECK_EQUAL(toJS(web3.ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt); | 	BOOST_CHECK_EQUAL(toJS(web3->ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(jsonrpc_transact) | BOOST_AUTO_TEST_CASE(jsonrpc_transact) | ||||||
| { | { | ||||||
| 	cnote << "Testing jsonrpc transact..."; | 	cnote << "Testing jsonrpc transact..."; | ||||||
| 	string coinbase = jsonrpcClient->coinbase(); | 	string coinbase = jsonrpcClient->eth_coinbase(); | ||||||
| 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); | 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address()); | ||||||
| 	 | 	 | ||||||
| 	dev::KeyPair key = KeyPair::create(); | 	dev::KeyPair key = KeyPair::create(); | ||||||
| 	auto address = key.address(); | 	auto address = key.address(); | ||||||
| 	auto receiver = KeyPair::create(); | 	auto receiver = KeyPair::create(); | ||||||
| 	web3.ethereum()->setAddress(address); | 	web3->ethereum()->setAddress(address); | ||||||
| 
 | 
 | ||||||
| 	coinbase = jsonrpcClient->coinbase(); | 	coinbase = jsonrpcClient->eth_coinbase(); | ||||||
| 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3.ethereum()->address()); | 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address()); | ||||||
| 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), address); | 	BOOST_CHECK_EQUAL(jsToAddress(coinbase), address); | ||||||
| 	 | 	 | ||||||
| 	jsonrpcServer->setAccounts({key}); | 	jsonrpcServer->setAccounts({key}); | ||||||
| 	auto balance = web3.ethereum()->balanceAt(address, 0); | 	auto balance = web3->ethereum()->balanceAt(address, 0); | ||||||
| 	string balanceString = jsonrpcClient->balanceAt(toJS(address)); | 	string balanceString = jsonrpcClient->eth_balanceAt(toJS(address)); | ||||||
| 	double countAt = jsonrpcClient->countAt(toJS(address)); | 	double countAt = jsonrpcClient->eth_countAt(toJS(address)); | ||||||
| 	 | 	 | ||||||
| 	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); | 	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address)); | ||||||
| 	BOOST_CHECK_EQUAL(countAt, 0); | 	BOOST_CHECK_EQUAL(countAt, 0); | ||||||
| 	BOOST_CHECK_EQUAL(toJS(balance), balanceString); | 	BOOST_CHECK_EQUAL(toJS(balance), balanceString); | ||||||
| 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0"); | 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0"); | ||||||
| 	 | 	 | ||||||
| 	dev::eth::mine(*(web3.ethereum()), 1); | 	dev::eth::mine(*(web3->ethereum()), 1); | ||||||
| 	balance = web3.ethereum()->balanceAt(address, 0); | 	balance = web3->ethereum()->balanceAt(address, 0); | ||||||
| 	balanceString = jsonrpcClient->balanceAt(toJS(address)); | 	balanceString = jsonrpcClient->eth_balanceAt(toJS(address)); | ||||||
| 	 | 	 | ||||||
| 	BOOST_CHECK_EQUAL(toJS(balance), balanceString); | 	BOOST_CHECK_EQUAL(toJS(balance), balanceString); | ||||||
| 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000"); | 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000"); | ||||||
| @ -231,23 +223,22 @@ BOOST_AUTO_TEST_CASE(jsonrpc_transact) | |||||||
| 	t["gas"] = toJS(gas); | 	t["gas"] = toJS(gas); | ||||||
| 	t["gasPrice"] = toJS(gasPrice); | 	t["gasPrice"] = toJS(gasPrice); | ||||||
| 	 | 	 | ||||||
| 	jsonrpcClient->transact(t); | 	jsonrpcClient->eth_transact(t); | ||||||
| 	jsonrpcServer->setAccounts({}); | 	jsonrpcServer->setAccounts({}); | ||||||
| 	dev::eth::mine(*(web3.ethereum()), 1); | 	dev::eth::mine(*(web3->ethereum()), 1); | ||||||
| 	 | 	 | ||||||
| 	countAt = jsonrpcClient->countAt(toJS(address)); | 	countAt = jsonrpcClient->eth_countAt(toJS(address)); | ||||||
| 	auto balance2 = web3.ethereum()->balanceAt(receiver.address()); | 	auto balance2 = web3->ethereum()->balanceAt(receiver.address()); | ||||||
| 	string balanceString2 = jsonrpcClient->balanceAt(toJS(receiver.address())); | 	string balanceString2 = jsonrpcClient->eth_balanceAt(toJS(receiver.address())); | ||||||
| 	 | 	 | ||||||
| 	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3.ethereum()->countAt(address)); | 	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address)); | ||||||
| 	BOOST_CHECK_EQUAL(countAt, 1); | 	BOOST_CHECK_EQUAL(countAt, 1); | ||||||
| 	BOOST_CHECK_EQUAL(toJS(balance2), balanceString2); | 	BOOST_CHECK_EQUAL(toJS(balance2), balanceString2); | ||||||
| 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000"); | 	BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000"); | ||||||
| 	BOOST_CHECK_EQUAL(txAmount, balance2); | 	BOOST_CHECK_EQUAL(txAmount, balance2); | ||||||
| } | } | ||||||
| 	 | 	 | ||||||
| } | BOOST_AUTO_TEST_SUITE_END() | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								main.cpp
									
									
									
									
									
								
							| @ -41,8 +41,8 @@ using namespace std; | |||||||
| using namespace dev; | using namespace dev; | ||||||
| using namespace dev::eth; | using namespace dev::eth; | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(basic_tests) | //BOOST_AUTO_TEST_CASE(basic_tests)
 | ||||||
| { | //{
 | ||||||
| /*	RLPStream s;
 | /*	RLPStream s;
 | ||||||
| 	BlockInfo::genesis().streamRLP(s, false); | 	BlockInfo::genesis().streamRLP(s, false); | ||||||
| 	std::cout << RLP(s.out()) << std::endl; | 	std::cout << RLP(s.out()) << std::endl; | ||||||
| @ -54,5 +54,5 @@ BOOST_AUTO_TEST_CASE(basic_tests) | |||||||
| //	r += stateTest();
 | //	r += stateTest();
 | ||||||
| //	r += peerTest(argc, argv);
 | //	r += peerTest(argc, argv);
 | ||||||
| //	BOOST_REQUIRE(!r);
 | //	BOOST_REQUIRE(!r);
 | ||||||
| } | //}
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								rlp.cpp
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								rlp.cpp
									
									
									
									
									
								
							| @ -29,6 +29,7 @@ | |||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include "JsonSpiritHeaders.h" | #include "JsonSpiritHeaders.h" | ||||||
|  | #include "TestHelper.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| @ -61,16 +62,8 @@ namespace dev | |||||||
| 
 | 
 | ||||||
| 		static void getRLPTestCases(js::mValue& v) | 		static void getRLPTestCases(js::mValue& v) | ||||||
| 		{ | 		{ | ||||||
| 			const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); | 			string testPath = getTestPath(); | ||||||
| 			string testPath; | 			testPath += "/BasicTests"; | ||||||
| 
 |  | ||||||
| 			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")); | 			string s = asString(contents(testPath + "/rlptest.json")); | ||||||
| 			BOOST_REQUIRE_MESSAGE( s.length() > 0,  | 			BOOST_REQUIRE_MESSAGE( s.length() > 0,  | ||||||
| @ -144,6 +137,7 @@ namespace dev | |||||||
| 	} | 	} | ||||||
| }  | }  | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(BasicTests) | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(rlp_encoding_test) | BOOST_AUTO_TEST_CASE(rlp_encoding_test) | ||||||
| { | { | ||||||
| @ -202,4 +196,5 @@ BOOST_AUTO_TEST_CASE(rlp_decoding_test) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,4 +1,3 @@ | |||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
| 	This file is part of cpp-ethereum. | 	This file is part of cpp-ethereum. | ||||||
| 
 | 
 | ||||||
| @ -18,18 +17,21 @@ | |||||||
| /**
 | /**
 | ||||||
|  * @author Christian <c@ethdev.com> |  * @author Christian <c@ethdev.com> | ||||||
|  * @date 2014 |  * @date 2014 | ||||||
|  * Unit tests for the name and type resolution of the solidity parser. |  * Unit tests for the solidity compiler. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <string> | #include <string> | ||||||
| 
 | #include <iostream> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
| #include <libdevcore/Log.h> | #include <libdevcore/Log.h> | ||||||
| #include <libsolidity/Scanner.h> | #include <libsolidity/Scanner.h> | ||||||
| #include <libsolidity/Parser.h> | #include <libsolidity/Parser.h> | ||||||
| #include <libsolidity/NameAndTypeResolver.h> | #include <libsolidity/NameAndTypeResolver.h> | ||||||
| #include <libsolidity/Compiler.h> | #include <libsolidity/Compiler.h> | ||||||
| #include <libsolidity/AST.h> | #include <libsolidity/AST.h> | ||||||
| #include <boost/test/unit_test.hpp> | 
 | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev::eth; | ||||||
| 
 | 
 | ||||||
| namespace dev | namespace dev | ||||||
| { | { | ||||||
| @ -41,184 +43,185 @@ namespace test | |||||||
| namespace | namespace | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| /**
 | bytes compileContract(const string& _sourceCode) | ||||||
|  * Helper class that extracts the first expression in an AST. |  | ||||||
|  */ |  | ||||||
| class FirstExpressionExtractor: private ASTVisitor |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); } |  | ||||||
| 	Expression* getExpression() const { return m_expression; } |  | ||||||
| private: |  | ||||||
| 	virtual bool visit(Expression& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(PrimaryExpression& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	virtual bool visit(Literal& _expression) override { return checkExpression(_expression); } |  | ||||||
| 	bool checkExpression(Expression& _expression) |  | ||||||
| 	{ |  | ||||||
| 		if (m_expression == nullptr) |  | ||||||
| 			m_expression = &_expression; |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| private: |  | ||||||
| 	Expression* m_expression; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| bytes compileFirstExpression(std::string const& _sourceCode) |  | ||||||
| { | { | ||||||
| 	Parser parser; | 	Parser parser; | ||||||
| 	ASTPointer<ContractDefinition> contract; | 	ASTPointer<ContractDefinition> contract; | ||||||
| 	BOOST_REQUIRE_NO_THROW(contract = parser.parse(std::make_shared<Scanner>(CharStream(_sourceCode)))); | 	BOOST_REQUIRE_NO_THROW(contract = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); | ||||||
| 	NameAndTypeResolver resolver; | 	NameAndTypeResolver resolver; | ||||||
| 	BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); | 	BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); | ||||||
| 	FirstExpressionExtractor extractor(*contract); |  | ||||||
| 	BOOST_REQUIRE(extractor.getExpression() != nullptr); |  | ||||||
| 
 | 
 | ||||||
| 	CompilerContext context; | 	Compiler compiler; | ||||||
| 	ExpressionCompiler compiler(context); | 	compiler.compileContract(*contract); | ||||||
| 	compiler.compile(*extractor.getExpression()); |  | ||||||
| 	bytes instructions = compiler.getAssembledBytecode(); |  | ||||||
| 	// debug
 | 	// debug
 | ||||||
| 	//std::cout << eth::disassemble(instructions) << std::endl;
 | 	//compiler.streamAssembly(cout);
 | ||||||
| 	return instructions; | 	return compiler.getAssembledBytecode(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Checks that @a _compiledCode is present starting from offset @a _offset in @a _expectation.
 | ||||||
|  | /// This is necessary since the compiler will add boilerplate add the beginning that is not
 | ||||||
|  | /// tested here.
 | ||||||
|  | void checkCodePresentAt(bytes const& _compiledCode, bytes const& _expectation, unsigned _offset) | ||||||
|  | { | ||||||
|  | 	BOOST_REQUIRE(_compiledCode.size() >= _offset + _expectation.size()); | ||||||
|  | 	auto checkStart = _compiledCode.begin() + _offset; | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(checkStart, checkStart + _expectation.size(), | ||||||
|  | 								  _expectation.begin(), _expectation.end()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // end anonymous namespace
 | } // end anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler) | BOOST_AUTO_TEST_SUITE(SolidityCompiler) | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(literal_true) | BOOST_AUTO_TEST_CASE(smoke_test) | ||||||
| { | { | ||||||
| 	char const* sourceCode = "contract test {\n" | 	char const* sourceCode = "contract test {\n" | ||||||
| 							 "  function f() { var x = true; }" | 							 "  function f() { var x = 2; }\n" | ||||||
| 							 "}\n"; | 							 "}\n"; | ||||||
| 	bytes code = compileFirstExpression(sourceCode); | 	bytes code = compileContract(sourceCode); | ||||||
| 
 | 
 | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1}); | 	unsigned boilerplateSize = 42; | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | 	bytes expectation({byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x0, // initialize local variable x
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x2, | ||||||
|  | 					   byte(Instruction::SWAP1), | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMP)}); | ||||||
|  | 	checkCodePresentAt(code, expectation, boilerplateSize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(literal_false) | BOOST_AUTO_TEST_CASE(different_argument_numbers) | ||||||
| { | { | ||||||
| 	char const* sourceCode = "contract test {\n" | 	char const* sourceCode = "contract test {\n" | ||||||
| 							 "  function f() { var x = false; }" | 							 "  function f(uint a, uint b, uint c) returns(uint d) { return b; }\n" | ||||||
|  | 							 "  function g() returns (uint e, uint h) { h = f(1, 2, 3); }\n" | ||||||
| 							 "}\n"; | 							 "}\n"; | ||||||
| 	bytes code = compileFirstExpression(sourceCode); | 	bytes code = compileContract(sourceCode); | ||||||
| 
 | 
 | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH1), 0x0}); | 	unsigned shift = 70; | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | 	unsigned boilerplateSize = 83; | ||||||
|  | 	bytes expectation({byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x0, // initialize return variable d
 | ||||||
|  | 					   byte(Instruction::DUP3), | ||||||
|  | 					   byte(Instruction::SWAP1), // assign b to d
 | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0xa + shift), // jump to return
 | ||||||
|  | 					   byte(Instruction::JUMP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::SWAP4), // store d and fetch return address
 | ||||||
|  | 					   byte(Instruction::SWAP3), // store return address
 | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMP), // end of f
 | ||||||
|  | 					   byte(Instruction::JUMPDEST), // beginning of g
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x0, | ||||||
|  | 					   byte(Instruction::DUP1), // initialized e and h
 | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x29 + shift), // ret address
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x2, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x3, byte(Instruction::PUSH1), 0xff, byte(Instruction::AND), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x1 + shift), | ||||||
|  | 					   // stack here: ret e h 0x20 1 2 3 0x1
 | ||||||
|  | 					   byte(Instruction::JUMP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   // stack here: ret e h f(1,2,3)
 | ||||||
|  | 					   byte(Instruction::SWAP1), | ||||||
|  | 					   // stack here: ret e f(1,2,3) h
 | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::DUP1), // retrieve it again as "value of expression"
 | ||||||
|  | 					   byte(Instruction::POP), // end of assignment
 | ||||||
|  | 					   // stack here: ret e f(1,2,3)
 | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::SWAP1), | ||||||
|  | 					   // ret e f(1,2,3)
 | ||||||
|  | 					   byte(Instruction::SWAP2), | ||||||
|  | 					   // f(1,2,3) e ret
 | ||||||
|  | 					   byte(Instruction::JUMP) // end of g
 | ||||||
|  | 					   }); | ||||||
|  | 	checkCodePresentAt(code, expectation, boilerplateSize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(int_literal) | BOOST_AUTO_TEST_CASE(ifStatement) | ||||||
| { | { | ||||||
| 	char const* sourceCode = "contract test {\n" | 	char const* sourceCode = "contract test {\n" | ||||||
| 							 "  function f() { var x = 0x12345678901234567890; }" | 							 "  function f() { bool x; if (x) 77; else if (!x) 78; else 79; }" | ||||||
| 							 "}\n"; | 							 "}\n"; | ||||||
| 	bytes code = compileFirstExpression(sourceCode); | 	bytes code = compileContract(sourceCode); | ||||||
| 
 | 
 | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, | 	unsigned shift = 29; | ||||||
| 													   0x12, 0x34, 0x56, 0x78, 0x90}); | 	unsigned boilerplateSize = 42; | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | 	bytes expectation({byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x0, | ||||||
|  | 					   byte(Instruction::DUP1), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x1b + shift), // "true" target
 | ||||||
|  | 					   byte(Instruction::JUMPI), | ||||||
|  | 					   // new check "else if" condition
 | ||||||
|  | 					   byte(Instruction::DUP1), | ||||||
|  | 					   byte(Instruction::ISZERO), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x13 + shift), | ||||||
|  | 					   byte(Instruction::JUMPI), | ||||||
|  | 					   // "else" body
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x4f, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x17 + shift), // exit path of second part
 | ||||||
|  | 					   byte(Instruction::JUMP), | ||||||
|  | 					   // "else if" body
 | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x4e, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x1f + shift), | ||||||
|  | 					   byte(Instruction::JUMP), | ||||||
|  | 					   // "if" body
 | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x4d, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::JUMP)}); | ||||||
|  | 	checkCodePresentAt(code, expectation, boilerplateSize); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(comparison) | BOOST_AUTO_TEST_CASE(loops) | ||||||
| { | { | ||||||
| 	char const* sourceCode = "contract test {\n" | 	char const* sourceCode = "contract test {\n" | ||||||
| 							 "  function f() { var x = (0x10aa < 0x11aa) != true; }" | 							 "  function f() { while(true){1;break;2;continue;3;return;4;} }" | ||||||
| 							 "}\n"; | 							 "}\n"; | ||||||
| 	bytes code = compileFirstExpression(sourceCode); | 	bytes code = compileContract(sourceCode); | ||||||
| 
 | 
 | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH2), 0x10, 0xaa, | 	unsigned shift = 29; | ||||||
| 					   byte(eth::Instruction::PUSH2), 0x11, 0xaa, | 	unsigned boilerplateSize = 42; | ||||||
| 					   byte(eth::Instruction::GT), | 	bytes expectation({byte(Instruction::JUMPDEST), | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x1, | 					   byte(Instruction::JUMPDEST), | ||||||
| 					   byte(eth::Instruction::EQ), | 					   byte(Instruction::PUSH1), 0x1, | ||||||
| 					   byte(eth::Instruction::NOT)}); | 					   byte(Instruction::ISZERO), | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | 					   byte(Instruction::PUSH1), byte(0x21 + shift), | ||||||
| } | 					   byte(Instruction::JUMPI), | ||||||
|  | 					   byte(Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x21 + shift), | ||||||
|  | 					   byte(Instruction::JUMP), // break
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x2, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x2 + shift), | ||||||
|  | 					   byte(Instruction::JUMP), // continue
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x3, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x22 + shift), | ||||||
|  | 					   byte(Instruction::JUMP), // return
 | ||||||
|  | 					   byte(Instruction::PUSH1), 0x4, | ||||||
|  | 					   byte(Instruction::POP), | ||||||
|  | 					   byte(Instruction::PUSH1), byte(0x2 + shift), | ||||||
|  | 					   byte(Instruction::JUMP), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::JUMPDEST), | ||||||
|  | 					   byte(Instruction::JUMP)}); | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(short_circuiting) | 	checkCodePresentAt(code, expectation, boilerplateSize); | ||||||
| { |  | ||||||
| 	char const* sourceCode = "contract test {\n" |  | ||||||
| 							 "  function f() { var x = (10 + 8 >= 4 || 2 != 9) != true; }" |  | ||||||
| 							 "}\n"; |  | ||||||
| 	bytes code = compileFirstExpression(sourceCode); |  | ||||||
| 
 |  | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH1), 0xa, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x8, |  | ||||||
| 					   byte(eth::Instruction::ADD), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x4, |  | ||||||
| 					   byte(eth::Instruction::GT), |  | ||||||
| 					   byte(eth::Instruction::NOT), // after this we have 10 + 8 >= 4
 |  | ||||||
| 					   byte(eth::Instruction::DUP1), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x14, |  | ||||||
| 					   byte(eth::Instruction::JUMPI), // short-circuit if it is true
 |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x2, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x9, |  | ||||||
| 					   byte(eth::Instruction::EQ), |  | ||||||
| 					   byte(eth::Instruction::NOT), // after this we have 2 != 9
 |  | ||||||
| 					   byte(eth::Instruction::JUMPDEST), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x1, |  | ||||||
| 					   byte(eth::Instruction::EQ), |  | ||||||
| 					   byte(eth::Instruction::NOT)}); |  | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(arithmetics) |  | ||||||
| { |  | ||||||
| 	char const* sourceCode = "contract test {\n" |  | ||||||
| 							 "  function f() { var x = (1 * (2 / (3 % (4 + (5 - (6 | (7 & (8 ^ 9)))))))); }" |  | ||||||
| 							 "}\n"; |  | ||||||
| 	bytes code = compileFirstExpression(sourceCode); |  | ||||||
| 
 |  | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x2, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x3, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x4, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x5, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x6, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x7, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x8, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x9, |  | ||||||
| 					   byte(eth::Instruction::XOR), |  | ||||||
| 					   byte(eth::Instruction::AND), |  | ||||||
| 					   byte(eth::Instruction::OR), |  | ||||||
| 					   byte(eth::Instruction::SWAP1), |  | ||||||
| 					   byte(eth::Instruction::SUB), |  | ||||||
| 					   byte(eth::Instruction::ADD), |  | ||||||
| 					   byte(eth::Instruction::MOD), |  | ||||||
| 					   byte(eth::Instruction::DIV), |  | ||||||
| 					   byte(eth::Instruction::MUL)}); |  | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| BOOST_AUTO_TEST_CASE(unary_operators) |  | ||||||
| { |  | ||||||
| 	char const* sourceCode = "contract test {\n" |  | ||||||
| 							 "  function f() { var x = !(~+-(--(++1++)--) == 2); }" |  | ||||||
| 							 "}\n"; |  | ||||||
| 	bytes code = compileFirstExpression(sourceCode); |  | ||||||
| 
 |  | ||||||
| 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1, |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x1, |  | ||||||
| 					   byte(eth::Instruction::ADD), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x1, |  | ||||||
| 					   byte(eth::Instruction::SWAP1), |  | ||||||
| 					   byte(eth::Instruction::SUB), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x0, |  | ||||||
| 					   byte(eth::Instruction::SUB), |  | ||||||
| 					   byte(eth::Instruction::NOT), |  | ||||||
| 					   byte(eth::Instruction::PUSH1), 0x2, |  | ||||||
| 					   byte(eth::Instruction::EQ), |  | ||||||
| 					   byte(eth::Instruction::ISZERO)}); |  | ||||||
| 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | |||||||
							
								
								
									
										708
									
								
								solidityEndToEndTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										708
									
								
								solidityEndToEndTest.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,708 @@ | |||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  | 	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 expression compiler, testing the behaviour of the code. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | #include <tuple> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include <libethereum/State.h> | ||||||
|  | #include <libethereum/Executive.h> | ||||||
|  | #include <libsolidity/CompilerStack.h> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | 
 | ||||||
|  | namespace dev | ||||||
|  | { | ||||||
|  | /// Provider another overload for toBigEndian to encode arguments and return values.
 | ||||||
|  | inline bytes toBigEndian(bool _value) { return bytes({byte(_value)}); } | ||||||
|  | 
 | ||||||
|  | namespace solidity | ||||||
|  | { | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class ExecutionFramework | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	ExecutionFramework() { g_logVerbosity = 0; } | ||||||
|  | 
 | ||||||
|  | 	bytes const& compileAndRun(string const& _sourceCode) | ||||||
|  | 	{ | ||||||
|  | 		bytes code = dev::solidity::CompilerStack::staticCompile(_sourceCode); | ||||||
|  | 		sendMessage(code, true); | ||||||
|  | 		BOOST_REQUIRE(!m_output.empty()); | ||||||
|  | 		return m_output; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bytes const& callContractFunction(byte _index, bytes const& _data = bytes()) | ||||||
|  | 	{ | ||||||
|  | 		sendMessage(bytes(1, _index) + _data, false); | ||||||
|  | 		return m_output; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template <class... Args> | ||||||
|  | 	bytes const& callContractFunction(byte _index, Args const&... _arguments) | ||||||
|  | 	{ | ||||||
|  | 		return callContractFunction(_index, argsToBigEndian(_arguments...)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template <class CppFunction, class... Args> | ||||||
|  | 	void testSolidityAgainstCpp(byte _index, CppFunction const& _cppFunction, Args const&... _arguments) | ||||||
|  | 	{ | ||||||
|  | 		bytes solidityResult = callContractFunction(_index, _arguments...); | ||||||
|  | 		bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); | ||||||
|  | 		BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." | ||||||
|  | 							"\nSolidity: " + toHex(solidityResult) + "\nC++:      " + toHex(cppResult)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	template <class CppFunction, class... Args> | ||||||
|  | 	void testSolidityAgainstCppOnRange(byte _index, CppFunction const& _cppFunction, | ||||||
|  | 									   u256 const& _rangeStart, u256 const& _rangeEnd) | ||||||
|  | 	{ | ||||||
|  | 		for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) | ||||||
|  | 		{ | ||||||
|  | 			bytes solidityResult = callContractFunction(_index, argument); | ||||||
|  | 			bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); | ||||||
|  | 			BOOST_CHECK_MESSAGE(solidityResult == cppResult, "Computed values do not match." | ||||||
|  | 								"\nSolidity: " + toHex(solidityResult) + "\nC++:      " + toHex(cppResult) + | ||||||
|  | 								"\nArgument: " + toHex(toBigEndian(argument))); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	template <class FirstArg, class... Args> | ||||||
|  | 	bytes argsToBigEndian(FirstArg const& _firstArg, Args const&... _followingArgs) const | ||||||
|  | 	{ | ||||||
|  | 		return toBigEndian(_firstArg) + argsToBigEndian(_followingArgs...); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bytes argsToBigEndian() const { return bytes(); } | ||||||
|  | 
 | ||||||
|  | 	template <class CppFunction, class... Args> | ||||||
|  | 	auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) | ||||||
|  | 	-> typename enable_if<is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type | ||||||
|  | 	{ | ||||||
|  | 		_cppFunction(_arguments...); | ||||||
|  | 		return bytes(); | ||||||
|  | 	} | ||||||
|  | 	template <class CppFunction, class... Args> | ||||||
|  | 	auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) | ||||||
|  | 	-> typename enable_if<!is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type | ||||||
|  | 	{ | ||||||
|  | 		return toBigEndian(_cppFunction(_arguments...)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void sendMessage(bytes const& _data, bool _isCreation) | ||||||
|  | 	{ | ||||||
|  | 		eth::Executive executive(m_state); | ||||||
|  | 		eth::Transaction t = _isCreation ? eth::Transaction(0, m_gasPrice, m_gas, _data, 0, KeyPair::create().sec()) | ||||||
|  | 										 : eth::Transaction(0, m_gasPrice, m_gas, m_contractAddress, _data, 0, KeyPair::create().sec()); | ||||||
|  | 		bytes transactionRLP = t.rlp(); | ||||||
|  | 		try | ||||||
|  | 		{ | ||||||
|  | 			// this will throw since the transaction is invalid, but it should nevertheless store the transaction
 | ||||||
|  | 			executive.setup(&transactionRLP); | ||||||
|  | 		} | ||||||
|  | 		catch (...) {} | ||||||
|  | 		if (_isCreation) | ||||||
|  | 		{ | ||||||
|  | 			BOOST_REQUIRE(!executive.create(Address(), 0, m_gasPrice, m_gas, &_data, Address())); | ||||||
|  | 			m_contractAddress = executive.newAddress(); | ||||||
|  | 			BOOST_REQUIRE(m_contractAddress); | ||||||
|  | 			BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			BOOST_REQUIRE(m_state.addressHasCode(m_contractAddress)); | ||||||
|  | 			BOOST_REQUIRE(!executive.call(m_contractAddress, Address(), 0, m_gasPrice, &_data, m_gas, Address())); | ||||||
|  | 		} | ||||||
|  | 		BOOST_REQUIRE(executive.go()); | ||||||
|  | 		executive.finalize(); | ||||||
|  | 		m_output = executive.out().toVector(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  | 	Address m_contractAddress; | ||||||
|  | 	eth::State m_state; | ||||||
|  | 	u256 const m_gasPrice = 100 * eth::szabo; | ||||||
|  | 	u256 const m_gas = 1000000; | ||||||
|  | 	bytes m_output; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | BOOST_FIXTURE_TEST_SUITE(SolidityCompilerEndToEndTest, ExecutionFramework) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(smoke_test) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint a) returns(uint d) { return a * 7; }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	testSolidityAgainstCppOnRange(0, [](u256 const& a) -> u256 { return a * 7; }, 0, 100); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(empty_contract) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes()).empty()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(recursive_calls) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint n) returns(uint nfac) {\n" | ||||||
|  | 							 "    if (n <= 1) return 1;\n" | ||||||
|  | 							 "    else return n * f(n - 1);\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		if (n <= 1) | ||||||
|  | 			return 1; | ||||||
|  | 		else | ||||||
|  | 			return n * recursive_calls_cpp(n - 1); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	testSolidityAgainstCppOnRange(0, recursive_calls_cpp, 0, 5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multiple_functions) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function a() returns(uint n) { return 0; }\n" | ||||||
|  | 							 "  function b() returns(uint n) { return 1; }\n" | ||||||
|  | 							 "  function c() returns(uint n) { return 2; }\n" | ||||||
|  | 							 "  function f() returns(uint n) { return 3; }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes()) == toBigEndian(u256(0))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(1, bytes()) == toBigEndian(u256(1))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(2, bytes()) == toBigEndian(u256(2))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(3, bytes()) == toBigEndian(u256(3))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(4, bytes()) == bytes()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(while_loop) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint n) returns(uint nfac) {\n" | ||||||
|  | 							 "    nfac = 1;\n" | ||||||
|  | 							 "    var i = 2;\n" | ||||||
|  | 							 "    while (i <= n) nfac *= i++;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	auto while_loop_cpp = [](u256 const& n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		u256 nfac = 1; | ||||||
|  | 		u256 i = 2; | ||||||
|  | 		while (i <= n) | ||||||
|  | 			nfac *= i++; | ||||||
|  | 
 | ||||||
|  | 		return nfac; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	testSolidityAgainstCppOnRange(0, while_loop_cpp, 0, 5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(break_outside_loop) | ||||||
|  | { | ||||||
|  | 	// break and continue outside loops should be simply ignored
 | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    break; continue; return 2;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	testSolidityAgainstCpp(0, [](u256 const&) -> u256 { return 2; }, u256(0)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(nested_loops) | ||||||
|  | { | ||||||
|  | 	// tests that break and continue statements in nested loops jump to the correct place
 | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    while (x > 1) {\n" | ||||||
|  | 							 "      if (x == 10) break;\n" | ||||||
|  | 							 "      while (x > 5) {\n" | ||||||
|  | 							 "        if (x == 8) break;\n" | ||||||
|  | 							 "        x--;\n" | ||||||
|  | 							 "        if (x == 6) continue;\n" | ||||||
|  | 							 "        return x;\n" | ||||||
|  | 							 "      }\n" | ||||||
|  | 							 "      x--;\n" | ||||||
|  | 							 "      if (x == 3) continue;\n" | ||||||
|  | 							 "      break;\n" | ||||||
|  | 							 "    }\n" | ||||||
|  | 							 "    return x;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	auto nested_loops_cpp = [](u256  n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		while (n > 1) | ||||||
|  | 		{ | ||||||
|  | 			if (n == 10) | ||||||
|  | 				break; | ||||||
|  | 			while (n > 5) | ||||||
|  | 			{ | ||||||
|  | 				if (n == 8) | ||||||
|  | 					break; | ||||||
|  | 				n--; | ||||||
|  | 				if (n == 6) | ||||||
|  | 					continue; | ||||||
|  | 				return n; | ||||||
|  | 			} | ||||||
|  | 			n--; | ||||||
|  | 			if (n == 3) | ||||||
|  | 				continue; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return n; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	testSolidityAgainstCppOnRange(0, nested_loops_cpp, 0, 12); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(calling_other_functions) | ||||||
|  | { | ||||||
|  | 	// note that the index of a function is its index in the sorted sequence of functions
 | ||||||
|  | 	char const* sourceCode = "contract collatz {\n" | ||||||
|  | 							 "  function run(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    while ((y = x) > 1) {\n" | ||||||
|  | 							 "      if (x % 2 == 0) x = evenStep(x);\n" | ||||||
|  | 							 "      else x = oddStep(x);\n" | ||||||
|  | 							 "    }\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function evenStep(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    return x / 2;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function oddStep(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    return 3 * x + 1;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	auto evenStep_cpp = [](u256 const& n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		return n / 2; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	auto oddStep_cpp = [](u256 const& n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		return 3 * n + 1; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	auto collatz_cpp = [&evenStep_cpp, &oddStep_cpp](u256 n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		u256 y; | ||||||
|  | 		while ((y = n) > 1) | ||||||
|  | 		{ | ||||||
|  | 			if (n % 2 == 0) | ||||||
|  | 				n = evenStep_cpp(n); | ||||||
|  | 			else | ||||||
|  | 				n = oddStep_cpp(n); | ||||||
|  | 		} | ||||||
|  | 		return y; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	testSolidityAgainstCpp(2, collatz_cpp, u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(2, collatz_cpp, u256(1)); | ||||||
|  | 	testSolidityAgainstCpp(2, collatz_cpp, u256(2)); | ||||||
|  | 	testSolidityAgainstCpp(2, collatz_cpp, u256(8)); | ||||||
|  | 	testSolidityAgainstCpp(2, collatz_cpp, u256(127)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(many_local_variables) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run(uint x1, uint x2, uint x3) returns(uint y) {\n" | ||||||
|  | 							 "    var a = 0x1; var b = 0x10; var c = 0x100;\n" | ||||||
|  | 							 "    y = a + b + c + x1 + x2 + x3;\n" | ||||||
|  | 							 "    y += b + x2;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		u256 a = 0x1; | ||||||
|  | 		u256 b = 0x10; | ||||||
|  | 		u256 c = 0x100; | ||||||
|  | 		u256 y = a + b + c + x1 + x2 + x3; | ||||||
|  | 		return y + b + x2; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(0x1000), u256(0x10000), u256(0x100000)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(packing_unpacking_types) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n" | ||||||
|  | 							 "    if (a) y = 1;\n" | ||||||
|  | 							 "    y = y * 0x100000000 | ~b;\n" | ||||||
|  | 							 "    y = y * 0x10000000000000000 | ~c;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, fromHex("01""0f0f0f0f""f0f0f0f0f0f0f0f0")) | ||||||
|  | 				== fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multiple_return_values) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) {\n" | ||||||
|  | 							 "    y1 = x2; y2 = x1;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 1) + toBigEndian(u256(0xcd))) | ||||||
|  | 				== toBigEndian(u256(0xcd)) + bytes(1, 1) + toBigEndian(u256(0))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(short_circuiting) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run(uint x) returns(uint y) {\n" | ||||||
|  | 							 "    x == 0 || ((x = 8) > 0);\n" | ||||||
|  | 							 "    return x;" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	auto short_circuiting_cpp = [](u256 n) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		n == 0 || (n = 8) > 0; | ||||||
|  | 		return n; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	testSolidityAgainstCppOnRange(0, short_circuiting_cpp, 0, 2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(high_bits_cleaning) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run() returns(uint256 y) {\n" | ||||||
|  | 							 "    uint32 x = uint32(0xffffffff) + 10;\n" | ||||||
|  | 							 "    if (x >= 0xffffffff) return 0;\n" | ||||||
|  | 							 "    return x;" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	auto high_bits_cleaning_cpp = []() -> u256 | ||||||
|  | 	{ | ||||||
|  | 		uint32_t x = uint32_t(0xffffffff) + 10; | ||||||
|  | 		if (x >= 0xffffffff) | ||||||
|  | 			return 0; | ||||||
|  | 		return x; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, high_bits_cleaning_cpp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(sign_extension) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run() returns(uint256 y) {\n" | ||||||
|  | 							 "    int64 x = -int32(0xff);\n" | ||||||
|  | 							 "    if (x >= 0xff) return 0;\n" | ||||||
|  | 							 "    return -uint256(x);" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	auto sign_extension_cpp = []() -> u256 | ||||||
|  | 	{ | ||||||
|  | 		int64_t x = -int32_t(0xff); | ||||||
|  | 		if (x >= 0xff) | ||||||
|  | 			return 0; | ||||||
|  | 		return u256(x) * -1; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, sign_extension_cpp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(small_unsigned_types) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run() returns(uint256 y) {\n" | ||||||
|  | 							 "    uint32 x = uint32(0xffffff) * 0xffffff;\n" | ||||||
|  | 							 "    return x / 0x100;" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	auto small_unsigned_types_cpp = []() -> u256 | ||||||
|  | 	{ | ||||||
|  | 		uint32_t x = uint32_t(0xffffff) * 0xffffff; | ||||||
|  | 		return x / 0x100; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, small_unsigned_types_cpp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(small_signed_types) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function run() returns(int256 y) {\n" | ||||||
|  | 							 "    return -int32(10) * -int64(20);\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	auto small_signed_types_cpp = []() -> u256 | ||||||
|  | 	{ | ||||||
|  | 		return -int32_t(10) * -int64_t(20); | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, small_signed_types_cpp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(state_smoke_test) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  uint256 value1;\n" | ||||||
|  | 							 "  uint256 value2;\n" | ||||||
|  | 							 "  function get(uint8 which) returns (uint256 value) {\n" | ||||||
|  | 							 "    if (which == 0) return value1;\n" | ||||||
|  | 							 "    else return value2;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function set(uint8 which, uint256 value) {\n" | ||||||
|  | 							 "    if (which == 0) value1 = value;\n" | ||||||
|  | 							 "    else value2 = value;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x1234))) == bytes()); | ||||||
|  | 	BOOST_CHECK(callContractFunction(1, bytes(1, 0x01) + toBigEndian(u256(0x8765))) == bytes()); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x1234))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 0x01)) == toBigEndian(u256(0x8765))); | ||||||
|  | 	BOOST_CHECK(callContractFunction(1, bytes(1, 0x00) + toBigEndian(u256(0x3))) == bytes()); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes(1, 0x00)) == toBigEndian(u256(0x3))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(simple_mapping) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  mapping(uint8 => uint8) table;\n" | ||||||
|  | 							 "  function get(uint8 k) returns (uint8 v) {\n" | ||||||
|  | 							 "    return table[k];\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function set(uint8 k, uint8 v) {\n" | ||||||
|  | 							 "    table[k] = v;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x00})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); | ||||||
|  | 	callContractFunction(1, bytes({0x01, 0xa1})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0x00})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); | ||||||
|  | 	callContractFunction(1, bytes({0x00, 0xef})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0xa1})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); | ||||||
|  | 	callContractFunction(1, bytes({0x01, 0x05})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x00})) == bytes({0xef})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0x01})) == bytes({0x05})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0, bytes({0xa7})) == bytes({0x00})); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(mapping_state) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract Ballot {\n" | ||||||
|  | 							 "  mapping(address => bool) canVote;\n" | ||||||
|  | 							 "  mapping(address => uint) voteCount;\n" | ||||||
|  | 							 "  mapping(address => bool) voted;\n" | ||||||
|  | 							 "  function getVoteCount(address addr) returns (uint retVoteCount) {\n" | ||||||
|  | 							 "    return voteCount[addr];\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function grantVoteRight(address addr) {\n" | ||||||
|  | 							 "    canVote[addr] = true;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function vote(address voter, address vote) returns (bool success) {\n" | ||||||
|  | 							 "    if (!canVote[voter] || voted[voter]) return false;\n" | ||||||
|  | 							 "    voted[voter] = true;\n" | ||||||
|  | 							 "    voteCount[vote] = voteCount[vote] + 1;\n" | ||||||
|  | 							 "    return true;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	class Ballot | ||||||
|  | 	{ | ||||||
|  | 	public: | ||||||
|  | 		u256 getVoteCount(u160 _address) { return m_voteCount[_address]; } | ||||||
|  | 		void grantVoteRight(u160 _address) { m_canVote[_address] = true; } | ||||||
|  | 		bool vote(u160 _voter, u160 _vote) | ||||||
|  | 		{ | ||||||
|  | 			if (!m_canVote[_voter] || m_voted[_voter]) return false; | ||||||
|  | 			m_voted[_voter] = true; | ||||||
|  | 			m_voteCount[_vote]++; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 	private: | ||||||
|  | 		map<u160, bool> m_canVote; | ||||||
|  | 		map<u160, u256> m_voteCount; | ||||||
|  | 		map<u160, bool> m_voted; | ||||||
|  | 	} ballot; | ||||||
|  | 
 | ||||||
|  | 	auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1); | ||||||
|  | 	auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1); | ||||||
|  | 	auto vote = bind(&Ballot::vote, &ballot, _1, _2); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | 	// voting without vote right shourd be rejected
 | ||||||
|  | 	testSolidityAgainstCpp(2, vote, u160(0), u160(2)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | 	// grant vote rights
 | ||||||
|  | 	testSolidityAgainstCpp(1, grantVoteRight, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(1, grantVoteRight, u160(1)); | ||||||
|  | 	// vote, should increase 2's vote count
 | ||||||
|  | 	testSolidityAgainstCpp(2, vote, u160(0), u160(2)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | 	// vote again, should be rejected
 | ||||||
|  | 	testSolidityAgainstCpp(2, vote, u160(0), u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | 	// vote without right to vote
 | ||||||
|  | 	testSolidityAgainstCpp(2, vote, u160(2), u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | 	// grant vote right and now vote again
 | ||||||
|  | 	testSolidityAgainstCpp(1, grantVoteRight, u160(2)); | ||||||
|  | 	testSolidityAgainstCpp(2, vote, u160(2), u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(1)); | ||||||
|  | 	testSolidityAgainstCpp(0, getVoteCount, u160(2)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  uint value;\n" | ||||||
|  | 							 "  mapping(uint => uint) table;\n" | ||||||
|  | 							 "  function f(uint x) returns (uint y) {\n" | ||||||
|  | 							 "    value = x;\n" | ||||||
|  | 							 "    if (x > 0) table[++value] = 8;\n" | ||||||
|  | 							 "    if (x > 1) value--;\n" | ||||||
|  | 							 "    if (x > 2) table[value]++;\n" | ||||||
|  | 							 "    return --table[value++];\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	u256 value = 0; | ||||||
|  | 	map<u256, u256> table; | ||||||
|  | 	auto f = [&](u256 const& _x) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		value = _x; | ||||||
|  | 		if (_x > 0) | ||||||
|  | 			table[++value] = 8; | ||||||
|  | 		if (_x > 1) | ||||||
|  | 			value --; | ||||||
|  | 		if (_x > 2) | ||||||
|  | 			table[value]++; | ||||||
|  | 		return --table[value++]; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCppOnRange(0, f, 0, 5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multi_level_mapping) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  mapping(uint => mapping(uint => uint)) table;\n" | ||||||
|  | 							 "  function f(uint x, uint y, uint z) returns (uint w) {\n" | ||||||
|  | 							 "    if (z == 0) return table[x][y];\n" | ||||||
|  | 							 "    else return table[x][y] = z;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	map<u256, map<u256, u256>> table; | ||||||
|  | 	auto f = [&](u256 const& _x, u256 const& _y, u256 const& _z) -> u256 | ||||||
|  | 	{ | ||||||
|  | 		if (_z == 0) return table[_x][_y]; | ||||||
|  | 		else return table[_x][_y] = _z; | ||||||
|  | 	}; | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(9)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(7)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(4), u256(5), u256(0)); | ||||||
|  | 	testSolidityAgainstCpp(0, f, u256(5), u256(4), u256(0)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(structs) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  struct s1 {\n" | ||||||
|  | 							 "    uint8 x;\n" | ||||||
|  | 							 "    bool y;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  struct s2 {\n" | ||||||
|  | 							 "    uint32 z;\n" | ||||||
|  | 							 "    s1 s1data;\n" | ||||||
|  | 							 "    mapping(uint8 => s2) recursive;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  s2 data;\n" | ||||||
|  | 							 "  function check() returns (bool ok) {\n" | ||||||
|  | 							 "    return data.z == 1 && data.s1data.x == 2 && \n" | ||||||
|  | 							 "        data.s1data.y == true && \n" | ||||||
|  | 							 "        data.recursive[3].recursive[4].z == 5 && \n" | ||||||
|  | 							 "        data.recursive[4].recursive[3].z == 6 && \n" | ||||||
|  | 							 "        data.recursive[0].s1data.y == false && \n" | ||||||
|  | 							 "        data.recursive[4].z == 9;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "  function set() {\n" | ||||||
|  | 							 "    data.z = 1;\n" | ||||||
|  | 							 "    data.s1data.x = 2;\n" | ||||||
|  | 							 "    data.s1data.y = true;\n" | ||||||
|  | 							 "    data.recursive[3].recursive[4].z = 5;\n" | ||||||
|  | 							 "    data.recursive[4].recursive[3].z = 6;\n" | ||||||
|  | 							 "    data.recursive[0].s1data.y = false;\n" | ||||||
|  | 							 "    data.recursive[4].z = 9;\n" | ||||||
|  | 							 "  }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	compileAndRun(sourceCode); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0) == bytes({0x00})); | ||||||
|  | 	BOOST_CHECK(callContractFunction(1) == bytes()); | ||||||
|  | 	BOOST_CHECK(callContractFunction(0) == bytes({0x01})); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
|  | } // end namespaces
 | ||||||
|  | 
 | ||||||
							
								
								
									
										389
									
								
								solidityExpressionCompiler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										389
									
								
								solidityExpressionCompiler.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,389 @@ | |||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  | 	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 expression compiler. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | #include <libdevcore/Log.h> | ||||||
|  | #include <libsolidity/Scanner.h> | ||||||
|  | #include <libsolidity/Parser.h> | ||||||
|  | #include <libsolidity/NameAndTypeResolver.h> | ||||||
|  | #include <libsolidity/CompilerContext.h> | ||||||
|  | #include <libsolidity/ExpressionCompiler.h> | ||||||
|  | #include <libsolidity/AST.h> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | 
 | ||||||
|  | using namespace std; | ||||||
|  | 
 | ||||||
|  | namespace dev | ||||||
|  | { | ||||||
|  | namespace solidity | ||||||
|  | { | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | namespace | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | /// Helper class that extracts the first expression in an AST.
 | ||||||
|  | class FirstExpressionExtractor: private ASTVisitor | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); } | ||||||
|  | 	Expression* getExpression() const { return m_expression; } | ||||||
|  | private: | ||||||
|  | 	virtual bool visit(Expression& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(PrimaryExpression& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	virtual bool visit(Literal& _expression) override { return checkExpression(_expression); } | ||||||
|  | 	bool checkExpression(Expression& _expression) | ||||||
|  | 	{ | ||||||
|  | 		if (m_expression == nullptr) | ||||||
|  | 			m_expression = &_expression; | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | private: | ||||||
|  | 	Expression* m_expression; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | Declaration const& resolveDeclaration(vector<string> const& _namespacedName, | ||||||
|  | 											  NameAndTypeResolver const& _resolver) | ||||||
|  | { | ||||||
|  | 	Declaration const* declaration = nullptr; | ||||||
|  | 	for (string const& namePart: _namespacedName) | ||||||
|  | 		BOOST_REQUIRE(declaration = _resolver.resolveName(namePart, declaration)); | ||||||
|  | 	BOOST_REQUIRE(declaration); | ||||||
|  | 	return *declaration; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bytes compileFirstExpression(const string& _sourceCode, vector<vector<string>> _functions = {}, | ||||||
|  | 							 vector<vector<string>> _localVariables = {}) | ||||||
|  | { | ||||||
|  | 	Parser parser; | ||||||
|  | 	ASTPointer<ContractDefinition> contract; | ||||||
|  | 	BOOST_REQUIRE_NO_THROW(contract = parser.parse(make_shared<Scanner>(CharStream(_sourceCode)))); | ||||||
|  | 	NameAndTypeResolver resolver; | ||||||
|  | 	BOOST_REQUIRE_NO_THROW(resolver.resolveNamesAndTypes(*contract)); | ||||||
|  | 	FirstExpressionExtractor extractor(*contract); | ||||||
|  | 	BOOST_REQUIRE(extractor.getExpression() != nullptr); | ||||||
|  | 
 | ||||||
|  | 	CompilerContext context; | ||||||
|  | 	for (vector<string> const& function: _functions) | ||||||
|  | 		context.addFunction(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver))); | ||||||
|  | 	for (vector<string> const& variable: _localVariables) | ||||||
|  | 		context.addVariable(dynamic_cast<VariableDeclaration const&>(resolveDeclaration(variable, resolver))); | ||||||
|  | 
 | ||||||
|  | 	ExpressionCompiler::compileExpression(context, *extractor.getExpression()); | ||||||
|  | 
 | ||||||
|  | 	for (vector<string> const& function: _functions) | ||||||
|  | 		context << context.getFunctionEntryLabel(dynamic_cast<FunctionDefinition const&>(resolveDeclaration(function, resolver))); | ||||||
|  | 	bytes instructions = context.getAssembledBytecode(); | ||||||
|  | 	// debug
 | ||||||
|  | 	// cout << eth::disassemble(instructions) << endl;
 | ||||||
|  | 	return instructions; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // end anonymous namespace
 | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(literal_true) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = true; }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(literal_false) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = false; }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x0}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(int_literal) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = 0x12345678901234567890; }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, | ||||||
|  | 													   0x12, 0x34, 0x56, 0x78, 0x90}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(comparison) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = (0x10aa < 0x11aa) != true; }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::PUSH2), 0x11, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH2), 0x10, 0xaa, byte(eth::Instruction::PUSH2), 0xff, 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::LT), | ||||||
|  | 					   byte(eth::Instruction::EQ), | ||||||
|  | 					   byte(eth::Instruction::ISZERO)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(short_circuiting) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = true != (4 <= 8 + 10 || 9 != 2); }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0xa, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x8, | ||||||
|  | 					   byte(eth::Instruction::ADD), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x4, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::GT), | ||||||
|  | 					   byte(eth::Instruction::ISZERO), // after this we have 10 + 8 >= 4
 | ||||||
|  | 					   byte(eth::Instruction::DUP1), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x20, | ||||||
|  | 					   byte(eth::Instruction::JUMPI), // short-circuit if it is true
 | ||||||
|  | 					   byte(eth::Instruction::POP), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x9, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::EQ), | ||||||
|  | 					   byte(eth::Instruction::ISZERO), // after this we have 2 != 9
 | ||||||
|  | 					   byte(eth::Instruction::JUMPDEST), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::EQ), | ||||||
|  | 					   byte(eth::Instruction::ISZERO)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(arithmetics) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = ((((((((9 ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x2, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x3, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x4, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x5, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x6, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x7, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x8, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x9, | ||||||
|  | 					   byte(eth::Instruction::XOR), | ||||||
|  | 					   byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::OR), | ||||||
|  | 					   byte(eth::Instruction::SUB), | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::MOD), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::DIV), | ||||||
|  | 					   byte(eth::Instruction::MUL)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(unary_operators) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { var x = !(~+- 1 == 2); }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x0, | ||||||
|  | 					   byte(eth::Instruction::SUB), | ||||||
|  | 					   byte(eth::Instruction::NOT), byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::EQ), | ||||||
|  | 					   byte(eth::Instruction::ISZERO)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(unary_inc_dec) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}}); | ||||||
|  | 
 | ||||||
|  | 	// Stack: a, x
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::DUP2), | ||||||
|  | 					   byte(eth::Instruction::DUP1), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   // Stack here: a x a (a+1)
 | ||||||
|  | 					   byte(eth::Instruction::SWAP3), | ||||||
|  | 					   byte(eth::Instruction::POP), // first ++
 | ||||||
|  | 					   // Stack here: (a+1) x a
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   // Stack here: (a+1) x a (a+2)
 | ||||||
|  | 					   byte(eth::Instruction::SWAP3), | ||||||
|  | 					   byte(eth::Instruction::POP), | ||||||
|  | 					   // Stack here: (a+2) x a
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), // second ++
 | ||||||
|  | 					   byte(eth::Instruction::XOR), | ||||||
|  | 					   // Stack here: (a+2) x a^(a+2)
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), | ||||||
|  | 					   byte(eth::Instruction::DUP1), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::SWAP1), | ||||||
|  | 					   byte(eth::Instruction::SUB), | ||||||
|  | 					   // Stack here: (a+2) x a^(a+2) (a+2) (a+1)
 | ||||||
|  | 					   byte(eth::Instruction::SWAP4), | ||||||
|  | 					   byte(eth::Instruction::POP), // first --
 | ||||||
|  | 					   byte(eth::Instruction::XOR), | ||||||
|  | 					   // Stack here: (a+1) x a^(a+2)^(a+2)
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x1, | ||||||
|  | 					   byte(eth::Instruction::SWAP1), | ||||||
|  | 					   byte(eth::Instruction::SUB), | ||||||
|  | 					   // Stack here: (a+1) x a^(a+2)^(a+2) a
 | ||||||
|  | 					   byte(eth::Instruction::SWAP3), | ||||||
|  | 					   byte(eth::Instruction::POP), // second ++
 | ||||||
|  | 					   // Stack here: a x a^(a+2)^(a+2)
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), // will change
 | ||||||
|  | 					   byte(eth::Instruction::XOR)}); | ||||||
|  | 					   // Stack here: a x a^(a+2)^(a+2)^a
 | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(assignment) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint a, uint b) { (a += b) * 2; }" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); | ||||||
|  | 
 | ||||||
|  | 	// Stack: a, b
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x2, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::DUP2), | ||||||
|  | 					   byte(eth::Instruction::DUP4), | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   // Stack here: a b 2 a+b
 | ||||||
|  | 					   byte(eth::Instruction::SWAP3), | ||||||
|  | 					   byte(eth::Instruction::POP), | ||||||
|  | 					   byte(eth::Instruction::DUP3), | ||||||
|  | 					   // Stack here: a+b b 2 a+b
 | ||||||
|  | 					   byte(eth::Instruction::MUL)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(function_call) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f(uint a, uint b) { a += g(a + 1, b) * 2; }\n" | ||||||
|  | 							 "  function g(uint a, uint b) returns (uint c) {}\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode, {{"test", "g"}}, | ||||||
|  | 										{{"test", "f", "a"}, {"test", "f", "b"}}); | ||||||
|  | 
 | ||||||
|  | 	// Stack: a, b
 | ||||||
|  | 	bytes expectation({byte(eth::Instruction::PUSH1), 0x02, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x12, | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x01, byte(eth::Instruction::PUSH1), 0xff, byte(eth::Instruction::AND), | ||||||
|  | 					   byte(eth::Instruction::DUP5), | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   // Stack here: a b 2 <ret label> (a+1)
 | ||||||
|  | 					   byte(eth::Instruction::DUP4), | ||||||
|  | 					   byte(eth::Instruction::PUSH1), 0x19, | ||||||
|  | 					   byte(eth::Instruction::JUMP), | ||||||
|  | 					   byte(eth::Instruction::JUMPDEST), | ||||||
|  | 					   // Stack here: a b 2 g(a+1, b)
 | ||||||
|  | 					   byte(eth::Instruction::MUL), | ||||||
|  | 					   // Stack here: a b g(a+1, b)*2
 | ||||||
|  | 					   byte(eth::Instruction::DUP3), | ||||||
|  | 					   byte(eth::Instruction::ADD), | ||||||
|  | 					   // Stack here: a b a+g(a+1, b)*2
 | ||||||
|  | 					   byte(eth::Instruction::SWAP2), | ||||||
|  | 					   byte(eth::Instruction::POP), | ||||||
|  | 					   byte(eth::Instruction::DUP2), | ||||||
|  | 					   byte(eth::Instruction::JUMPDEST)}); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(negative_literals_8bits) | ||||||
|  | { | ||||||
|  | 	// these all fit in 8 bits
 | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { int8 x = -0 + -1 + -0x01 + -127 + -128; }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x81) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH1), 0x00, | ||||||
|  | 							 byte(eth::Instruction::ADD), | ||||||
|  | 							 byte(eth::Instruction::ADD), | ||||||
|  | 							 byte(eth::Instruction::ADD), | ||||||
|  | 							 byte(eth::Instruction::ADD)})); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(negative_literals_16bits) | ||||||
|  | { | ||||||
|  | 	// -1 should need 8 bits, -129 should need 16 bits, how many bits are used is visible
 | ||||||
|  | 	// from the SIGNEXTEND opcodes
 | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 							 "  function f() { int64 x = int64(-1 + -129); }\n" | ||||||
|  | 							 "}\n"; | ||||||
|  | 	bytes code = compileFirstExpression(sourceCode); | ||||||
|  | 
 | ||||||
|  | 	bytes expectation(bytes({byte(eth::Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x7f) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH32)}) + bytes(32, 0xff) + | ||||||
|  | 					  bytes({byte(eth::Instruction::PUSH1), 0x00, | ||||||
|  | 							 byte(eth::Instruction::SIGNEXTEND), | ||||||
|  | 							 byte(eth::Instruction::ADD), | ||||||
|  | 							 byte(eth::Instruction::PUSH1), 0x01, | ||||||
|  | 							 byte(eth::Instruction::SIGNEXTEND)})); | ||||||
|  | 	BOOST_CHECK_EQUAL_COLLECTIONS(code.begin(), code.end(), expectation.begin(), expectation.end()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
|  | } // end namespaces
 | ||||||
|  | 
 | ||||||
							
								
								
									
										214
									
								
								solidityJSONInterfaceTest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								solidityJSONInterfaceTest.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,214 @@ | |||||||
|  | /*
 | ||||||
|  | 	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 Marek Kotewicz <marek@ethdev.com> | ||||||
|  |  * @date 2014 | ||||||
|  |  * Unit tests for the solidity compiler JSON Interface output. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include <libsolidity/CompilerStack.h> | ||||||
|  | #include <jsonrpc/json/json.h> | ||||||
|  | 
 | ||||||
|  | namespace dev | ||||||
|  | { | ||||||
|  | namespace solidity | ||||||
|  | { | ||||||
|  | namespace test | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class InterfaceChecker | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	bool checkInterface(std::string const& _code, std::string const& _expectedInterfaceString) | ||||||
|  | 	{ | ||||||
|  | 		m_compilerStack.parse(_code); | ||||||
|  | 		std::string generatedInterfaceString = m_compilerStack.getInterface(); | ||||||
|  | 		Json::Value generatedInterface; | ||||||
|  | 		m_reader.parse(generatedInterfaceString, generatedInterface); | ||||||
|  | 		Json::Value expectedInterface; | ||||||
|  | 		m_reader.parse(_expectedInterfaceString, expectedInterface); | ||||||
|  | 		return expectedInterface == generatedInterface; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | private: | ||||||
|  | 	CompilerStack m_compilerStack; | ||||||
|  | 	Json::Reader m_reader; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | BOOST_FIXTURE_TEST_SUITE(SolidityCompilerJSONInterfaceOutput, InterfaceChecker) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(basic_test) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 	"  function f(uint a) returns(uint d) { return a * 7; }\n" | ||||||
|  | 	"}\n"; | ||||||
|  | 
 | ||||||
|  | 	char const* interface = R"([ | ||||||
|  | 	{ | ||||||
|  | 		"name": "f", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "a", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "d", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	} | ||||||
|  | 	])"; | ||||||
|  | 
 | ||||||
|  | 	BOOST_CHECK(checkInterface(sourceCode, interface)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(empty_contract) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 	"}\n"; | ||||||
|  | 
 | ||||||
|  | 	char const* interface = "[]"; | ||||||
|  | 
 | ||||||
|  | 	BOOST_CHECK(checkInterface(sourceCode, interface)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multiple_methods) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 	"  function f(uint a) returns(uint d) { return a * 7; }\n" | ||||||
|  | 	"  function g(uint b) returns(uint e) { return b * 8; }\n" | ||||||
|  | 	"}\n"; | ||||||
|  | 	 | ||||||
|  | 	char const* interface = R"([ | ||||||
|  | 	{ | ||||||
|  | 		"name": "f", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "a", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "d", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"name": "g", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "b", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "e", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	} | ||||||
|  | 	])"; | ||||||
|  | 
 | ||||||
|  | 	BOOST_CHECK(checkInterface(sourceCode, interface)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multiple_params) | ||||||
|  | { | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 	"  function f(uint a, uint b) returns(uint d) { return a + b; }\n" | ||||||
|  | 	"}\n"; | ||||||
|  | 
 | ||||||
|  | 	char const* interface = R"([ | ||||||
|  | 	{ | ||||||
|  | 		"name": "f", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "a", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			"name": "b", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "d", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	} | ||||||
|  | 	])"; | ||||||
|  | 
 | ||||||
|  | 	BOOST_CHECK(checkInterface(sourceCode, interface)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(multiple_methods_order) | ||||||
|  | { | ||||||
|  | 	// methods are expected to be in alpabetical order
 | ||||||
|  | 	char const* sourceCode = "contract test {\n" | ||||||
|  | 	"  function f(uint a) returns(uint d) { return a * 7; }\n" | ||||||
|  | 	"  function c(uint b) returns(uint e) { return b * 8; }\n" | ||||||
|  | 	"}\n"; | ||||||
|  | 		 | ||||||
|  | 	char const* interface = R"([ | ||||||
|  | 	{ | ||||||
|  | 		"name": "c", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "b", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "e", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"name": "f", | ||||||
|  | 		"inputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "a", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		], | ||||||
|  | 		"outputs": [ | ||||||
|  | 		{ | ||||||
|  | 			"name": "d", | ||||||
|  | 			"type": "uint256" | ||||||
|  | 		} | ||||||
|  | 		] | ||||||
|  | 	} | ||||||
|  | 	])"; | ||||||
|  | 	 | ||||||
|  | 	BOOST_CHECK(checkInterface(sourceCode, interface)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | } | ||||||
|  | } | ||||||
| @ -121,6 +121,44 @@ BOOST_AUTO_TEST_CASE(reference_to_later_declaration) | |||||||
| 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  struct MyStructName {\n" | ||||||
|  | 					   "    address addr;\n" | ||||||
|  | 					   "    MyStructName x;\n" | ||||||
|  | 					   "  }\n" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  struct MyStructName1 {\n" | ||||||
|  | 					   "    address addr;\n" | ||||||
|  | 					   "    uint256 count;\n" | ||||||
|  | 					   "    MyStructName2 x;\n" | ||||||
|  | 					   "  }\n" | ||||||
|  | 					   "  struct MyStructName2 {\n" | ||||||
|  | 					   "    MyStructName1 x;\n" | ||||||
|  | 					   "  }\n" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  struct MyStructName1 {\n" | ||||||
|  | 					   "    address addr;\n" | ||||||
|  | 					   "    uint256 count;\n" | ||||||
|  | 					   "    mapping(uint => MyStructName1) x;\n" | ||||||
|  | 					   "  }\n" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(type_inference_smoke_test) | BOOST_AUTO_TEST_CASE(type_inference_smoke_test) | ||||||
| { | { | ||||||
| 	char const* text = "contract test {\n" | 	char const* text = "contract test {\n" | ||||||
| @ -162,6 +200,22 @@ BOOST_AUTO_TEST_CASE(type_checking_function_call) | |||||||
| 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(type_conversion_for_comparison) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  function f() { uint32(2) == int64(2); }" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  function f() { int32(2) == uint64(2); }" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) | BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) | ||||||
| { | { | ||||||
| 	char const* text = "contract test {\n" | 	char const* text = "contract test {\n" | ||||||
|  | |||||||
| @ -211,7 +211,15 @@ BOOST_AUTO_TEST_CASE(else_if_statement) | |||||||
| 	BOOST_CHECK_NO_THROW(parseText(text)); | 	BOOST_CHECK_NO_THROW(parseText(text)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion) | ||||||
|  | { | ||||||
|  | 	char const* text = "contract test {\n" | ||||||
|  | 					   "  function fun() {\n" | ||||||
|  | 					   "    uint64(2);\n" | ||||||
|  | 					   "  }\n" | ||||||
|  | 					   "}\n"; | ||||||
|  | 	BOOST_CHECK_NO_THROW(parseText(text)); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -97,6 +97,27 @@ BOOST_AUTO_TEST_CASE(hex_numbers) | |||||||
| 	BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); | 	BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(negative_numbers) | ||||||
|  | { | ||||||
|  | 	Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;")); | ||||||
|  | 	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(), "-.2"); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-0x78"); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "-7.3"); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::ADD); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::NUMBER); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.getCurrentLiteral(), "8.9"); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); | ||||||
|  | 	BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(locations) | BOOST_AUTO_TEST_CASE(locations) | ||||||
| { | { | ||||||
| 	Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); | 	Scanner scanner(CharStream("function_identifier has ; -0x743/*comment*/\n ident //comment")); | ||||||
| @ -109,11 +130,8 @@ BOOST_AUTO_TEST_CASE(locations) | |||||||
| 	BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); | 	BOOST_CHECK_EQUAL(scanner.next(), Token::SEMICOLON); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); | 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 24); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 25); | 	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.next(), Token::NUMBER); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 27); | 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 26); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); | 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().end, 32); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); | 	BOOST_CHECK_EQUAL(scanner.next(), Token::IDENTIFIER); | ||||||
| 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); | 	BOOST_CHECK_EQUAL(scanner.getCurrentLocation().start, 45); | ||||||
|  | |||||||
							
								
								
									
										717
									
								
								stPreCompiledContractsFiller.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										717
									
								
								stPreCompiledContractsFiller.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,717 @@ | |||||||
|  | { | ||||||
|  |     "CallEcrecover0": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover0_gas500": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 500 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover0_Gas499": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 499 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover0_0input": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover1": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 1) (MSTORE 64 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 96 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover2": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c) (MSTORE 32 28) (MSTORE 33 0x73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f) (MSTORE 65 0xeeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549) [[ 2 ]] (CALL 1000 1 0 0 97 97 32) [[ 0 ]] (MOD (MLOAD 97) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallEcrecover3": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code": "{ (MSTORE 0 0x2f380a2dea7e778d81affc2443403b8fe4644db442ae4862ff5bb3732829cdb9) (MSTORE 32 27) (MSTORE 64 0x6b65ccb0558806e9b097f27a396d08f964e37b8b7af6ceeb516ff86739fbea0a) (MSTORE 96 0x37cbc8d883e129a4b1ef9d5f1df53c4f21a3ef147cf2a50a4ede0eb06ce092d4) [[ 2 ]] (CALL 1000 1 0 0 128 128 32) [[ 0 ]] (MOD (MLOAD 128) (EXP 2 160)) [[ 1 ]] (EQ (ORIGIN) (SLOAD 0))  }", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_0": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "0x600160005260206000602060006000600260fff1600051600055", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_1": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ [[ 2 ]] (CALL 500 2 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_2": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_3": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 2 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_4": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_4_gas99": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 2 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallSha256_5": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 2 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "10000000", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_0": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "0x600160005260206000602060006000600360fff1600051600055", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_1": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ [[ 2 ]] (CALL 500 3 0 0 0 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_2": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 5 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_3": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xf34578907f) [[ 2 ]] (CALL 500 3 0 0 37 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_4": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 100 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_4_gas99": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 99 3 0 0 32 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "365224", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  |     "CallRipemd160_5": { | ||||||
|  |          "env" : { | ||||||
|  |              "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |              "currentNumber" : "0", | ||||||
|  |              "currentGasLimit" : "10000000", | ||||||
|  |              "currentDifficulty" : "256", | ||||||
|  |              "currentTimestamp" : 1, | ||||||
|  |              "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |          }, | ||||||
|  |          "pre" : { | ||||||
|  |              "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { | ||||||
|  |                  "balance" : "20000000", | ||||||
|  |                  "nonce" : 0, | ||||||
|  |                  "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) [[ 2 ]] (CALL 500 3 0 0 1000000 0 32) [[ 0 ]] (MLOAD 0)}", | ||||||
|  |                  "storage": {} | ||||||
|  |              }, | ||||||
|  |             "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "transaction" : { | ||||||
|  |             "nonce" : "0", | ||||||
|  |             "gasPrice" : "1", | ||||||
|  |             "gasLimit" : "10000000", | ||||||
|  |             "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", | ||||||
|  |             "value" : "100000", | ||||||
|  |             "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", | ||||||
|  |             "data" : "" | ||||||
|  |         } | ||||||
|  |      }, | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										1334
									
								
								stSystemOperationsTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1334
									
								
								stSystemOperationsTestFiller.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										191
									
								
								state.cpp
									
									
									
									
									
								
							
							
						
						
									
										191
									
								
								state.cpp
									
									
									
									
									
								
							| @ -15,81 +15,150 @@ | |||||||
| 	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | 	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | ||||||
| */ | */ | ||||||
| /** @file state.cpp
 | /** @file state.cpp
 | ||||||
|  * @author Gav Wood <i@gavwood.com> |  * @author Christoph Jentzsch <cj@ethdev.com> | ||||||
|  * @date 2014 |  * @date 2014 | ||||||
|  * State test functions. |  * State test functions. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <boost/filesystem/operations.hpp> | #include <boost/filesystem/operations.hpp> | ||||||
| #include <secp256k1/secp256k1.h> | #include <boost/test/unit_test.hpp> | ||||||
|  | #include "JsonSpiritHeaders.h" | ||||||
|  | #include <libdevcore/CommonIO.h> | ||||||
| #include <libethereum/BlockChain.h> | #include <libethereum/BlockChain.h> | ||||||
| #include <libethereum/State.h> | #include <libethereum/State.h> | ||||||
|  | #include <libethereum/ExtVM.h> | ||||||
| #include <libethereum/Defaults.h> | #include <libethereum/Defaults.h> | ||||||
|  | #include <libevm/VM.h> | ||||||
|  | #include "TestHelper.h" | ||||||
|  | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
|  | using namespace json_spirit; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| using namespace dev::eth; | using namespace dev::eth; | ||||||
|  | using namespace dev::eth; | ||||||
| 
 | 
 | ||||||
| int stateTest() | namespace dev {  namespace test { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void doStateTests(json_spirit::mValue& v, bool _fillin) | ||||||
| { | { | ||||||
| 	cnote << "Testing State..."; | 	for (auto& i: v.get_obj()) | ||||||
| 
 |  | ||||||
| 	KeyPair me = sha3("Gav Wood"); |  | ||||||
| 	KeyPair myMiner = sha3("Gav's Miner"); |  | ||||||
| //	KeyPair you = sha3("123");
 |  | ||||||
| 
 |  | ||||||
| 	Defaults::setDBPath(boost::filesystem::temp_directory_path().string()); |  | ||||||
| 
 |  | ||||||
| 	OverlayDB stateDB = State::openDB(); |  | ||||||
| 	BlockChain bc; |  | ||||||
| 	State s(myMiner.address(), stateDB); |  | ||||||
| 
 |  | ||||||
| 	cout << bc; |  | ||||||
| 
 |  | ||||||
| 	// Sync up - this won't do much until we use the last state.
 |  | ||||||
| 	s.sync(bc); |  | ||||||
| 
 |  | ||||||
| 	cout << s; |  | ||||||
| 
 |  | ||||||
| 	// Mine to get some ether!
 |  | ||||||
| 	s.commitToMine(bc); |  | ||||||
| 	while (!s.mine(100).completed) {} |  | ||||||
| 	s.completeMine(); |  | ||||||
| 	bc.attemptImport(s.blockData(), stateDB); |  | ||||||
| 
 |  | ||||||
| 	cout << bc; |  | ||||||
| 
 |  | ||||||
| 	s.sync(bc); |  | ||||||
| 
 |  | ||||||
| 	cout << s; |  | ||||||
| 
 |  | ||||||
| 	// Inject a transaction to transfer funds from miner to me.
 |  | ||||||
| 	bytes tx; |  | ||||||
| 	{ | 	{ | ||||||
| 		Transaction t; | 		cnote << i.first; | ||||||
| 		t.nonce = s.transactionsFrom(myMiner.address()); | 		mObject& o = i.second.get_obj(); | ||||||
| 		t.value = 1000;			// 1e3 wei.
 | 
 | ||||||
| 		t.type = eth::Transaction::MessageCall; | 		BOOST_REQUIRE(o.count("env") > 0); | ||||||
| 		t.receiveAddress = me.address(); | 		BOOST_REQUIRE(o.count("pre") > 0); | ||||||
| 		t.sign(myMiner.secret()); | 		BOOST_REQUIRE(o.count("transaction") > 0); | ||||||
| 		assert(t.sender() == myMiner.address()); | 
 | ||||||
| 		tx = t.rlp(); | 		ImportTest importer(o, _fillin); | ||||||
|  | 
 | ||||||
|  | 		State theState = importer.m_statePre; | ||||||
|  | 		bytes tx = importer.m_transaction.rlp(); | ||||||
|  | 		bytes output; | ||||||
|  | 
 | ||||||
|  | 		try | ||||||
|  | 		{ | ||||||
|  | 			theState.execute(tx, &output); | ||||||
| 		} | 		} | ||||||
| 	s.execute(tx); | 		catch (Exception const& _e) | ||||||
| 
 | 		{ | ||||||
| 	cout << s; | 			cnote << "state execution did throw an exception: " << diagnostic_information(_e); | ||||||
| 
 | 		} | ||||||
| 	// Mine to get some ether and set in stone.
 | 		catch (std::exception const& _e) | ||||||
| 	s.commitToMine(bc); | 		{ | ||||||
| 	while (!s.mine(100).completed) {} | 			cnote << "state execution did throw an exception: " << _e.what(); | ||||||
| 	s.completeMine(); |  | ||||||
| 	bc.attemptImport(s.blockData(), stateDB); |  | ||||||
| 
 |  | ||||||
| 	cout << bc; |  | ||||||
| 
 |  | ||||||
| 	s.sync(bc); |  | ||||||
| 
 |  | ||||||
| 	cout << s; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if (_fillin) | ||||||
|  | 			importer.exportTest(output, theState); | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			BOOST_REQUIRE(o.count("post") > 0); | ||||||
|  | 			BOOST_REQUIRE(o.count("out") > 0); | ||||||
|  | 
 | ||||||
|  | 			// check output
 | ||||||
|  | 			checkOutput(output, o); | ||||||
|  | 
 | ||||||
|  | 			// check addresses
 | ||||||
|  | 			auto expectedAddrs = importer.m_statePost.addresses(); | ||||||
|  | 			auto resultAddrs = theState.addresses(); | ||||||
|  | 			for (auto& expectedPair : expectedAddrs) | ||||||
|  | 			{ | ||||||
|  | 				auto& expectedAddr = expectedPair.first; | ||||||
|  | 				auto resultAddrIt = resultAddrs.find(expectedAddr); | ||||||
|  | 				if (resultAddrIt == resultAddrs.end()) | ||||||
|  | 					BOOST_ERROR("Missing expected address " << expectedAddr); | ||||||
|  | 				else | ||||||
|  | 				{ | ||||||
|  | 					BOOST_CHECK_MESSAGE(importer.m_statePost.balance(expectedAddr) ==  theState.balance(expectedAddr), expectedAddr << ": incorrect balance " << theState.balance(expectedAddr) << ", expected " << importer.m_statePost.balance(expectedAddr)); | ||||||
|  | 					BOOST_CHECK_MESSAGE(importer.m_statePost.transactionsFrom(expectedAddr) ==  theState.transactionsFrom(expectedAddr), expectedAddr << ": incorrect txCount " << theState.transactionsFrom(expectedAddr) << ", expected " << importer.m_statePost.transactionsFrom(expectedAddr)); | ||||||
|  | 					BOOST_CHECK_MESSAGE(importer.m_statePost.code(expectedAddr) == theState.code(expectedAddr), expectedAddr << ": incorrect code"); | ||||||
|  | 
 | ||||||
|  | 					checkStorage(importer.m_statePost.storage(expectedAddr), theState.storage(expectedAddr), expectedAddr); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			checkAddresses<map<Address, u256> >(expectedAddrs, resultAddrs); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | } }// Namespace Close
 | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(StateTests) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(stExample) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("stExample", "/StateTests", dev::test::doStateTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(stSystemOperationsTest) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("stSystemOperationsTest", "/StateTests", dev::test::doStateTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(stPreCompiledContracts) | ||||||
|  | { | ||||||
|  | 	dev::test::executeTests("stPreCompiledContracts", "/StateTests", dev::test::doStateTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(stCreateTest) | ||||||
|  | { | ||||||
|  | 	for (int i = 1; i < boost::unit_test::framework::master_test_suite().argc; ++i) | ||||||
|  | 	{ | ||||||
|  | 		string arg = boost::unit_test::framework::master_test_suite().argv[i]; | ||||||
|  | 		if (arg == "--createtest") | ||||||
|  | 		{ | ||||||
|  | 			if (boost::unit_test::framework::master_test_suite().argc <= i + 2) | ||||||
|  | 			{ | ||||||
|  | 				cnote << "usage: ./testeth --createtest <PathToConstructor> <PathToDestiny>\n"; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			try | ||||||
|  | 			{ | ||||||
|  | 				cnote << "Populating tests..."; | ||||||
|  | 				json_spirit::mValue v; | ||||||
|  | 				string s = asString(dev::contents(boost::unit_test::framework::master_test_suite().argv[i + 1])); | ||||||
|  | 				BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + (string)boost::unit_test::framework::master_test_suite().argv[i + 1] + " is empty."); | ||||||
|  | 				json_spirit::read_string(s, v); | ||||||
|  | 				dev::test::doStateTests(v, true); | ||||||
|  | 				writeFile(boost::unit_test::framework::master_test_suite().argv[i + 2], asBytes(json_spirit::write_string(v, true))); | ||||||
|  | 			} | ||||||
|  | 			catch (Exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed state test with Exception: " << diagnostic_information(_e)); | ||||||
|  | 			} | ||||||
|  | 			catch (std::exception const& _e) | ||||||
|  | 			{ | ||||||
|  | 				BOOST_ERROR("Failed state test with Exception: " << _e.what()); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(userDefinedFileState) | ||||||
|  | { | ||||||
|  | 	dev::test::userDefinedTest("--statetest", dev::test::doStateTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | |||||||
							
								
								
									
										90
									
								
								stateOriginal.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								stateOriginal.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | |||||||
|  | /*
 | ||||||
|  | 	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/>.
 | ||||||
|  | */ | ||||||
|  | /** @file stateOriginal.cpp
 | ||||||
|  |  * @author Gav Wood <i@gavwood.com> | ||||||
|  |  * @date 2014 | ||||||
|  |  * State test functions. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <boost/filesystem/operations.hpp> | ||||||
|  | #include <secp256k1/secp256k1.h> | ||||||
|  | #include <libethereum/BlockChain.h> | ||||||
|  | #include <libethereum/State.h> | ||||||
|  | #include <libethereum/Defaults.h> | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev; | ||||||
|  | using namespace dev::eth; | ||||||
|  | 
 | ||||||
|  | int stateTest() | ||||||
|  | { | ||||||
|  | 	cnote << "Testing State..."; | ||||||
|  | 
 | ||||||
|  | 	KeyPair me = sha3("Gav Wood"); | ||||||
|  | 	KeyPair myMiner = sha3("Gav's Miner"); | ||||||
|  | //	KeyPair you = sha3("123");
 | ||||||
|  | 
 | ||||||
|  | 	Defaults::setDBPath(boost::filesystem::temp_directory_path().string()); | ||||||
|  | 
 | ||||||
|  | 	OverlayDB stateDB = State::openDB(); | ||||||
|  | 	BlockChain bc; | ||||||
|  | 	State s(myMiner.address(), stateDB); | ||||||
|  | 
 | ||||||
|  | 	cout << bc; | ||||||
|  | 
 | ||||||
|  | 	// Sync up - this won't do much until we use the last state.
 | ||||||
|  | 	s.sync(bc); | ||||||
|  | 
 | ||||||
|  | 	cout << s; | ||||||
|  | 
 | ||||||
|  | 	// Mine to get some ether!
 | ||||||
|  | 	s.commitToMine(bc); | ||||||
|  | 	while (!s.mine(100).completed) {} | ||||||
|  | 	s.completeMine(); | ||||||
|  | 	bc.attemptImport(s.blockData(), stateDB); | ||||||
|  | 
 | ||||||
|  | 	cout << bc; | ||||||
|  | 
 | ||||||
|  | 	s.sync(bc); | ||||||
|  | 
 | ||||||
|  | 	cout << s; | ||||||
|  | 
 | ||||||
|  | 	// Inject a transaction to transfer funds from miner to me.
 | ||||||
|  | 	bytes tx; | ||||||
|  | 	{ | ||||||
|  | 		Transaction t(1000, 0, 0, me.address(), bytes(), s.transactionsFrom(myMiner.address()), myMiner.secret()); | ||||||
|  | 		assert(t.sender() == myMiner.address()); | ||||||
|  | 		tx = t.rlp(); | ||||||
|  | 	} | ||||||
|  | 	s.execute(tx); | ||||||
|  | 
 | ||||||
|  | 	cout << s; | ||||||
|  | 
 | ||||||
|  | 	// Mine to get some ether and set in stone.
 | ||||||
|  | 	s.commitToMine(bc); | ||||||
|  | 	while (!s.mine(100).completed) {} | ||||||
|  | 	s.completeMine(); | ||||||
|  | 	bc.attemptImport(s.blockData(), stateDB); | ||||||
|  | 
 | ||||||
|  | 	cout << bc; | ||||||
|  | 
 | ||||||
|  | 	s.sync(bc); | ||||||
|  | 
 | ||||||
|  | 	cout << s; | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										18
									
								
								trie.cpp
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								trie.cpp
									
									
									
									
									
								
							| @ -28,6 +28,7 @@ | |||||||
| #include "TrieHash.h" | #include "TrieHash.h" | ||||||
| #include "MemTrie.h" | #include "MemTrie.h" | ||||||
| #include <boost/test/unit_test.hpp> | #include <boost/test/unit_test.hpp> | ||||||
|  | #include "TestHelper.h" | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| @ -47,18 +48,14 @@ static unsigned fac(unsigned _i) | |||||||
| } | } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(TrieTests) | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(trie_tests) | BOOST_AUTO_TEST_CASE(trie_tests) | ||||||
| { | { | ||||||
| 	const char* ptestPath = getenv("ETHEREUM_TEST_PATH"); | 	string testPath = test::getTestPath(); | ||||||
| 	string testPath; |  | ||||||
| 
 | 
 | ||||||
| 	if (ptestPath == NULL) | 
 | ||||||
| 	{ | 	testPath += "/TrieTests"; | ||||||
| 		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; | ||||||
| @ -364,3 +361,6 @@ BOOST_AUTO_TEST_CASE(trieStess) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										496
									
								
								vm.cpp
									
									
									
									
									
								
							
							
						
						
									
										496
									
								
								vm.cpp
									
									
									
									
									
								
							| @ -20,11 +20,9 @@ | |||||||
|  * vm test functions. |  * vm test functions. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <boost/filesystem/path.hpp> | #include <boost/filesystem.hpp> | ||||||
| #include "vm.h" | #include "vm.h" | ||||||
| 
 | 
 | ||||||
| //#define FILL_TESTS
 |  | ||||||
| 
 |  | ||||||
| using namespace std; | using namespace std; | ||||||
| using namespace json_spirit; | using namespace json_spirit; | ||||||
| using namespace dev; | using namespace dev; | ||||||
| @ -32,140 +30,24 @@ using namespace dev::eth; | |||||||
| using namespace dev::test; | using namespace dev::test; | ||||||
| 
 | 
 | ||||||
| FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth):			/// TODO: XXX: remove the default argument & fix.
 | FakeExtVM::FakeExtVM(eth::BlockInfo const& _previousBlock, eth::BlockInfo const& _currentBlock, unsigned _depth):			/// TODO: XXX: remove the default argument & fix.
 | ||||||
| 	ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytesConstRef(), _previousBlock, _currentBlock, _depth) {} | 	ExtVMFace(Address(), Address(), Address(), 0, 1, bytesConstRef(), bytes(), _previousBlock, _currentBlock, _depth) {} | ||||||
| 
 | 
 | ||||||
| h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) | h160 FakeExtVM::create(u256 _endowment, u256* _gas, bytesConstRef _init, OnOpFunc const&) | ||||||
| { | { | ||||||
| 	Transaction t; | 	Address na = right160(sha3(rlpList(myAddress, get<1>(addresses[myAddress])))); | ||||||
| 	t.value = _endowment; |  | ||||||
| 	t.gasPrice = gasPrice; |  | ||||||
| 	t.gas = *_gas; |  | ||||||
| 	t.data = _init.toBytes(); |  | ||||||
| 
 | 
 | ||||||
| 	m_s.noteSending(myAddress); | 	Transaction t(_endowment, gasPrice, *_gas, _init.toBytes()); | ||||||
| 	m_ms.internal.resize(m_ms.internal.size() + 1); |  | ||||||
| 	auto ret = m_s.create(myAddress, _endowment, gasPrice, _gas, _init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); |  | ||||||
| 	if (!m_ms.internal.back().from) |  | ||||||
| 		m_ms.internal.pop_back(); |  | ||||||
| 
 |  | ||||||
| 	if (get<0>(addresses[myAddress]) >= _endowment) |  | ||||||
| 	{ |  | ||||||
| 		get<1>(addresses[myAddress])++; |  | ||||||
| 		get<0>(addresses[ret]) = _endowment; |  | ||||||
| 		get<3>(addresses[ret]) = m_s.code(ret); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	t.type = eth::Transaction::ContractCreation; |  | ||||||
| 	callcreates.push_back(t); | 	callcreates.push_back(t); | ||||||
| 	return ret; | 	return na; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) | bool FakeExtVM::call(Address _receiveAddress, u256 _value, bytesConstRef _data, u256* _gas, bytesRef _out, OnOpFunc const&, Address _myAddressOverride, Address _codeAddressOverride) | ||||||
| { | { | ||||||
| 	u256 contractgas = 0xffff; | 	Transaction t(_value, gasPrice, *_gas, _receiveAddress, _data.toVector()); | ||||||
| 
 |  | ||||||
| 	Transaction t; |  | ||||||
| 	t.value = _value; |  | ||||||
| 	t.gasPrice = gasPrice; |  | ||||||
| 	t.gas = *_gas; |  | ||||||
| 	t.data = _data.toVector(); |  | ||||||
| 	t.type = eth::Transaction::MessageCall; |  | ||||||
| 	t.receiveAddress = _receiveAddress; |  | ||||||
| 	callcreates.push_back(t); | 	callcreates.push_back(t); | ||||||
| 
 | 	(void)_out; | ||||||
| 	string codeOf_CodeAddress = _codeAddressOverride ? toHex(get<3>(addresses[_codeAddressOverride])) : toHex(get<3>(addresses[_receiveAddress]) ); | 	(void)_myAddressOverride; | ||||||
| 	string sizeOfCode = toHex(toCompactBigEndian((codeOf_CodeAddress.size()+1)/2)); | 	(void)_codeAddressOverride; | ||||||
| 
 |  | ||||||
| 	string codeOf_SenderAddress = toHex(get<3>(addresses[myAddress]) ); |  | ||||||
| 	string sizeOfSenderCode = toHex(toCompactBigEndian((codeOf_SenderAddress.size()+1)/2)); |  | ||||||
| 
 |  | ||||||
| 	if (codeOf_SenderAddress.size()) |  | ||||||
| 	{ |  | ||||||
| 		// create init code that returns given contract code
 |  | ||||||
| 		string initStringHex = "{ (CODECOPY 0 (- (CODESIZE) 0x" + sizeOfSenderCode + "  ) 0x" + sizeOfSenderCode + ") (RETURN 0 0x" + sizeOfSenderCode +")}"; |  | ||||||
| 		bytes initBytes = compileLLL(initStringHex, true, NULL); |  | ||||||
| 		initBytes += fromHex(codeOf_SenderAddress); |  | ||||||
| 		bytesConstRef init(&initBytes); |  | ||||||
| 
 |  | ||||||
| 		if (!m_s.addresses().count(myAddress)) |  | ||||||
| 		{ |  | ||||||
| 			m_ms.internal.resize(m_ms.internal.size() + 1); |  | ||||||
| 			auto na = m_s.createNewAddress(myAddress, myAddress, balance(myAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, {}, 1); |  | ||||||
| 			if (!m_ms.internal.back().from) |  | ||||||
| 				m_ms.internal.pop_back(); |  | ||||||
| 			if (na != myAddress) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "not able to call to : " << myAddress << "\n"; |  | ||||||
| 				cnote << "in FakeExtVM you can only make a call to " << na << "\n"; |  | ||||||
| 				BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(toString(myAddress))); |  | ||||||
| 				return false; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (codeOf_CodeAddress.size()) |  | ||||||
| 	{ |  | ||||||
| 		// create init code that returns given contract code
 |  | ||||||
| 		string initStringHex = "{ (CODECOPY 0 (- (CODESIZE) 0x" + sizeOfCode + "  ) 0x" + sizeOfCode + ") (RETURN 0 0x" + sizeOfCode +")}"; |  | ||||||
| 		bytes initBytes = compileLLL(initStringHex, true, NULL); |  | ||||||
| 		initBytes += fromHex(codeOf_CodeAddress); |  | ||||||
| 		bytesConstRef init(&initBytes); |  | ||||||
| 
 |  | ||||||
| 		if (!m_s.addresses().count(_codeAddressOverride ? _codeAddressOverride : _receiveAddress)) |  | ||||||
| 		{ |  | ||||||
| 			m_s.noteSending(myAddress); |  | ||||||
| 			m_ms.internal.resize(m_ms.internal.size() + 1); |  | ||||||
| 			auto na = m_s.createNewAddress(_codeAddressOverride ? _codeAddressOverride : _receiveAddress, myAddress, balance(_codeAddressOverride ? _codeAddressOverride : _receiveAddress), gasPrice, &contractgas, init, origin, &sub, &m_ms ? &(m_ms.internal.back()) : nullptr, OnOpFunc(), 1); |  | ||||||
| 			if (!m_ms.internal.back().from) |  | ||||||
| 				m_ms.internal.pop_back(); |  | ||||||
| 
 |  | ||||||
| 			if (na != (_codeAddressOverride ? _codeAddressOverride : _receiveAddress)) |  | ||||||
| 			{ |  | ||||||
| 				cnote << "not able to call to : " << (_codeAddressOverride ? _codeAddressOverride : _receiveAddress) << "\n"; |  | ||||||
| 				cnote << "in FakeExtVM you can only make a call to " << na << "\n"; |  | ||||||
| 				BOOST_THROW_EXCEPTION(FakeExtVMFailure() << errinfo_comment("Address not callable in FakeExtVM\n") << errinfo_wrongAddress(toString(_codeAddressOverride ? _codeAddressOverride : _receiveAddress))); |  | ||||||
| 				return false; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		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, &sub, &(m_ms.internal.back()), Executive::simpleTrace(), 1); |  | ||||||
| 
 |  | ||||||
| 		if (!m_ms.internal.back().from) |  | ||||||
| 			m_ms.internal.pop_back(); |  | ||||||
| 
 |  | ||||||
| 		// get correct balances, (also for sucicides in the call function)
 |  | ||||||
| 		for (auto const& f: addresses) |  | ||||||
| 		{ |  | ||||||
| 			if (m_s.addressInUse(f.first)) |  | ||||||
| 				get<0>(addresses[f.first]) = m_s.balance(f.first); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (!ret) |  | ||||||
| 			return false; |  | ||||||
| 
 |  | ||||||
| 		// TODO: @CJentzsch refund SSTORE stuff.
 |  | ||||||
| 		// TODO: @CJentzsch test logs.
 |  | ||||||
| 
 |  | ||||||
| 		// do suicides
 |  | ||||||
| 		for (auto const& f: sub.suicides) |  | ||||||
| 			addresses.erase(f); |  | ||||||
| 
 |  | ||||||
| 		// get storage
 |  | ||||||
| 		if ((get<0>(addresses[myAddress]) >= _value) && (sub.suicides.find(_receiveAddress) == sub.suicides.end())) |  | ||||||
| 		{ |  | ||||||
| 			for (auto const& j: m_s.storage(_receiveAddress)) |  | ||||||
| 			{ |  | ||||||
| 				u256 adr(j.first); |  | ||||||
| 				if ((j.second != 0) ) |  | ||||||
| 					get<2>(addresses[_receiveAddress])[adr] = j.second; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 		addresses.erase(_receiveAddress); // for the sake of comparison
 |  | ||||||
| 
 |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -198,45 +80,13 @@ void FakeExtVM::reset(u256 _myBalance, u256 _myNonce, map<u256, u256> const& _st | |||||||
| 	set(myAddress, _myBalance, _myNonce, _storage, get<3>(addresses[myAddress])); | 	set(myAddress, _myBalance, _myNonce, _storage, get<3>(addresses[myAddress])); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u256 FakeExtVM::toInt(mValue const& _v) |  | ||||||
| { |  | ||||||
| 	switch (_v.type()) |  | ||||||
| 	{ |  | ||||||
| 	case str_type: return u256(_v.get_str()); |  | ||||||
| 	case int_type: return (u256)_v.get_uint64(); |  | ||||||
| 	case bool_type: return (u256)(uint64_t)_v.get_bool(); |  | ||||||
| 	case real_type: return (u256)(uint64_t)_v.get_real(); |  | ||||||
| 	default: cwarn << "Bad type for scalar: " << _v.type(); |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| byte FakeExtVM::toByte(mValue const& _v) |  | ||||||
| { |  | ||||||
| 	switch (_v.type()) |  | ||||||
| 	{ |  | ||||||
| 	case str_type: return (byte)stoi(_v.get_str()); |  | ||||||
| 	case int_type: return (byte)_v.get_uint64(); |  | ||||||
| 	case bool_type: return (byte)_v.get_bool(); |  | ||||||
| 	case real_type: return (byte)_v.get_real(); |  | ||||||
| 	default: cwarn << "Bad type for scalar: " << _v.type(); |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void FakeExtVM::push(mObject& o, string const& _n, u256 _v) | void FakeExtVM::push(mObject& o, string const& _n, u256 _v) | ||||||
| { | { | ||||||
| 	//		if (_v < (u256)1 << 64)
 |  | ||||||
| 	//			o[_n] = (uint64_t)_v;
 |  | ||||||
| 	//		else
 |  | ||||||
| 	o[_n] = toString(_v); | 	o[_n] = toString(_v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FakeExtVM::push(mArray& a, u256 _v) | void FakeExtVM::push(mArray& a, u256 _v) | ||||||
| { | { | ||||||
| 	//		if (_v < (u256)1 << 64)
 |  | ||||||
| 	//			a.push_back((uint64_t)_v);
 |  | ||||||
| 	//		else
 |  | ||||||
| 	a.push_back(toString(_v)); | 	a.push_back(toString(_v)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -309,17 +159,7 @@ void FakeExtVM::importState(mObject& _object) | |||||||
| 		for (auto const& j: o["storage"].get_obj()) | 		for (auto const& j: o["storage"].get_obj()) | ||||||
| 			get<2>(a)[toInt(j.first)] = toInt(j.second); | 			get<2>(a)[toInt(j.first)] = toInt(j.second); | ||||||
| 
 | 
 | ||||||
| 		if (o["code"].type() == str_type) | 		get<3>(a) = importCode(o); | ||||||
| 			if (o["code"].get_str().find_first_of("0x") != 0) |  | ||||||
| 				get<3>(a) = compileLLL(o["code"].get_str(), false); |  | ||||||
| 			else |  | ||||||
| 				get<3>(a) = fromHex(o["code"].get_str().substr(2)); |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			get<3>(a).clear(); |  | ||||||
| 			for (auto const& j: o["code"].get_array()) |  | ||||||
| 				get<3>(a).push_back(toByte(j)); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -356,27 +196,15 @@ void FakeExtVM::importExec(mObject& _o) | |||||||
| 	gas = toInt(_o["gas"]); | 	gas = toInt(_o["gas"]); | ||||||
| 
 | 
 | ||||||
| 	thisTxCode.clear(); | 	thisTxCode.clear(); | ||||||
| 	code = &thisTxCode; | 	code = thisTxCode; | ||||||
| 	if (_o["code"].type() == str_type) | 
 | ||||||
| 		if (_o["code"].get_str().find_first_of("0x") == 0) | 	thisTxCode = importCode(_o); | ||||||
| 			thisTxCode = fromHex(_o["code"].get_str().substr(2)); | 	if (_o["code"].type() != str_type && _o["code"].type() != array_type) | ||||||
| 		else | 		code.clear(); | ||||||
| 			thisTxCode = compileLLL(_o["code"].get_str()); |  | ||||||
| 	else if (_o["code"].type() == array_type) |  | ||||||
| 		for (auto const& j: _o["code"].get_array()) |  | ||||||
| 			thisTxCode.push_back(toByte(j)); |  | ||||||
| 	else |  | ||||||
| 		code.reset(); |  | ||||||
| 
 | 
 | ||||||
| 	thisTxData.clear(); | 	thisTxData.clear(); | ||||||
| 	if (_o["data"].type() == str_type) | 	thisTxData = importData(_o); | ||||||
| 		if (_o["data"].get_str().find_first_of("0x") == 0) | 
 | ||||||
| 			thisTxData = fromHex(_o["data"].get_str().substr(2)); |  | ||||||
| 		else |  | ||||||
| 			thisTxData = fromHex(_o["data"].get_str()); |  | ||||||
| 	else |  | ||||||
| 		for (auto const& j: _o["data"].get_array()) |  | ||||||
| 			thisTxData.push_back(toByte(j)); |  | ||||||
| 	data = &thisTxData; | 	data = &thisTxData; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -386,10 +214,10 @@ mArray FakeExtVM::exportCallCreates() | |||||||
| 	for (Transaction const& tx: callcreates) | 	for (Transaction const& tx: callcreates) | ||||||
| 	{ | 	{ | ||||||
| 		mObject o; | 		mObject o; | ||||||
| 		o["destination"] = tx.type == Transaction::ContractCreation ? "" : toString(tx.receiveAddress); | 		o["destination"] = tx.isCreation() ? "" : 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()); | ||||||
| 		ret.push_back(o); | 		ret.push_back(o); | ||||||
| 	} | 	} | ||||||
| 	return ret; | 	return ret; | ||||||
| @ -404,19 +232,9 @@ void FakeExtVM::importCallCreates(mArray& _callcreates) | |||||||
| 		BOOST_REQUIRE(tx.count("value") > 0); | 		BOOST_REQUIRE(tx.count("value") > 0); | ||||||
| 		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 = tx["destination"].get_str().empty() ? | ||||||
| 		t.type = tx["destination"].get_str().empty() ? Transaction::ContractCreation : Transaction::MessageCall; | 			Transaction(toInt(tx["value"]), 0, toInt(tx["gasLimit"]), data.toBytes()) : | ||||||
| 		t.receiveAddress = Address(tx["destination"].get_str()); | 			Transaction(toInt(tx["value"]), 0, toInt(tx["gasLimit"]), Address(tx["destination"].get_str()), data.toBytes()); | ||||||
| 		t.value = toInt(tx["value"]); |  | ||||||
| 		t.gas = toInt(tx["gasLimit"]); |  | ||||||
| 		if (tx["data"].type() == str_type) |  | ||||||
| 			if (tx["data"].get_str().find_first_of("0x") == 0) |  | ||||||
| 				t.data = fromHex(tx["data"].get_str().substr(2)); |  | ||||||
| 			else |  | ||||||
| 				t.data = fromHex(tx["data"].get_str()); |  | ||||||
| 		else |  | ||||||
| 			for (auto const& j: tx["data"].get_array()) |  | ||||||
| 				t.data.push_back(toByte(j)); |  | ||||||
| 		callcreates.push_back(t); | 		callcreates.push_back(t); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -435,9 +253,6 @@ eth::OnOpFunc FakeExtVM::simpleTrace() | |||||||
| 		o << "    MEMORY" << std::endl << memDump(vm.memory()); | 		o << "    MEMORY" << std::endl << memDump(vm.memory()); | ||||||
| 		o << "    STORAGE" << std::endl; | 		o << "    STORAGE" << std::endl; | ||||||
| 
 | 
 | ||||||
| 		for (auto const& i: ext.state().storage(ext.myAddress)) |  | ||||||
| 			o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; |  | ||||||
| 
 |  | ||||||
| 		for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)) | 		for (auto const& i: std::get<2>(ext.addresses.find(ext.myAddress)->second)) | ||||||
| 			o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; | 			o << std::showbase << std::hex << i.first << ": " << i.second << std::endl; | ||||||
| 
 | 
 | ||||||
| @ -454,74 +269,9 @@ eth::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) |  | ||||||
| { |  | ||||||
| 	(void)o_sub; |  | ||||||
| 
 |  | ||||||
| 	if (!_origin) |  | ||||||
| 		_origin = _sender; |  | ||||||
| 
 |  | ||||||
| 	if (o_ms) |  | ||||||
| 	{ |  | ||||||
| 		o_ms->from = _sender; |  | ||||||
| 		o_ms->to = Address(); |  | ||||||
| 		o_ms->value = _endowment; |  | ||||||
| 		o_ms->input = _code.toBytes(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Set up new account...
 |  | ||||||
| 	m_cache[_newAddress] = Account(0, balance(_newAddress) + _endowment, h256(), h256()); |  | ||||||
| 
 |  | ||||||
| 	// Execute init code.
 |  | ||||||
| 	VM vm(*_gas); |  | ||||||
| 	ExtVM evm(*this, _newAddress, _sender, _origin, _endowment, _gasPrice, bytesConstRef(), _code, o_ms, _level); |  | ||||||
| 	bool revert = false; |  | ||||||
| 	bytesConstRef out; |  | ||||||
| 
 |  | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		out = vm.go(evm, _onOp); |  | ||||||
| 		if (o_ms) |  | ||||||
| 			o_ms->output = out.toBytes(); |  | ||||||
| 		// TODO: deal with evm.sub
 |  | ||||||
| 	} |  | ||||||
| 	catch (OutOfGas const& /*_e*/) |  | ||||||
| 	{ |  | ||||||
| 		clog(StateChat) << "Out of Gas! Reverting."; |  | ||||||
| 		revert = true; |  | ||||||
| 	} |  | ||||||
| 	catch (VMException const& _e) |  | ||||||
| 	{ |  | ||||||
| 		clog(StateChat) << "VM Exception: " << diagnostic_information(_e); |  | ||||||
| 	} |  | ||||||
| 	catch (Exception const& _e) |  | ||||||
| 	{ |  | ||||||
| 		clog(StateChat) << "Exception in VM: " << diagnostic_information(_e); |  | ||||||
| 	} |  | ||||||
| 	catch (std::exception const& _e) |  | ||||||
| 	{ |  | ||||||
| 		clog(StateChat) << "std::exception in VM: " << _e.what(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// TODO: CHECK: IS THIS CORRECT?! (esp. given account created prior to revertion init.)
 |  | ||||||
| 
 |  | ||||||
| 	// Write state out only in the case of a non-out-of-gas transaction.
 |  | ||||||
| 	if (revert) |  | ||||||
| 		evm.revert(); |  | ||||||
| 
 |  | ||||||
| 	// Set code.
 |  | ||||||
| 	if (addressInUse(_newAddress)) |  | ||||||
| 		m_cache[_newAddress].setCode(out); |  | ||||||
| 
 |  | ||||||
| 	*_gas = vm.gas(); |  | ||||||
| 
 |  | ||||||
| 	return _newAddress; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| namespace dev { namespace test { | namespace dev { namespace test { | ||||||
| 
 | 
 | ||||||
| void doTests(json_spirit::mValue& v, bool _fillin) | void doVMTests(json_spirit::mValue& v, bool _fillin) | ||||||
| { | { | ||||||
| 	for (auto& i: v.get_obj()) | 	for (auto& i: v.get_obj()) | ||||||
| 	{ | 	{ | ||||||
| @ -540,27 +290,35 @@ void doTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 			o["pre"] = mValue(fev.exportState()); | 			o["pre"] = mValue(fev.exportState()); | ||||||
| 
 | 
 | ||||||
| 		fev.importExec(o["exec"].get_obj()); | 		fev.importExec(o["exec"].get_obj()); | ||||||
| 		if (!fev.code) | 		if (fev.code.empty()) | ||||||
| 		{ | 		{ | ||||||
| 			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); | 			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress)); | ||||||
| 			fev.code = &fev.thisTxCode; | 			fev.code = fev.thisTxCode; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		bytes output; | 		bytes output; | ||||||
| 		VM vm(fev.gas); | 		VM vm(fev.gas); | ||||||
|  | 
 | ||||||
|  | 		u256 gas; | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			output = vm.go(fev, fev.simpleTrace()).toVector(); | 			output = vm.go(fev, fev.simpleTrace()).toVector(); | ||||||
|  | 			gas = vm.gas(); | ||||||
|  | 		} | ||||||
|  | 		catch (VMException const& _e) | ||||||
|  | 		{ | ||||||
|  | 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | ||||||
|  | 			gas = 0; | ||||||
| 		} | 		} | ||||||
| 		catch (Exception const& _e) | 		catch (Exception const& _e) | ||||||
| 		{ | 		{ | ||||||
| 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | 			cnote << "VM did throw an exception: " << diagnostic_information(_e); | ||||||
| 			//BOOST_ERROR("Failed VM Test with Exception: " << e.what());
 | 			BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); | ||||||
| 		} | 		} | ||||||
| 		catch (std::exception const& _e) | 		catch (std::exception const& _e) | ||||||
| 		{ | 		{ | ||||||
| 			cnote << "VM did throw an exception: " << _e.what(); | 			cnote << "VM did throw an exception: " << _e.what(); | ||||||
| 			//BOOST_ERROR("Failed VM Test with Exception: " << e.what());
 | 			BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// delete null entries in storage for the sake of comparison
 | 		// delete null entries in storage for the sake of comparison
 | ||||||
| @ -587,7 +345,7 @@ void doTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 			o["post"] = mValue(fev.exportState()); | 			o["post"] = mValue(fev.exportState()); | ||||||
| 			o["callcreates"] = fev.exportCallCreates(); | 			o["callcreates"] = fev.exportCallCreates(); | ||||||
| 			o["out"] = "0x" + toHex(output); | 			o["out"] = "0x" + toHex(output); | ||||||
| 			fev.push(o, "gas", vm.gas()); | 			fev.push(o, "gas", gas); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| @ -599,19 +357,10 @@ void doTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 			dev::test::FakeExtVM test; | 			dev::test::FakeExtVM test; | ||||||
| 			test.importState(o["post"].get_obj()); | 			test.importState(o["post"].get_obj()); | ||||||
| 			test.importCallCreates(o["callcreates"].get_array()); | 			test.importCallCreates(o["callcreates"].get_array()); | ||||||
| 			int i = 0; |  | ||||||
| 			if (o["out"].type() == array_type) |  | ||||||
| 				for (auto const& d: o["out"].get_array()) |  | ||||||
| 				{ |  | ||||||
| 					BOOST_CHECK_MESSAGE(output[i] == test.toInt(d), "Output byte [" << i << "] different!"); |  | ||||||
| 					++i; |  | ||||||
| 				} |  | ||||||
| 			else if (o["out"].get_str().find("0x") == 0) |  | ||||||
| 				BOOST_CHECK(output == fromHex(o["out"].get_str().substr(2))); |  | ||||||
| 			else |  | ||||||
| 				BOOST_CHECK(output == fromHex(o["out"].get_str())); |  | ||||||
| 
 | 
 | ||||||
| 			BOOST_CHECK_EQUAL(test.toInt(o["gas"]), vm.gas()); | 			checkOutput(output, o); | ||||||
|  | 
 | ||||||
|  | 			BOOST_CHECK_EQUAL(toInt(o["gas"]), gas); | ||||||
| 
 | 
 | ||||||
| 			auto& expectedAddrs = test.addresses; | 			auto& expectedAddrs = test.addresses; | ||||||
| 			auto& resultAddrs = fev.addresses; | 			auto& resultAddrs = fev.addresses; | ||||||
| @ -629,189 +378,96 @@ void doTests(json_spirit::mValue& v, bool _fillin) | |||||||
| 					BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); | 					BOOST_CHECK_MESSAGE(std::get<1>(expectedState) == std::get<1>(resultState), expectedAddr << ": incorrect txCount " << std::get<1>(resultState) << ", expected " << std::get<1>(expectedState)); | ||||||
| 					BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); | 					BOOST_CHECK_MESSAGE(std::get<3>(expectedState) == std::get<3>(resultState), expectedAddr << ": incorrect code"); | ||||||
| 
 | 
 | ||||||
| 					auto&& expectedStore = std::get<2>(expectedState); | 					checkStorage(std::get<2>(expectedState), std::get<2>(resultState), expectedAddr); | ||||||
| 					auto&& resultStore = std::get<2>(resultState); |  | ||||||
| 
 |  | ||||||
| 					for (auto&& expectedStorePair : expectedStore) |  | ||||||
| 					{ |  | ||||||
| 						auto& expectedStoreKey = expectedStorePair.first; |  | ||||||
| 						auto resultStoreIt = resultStore.find(expectedStoreKey); |  | ||||||
| 						if (resultStoreIt == resultStore.end()) |  | ||||||
| 							BOOST_ERROR(expectedAddr << ": missing store key " << expectedStoreKey); |  | ||||||
| 						else |  | ||||||
| 						{ |  | ||||||
| 							auto& expectedStoreValue = expectedStorePair.second; |  | ||||||
| 							auto& resultStoreValue = resultStoreIt->second; |  | ||||||
| 							BOOST_CHECK_MESSAGE(expectedStoreValue == resultStoreValue, expectedAddr << ": store[" << expectedStoreKey << "] = " << resultStoreValue << ", expected " << expectedStoreValue); |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			BOOST_CHECK(test.addresses == fev.addresses);	// Just to make sure nothing missed
 | 			checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses); | ||||||
| 			BOOST_CHECK(test.callcreates == fev.callcreates); | 			BOOST_CHECK(test.callcreates == fev.callcreates); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*string makeTestCase()
 |  | ||||||
| { |  | ||||||
| 	json_spirit::mObject o; |  | ||||||
| 
 |  | ||||||
| 	VM vm; |  | ||||||
| 	BlockInfo pb; |  | ||||||
| 	pb.hash = sha3("previousHash"); |  | ||||||
| 	pb.nonce = sha3("previousNonce"); |  | ||||||
| 	BlockInfo cb = pb; |  | ||||||
| 	cb.difficulty = 256; |  | ||||||
| 	cb.timestamp = 1; |  | ||||||
| 	cb.coinbaseAddress = toAddress(sha3("coinbase")); |  | ||||||
| 	FakeExtVM fev(pb, cb, 0); |  | ||||||
| 	bytes init; |  | ||||||
| 	fev.setContract(toAddress(sha3("contract")), ether, 0, compileLisp("(suicide (txsender))", false, init), map<u256, u256>()); |  | ||||||
| 	o["env"] = fev.exportEnv(); |  | ||||||
| 	o["pre"] = fev.exportState(); |  | ||||||
| 	fev.setTransaction(toAddress(sha3("sender")), ether, finney, bytes()); |  | ||||||
| 	mArray execs; |  | ||||||
| 	execs.push_back(fev.exportExec()); |  | ||||||
| 	o["exec"] = execs; |  | ||||||
| 	vm.go(fev); |  | ||||||
| 	o["post"] = fev.exportState(); |  | ||||||
| 	o["txs"] = fev.exportTxs(); |  | ||||||
| 
 |  | ||||||
| 	return json_spirit::write_string(json_spirit::mValue(o), true); |  | ||||||
| }*/ |  | ||||||
| 
 |  | ||||||
| void executeTests(const string& _name) |  | ||||||
| { |  | ||||||
| 	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; |  | ||||||
| 
 |  | ||||||
| 	testPath += "/vmtests"; |  | ||||||
| 
 |  | ||||||
| #ifdef FILL_TESTS |  | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		cnote << "Populating VM tests..."; |  | ||||||
| 		json_spirit::mValue v; |  | ||||||
| 		boost::filesystem::path p(__FILE__); |  | ||||||
| 		boost::filesystem::path dir = p.parent_path(); |  | ||||||
| 		string s = asString(contents(dir.string() + "/" + _name + "Filler.json")); |  | ||||||
| 		BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + _name + "Filler.json is empty."); |  | ||||||
| 		json_spirit::read_string(s, v); |  | ||||||
| 		dev::test::doTests(v, true); |  | ||||||
| 		writeFile(testPath + "/" + _name + ".json", asBytes(json_spirit::write_string(v, true))); |  | ||||||
| 	} |  | ||||||
| 	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()); |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	try |  | ||||||
| 	{ |  | ||||||
| 		cnote << "Testing VM..." << _name; |  | ||||||
| 		json_spirit::mValue v; |  | ||||||
| 		string s = asString(contents(testPath + "/" + _name + ".json")); |  | ||||||
| 		BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + testPath + "/" + _name + ".json is empty. Have you cloned the 'tests' repo branch develop and set ETHEREUM_TEST_PATH to its path?"); |  | ||||||
| 		json_spirit::read_string(s, v); |  | ||||||
| 		dev::test::doTests(v, false); |  | ||||||
| 	} |  | ||||||
| 	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()); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } } // Namespace Close
 | } } // Namespace Close
 | ||||||
| 
 | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(VMTests) | ||||||
|  | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vm_tests) | BOOST_AUTO_TEST_CASE(vm_tests) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmtests"); | 	dev::test::executeTests("vmtests", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmArithmeticTest) | BOOST_AUTO_TEST_CASE(vmArithmeticTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmArithmeticTest"); | 	dev::test::executeTests("vmArithmeticTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmBitwiseLogicOperationTest) | BOOST_AUTO_TEST_CASE(vmBitwiseLogicOperationTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmBitwiseLogicOperationTest"); | 	dev::test::executeTests("vmBitwiseLogicOperationTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmSha3Test) | BOOST_AUTO_TEST_CASE(vmSha3Test) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmSha3Test"); | 	dev::test::executeTests("vmSha3Test", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmEnvironmentalInfoTest) | BOOST_AUTO_TEST_CASE(vmEnvironmentalInfoTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmEnvironmentalInfoTest"); | 	dev::test::executeTests("vmEnvironmentalInfoTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmBlockInfoTest) | BOOST_AUTO_TEST_CASE(vmBlockInfoTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmBlockInfoTest"); | 	dev::test::executeTests("vmBlockInfoTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmIOandFlowOperationsTest) | BOOST_AUTO_TEST_CASE(vmIOandFlowOperationsTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmIOandFlowOperationsTest"); | 	dev::test::executeTests("vmIOandFlowOperationsTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmPushDupSwapTest) | BOOST_AUTO_TEST_CASE(vmPushDupSwapTest) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmPushDupSwapTest"); | 	dev::test::executeTests("vmPushDupSwapTest", "/VMTests", dev::test::doVMTests); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(vmSystemOperationsTest) | BOOST_AUTO_TEST_CASE(vmRandom) | ||||||
| { | { | ||||||
| 	dev::test::executeTests("vmSystemOperationsTest"); | 	string testPath = getTestPath(); | ||||||
| } | 	testPath += "/VMTests/RandomTests"; | ||||||
| 
 | 
 | ||||||
| BOOST_AUTO_TEST_CASE(userDefinedFile) | 	vector<boost::filesystem::path> testFiles; | ||||||
| { | 	boost::filesystem::directory_iterator iterator(testPath); | ||||||
|  | 	for(; iterator != boost::filesystem::directory_iterator(); ++iterator) | ||||||
|  | 		if (boost::filesystem::is_regular_file(iterator->path()) && iterator->path().extension() == ".json") | ||||||
|  | 			testFiles.push_back(iterator->path()); | ||||||
| 
 | 
 | ||||||
| 	if (boost::unit_test::framework::master_test_suite().argc == 2) | 	for (auto& path: testFiles) | ||||||
| 	{ | 	{ | ||||||
| 		string filename = boost::unit_test::framework::master_test_suite().argv[1]; |  | ||||||
| 		int currentVerbosity = g_logVerbosity; |  | ||||||
| 		g_logVerbosity = 12; |  | ||||||
| 		try | 		try | ||||||
| 		{ | 		{ | ||||||
| 			cnote << "Testing VM..." << "user defined test"; | 			cnote << "Testing ..." << path.filename(); | ||||||
| 			json_spirit::mValue v; | 			json_spirit::mValue v; | ||||||
| 			string s = asString(contents(filename)); | 			string s = asString(dev::contents(path.string())); | ||||||
| 			BOOST_REQUIRE_MESSAGE(s.length() > 0, "Contents of " + filename + " is empty. "); | 			BOOST_REQUIRE_MESSAGE(s.length() > 0, "Content of " + path.string() + " 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); | 			doVMTests(v, false); | ||||||
| 		} | 		} | ||||||
| 		catch (Exception const& _e) | 		catch (Exception const& _e) | ||||||
| 		{ | 		{ | ||||||
| 			BOOST_ERROR("Failed VM Test with Exception: " << diagnostic_information(_e)); | 			BOOST_ERROR("Failed test with Exception: " << diagnostic_information(_e)); | ||||||
| 		} | 		} | ||||||
| 		catch (std::exception const& _e) | 		catch (std::exception const& _e) | ||||||
| 		{ | 		{ | ||||||
| 			BOOST_ERROR("Failed VM Test with Exception: " << _e.what()); | 			BOOST_ERROR("Failed test with Exception: " << _e.what()); | ||||||
| 		} |  | ||||||
| 		g_logVerbosity = currentVerbosity; |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(userDefinedFileVM) | ||||||
|  | { | ||||||
|  | 	dev::test::userDefinedTest("--vmtest", dev::test::doVMTests); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								vm.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								vm.h
									
									
									
									
									
								
							| @ -29,25 +29,19 @@ along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| #include "JsonSpiritHeaders.h" | #include "JsonSpiritHeaders.h" | ||||||
| #include <libdevcore/Log.h> | #include <libdevcore/Log.h> | ||||||
| #include <libdevcore/CommonIO.h> | #include <libdevcore/CommonIO.h> | ||||||
| #include <libevmface/Instruction.h> | #include <libevmcore/Instruction.h> | ||||||
| #include <libevm/ExtVMFace.h> | #include <libevm/ExtVMFace.h> | ||||||
| #include <libevm/VM.h> | #include <libevm/VM.h> | ||||||
| #include <liblll/Compiler.h> | #include <liblll/Compiler.h> | ||||||
| #include <libethereum/Transaction.h> | #include <libethereum/Transaction.h> | ||||||
| #include <libethereum/ExtVM.h> | #include <libethereum/ExtVM.h> | ||||||
| #include <libethereum/State.h> | #include <libethereum/State.h> | ||||||
|  | #include "TestHelper.h" | ||||||
| 
 | 
 | ||||||
| namespace dev { namespace test { | namespace dev { namespace test { | ||||||
| 
 | 
 | ||||||
| struct FakeExtVMFailure : virtual Exception {}; | struct FakeExtVMFailure : virtual Exception {}; | ||||||
| 
 | 
 | ||||||
| class FakeState: public eth::State |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	/// Execute a contract-creation transaction.
 |  | ||||||
| 	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: | ||||||
| @ -67,8 +61,6 @@ public: | |||||||
| 	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); | ||||||
| 	void reset(u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage); | 	void reset(u256 _myBalance, u256 _myNonce, std::map<u256, u256> const& _storage); | ||||||
| 	u256 toInt(json_spirit::mValue const& _v); |  | ||||||
| 	byte toByte(json_spirit::mValue const& _v); |  | ||||||
| 	void push(json_spirit::mObject& o, std::string const& _n, u256 _v); | 	void push(json_spirit::mObject& o, std::string const& _n, u256 _v); | ||||||
| 	void push(json_spirit::mArray& a, u256 _v); | 	void push(json_spirit::mArray& a, u256 _v); | ||||||
| 	u256 doPosts(); | 	u256 doPosts(); | ||||||
| @ -82,7 +74,6 @@ public: | |||||||
| 	void importCallCreates(json_spirit::mArray& _callcreates); | 	void importCallCreates(json_spirit::mArray& _callcreates); | ||||||
| 
 | 
 | ||||||
| 	eth::OnOpFunc simpleTrace(); | 	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,7 +82,6 @@ public: | |||||||
| 	u256 gas; | 	u256 gas; | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	FakeState m_s; |  | ||||||
| 	eth::Manifest m_ms; | 	eth::Manifest m_ms; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -12,7 +12,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x6002600360045057", |             "code" : "0x6002600360045055", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -40,7 +40,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x5060026003600457", |             "code" : "0x5060026003600455", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -68,7 +68,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x600260035157", |             "code" : "0x600260035155", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -96,7 +96,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x600260035257", |             "code" : "0x600260035255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -488,7 +488,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x6023600058", |             "code" : "0x600056", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -516,7 +516,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x60236007586001600257", |             "code" : "0x60236007566001600255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -543,7 +543,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x602360085860015d600257", |             "code" : "0x602360075660015b600255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -571,7 +571,91 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x602360075860015d600257", |             "code" : "0x602360085660015b600255", | ||||||
|  |             "storage": {} | ||||||
|  |         } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "jump0_jumpdest2": { | ||||||
|  |         "env" : { | ||||||
|  |         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |         "currentNumber" : "0", | ||||||
|  |         "currentGasLimit" : "1000000", | ||||||
|  |         "currentDifficulty" : "256", | ||||||
|  |         "currentTimestamp" : 1, | ||||||
|  |         "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |             "balance" : "1000000000000000000", | ||||||
|  |             "nonce" : 0, | ||||||
|  |             "code" : "0x6023600a6008505660015b600255", | ||||||
|  |             "storage": {} | ||||||
|  |         } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "jump0_jumpdest3": { | ||||||
|  |         "env" : { | ||||||
|  |         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |         "currentNumber" : "0", | ||||||
|  |         "currentGasLimit" : "1000000", | ||||||
|  |         "currentDifficulty" : "256", | ||||||
|  |         "currentTimestamp" : 1, | ||||||
|  |         "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |             "balance" : "1000000000000000000", | ||||||
|  |             "nonce" : 0, | ||||||
|  |             "code" : "0x6023600b6008505660015b600255", | ||||||
|  |             "storage": {} | ||||||
|  |         } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "jump1": { | ||||||
|  |         "env" : { | ||||||
|  |         "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |         "currentNumber" : "0", | ||||||
|  |         "currentGasLimit" : "1000000", | ||||||
|  |         "currentDifficulty" : "256", | ||||||
|  |         "currentTimestamp" : 1, | ||||||
|  |         "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |             "balance" : "1000000000000000000", | ||||||
|  |             "nonce" : 0, | ||||||
|  |             "code" : "0x620fffff620fffff0156", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -599,7 +683,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x602360016009596001600257", |             "code" : "0x602360016009576001600255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -627,7 +711,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x60236001600a5960015d600257", |             "code" : "0x60236001600a5760015b600255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -655,7 +739,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x602360006009596001600257", |             "code" : "0x602360006009576001600255", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
| @ -683,7 +767,7 @@ | |||||||
|         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |         "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|             "balance" : "1000000000000000000", |             "balance" : "1000000000000000000", | ||||||
|             "nonce" : 0, |             "nonce" : 0, | ||||||
|             "code" : "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff596002600357", |             "code" : "0x60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff576002600355", | ||||||
|             "storage": {} |             "storage": {} | ||||||
|         } |         } | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -12,7 +12,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60ff600357", |                 "code" : "0x60ff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -68,7 +68,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x61eeff600357", |                 "code" : "0x61eeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -96,7 +96,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x62ddeeff600357", |                 "code" : "0x62ddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -124,7 +124,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x63ccddeeff600357", |                 "code" : "0x63ccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -152,7 +152,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x64bbccddeeff600357", |                 "code" : "0x64bbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -180,7 +180,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x65aabbccddeeff600357", |                 "code" : "0x65aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -208,7 +208,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6699aabbccddeeff600357", |                 "code" : "0x6699aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -236,7 +236,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x678899aabbccddeeff600357", |                 "code" : "0x678899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -264,7 +264,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x68778899aabbccddeeff600357", |                 "code" : "0x68778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -292,7 +292,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6966778899aabbccddeeff600357", |                 "code" : "0x6966778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -320,7 +320,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6a5566778899aabbccddeeff600357", |                 "code" : "0x6a5566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -348,7 +348,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6b445566778899aabbccddeeff600357", |                 "code" : "0x6b445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -376,7 +376,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6c33445566778899aabbccddeeff600357", |                 "code" : "0x6c33445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -404,7 +404,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6d2233445566778899aabbccddeeff600357", |                 "code" : "0x6d2233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -432,7 +432,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6e112233445566778899aabbccddeeff600357", |                 "code" : "0x6e112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -460,7 +460,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6f10112233445566778899aabbccddeeff600357", |                 "code" : "0x6f10112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -488,7 +488,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x70ff00112233445566778899aabbccddeeff600357", |                 "code" : "0x70ff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -516,7 +516,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x71eeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x71eeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -544,7 +544,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x72ddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x72ddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -572,7 +572,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x73ccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x73ccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -600,7 +600,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x74bbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x74bbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -628,7 +628,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x75aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x75aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -656,7 +656,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7699aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7699aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -684,7 +684,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -712,7 +712,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x78778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x78778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -740,7 +740,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7966778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7966778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -769,7 +769,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7a5566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7a5566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -797,7 +797,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7b445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7b445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -825,7 +825,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7c33445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7c33445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -853,7 +853,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7d2233445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7d2233445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -881,7 +881,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7e112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7e112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -909,7 +909,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -937,7 +937,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7fff10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600357", |                 "code" : "0x7fff10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -965,7 +965,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff80600357", |                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff80600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -993,7 +993,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff81600357", |                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff81600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1021,7 +1021,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6002600181600357", |                 "code" : "0x6002600181600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1049,7 +1049,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60036002600182600357", |                 "code" : "0x60036002600182600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1077,7 +1077,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600460036002600183600357", |                 "code" : "0x600460036002600183600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1105,7 +1105,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6005600460036002600184600357", |                 "code" : "0x6005600460036002600184600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1133,7 +1133,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60066005600460036002600185600357", |                 "code" : "0x60066005600460036002600185600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1161,7 +1161,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600760066005600460036002600186600357", |                 "code" : "0x600760066005600460036002600186600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1189,7 +1189,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6008600760066005600460036002600187600357", |                 "code" : "0x6008600760066005600460036002600187600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1217,7 +1217,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60096008600760066005600460036002600188600357", |                 "code" : "0x60096008600760066005600460036002600188600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1245,7 +1245,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600a60096008600760066005600460036002600189600357", |                 "code" : "0x600a60096008600760066005600460036002600189600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1273,7 +1273,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600b600a6009600860076006600560046003600260018a600357", |                 "code" : "0x600b600a6009600860076006600560046003600260018a600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1301,7 +1301,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600c600b600a6009600860076006600560046003600260018b600357", |                 "code" : "0x600c600b600a6009600860076006600560046003600260018b600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1329,7 +1329,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600d600c600b600a6009600860076006600560046003600260018c600357", |                 "code" : "0x600d600c600b600a6009600860076006600560046003600260018c600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1357,7 +1357,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600e600d600c600b600a6009600860076006600560046003600260018d600357", |                 "code" : "0x600e600d600c600b600a6009600860076006600560046003600260018d600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1385,7 +1385,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600f600e600d600c600b600a6009600860076006600560046003600260018e600357", |                 "code" : "0x600f600e600d600c600b600a6009600860076006600560046003600260018e600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1413,7 +1413,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6010600f600e600d600c600b600a6009600860076006600560046003600260018f600357", |                 "code" : "0x6010600f600e600d600c600b600a6009600860076006600560046003600260018f600355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1441,7 +1441,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff60039057", |                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff60039055", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1469,7 +1469,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff60039157", |                 "code" : "0x7f10112233445566778899aabbccddeeff00112233445566778899aabbccddeeff60039155", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1497,7 +1497,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6002600160039157", |                 "code" : "0x6002600160039155", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1525,7 +1525,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60036002600160039257", |                 "code" : "0x60036002600160039255", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1553,7 +1553,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600460036002600160039357", |                 "code" : "0x600460036002600160039355", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1581,7 +1581,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6005600460036002600160039457", |                 "code" : "0x6005600460036002600160039455", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1609,7 +1609,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60066005600460036002600160039557", |                 "code" : "0x60066005600460036002600160039555", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1637,7 +1637,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600760066005600460036002600160039657", |                 "code" : "0x600760066005600460036002600160039655", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1665,7 +1665,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6008600760066005600460036002600160039757", |                 "code" : "0x6008600760066005600460036002600160039755", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1693,7 +1693,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x60096008600760066005600460036002600160039857", |                 "code" : "0x60096008600760066005600460036002600160039855", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1721,7 +1721,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600a60096008600760066005600460036002600160039957", |                 "code" : "0x600a60096008600760066005600460036002600160039955", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1749,7 +1749,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600b600a60096008600760066005600460036002600160039a57", |                 "code" : "0x600b600a60096008600760066005600460036002600160039a55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1777,7 +1777,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600c600b600a60096008600760066005600460036002600160039b57", |                 "code" : "0x600c600b600a60096008600760066005600460036002600160039b55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1805,7 +1805,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600d600c600b600a60096008600760066005600460036002600160039c57", |                 "code" : "0x600d600c600b600a60096008600760066005600460036002600160039c55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1833,7 +1833,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600e600d600c600b600a60096008600760066005600460036002600160039d57", |                 "code" : "0x600e600d600c600b600a60096008600760066005600460036002600160039d55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1861,7 +1861,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x600f600e600d600c600b600a60096008600760066005600460036002600160039e57", |                 "code" : "0x600f600e600d600c600b600a60096008600760066005600460036002600160039e55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @ -1889,7 +1889,7 @@ | |||||||
|             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|                 "balance" : "1000000000000000000", |                 "balance" : "1000000000000000000", | ||||||
|                 "nonce" : 0, |                 "nonce" : 0, | ||||||
|                 "code" : "0x6010600f600e600d600c600b600a60096008600760066005600460036002600160039f57", |                 "code" : "0x6010600f600e600d600c600b600a60096008600760066005600460036002600160039f55", | ||||||
|                 "storage": {} |                 "storage": {} | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -111,7 +111,7 @@ | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
| 
 | 
 | ||||||
|     "sha3_3": { |     "sha3_4": { | ||||||
|         "env" : { |         "env" : { | ||||||
|             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|             "currentNumber" : "0", |             "currentNumber" : "0", | ||||||
| @ -137,8 +137,61 @@ | |||||||
|             "gasPrice" : "100000000000000", |             "gasPrice" : "100000000000000", | ||||||
|             "gas" : "10000" |             "gas" : "10000" | ||||||
|         } |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "sha3_5": { | ||||||
|  |         "env" : { | ||||||
|  |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |             "currentNumber" : "0", | ||||||
|  |             "currentGasLimit" : "1000000", | ||||||
|  |             "currentDifficulty" : "256", | ||||||
|  |             "currentTimestamp" : 1, | ||||||
|  |             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "{ [[ 0 ]] (SHA3 10000 0xfffffffff )}", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  | 
 | ||||||
|  |     "sha3_6": { | ||||||
|  |         "env" : { | ||||||
|  |             "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6", | ||||||
|  |             "currentNumber" : "0", | ||||||
|  |             "currentGasLimit" : "1000000", | ||||||
|  |             "currentDifficulty" : "256", | ||||||
|  |             "currentTimestamp" : 1, | ||||||
|  |             "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" | ||||||
|  |         }, | ||||||
|  |         "pre" : { | ||||||
|  |             "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { | ||||||
|  |                 "balance" : "1000000000000000000", | ||||||
|  |                 "nonce" : 0, | ||||||
|  |                 "code" : "{ [[ 0 ]] (SHA3 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)}", | ||||||
|  |                 "storage": {} | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "exec" : { | ||||||
|  |             "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", | ||||||
|  |             "origin" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "caller" : "cd1722f3947def4cf144679da39c4c32bdc35681", | ||||||
|  |             "value" : "1000000000000000000", | ||||||
|  |             "data" : "", | ||||||
|  |             "gasPrice" : "100000000000000", | ||||||
|  |             "gas" : "10000" | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,444 +12,444 @@ class WebThreeStubClient : public jsonrpc::Client | |||||||
|     public: |     public: | ||||||
|         WebThreeStubClient(jsonrpc::IClientConnector &conn) : jsonrpc::Client(conn) {} |         WebThreeStubClient(jsonrpc::IClientConnector &conn) : jsonrpc::Client(conn) {} | ||||||
| 
 | 
 | ||||||
|         std::string coinbase() throw (jsonrpc::JsonRpcException) |         std::string eth_coinbase() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("coinbase",p); |             Json::Value result = this->CallMethod("eth_coinbase",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) |         bool eth_setCoinbase(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("setCoinbase",p); |             Json::Value result = this->CallMethod("eth_setCoinbase",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool listening() throw (jsonrpc::JsonRpcException) |         bool eth_listening() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("listening",p); |             Json::Value result = this->CallMethod("eth_listening",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool setListening(const bool& param1) throw (jsonrpc::JsonRpcException) |         bool eth_setListening(const bool& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("setListening",p); |             Json::Value result = this->CallMethod("eth_setListening",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool mining() throw (jsonrpc::JsonRpcException) |         bool eth_mining() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("mining",p); |             Json::Value result = this->CallMethod("eth_mining",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool setMining(const bool& param1) throw (jsonrpc::JsonRpcException) |         bool eth_setMining(const bool& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("setMining",p); |             Json::Value result = this->CallMethod("eth_setMining",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string gasPrice() throw (jsonrpc::JsonRpcException) |         std::string eth_gasPrice() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("gasPrice",p); |             Json::Value result = this->CallMethod("eth_gasPrice",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string account() throw (jsonrpc::JsonRpcException) |         Json::Value eth_accounts() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("account",p); |             Json::Value result = this->CallMethod("eth_accounts",p); | ||||||
|             if (result.isString()) |  | ||||||
|                 return result.asString(); |  | ||||||
|             else |  | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |  | ||||||
|         } |  | ||||||
|         Json::Value accounts() throw (jsonrpc::JsonRpcException) |  | ||||||
|         { |  | ||||||
|             Json::Value p; |  | ||||||
|             p = Json::nullValue; |  | ||||||
|             Json::Value result = this->CallMethod("accounts",p); |  | ||||||
|             if (result.isArray()) |             if (result.isArray()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int peerCount() throw (jsonrpc::JsonRpcException) |         int eth_peerCount() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("peerCount",p); |             Json::Value result = this->CallMethod("eth_peerCount",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int defaultBlock() throw (jsonrpc::JsonRpcException) |         int eth_defaultBlock() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("defaultBlock",p); |             Json::Value result = this->CallMethod("eth_defaultBlock",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) |         bool eth_setDefaultBlock(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("setDefaultBlock",p); |             Json::Value result = this->CallMethod("eth_setDefaultBlock",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int number() throw (jsonrpc::JsonRpcException) |         int eth_number() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("number",p); |             Json::Value result = this->CallMethod("eth_number",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_balanceAt(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("balanceAt",p); |             Json::Value result = this->CallMethod("eth_balanceAt",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |         std::string eth_stateAt(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("stateAt",p); |             Json::Value result = this->CallMethod("eth_stateAt",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         double countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |         double eth_countAt(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("countAt",p); |             Json::Value result = this->CallMethod("eth_countAt",p); | ||||||
|             if (result.isDouble()) |             if (result.isDouble()) | ||||||
|                 return result.asDouble(); |                 return result.asDouble(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_codeAt(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("codeAt",p); |             Json::Value result = this->CallMethod("eth_codeAt",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_transact(const Json::Value& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("transact",p); |             Json::Value result = this->CallMethod("eth_transact",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_call(const Json::Value& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("call",p); |             Json::Value result = this->CallMethod("eth_call",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) |         Json::Value eth_blockByHash(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("blockByHash",p); |             Json::Value result = this->CallMethod("eth_blockByHash",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) |         Json::Value eth_blockByNumber(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("blockByNumber",p); |             Json::Value result = this->CallMethod("eth_blockByNumber",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) |         Json::Value eth_transactionByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("transactionByHash",p); |             Json::Value result = this->CallMethod("eth_transactionByHash",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) |         Json::Value eth_transactionByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("transactionByNumber",p); |             Json::Value result = this->CallMethod("eth_transactionByNumber",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) |         Json::Value eth_uncleByHash(const std::string& param1, const int& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("uncleByHash",p); |             Json::Value result = this->CallMethod("eth_uncleByHash",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) |         Json::Value eth_uncleByNumber(const int& param1, const int& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("uncleByNumber",p); |             Json::Value result = this->CallMethod("eth_uncleByNumber",p); | ||||||
|             if (result.isObject()) |             if (result.isObject()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string compile(const std::string& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_lll(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("compile",p); |             Json::Value result = this->CallMethod("eth_lll",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |         std::string eth_compile(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("newFilter",p); |             Json::Value result = this->CallMethod("eth_compile",p); | ||||||
|  |             if (result.isString()) | ||||||
|  |                 return result.asString(); | ||||||
|  |             else | ||||||
|  |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|  |         } | ||||||
|  |         int eth_newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) | ||||||
|  |         { | ||||||
|  |             Json::Value p; | ||||||
|  |             p.append(param1); | ||||||
|  |             Json::Value result = this->CallMethod("eth_newFilter",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) |         int eth_newFilterString(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("newFilterString",p); |             Json::Value result = this->CallMethod("eth_newFilterString",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) |         bool eth_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("uninstallFilter",p); |             Json::Value result = this->CallMethod("eth_uninstallFilter",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool changed(const int& param1) throw (jsonrpc::JsonRpcException) |         bool eth_changed(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("changed",p); |             Json::Value result = this->CallMethod("eth_changed",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value getMessages(const int& param1) throw (jsonrpc::JsonRpcException) |         Json::Value eth_getMessages(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("getMessages",p); |             Json::Value result = this->CallMethod("eth_getMessages",p); | ||||||
|             if (result.isArray()) |             if (result.isArray()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |         bool db_put(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             p.append(param3); |             p.append(param3); | ||||||
|             Json::Value result = this->CallMethod("put",p); |             Json::Value result = this->CallMethod("db_put",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |         std::string db_get(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("get",p); |             Json::Value result = this->CallMethod("db_get",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) |         bool db_putString(const std::string& param1, const std::string& param2, const std::string& param3) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             p.append(param3); |             p.append(param3); | ||||||
|             Json::Value result = this->CallMethod("putString",p); |             Json::Value result = this->CallMethod("db_putString",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string getString(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |         std::string db_getString(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("getString",p); |             Json::Value result = this->CallMethod("db_getString",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |         bool shh_post(const Json::Value& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("post",p); |             Json::Value result = this->CallMethod("shh_post",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string newIdentity() throw (jsonrpc::JsonRpcException) |         std::string shh_newIdentity() throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p = Json::nullValue; |             p = Json::nullValue; | ||||||
|             Json::Value result = this->CallMethod("newIdentity",p); |             Json::Value result = this->CallMethod("shh_newIdentity",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) |         bool shh_haveIdentity(const std::string& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("haveIdentity",p); |             Json::Value result = this->CallMethod("shh_haveIdentity",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |         std::string shh_newGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("newGroup",p); |             Json::Value result = this->CallMethod("shh_newGroup",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         std::string addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) |         std::string shh_addToGroup(const std::string& param1, const std::string& param2) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             p.append(param2); |             p.append(param2); | ||||||
|             Json::Value result = this->CallMethod("addToGroup",p); |             Json::Value result = this->CallMethod("shh_addToGroup",p); | ||||||
|             if (result.isString()) |             if (result.isString()) | ||||||
|                 return result.asString(); |                 return result.asString(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         int shhNewFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) |         int shh_newFilter(const Json::Value& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("shhNewFilter",p); |             Json::Value result = this->CallMethod("shh_newFilter",p); | ||||||
|             if (result.isInt()) |             if (result.isInt()) | ||||||
|                 return result.asInt(); |                 return result.asInt(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         bool shhUninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) |         bool shh_uninstallFilter(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("shhUninstallFilter",p); |             Json::Value result = this->CallMethod("shh_uninstallFilter",p); | ||||||
|             if (result.isBool()) |             if (result.isBool()) | ||||||
|                 return result.asBool(); |                 return result.asBool(); | ||||||
|             else |             else | ||||||
|                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); |                 throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); | ||||||
|         } |         } | ||||||
|         Json::Value shhChanged(const int& param1) throw (jsonrpc::JsonRpcException) |         Json::Value shh_changed(const int& param1) throw (jsonrpc::JsonRpcException) | ||||||
|         { |         { | ||||||
|             Json::Value p; |             Json::Value p; | ||||||
|             p.append(param1); |             p.append(param1); | ||||||
|             Json::Value result = this->CallMethod("shhChanged",p); |             Json::Value result = this->CallMethod("shh_changed",p); | ||||||
|             if (result.isArray()) |             if (result.isArray()) | ||||||
|                 return result; |                 return result; | ||||||
|             else |             else | ||||||
|  | |||||||
							
								
								
									
										84
									
								
								whisperTopic.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								whisperTopic.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | |||||||
|  | /*
 | ||||||
|  | 	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/>.
 | ||||||
|  | */ | ||||||
|  | /** @file whisperTopic.cpp
 | ||||||
|  |  * @author Gav Wood <i@gavwood.com> | ||||||
|  |  * @date 2014 | ||||||
|  |  */ | ||||||
|  | #include <functional> | ||||||
|  | #include <boost/test/unit_test.hpp> | ||||||
|  | #include <libp2p/Host.h> | ||||||
|  | #include <libwhisper/WhisperPeer.h> | ||||||
|  | #include <libwhisper/WhisperHost.h> | ||||||
|  | using namespace std; | ||||||
|  | using namespace dev; | ||||||
|  | using namespace dev::p2p; | ||||||
|  | using namespace dev::shh; | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE(whisper) | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_CASE(topic) | ||||||
|  | { | ||||||
|  | 	g_logVerbosity = 0; | ||||||
|  | 
 | ||||||
|  | 	bool started = false; | ||||||
|  | 	unsigned result = 0; | ||||||
|  | 	std::thread listener([&]() | ||||||
|  | 	{ | ||||||
|  | 		setThreadName("other"); | ||||||
|  | 
 | ||||||
|  | 		Host ph("Test", NetworkPreferences(30303, "", false, true)); | ||||||
|  | 		auto wh = ph.registerCapability(new WhisperHost()); | ||||||
|  | 		ph.start(); | ||||||
|  | 
 | ||||||
|  | 		started = true; | ||||||
|  | 
 | ||||||
|  | 		/// Only interested in odd packets
 | ||||||
|  | 		auto w = wh->installWatch(BuildTopicMask()("odd")); | ||||||
|  | 
 | ||||||
|  | 		for (int i = 0, last = 0; i < 100 && last < 81; ++i) | ||||||
|  | 		{ | ||||||
|  | 			for (auto i: wh->checkWatch(w)) | ||||||
|  | 			{ | ||||||
|  | 				Message msg = wh->envelope(i).open(); | ||||||
|  | 				last = RLP(msg.payload()).toInt<unsigned>(); | ||||||
|  | 				cnote << "New message from:" << msg.from().abridged() << RLP(msg.payload()).toInt<unsigned>(); | ||||||
|  | 				result += last; | ||||||
|  | 			} | ||||||
|  | 			this_thread::sleep_for(chrono::milliseconds(50)); | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	while (!started) | ||||||
|  | 		this_thread::sleep_for(chrono::milliseconds(50)); | ||||||
|  | 
 | ||||||
|  | 	Host ph("Test", NetworkPreferences(30300, "", false, true)); | ||||||
|  | 	auto wh = ph.registerCapability(new WhisperHost()); | ||||||
|  | 	ph.start(); | ||||||
|  | 	ph.connect("127.0.0.1", 30303); | ||||||
|  | 
 | ||||||
|  | 	KeyPair us = KeyPair::create(); | ||||||
|  | 	for (int i = 0; i < 10; ++i) | ||||||
|  | 	{ | ||||||
|  | 		wh->post(us.sec(), RLPStream().append(i * i).out(), BuildTopic(i)(i % 2 ? "odd" : "even")); | ||||||
|  | 		this_thread::sleep_for(chrono::milliseconds(250)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	listener.join(); | ||||||
|  | 	BOOST_REQUIRE_EQUAL(result, 1 + 9 + 25 + 49 + 81); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | BOOST_AUTO_TEST_SUITE_END() | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user