aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TestHelper.cpp15
-rw-r--r--TestHelper.h1
-rw-r--r--stTransactionTestFiller.json105
-rw-r--r--transaction.cpp236
-rw-r--r--ttTransactionTestFiller.json80
5 files changed, 426 insertions, 11 deletions
diff --git a/TestHelper.cpp b/TestHelper.cpp
index ea848c7c..1b854162 100644
--- a/TestHelper.cpp
+++ b/TestHelper.cpp
@@ -228,14 +228,21 @@ byte toByte(json_spirit::mValue const& _v)
return 0;
}
+bytes importByteArray(const std::string& str)
+{
+ bytes data;
+ if (str.find_first_of("0x") == 0)
+ data = fromHex(str.substr(2));
+ else
+ data = fromHex(str);
+ return data;
+}
+
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());
+ data = importByteArray(_o["data"].get_str());
else
for (auto const& j: _o["data"].get_array())
data.push_back(toByte(j));
diff --git a/TestHelper.h b/TestHelper.h
index 20328c91..e605c74a 100644
--- a/TestHelper.h
+++ b/TestHelper.h
@@ -68,6 +68,7 @@ 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);
+bytes importByteArray(const std::string& str);
eth::LogEntries importLog(json_spirit::mArray& _o);
json_spirit::mArray exportLog(eth::LogEntries _logs);
void checkOutput(bytes const& _output, json_spirit::mObject& _o);
diff --git a/stTransactionTestFiller.json b/stTransactionTestFiller.json
index 09c323cf..c1c71a53 100644
--- a/stTransactionTestFiller.json
+++ b/stTransactionTestFiller.json
@@ -289,7 +289,7 @@
}
},
- "TransactionTooManyRlpElements" : {
+ "InternlCallStoreClearsOOG" : {
"env" : {
"currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"currentDifficulty" : "45678256",
@@ -301,24 +301,115 @@
"pre" :
{
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
- "balance" : "100000",
+ "balance" : "7000",
"code" : "",
"nonce" : "0",
"storage" : {
}
+ },
+
+ "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "10",
+ "//" : "gas = 19 going OOG, gas = 20 fine",
+ "code" : "{ (CALL 19 0 1 0 0 0 0) }",
+ "nonce" : "0",
+ "storage" : {
+ }
+ },
+
+ "0000000000000000000000000000000000000000" : {
+ "balance" : "0",
+ "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0)(SSTORE 4 0)(SSTORE 5 0)(SSTORE 6 0)(SSTORE 7 0)(SSTORE 8 0)(SSTORE 9 0)}",
+ "nonce" : "0",
+ "storage" : {
+ "0x" : "0x0c",
+ "0x01" : "0x0c",
+ "0x02" : "0x0c",
+ "0x03" : "0x0c",
+ "0x04" : "0x0c",
+ "0x05" : "0x0c",
+ "0x06" : "0x0c",
+ "0x07" : "0x0c",
+ "0x08" : "0x0c",
+ "0x09" : "0x0c"
+ }
}
+
},
+
"transaction" :
{
"data" : "",
- "gasLimit" : "600",
- "gasLimit" : "1600",
+ "gasLimit" : "700",
"gasPrice" : "1",
- "gasPrice" : "12",
"nonce" : "",
- "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d9",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
- "to" : "d2571607e241ecf590ed94b12d87c94babe36db6",
+ "to" : "c94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "value" : "10"
+ }
+ },
+
+ "StoreClearsAndInternlCallStoreClearsOOG" : {
+ "env" : {
+ "currentCoinbase" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "currentDifficulty" : "45678256",
+ "currentGasLimit" : "10000",
+ "currentNumber" : "0",
+ "currentTimestamp" : 1,
+ "previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
+ },
+ "pre" :
+ {
+ "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "7000",
+ "code" : "",
+ "nonce" : "0",
+ "storage" : {
+ }
+ },
+
+ "c94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
+ "balance" : "10",
+ "//" : "gas = 19 going OOG, gas = 20 fine",
+ "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0) (CALL 19 0 1 0 0 0 0) }",
+ "nonce" : "0",
+ "storage" : {
+ "0x" : "0x0c",
+ "0x01" : "0x0c",
+ "0x02" : "0x0c",
+ "0x03" : "0x0c",
+ "0x04" : "0x0c"
+ }
+ },
+
+ "0000000000000000000000000000000000000000" : {
+ "balance" : "0",
+ "code" : "{(SSTORE 0 0)(SSTORE 1 0)(SSTORE 2 0)(SSTORE 3 0)(SSTORE 4 0)(SSTORE 5 0)(SSTORE 6 0)(SSTORE 7 0)(SSTORE 8 0)(SSTORE 9 0)}",
+ "nonce" : "0",
+ "storage" : {
+ "0x" : "0x0c",
+ "0x01" : "0x0c",
+ "0x02" : "0x0c",
+ "0x03" : "0x0c",
+ "0x04" : "0x0c",
+ "0x05" : "0x0c",
+ "0x06" : "0x0c",
+ "0x07" : "0x0c",
+ "0x08" : "0x0c",
+ "0x09" : "0x0c"
+ }
+ }
+
+ },
+
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "700",
+ "gasPrice" : "1",
+ "nonce" : "",
+ "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "to" : "c94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : "10"
}
},
diff --git a/transaction.cpp b/transaction.cpp
new file mode 100644
index 00000000..db66b33e
--- /dev/null
+++ b/transaction.cpp
@@ -0,0 +1,236 @@
+/*
+ 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 transaction.cpp
+ * @author Dmitrii Khokhlov <winsvega@mail.ru>
+ * @date 2014
+ * Transaaction test functions.
+ */
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/test/unit_test.hpp>
+#include "JsonSpiritHeaders.h"
+#include <libdevcore/CommonIO.h>
+#include <libethereum/BlockChain.h>
+#include <libethereum/State.h>
+#include <libethereum/ExtVM.h>
+#include <libethereum/Defaults.h>
+#include <libevm/VM.h>
+#include "TestHelper.h"
+
+using namespace std;
+using namespace json_spirit;
+using namespace dev;
+using namespace dev::eth;
+using namespace dev::eth;
+
+namespace dev { namespace test {
+
+Transaction createTransactionFromFields(mObject& _tObj)
+{
+ BOOST_REQUIRE(_tObj.count("data") > 0);
+ BOOST_REQUIRE(_tObj.count("value") > 0);
+ BOOST_REQUIRE(_tObj.count("gasPrice") > 0);
+ BOOST_REQUIRE(_tObj.count("gasLimit") > 0);
+ BOOST_REQUIRE(_tObj.count("nonce")> 0);
+ BOOST_REQUIRE(_tObj.count("to") > 0);
+
+ BOOST_REQUIRE(_tObj.count("v") > 0);
+ BOOST_REQUIRE(_tObj.count("r") > 0);
+ BOOST_REQUIRE(_tObj.count("s") > 0);
+
+ //Construct Rlp of the given transaction
+ RLPStream rlpStream;
+ rlpStream.appendList(9);
+ rlpStream << toInt(_tObj["nonce"]) << toInt(_tObj["gasPrice"]) << toInt(_tObj["gasLimit"]);
+ if (_tObj["to"].get_str().empty())
+ rlpStream << "";
+ else
+ rlpStream << Address(_tObj["to"].get_str());
+ rlpStream << toInt(_tObj["value"]) << importData(_tObj);
+
+ u256 r = h256(fromHex(_tObj["r"].get_str()));
+ u256 s = h256(fromHex(_tObj["s"].get_str()));
+ rlpStream << toInt(_tObj["v"]) << r << s;
+
+ return Transaction(rlpStream.out(), true);
+}
+
+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 == false)
+ {
+ BOOST_REQUIRE(o.count("rlp") > 0);
+ bytes rlpReaded = importByteArray(o["rlp"].get_str());
+ Transaction txFromRlp;
+
+ try
+ {
+ txFromRlp = Transaction(rlpReaded, true);
+ if (!txFromRlp.signature().isValid())
+ BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
+ }
+ catch(...)
+ {
+ BOOST_CHECK_MESSAGE(o.count("transaction") == 0, "A transction object should not be defined because the RLP is invalid!");
+ return;
+ }
+
+ BOOST_REQUIRE(o.count("transaction") > 0);
+
+ mObject tObj = o["transaction"].get_obj();
+ Transaction txFromFields = createTransactionFromFields(tObj);
+
+ //Check the fields restored from RLP to original fields
+ BOOST_CHECK_MESSAGE(txFromFields.data() == txFromRlp.data(), "Data in given RLP not matching the Transaction data!");
+ BOOST_CHECK_MESSAGE(txFromFields.value() == txFromRlp.value(), "Value in given RLP not matching the Transaction value!");
+ BOOST_CHECK_MESSAGE(txFromFields.gasPrice() == txFromRlp.gasPrice(), "GasPrice in given RLP not matching the Transaction gasPrice!");
+ BOOST_CHECK_MESSAGE(txFromFields.gas() == txFromRlp.gas(),"Gas in given RLP not matching the Transaction gas!");
+ BOOST_CHECK_MESSAGE(txFromFields.nonce() == txFromRlp.nonce(),"Nonce in given RLP not matching the Transaction nonce!");
+ BOOST_CHECK_MESSAGE(txFromFields.receiveAddress() == txFromRlp.receiveAddress(), "Receive address in given RLP not matching the Transaction 'to' address!");
+ BOOST_CHECK_MESSAGE(txFromFields.sender() == txFromRlp.sender(), "Transaction sender address in given RLP not matching the Transaction 'vrs' signature!");
+ BOOST_CHECK_MESSAGE(txFromFields == txFromRlp, "However, txFromFields != txFromRlp!");
+ BOOST_REQUIRE (o.count("sender") > 0);
+
+ Address addressReaded = Address(o["sender"].get_str());
+ BOOST_CHECK_MESSAGE(txFromFields.sender() == addressReaded || txFromRlp.sender() == addressReaded, "Signature address of sender does not match given sender address!");
+ }
+
+ if(_fillin == true)
+ {
+ BOOST_REQUIRE(o.count("transaction") > 0);
+ mObject tObj = o["transaction"].get_obj();
+
+ //Construct Rlp of the given transaction
+ RLPStream rlpStream;
+ rlpStream.appendList(tObj.size());
+
+ if(tObj.count("nonce") > 0)
+ rlpStream << toInt(tObj["nonce"]);
+
+ if(tObj.count("gasPrice") > 0)
+ rlpStream << toInt(tObj["gasPrice"]);
+
+ if(tObj.count("gasLimit") > 0)
+ rlpStream << toInt(tObj["gasLimit"]);
+
+ if(tObj.count("to") > 0)
+ {
+ if (tObj["to"].get_str().empty())
+ rlpStream << "";
+ else
+ rlpStream << Address(tObj["to"].get_str());
+ }
+
+ if(tObj.count("value") > 0)
+ rlpStream << toInt(tObj["value"]);
+
+
+ if(tObj.count("data") > 0)
+ rlpStream << importData(tObj);
+
+ if(tObj.count("v") > 0)
+ rlpStream << toInt(tObj["v"]);
+
+ if(tObj.count("r") > 0)
+ {
+ u256 r = h256(fromHex(tObj["r"].get_str()));
+ rlpStream << r;
+ }
+
+ if(tObj.count("s") > 0)
+ {
+ u256 s = h256(fromHex(tObj["s"].get_str()));
+ rlpStream << s;
+ }
+
+ if(tObj.count("extrafield") > 0)
+ rlpStream << toInt(tObj["extrafield"]);
+
+ o["rlp"] = "0x" + toHex(rlpStream.out());
+
+ try
+ {
+ Transaction txFromFields(rlpStream.out(), true);
+ if (!txFromFields.signature().isValid())
+ BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("transaction from RLP signature is invalid") );
+
+ o["sender"] = toString(txFromFields.sender());
+
+ }
+ catch(...)
+ {
+ o.erase(o.find("transaction"));
+ }
+ }
+ }//for
+}//doTransactionTests
+
+} }// Namespace Close
+
+
+BOOST_AUTO_TEST_SUITE(TransactionTests)
+
+BOOST_AUTO_TEST_CASE(ttFillerTest)
+{
+ dev::test::executeTests("ttTransactionTest", "/TransactionTests", dev::test::doTransactionTests);
+}
+
+BOOST_AUTO_TEST_CASE(ttCreateTest)
+{
+ 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::doTransactionTests(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 transaction test with Exception: " << diagnostic_information(_e));
+ }
+ catch (std::exception const& _e)
+ {
+ BOOST_ERROR("Failed transaction test with Exception: " << _e.what());
+ }
+ }
+ }
+}
+
+BOOST_AUTO_TEST_CASE(userDefinedFileTT)
+{
+ dev::test::userDefinedTest("--ttTest", dev::test::doTransactionTests);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/ttTransactionTestFiller.json b/ttTransactionTestFiller.json
new file mode 100644
index 00000000..6c68bd75
--- /dev/null
+++ b/ttTransactionTestFiller.json
@@ -0,0 +1,80 @@
+{
+ "RightVRSTest" : {
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "2000",
+ "gasPrice" : "1",
+ "nonce" : "0",
+ "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "value" : "10",
+ "v" : "28",
+ "r" : "0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a",
+ "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"
+
+ }
+ },
+
+ "WrongVRSTest" : {
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "2000",
+ "gasPrice" : "1",
+ "nonce" : "0",
+ "to" : "b94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "value" : "10",
+ "v" : "1",
+ "r" : "0x98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a",
+ "s" : "0x8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"
+ }
+ },
+
+ "SenderTest" : {
+ "//" : "sender a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "850",
+ "gasPrice" : "1",
+ "nonce" : "0",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "10",
+ "v" : "27",
+ "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
+ "s" : "secretkey 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
+ "s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
+ }
+ },
+
+ "TransactionWithTooManyRLPElements" : {
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "850",
+ "gasPrice" : "1",
+ "nonce" : "0",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "10",
+ "v" : "27",
+ "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
+ "s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804",
+ "extrafield" : "128472387293"
+ }
+ },
+
+ "TransactionWithHihghValue" : {
+ "transaction" :
+ {
+ "data" : "",
+ "gasLimit" : "850",
+ "gasPrice" : "1",
+ "nonce" : "0",
+ "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
+ "value" : "115792089237316195423570985008687907853269984665640564039457584007913129639936",
+ "v" : "27",
+ "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353",
+ "s" : "0xefffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"
+ }
+ }
+}