예제 #1
0
uint64_t toUnsigned(js::mValue const& _v)
{
	switch (_v.type())
	{
	case js::int_type: return _v.get_uint64();
	case js::str_type: return fromBigEndian<uint64_t>(fromHex(_v.get_str()));
	default: return 0;
	}
}
예제 #2
0
	static void buildRLP(js::mValue& _v, RLPStream& _rlp)
	{
		if (_v.type() == js::array_type)
		{
			RLPStream s;
			for (auto& i: _v.get_array())
				buildRLP(i, s);
			_rlp.appendList(s.out());
		}
		else if (_v.type() == js::int_type)
			_rlp.append(_v.get_uint64());
		else if (_v.type() == js::str_type)
		{
			auto s = _v.get_str();
			if (s.size() && s[0] == '#')
				_rlp.append(bigint(s.substr(1)));
			else
				_rlp.append(s);
		}
	}
예제 #3
0
void doTransactionTests(json_spirit::mValue& _v, bool _fillin)
{
	for (auto& i: _v.get_obj())
	{
		cerr << i.first << endl;
		mObject& o = i.second.get_obj();

		if (_fillin)
		{
			TBOOST_REQUIRE((o.count("transaction") > 0));
			mObject tObj = o["transaction"].get_obj();

			//Construct Rlp of the given transaction
			RLPStream rlpStream = createRLPStreamFromTransactionFields(tObj);
			o["rlp"] = toHex(rlpStream.out(), 2, HexPrefix::Add);

			try
			{
				Transaction txFromFields(rlpStream.out(), CheckTransaction::Everything);
				if (!txFromFields.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );

				o["sender"] = toString(txFromFields.sender());				
				o["transaction"] = ImportTest::makeAllFieldsHex(tObj);
			}
			catch(Exception const& _e)
			{
				//Transaction is InValid
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				o.erase(o.find("transaction"));
				if (o.count("expect") > 0)
				{
					bool expectInValid = (o["expect"].get_str() == "invalid");
					if (Options::get().checkState)
							{TBOOST_CHECK_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");}
						else
							{TBOOST_WARN_MESSAGE(expectInValid, "Check state: Transaction '" << i.first << "' is expected to be valid!");}

					o.erase(o.find("expect"));
				}
			}

			//Transaction is Valid
			if (o.count("expect") > 0)
			{
				bool expectValid = (o["expect"].get_str() == "valid");
				if (Options::get().checkState)
						{TBOOST_CHECK_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");}
					else
						{TBOOST_WARN_MESSAGE(expectValid, "Check state: Transaction '" << i.first << "' is expected to be invalid!");}

				o.erase(o.find("expect"));
			}
		}
		else
		{			
			TBOOST_REQUIRE((o.count("rlp") > 0));
			Transaction txFromRlp;
			try
			{
				bytes stream = importByteArray(o["rlp"].get_str());
				RLP rlp(stream);
				txFromRlp = Transaction(rlp.data(), CheckTransaction::Everything);
				if (!txFromRlp.signature().isValid())
					BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
			}
			catch(Exception const& _e)
			{
				cnote << i.first;
				cnote << "Transaction Exception: " << diagnostic_information(_e);
				TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}
			catch(...)
			{
				TBOOST_CHECK_MESSAGE((o.count("transaction") == 0), "A transaction object should not be defined because the RLP is invalid!");
				continue;
			}

			TBOOST_REQUIRE((o.count("transaction") > 0));

			mObject tObj = o["transaction"].get_obj();
			Transaction txFromFields(createRLPStreamFromTransactionFields(tObj).out(), CheckTransaction::Everything);

			//Check the fields restored from RLP to original fields
			TBOOST_CHECK_MESSAGE((txFromFields.data() == txFromRlp.data()), "Data in given RLP not matching the Transaction data!");
			TBOOST_CHECK_MESSAGE((txFromFields.value() == txFromRlp.value()), "Value in given RLP not matching the Transaction value!");
			TBOOST_CHECK_MESSAGE((txFromFields.gasPrice() == txFromRlp.gasPrice()), "GasPrice in given RLP not matching the Transaction gasPrice!");
			TBOOST_CHECK_MESSAGE((txFromFields.gas() == txFromRlp.gas()),"Gas in given RLP not matching the Transaction gas!");
			TBOOST_CHECK_MESSAGE((txFromFields.nonce() == txFromRlp.nonce()),"Nonce in given RLP not matching the Transaction nonce!");
			TBOOST_CHECK_MESSAGE((txFromFields.receiveAddress() == txFromRlp.receiveAddress()), "Receive address in given RLP not matching the Transaction 'to' address!");
			TBOOST_CHECK_MESSAGE((txFromFields.sender() == txFromRlp.sender()), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
			TBOOST_CHECK_MESSAGE((txFromFields == txFromRlp), "However, txFromFields != txFromRlp!");
			TBOOST_REQUIRE ((o.count("sender") > 0));

			Address addressReaded = Address(o["sender"].get_str());
			TBOOST_CHECK_MESSAGE((txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded), "Signature address of sender does not match given sender address!");
		}
	}//for
}//doTransactionTests
예제 #4
0
파일: vm.cpp 프로젝트: caktux/cpp-ethereum
void doVMTests(json_spirit::mValue& v, bool _fillin)
{
	processCommandLineOptions();

	for (auto& i: v.get_obj())
	{
		cnote << i.first;
		mObject& o = i.second.get_obj();

		BOOST_REQUIRE(o.count("env") > 0);
		BOOST_REQUIRE(o.count("pre") > 0);
		BOOST_REQUIRE(o.count("exec") > 0);

		FakeExtVM fev;
		fev.importEnv(o["env"].get_obj());
		fev.importState(o["pre"].get_obj());

		if (_fillin)
			o["pre"] = mValue(fev.exportState());

		fev.importExec(o["exec"].get_obj());
		if (fev.code.empty())
		{
			fev.thisTxCode = get<3>(fev.addresses.at(fev.myAddress));
			fev.code = fev.thisTxCode;
		}

		bytes output;
		u256 gas;
		bool vmExceptionOccured = false;
		auto startTime = std::chrono::high_resolution_clock::now();
		try
		{
			auto vm = eth::VMFactory::create(fev.gas);
			output = vm->go(fev, fev.simpleTrace()).toBytes();
			gas = vm->gas();
		}
		catch (VMException const& _e)
		{
			cnote << "Safe VM Exception";
			vmExceptionOccured = true;
		}
		catch (Exception const& _e)
		{
			cnote << "VM did throw an exception: " << diagnostic_information(_e);
			BOOST_ERROR("Failed VM Test with Exception: " << _e.what());
		}
		catch (std::exception const& _e)
		{
			cnote << "VM did throw an exception: " << _e.what();
			BOOST_ERROR("Failed VM Test with Exception: " << _e.what());
		}

		auto endTime = std::chrono::high_resolution_clock::now();
		auto argc = boost::unit_test::framework::master_test_suite().argc;
		auto argv = boost::unit_test::framework::master_test_suite().argv;
		for (auto i = 0; i < argc; ++i)
		{	       
			if (std::string(argv[i]) == "--show-times")
			{
				auto testDuration = endTime - startTime;
				cnote << "Execution time: "
				      << std::chrono::duration_cast<std::chrono::milliseconds>(testDuration).count()
				      << " ms";
				break;
			}
		}

		// delete null entries in storage for the sake of comparison

		for (auto  &a: fev.addresses)
		{
			vector<u256> keystoDelete;
			for (auto &s: get<2>(a.second))
			{
				if (s.second == 0)
					keystoDelete.push_back(s.first);
			}
			for (auto const key: keystoDelete )
			{
				get<2>(a.second).erase(key);
			}
		}


		if (_fillin)
		{
			o["env"] = mValue(fev.exportEnv());
			o["exec"] = mValue(fev.exportExec());
			if (!vmExceptionOccured)
			{
				o["post"] = mValue(fev.exportState());
				o["callcreates"] = fev.exportCallCreates();
				o["out"] = "0x" + toHex(output);
				fev.push(o, "gas", gas);
				o["logs"] = exportLog(fev.sub.logs);
			}
		}
		else
		{
			if (o.count("post") > 0)	// No exceptions expected
			{
				BOOST_CHECK(!vmExceptionOccured);

				BOOST_REQUIRE(o.count("post") > 0);
				BOOST_REQUIRE(o.count("callcreates") > 0);
				BOOST_REQUIRE(o.count("out") > 0);
				BOOST_REQUIRE(o.count("gas") > 0);
				BOOST_REQUIRE(o.count("logs") > 0);

				dev::test::FakeExtVM test;
				test.importState(o["post"].get_obj());
				test.importCallCreates(o["callcreates"].get_array());
				test.sub.logs = importLog(o["logs"].get_array());

				checkOutput(output, o);

				BOOST_CHECK_EQUAL(toInt(o["gas"]), gas);

				auto& expectedAddrs = test.addresses;
				auto& resultAddrs = fev.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
					{
						auto& expectedState = expectedPair.second;
						auto& resultState = resultAddrIt->second;
						BOOST_CHECK_MESSAGE(std::get<0>(expectedState) == std::get<0>(resultState), expectedAddr << ": incorrect balance " << std::get<0>(resultState) << ", expected " << std::get<0>(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");

						checkStorage(std::get<2>(expectedState), std::get<2>(resultState), expectedAddr);
					}
				}

				checkAddresses<std::map<Address, std::tuple<u256, u256, std::map<u256, u256>, bytes> > >(test.addresses, fev.addresses);
				BOOST_CHECK(test.callcreates == fev.callcreates);

				checkLog(fev.sub.logs, test.sub.logs);
			}
			else	// Exception expected
				BOOST_CHECK(vmExceptionOccured);
		}
	}
}