diff options
-rw-r--r-- | TestHelper.cpp | 43 | ||||
-rw-r--r-- | TestHelper.h | 4 | ||||
-rw-r--r-- | blValidBlockTestFiller.json | 51 | ||||
-rw-r--r-- | block.cpp | 520 | ||||
-rw-r--r-- | stSystemOperationsTestFiller.json | 4 | ||||
-rw-r--r-- | transaction.cpp | 47 |
6 files changed, 621 insertions, 48 deletions
diff --git a/TestHelper.cpp b/TestHelper.cpp index 5e747210..1e6b97f0 100644 --- a/TestHelper.cpp +++ b/TestHelper.cpp @@ -504,6 +504,49 @@ void executeTests(const string& _name, const string& _testPathAppendix, std::fun } } +RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj) +{ + //Construct Rlp of the given transaction + RLPStream rlpStream; + rlpStream.appendList(_tObj.size()); + + if (_tObj.count("nonce") > 0) + rlpStream << bigint(_tObj["nonce"].get_str()); + + if (_tObj.count("gasPrice") > 0) + rlpStream << bigint(_tObj["gasPrice"].get_str()); + + if (_tObj.count("gasLimit") > 0) + rlpStream << bigint(_tObj["gasLimit"].get_str()); + + if (_tObj.count("to") > 0) + { + if (_tObj["to"].get_str().empty()) + rlpStream << ""; + else + rlpStream << importByteArray(_tObj["to"].get_str()); + } + + if (_tObj.count("value") > 0) + rlpStream << bigint(_tObj["value"].get_str()); + + if (_tObj.count("data") > 0) + rlpStream << importData(_tObj); + + if (_tObj.count("v") > 0) + rlpStream << bigint(_tObj["v"].get_str()); + + if (_tObj.count("r") > 0) + rlpStream << bigint(_tObj["r"].get_str()); + + if (_tObj.count("s") > 0) + rlpStream << bigint(_tObj["s"].get_str()); + + if (_tObj.count("extrafield") > 0) + rlpStream << bigint(_tObj["extrafield"].get_str()); + + return rlpStream; +} void processCommandLineOptions() { diff --git a/TestHelper.h b/TestHelper.h index ae6ea20c..f7df3a2c 100644 --- a/TestHelper.h +++ b/TestHelper.h @@ -45,7 +45,7 @@ namespace test class ImportTest { public: - ImportTest() = default; + ImportTest(json_spirit::mObject& _o) : m_TestObject(_o) {} ImportTest(json_spirit::mObject& _o, bool isFiller); // imports @@ -53,6 +53,7 @@ public: void importState(json_spirit::mObject& _o, eth::State& _state); void importTransaction(json_spirit::mObject& _o); void exportTest(bytes _output, eth::State& _statePost); + std::map<Address, eth::Account> getStateMap(eth::State& _state){return _state.m_cache;} eth::State m_statePre; eth::State m_statePost; @@ -79,6 +80,7 @@ void checkCallCreates(eth::Transactions _resultCallCreates, eth::Transactions _e 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); +RLPStream createRLPStreamFromTransactionFields(json_spirit::mObject& _tObj); void processCommandLineOptions(); eth::LastHashes lastHashes(u256 _currentBlockNumber); diff --git a/blValidBlockTestFiller.json b/blValidBlockTestFiller.json new file mode 100644 index 00000000..db7138b5 --- /dev/null +++ b/blValidBlockTestFiller.json @@ -0,0 +1,51 @@ +{ + "log1" : { + "blockHeader" : { + "number" : "2" + }, + "genesisBlockHeader" : { + "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "coinbase" : "0x8888f1f195afa192cfee860698584c030f4c9db1", + "difficulty" : "10000", + "extraData" : "42", + "gasLimit" : "100000", + "gasUsed" : "0", + "nonce" : "0x498e88f5c14b0b60d6e14ce9c6cc958cbe16a1df8dd90210e50d2d77562a348d", + "number" : "0", + "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", + "receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "stateRoot" : "0xf99eb1626cfa6db435c0836235942d7ccaa935f1ae247d3f1c21e495685f903a", + "timestamp" : "0x54c98c81", + "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", + "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" + }, + "pre" : { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { + "balance" : "10000000000", + "nonce" : "0", + "code" : "", + "storage": {} + }, + "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { + "balance" : "100", + "nonce" : "0", + "code" : "{ (MSTORE 0 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) (LOG1 0 32 0) }", + "storage": {} + } + }, + "transactions" : [ + { + "data" : "", + "gasLimit" : "5000", + "gasPrice" : "10", + "nonce" : "0", + "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", + "value" : "5000000000" + } + ], + "uncleHeaders" : [ + ] + } +} + diff --git a/block.cpp b/block.cpp new file mode 100644 index 00000000..4d1f5acc --- /dev/null +++ b/block.cpp @@ -0,0 +1,520 @@ +/* + 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 block.cpp + * @author Christoph Jentzsch <cj@ethdev.com> + * @date 2015 + * block test functions. + */ + +#include <libethereum/CanonBlockChain.h> +#include "TestHelper.h" + +using namespace std; +using namespace json_spirit; +using namespace dev; +using namespace dev::eth; + +namespace dev { namespace test { + +bytes createBlockRLPFromFields(mObject& _tObj) +{ + RLPStream rlpStream; + rlpStream.appendList(_tObj.size()); + + if (_tObj.count("parentHash") > 0) + rlpStream << importByteArray(_tObj["parentHash"].get_str()); + + if (_tObj.count("uncleHash") > 0) + rlpStream << importByteArray(_tObj["uncleHash"].get_str()); + + if (_tObj.count("coinbase") > 0) + rlpStream << importByteArray(_tObj["coinbase"].get_str()); + + if (_tObj.count("stateRoot") > 0) + rlpStream << importByteArray(_tObj["stateRoot"].get_str()); + + if (_tObj.count("transactionsTrie") > 0) + rlpStream << importByteArray(_tObj["transactionsTrie"].get_str()); + + if (_tObj.count("receiptTrie") > 0) + rlpStream << importByteArray(_tObj["receiptTrie"].get_str()); + + if (_tObj.count("bloom") > 0) + rlpStream << importByteArray(_tObj["bloom"].get_str()); + + if (_tObj.count("difficulty") > 0) + rlpStream << bigint(_tObj["difficulty"].get_str()); + + if (_tObj.count("number") > 0) + rlpStream << bigint(_tObj["number"].get_str()); + + if (_tObj.count("gasLimit") > 0) + rlpStream << bigint(_tObj["gasLimit"].get_str()); + + if (_tObj.count("gasUsed") > 0) + rlpStream << bigint(_tObj["gasUsed"].get_str()); + + if (_tObj.count("timestamp") > 0) + rlpStream << bigint(_tObj["timestamp"].get_str()); + + if (_tObj.count("extraData") > 0) + rlpStream << importByteArray(_tObj["extraData"].get_str()); + + if (_tObj.count("nonce") > 0) + rlpStream << importByteArray(_tObj["nonce"].get_str()); + + return rlpStream.out(); +} + +void doBlockTests(json_spirit::mValue& _v, bool _fillin) +{ + for (auto& i: _v.get_obj()) + { + cerr << i.first << endl; + mObject& o = i.second.get_obj(); + + BOOST_REQUIRE(o.count("genesisBlockHeader") > 0); + cout << "construc genesis\n"; + + // construct RLP of the genesis block + const bytes c_blockRLP = createBlockRLPFromFields(o["genesisBlockHeader"].get_obj()); + const RLP c_bRLP(c_blockRLP); + BlockInfo blockFromFields; + + try + { + blockFromFields.populateFromHeader(c_bRLP, false); + } + catch (Exception const& _e) + { + cnote << "block population did throw an exception: " << diagnostic_information(_e); + BOOST_ERROR("Failed block population with Exception: " << _e.what()); + return; + } + catch (std::exception const& _e) + { + BOOST_ERROR("Failed block population with Exception: " << _e.what()); + return; + } + catch(...) + { + cnote << "block population did throw an unknown exception\n"; + return; + } + + BOOST_REQUIRE(o.count("pre") > 0); + cout << "read state\n"; + + ImportTest importer(o["pre"].get_obj()); + State state(Address(), OverlayDB(), BaseState::Empty); + importer.importState(o["pre"].get_obj(), state); + + // commit changes to DB + state.commit(); + + if (_fillin) + blockFromFields.stateRoot = state.rootHash(); + else + BOOST_CHECK_MESSAGE(blockFromFields.stateRoot == state.rootHash(), "root hash does not match"); + + if (_fillin) + { + // find new valid nonce + ProofOfWork pow; + MineInfo ret; + tie(ret, blockFromFields.nonce) = pow.mine(blockFromFields.headerHash(WithoutNonce), blockFromFields.difficulty, 1000, true, false); + + //update genesis block in json file + o["genesisBlockHeader"].get_obj()["stateRoot"] = toString(blockFromFields.stateRoot); + o["genesisBlockHeader"].get_obj()["nonce"] = toString(blockFromFields.nonce); + } + + // create new "genesis" block + RLPStream rlpStream; + blockFromFields.streamRLP(rlpStream, WithNonce); + + RLPStream block(3); + block.appendRaw(rlpStream.out()); + block.appendRaw(RLPEmptyList); + block.appendRaw(RLPEmptyList); + + blockFromFields.verifyInternals(&block.out()); + + // construct blockchain + BlockChain bc(block.out(), string(), true); + + cout << "constructed bc\n"; + + if (_fillin) + { + BOOST_REQUIRE(o.count("transactions") > 0); + cout << "read transactions\n"; + + TransactionQueue txs; + + for (auto const& txObj: o["transactions"].get_array()) + { + mObject tx = txObj.get_obj(); + importer.importTransaction(tx); + if (!txs.attemptImport(importer.m_transaction.rlp())) + cnote << "failed importing transaction\n"; + } + + try + { + state.sync(bc); + state.sync(bc,txs); + state.commitToMine(bc); + MineInfo info; + for (info.completed = false; !info.completed; info = state.mine()) {} + state.completeMine(); + } + catch (Exception const& _e) + { + cnote << "state sync or mining did throw an exception: " << diagnostic_information(_e); + return; + } + catch (std::exception const& _e) + { + cnote << "state sync or mining did throw an exception: " << _e.what(); + return; + } + + // write valid txs + cout << "number of valid txs: " << txs.transactions().size(); + mArray txArray; + Transactions txList; + for (auto const& txi: txs.transactions()) + { + cout << "AHA0" << endl; + Transaction tx(txi.second, CheckSignature::Sender); + txList.push_back(tx); + mObject txObject; + txObject["nonce"] = toString(tx.nonce()); + txObject["data"] = toHex(tx.data()); + txObject["gasLimit"] = toString(tx.gas()); + txObject["gasPrice"] = toString(tx.gasPrice()); + txObject["r"] = "0x" + toString(tx.signature().r); + txObject["s"] = "0x" + toString(tx.signature().s); + txObject["v"] = to_string(tx.signature().v + 27); + txObject["to"] = toString(tx.receiveAddress()); + txObject["value"] = toString(tx.value()); + cout << "AHA0.5" << endl; + + txArray.push_back(txObject); + } + cout << "AHA1" << endl; + o["transactions"] = txArray; + + o["rlp"] = "0x" + toHex(state.blockData()); + + // write block header + + mObject oBlockHeader; + BlockInfo current_BlockHeader = state.info(); + oBlockHeader["parentHash"] = toString(current_BlockHeader.parentHash); + oBlockHeader["uncleHash"] = toString(current_BlockHeader.sha3Uncles); + oBlockHeader["coinbase"] = toString(current_BlockHeader.coinbaseAddress); + oBlockHeader["stateRoot"] = toString(current_BlockHeader.stateRoot); + oBlockHeader["transactionsTrie"] = toString(current_BlockHeader.transactionsRoot); + oBlockHeader["receiptTrie"] = toString(current_BlockHeader.receiptsRoot); + oBlockHeader["bloom"] = toString(current_BlockHeader.logBloom); + oBlockHeader["difficulty"] = toString(current_BlockHeader.difficulty); + oBlockHeader["number"] = toString(current_BlockHeader.number); + oBlockHeader["gasLimit"] = toString(current_BlockHeader.gasLimit); + oBlockHeader["gasUsed"] = toString(current_BlockHeader.gasUsed); + oBlockHeader["timestamp"] = toString(current_BlockHeader.timestamp); + oBlockHeader["extraData"] = toHex(current_BlockHeader.extraData); + oBlockHeader["nonce"] = toString(current_BlockHeader.nonce); + + + + // overwrite (wrong) data from blockheader in filler" << endl; + + if (o.count("blockHeader") > 0) + { + if (o["blockHeader"].get_obj().size() != 14) + { + + BlockInfo tmp = current_BlockHeader; + + if (o["blockHeader"].get_obj().count("parentHash") > 0) + tmp.parentHash = h256(o["blockHeader"].get_obj()["parentHash"].get_str()); + + if (o["blockHeader"].get_obj().count("sha3Uncles") > 0) + tmp.sha3Uncles = h256(o["blockHeader"].get_obj()["uncleHash"].get_str()); + + if (o["blockHeader"].get_obj().count("coinbase") > 0) + tmp.coinbaseAddress = Address(o["blockHeader"].get_obj()["coinbase"].get_str()); + + if (o["blockHeader"].get_obj().count("stateRoot") > 0) + tmp.stateRoot = h256(o["blockHeader"].get_obj()["stateRoot"].get_str()); + + if (o["blockHeader"].get_obj().count("transactionsTrie") > 0) + tmp.transactionsRoot = h256(o["blockHeader"].get_obj()["transactionsTrie"].get_str()); + + if (o["blockHeader"].get_obj().count("receiptTrie") > 0) + tmp.receiptsRoot = h256(o["blockHeader"].get_obj()["receiptTrie"].get_str()); + + if (o["blockHeader"].get_obj().count("bloom") > 0) + tmp.logBloom = LogBloom(o["blockHeader"].get_obj()["bloom"].get_str()); + + if (o["blockHeader"].get_obj().count("difficulty") > 0) + tmp.difficulty = toInt(o["blockHeader"].get_obj()["difficulty"]); + + if (o["blockHeader"].get_obj().count("number") > 0) + tmp.number = toInt(o["blockHeader"].get_obj()["number"]); + + if (o["blockHeader"].get_obj().count("gasLimit") > 0) + tmp.gasLimit = toInt(o["blockHeader"].get_obj()["gasLimit"]); + + if (o["blockHeader"].get_obj().count("gasUsed") > 0) + tmp.gasUsed = toInt(o["blockHeader"].get_obj()["gasUsed"]); + + if (o["blockHeader"].get_obj().count("timestamp") > 0) + tmp.timestamp = toInt(o["blockHeader"].get_obj()["timestamp"]); + + if (o["blockHeader"].get_obj().count("extraData") > 0) + tmp.extraData = importByteArray(o["blockHeader"].get_obj()["extraData"].get_str()); + + // find new valid nonce + + if (tmp != current_BlockHeader) + { + current_BlockHeader = tmp; + cout << "new header!\n"; + ProofOfWork pow; + MineInfo ret; + while (!ProofOfWork::verify(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.nonce, current_BlockHeader.difficulty)) + tie(ret, current_BlockHeader.nonce) = pow.mine(current_BlockHeader.headerHash(WithoutNonce), current_BlockHeader.difficulty, 10000, true, true); + oBlockHeader["nonce"] = toString(current_BlockHeader.nonce); + } + } + else + { + // take the blockheader as is + const bytes c_blockRLP = createBlockRLPFromFields(o["genesisBlockHeader"].get_obj()); + const RLP c_bRLP(c_blockRLP); + current_BlockHeader.populateFromHeader(c_bRLP, false); + } + } + + //txs: + + RLPStream txStream; + txStream.appendList(txList.size()); + for (unsigned i = 0; i < txList.size(); ++i) + { + RLPStream txrlp; + txList[i].streamRLP(txrlp); + txStream.appendRaw(txrlp.out()); + } + + cout << "create block:" << endl; + + RLPStream rlpStream2; + current_BlockHeader.streamRLP(rlpStream2, WithNonce); + + RLPStream block2(3); + block2.appendRaw(rlpStream2.out()); + block2.appendRaw(txStream.out()); + block2.appendRaw(RLPEmptyList); + + if (sha3(RLP(state.blockData())[0].data()) != sha3(RLP(block2.out())[0].data())) + cout << "block 0 wrong" << endl; + + if (sha3(RLP(state.blockData())[1].data()) != sha3(RLP(block2.out())[1].data())) + cout << "block 1 wrong" << endl; + + if (sha3(RLP(state.blockData())[2].data()) != sha3(RLP(block2.out())[2].data())) + cout << "block 2 wrong" << endl; + + + if (sha3(state.blockData()) != sha3(block2.out())) + { + cout << "blocks do not match!" << endl; + o["rlp"] = "0x" + toHex(block2.out()); + o.erase(o.find("blockHeader")); + o.erase(o.find("uncleHeaders")); + o.erase(o.find("transactions")); + } + else + { + o["blockHeader"] = oBlockHeader; + + // write uncle list + mArray aUncleList; // as of now, our parent is always the genesis block, so we can not have uncles. + o["uncleHeaders"] = aUncleList; + } + } + + else + { + try + { + state.sync(bc); + bytes blockRLP = importByteArray(o["rlp"].get_str()); + bc.import(blockRLP, state.db()); + state.sync(bc); + } + // if exception is thrown, RLP is invalid and no blockHeader, Transaction list, or Uncle list should be given + catch (Exception const& _e) + { + cnote << "state sync or block import did throw an exception: " << diagnostic_information(_e); + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + return; + } + catch (std::exception const& _e) + { + cnote << "state sync or block import did throw an exception: " << _e.what(); + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + return; + } + catch(...) + { + cnote << "state sync or block import did throw an exception\n"; + BOOST_CHECK(o.count("blockHeader") == 0); + BOOST_CHECK(o.count("transactions") == 0); + BOOST_CHECK(o.count("uncleHeaders") == 0); + return; + } + cout << "valid block header\n"; + //cout << "block number: " << + BOOST_REQUIRE(o.count("blockHeader") > 0); + + mObject tObj = o["blockHeader"].get_obj(); + BlockInfo blockHeaderFromFields; + const bytes c_rlpBytesBlockHeader = createBlockRLPFromFields(tObj); + const RLP c_blockHeaderRLP(c_rlpBytesBlockHeader); + blockHeaderFromFields.populateFromHeader(c_blockHeaderRLP, false); + + BlockInfo blockFromRlp = bc.info(); + + //Check the fields restored from RLP to original fields + BOOST_CHECK_MESSAGE(blockHeaderFromFields.headerHash(WithNonce) == blockFromRlp.headerHash(WithNonce), "hash in given RLP not matching the block hash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.parentHash == blockFromRlp.parentHash, "parentHash in given RLP not matching the block parentHash!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.sha3Uncles == blockFromRlp.sha3Uncles, "sha3Uncles in given RLP not matching the block sha3Uncles!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.coinbaseAddress == blockFromRlp.coinbaseAddress,"coinbaseAddress in given RLP not matching the block coinbaseAddress!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.stateRoot == blockFromRlp.stateRoot, "stateRoot in given RLP not matching the block stateRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.transactionsRoot == blockFromRlp.transactionsRoot, "transactionsRoot in given RLP not matching the block transactionsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.receiptsRoot == blockFromRlp.receiptsRoot, "receiptsRoot in given RLP not matching the block receiptsRoot!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.logBloom == blockFromRlp.logBloom, "logBloom in given RLP not matching the block logBloom!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.difficulty == blockFromRlp.difficulty, "difficulty in given RLP not matching the block difficulty!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.number == blockFromRlp.number, "number in given RLP not matching the block number!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasLimit == blockFromRlp.gasLimit,"gasLimit in given RLP not matching the block gasLimit!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.gasUsed == blockFromRlp.gasUsed, "gasUsed in given RLP not matching the block gasUsed!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.timestamp == blockFromRlp.timestamp, "timestamp in given RLP not matching the block timestamp!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.extraData == blockFromRlp.extraData, "extraData in given RLP not matching the block extraData!"); + BOOST_CHECK_MESSAGE(blockHeaderFromFields.nonce == blockFromRlp.nonce, "nonce in given RLP not matching the block nonce!"); + + BOOST_CHECK_MESSAGE(blockHeaderFromFields == blockFromRlp, "However, blockHeaderFromFields != blockFromRlp!"); + + cout << "checked block header bc\n"; + + //Check transaction list + + Transactions txsFromField; + + for (auto const& txObj: o["transactions"].get_array()) + { + mObject tx = txObj.get_obj(); + + cout << "read single tx\n"; + + BOOST_REQUIRE(tx.count("nonce") > 0); + BOOST_REQUIRE(tx.count("gasPrice") > 0); + BOOST_REQUIRE(tx.count("gasLimit") > 0); + BOOST_REQUIRE(tx.count("to") > 0); + BOOST_REQUIRE(tx.count("value") > 0); + BOOST_REQUIRE(tx.count("v") > 0); + BOOST_REQUIRE(tx.count("r") > 0); + BOOST_REQUIRE(tx.count("s") > 0); + BOOST_REQUIRE(tx.count("data") > 0); + + cout << "construct single tx\n"; + try + { + Transaction t(createRLPStreamFromTransactionFields(tx).out(), CheckSignature::Sender); + txsFromField.push_back(t); + } + catch (Exception const& _e) + { + BOOST_ERROR("Failed transaction constructor with Exception: " << diagnostic_information(_e)); + + } + catch (exception const& _e) + { + cout << _e.what() << endl; + } + } + + cout << "read txs bc\n"; + + Transactions txsFromRlp; + bytes blockRLP = importByteArray(o["rlp"].get_str()); + RLP root(blockRLP); + for (auto const& tr: root[1]) + { + Transaction tx(tr.data(), CheckSignature::Sender); + txsFromRlp.push_back(tx); + } + + BOOST_CHECK_MESSAGE(txsFromRlp.size() == txsFromField.size(), "transaction list size does not match"); + + for (size_t i = 0; i < txsFromField.size(); ++i) + { + BOOST_CHECK_MESSAGE(txsFromField[i].data() == txsFromRlp[i].data(), "transaction data in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gas() == txsFromRlp[i].gas(), "transaction gasLimit in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].gasPrice() == txsFromRlp[i].gasPrice(), "transaction gasPrice in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].nonce() == txsFromRlp[i].nonce(), "transaction nonce in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().r == txsFromRlp[i].signature().r, "transaction r in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().s == txsFromRlp[i].signature().s, "transaction s in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].signature().v == txsFromRlp[i].signature().v, "transaction v in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].receiveAddress() == txsFromRlp[i].receiveAddress(), "transaction receiveAddress in rlp and in field do not match"); + BOOST_CHECK_MESSAGE(txsFromField[i].value() == txsFromRlp[i].value(), "transaction receiveAddress in rlp and in field do not match"); + + BOOST_CHECK_MESSAGE(txsFromField[i] == txsFromRlp[i], "however, transactions in rlp and in field do not match"); + } + cout << "checked txs bc\n"; + + // check uncle list + + BOOST_CHECK_MESSAGE((o["uncleList"].type() == json_spirit::null_type ? 0 : o["uncleList"].get_array().size()) == 0, "Uncle list is not empty, but the genesis block can not have uncles"); + } + } +} + +} }// Namespace Close + + +BOOST_AUTO_TEST_SUITE(BlockTests) + +BOOST_AUTO_TEST_CASE(blValidBlockTest) +{ + dev::test::executeTests("blValidBlockTest", "/BlockTests", dev::test::doBlockTests); +} + +BOOST_AUTO_TEST_CASE(userDefinedFileBl) +{ + dev::test::userDefinedTest("--bltest", dev::test::doBlockTests); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/stSystemOperationsTestFiller.json b/stSystemOperationsTestFiller.json index eae39364..9f47b2fe 100644 --- a/stSystemOperationsTestFiller.json +++ b/stSystemOperationsTestFiller.json @@ -81,13 +81,13 @@ "pre" : { "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { "balance" : "1000000000000000000", - "nonce" : 0, + "nonce" : "0", "code" : "0x444242424245434253f0", "storage": {} }, "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { "balance" : "1000000000000000000", - "nonce" : 0, + "nonce" : "0", "code" : "", "storage": {} } diff --git a/transaction.cpp b/transaction.cpp index 9f942953..7bd8ac20 100644 --- a/transaction.cpp +++ b/transaction.cpp @@ -21,6 +21,7 @@ */ #include "TestHelper.h" + using namespace std; using namespace json_spirit; using namespace dev; @@ -28,50 +29,6 @@ using namespace dev::eth; namespace dev { namespace test { -RLPStream createRLPStreamFromTransactionFields(mObject& _tObj) -{ - //Construct Rlp of the given transaction - RLPStream rlpStream; - rlpStream.appendList(_tObj.size()); - - if (_tObj.count("nonce") > 0) - rlpStream << bigint(_tObj["nonce"].get_str()); - - if (_tObj.count("gasPrice") > 0) - rlpStream << bigint(_tObj["gasPrice"].get_str()); - - if (_tObj.count("gasLimit") > 0) - rlpStream << bigint(_tObj["gasLimit"].get_str()); - - if (_tObj.count("to") > 0) - { - if (_tObj["to"].get_str().empty()) - rlpStream << ""; - else - rlpStream << importByteArray(_tObj["to"].get_str()); - } - - if (_tObj.count("value") > 0) - rlpStream << bigint(_tObj["value"].get_str()); - - if (_tObj.count("data") > 0) - rlpStream << importData(_tObj); - - if (_tObj.count("v") > 0) - rlpStream << bigint(_tObj["v"].get_str()); - - if (_tObj.count("r") > 0) - rlpStream << bigint(_tObj["r"].get_str()); - - if (_tObj.count("s") > 0) - rlpStream << bigint(_tObj["s"].get_str()); - - if (_tObj.count("extrafield") > 0) - rlpStream << bigint(_tObj["extrafield"].get_str()); - - return rlpStream; -} - void doTransactionTests(json_spirit::mValue& _v, bool _fillin) { for (auto& i: _v.get_obj()) @@ -115,7 +72,6 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) 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!"); - } else { @@ -141,6 +97,7 @@ void doTransactionTests(json_spirit::mValue& _v, bool _fillin) } }//for }//doTransactionTests + } }// Namespace Close |