<commit_before>/*
	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 <NAME> <<EMAIL>>
 * @date 2015
 * block test functions.
 */

#include <libdevcrypto/FileSystem.h>
#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);
void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj);
BlockInfo constructBlock(mObject& _o);
void updatePoW(BlockInfo& _bi);
void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi);
RLPStream createFullBlockFromHeader(const BlockInfo& _bi, const bytes& _txs = RLPEmptyList, const bytes& _uncles = RLPEmptyList);

void doBlockchainTests(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"));
		BlockInfo biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj());

		BOOST_REQUIRE(o.count("pre"));
		ImportTest importer(o["pre"].get_obj());
		State state(biGenesisBlock.coinbaseAddress, OverlayDB(), BaseState::Empty);
		importer.importState(o["pre"].get_obj(), state);
		o["pre"] = fillJsonWithState(state);
		state.commit();

		if (_fillin)
			biGenesisBlock.stateRoot = state.rootHash();
		else
			BOOST_CHECK_MESSAGE(biGenesisBlock.stateRoot == state.rootHash(), "root hash does not match");

		if (_fillin)
		{
			// find new valid nonce
			updatePoW(biGenesisBlock);

			//update genesis block in json file
			writeBlockHeaderToJson(o["genesisBlockHeader"].get_obj(), biGenesisBlock);
		}

		// create new "genesis" block
		RLPStream rlpGenesisBlock = createFullBlockFromHeader(biGenesisBlock);
		biGenesisBlock.verifyInternals(&rlpGenesisBlock.out());

		// construct blockchain
		BlockChain bc(rlpGenesisBlock.out(), string(), true);

		if (_fillin)
		{
			BOOST_REQUIRE(o.count("blocks"));
			mArray blArray;
			vector<BlockInfo> vBiBlocks;
			vBiBlocks.push_back(biGenesisBlock);
			for (auto const& bl: o["blocks"].get_array())
			{
				mObject blObj = bl.get_obj();

				// get txs
				TransactionQueue txs;
				ZeroGasPricer gp;
				BOOST_REQUIRE(blObj.count("transactions"));
				for (auto const& txObj: blObj["transactions"].get_array())
				{
					mObject tx = txObj.get_obj();
					importer.importTransaction(tx);
					if (!txs.attemptImport(importer.m_transaction.rlp()))
						cnote << "failed importing transaction\n";
				}

				// write uncle list
				BlockQueue uncleBlockQueue;
				mArray aUncleList;
				vector<BlockInfo> vBiUncles;
				mObject uncleHeaderObj_pre;

				for (auto const& uHObj: blObj["uncleHeaders"].get_array())
				{
					mObject uncleHeaderObj = uHObj.get_obj();
					if (uncleHeaderObj.count("sameAsPreviousSibling"))
					{
						writeBlockHeaderToJson(uncleHeaderObj_pre, vBiUncles[vBiUncles.size()-1]);
						aUncleList.push_back(uncleHeaderObj_pre);
						vBiUncles.push_back(vBiUncles[vBiUncles.size()-1]);
						continue;
					}
					BlockInfo uncleBlockFromFields = constructBlock(uncleHeaderObj);

					// make uncle header valid
					uncleBlockFromFields.timestamp = (u256)time(0);
					if (vBiBlocks.size() > 2)
					{
						if (uncleBlockFromFields.number - 1 < vBiBlocks.size())
							uncleBlockFromFields.populateFromParent(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
						else
							uncleBlockFromFields.populateFromParent(vBiBlocks[vBiBlocks.size() - 2]);
					}
					else
						continue;

					updatePoW(uncleBlockFromFields);
					writeBlockHeaderToJson(uncleHeaderObj, uncleBlockFromFields);

					aUncleList.push_back(uncleHeaderObj);
					vBiUncles.push_back(uncleBlockFromFields);

					cnote << "import uncle in blockQueue";
					RLPStream uncle = createFullBlockFromHeader(uncleBlockFromFields);<commit_msg>add possibility to have in-chain uncles as tests<commit_after>/*
	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 <NAME> <<EMAIL>>
 * @date 2015
 * block test functions.
 */

#include <libdevcrypto/FileSystem.h>
#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);
void overwriteBlockHeader(BlockInfo& _current_BlockHeader, mObject& _blObj);
BlockInfo constructBlock(mObject& _o);
void updatePoW(BlockInfo& _bi);
void writeBlockHeaderToJson(mObject& _o, const BlockInfo& _bi);
RLPStream createFullBlockFromHeader(const BlockInfo& _bi, const bytes& _txs = RLPEmptyList, const bytes& _uncles = RLPEmptyList);

void doBlockchainTests(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"));
		BlockInfo biGenesisBlock = constructBlock(o["genesisBlockHeader"].get_obj());

		BOOST_REQUIRE(o.count("pre"));
		ImportTest importer(o["pre"].get_obj());
		State state(biGenesisBlock.coinbaseAddress, OverlayDB(), BaseState::Empty);
		importer.importState(o["pre"].get_obj(), state);
		o["pre"] = fillJsonWithState(state);
		state.commit();

		if (_fillin)
			biGenesisBlock.stateRoot = state.rootHash();
		else
			BOOST_CHECK_MESSAGE(biGenesisBlock.stateRoot == state.rootHash(), "root hash does not match");

		if (_fillin)
		{
			// find new valid nonce
			updatePoW(biGenesisBlock);

			//update genesis block in json file
			writeBlockHeaderToJson(o["genesisBlockHeader"].get_obj(), biGenesisBlock);
		}

		// create new "genesis" block
		RLPStream rlpGenesisBlock = createFullBlockFromHeader(biGenesisBlock);
		biGenesisBlock.verifyInternals(&rlpGenesisBlock.out());
		o["genesisRLP"] = "0x" + toHex(rlpGenesisBlock.out());

		// construct blockchain
		BlockChain bc(rlpGenesisBlock.out(), string(), true);

		if (_fillin)
		{
			BOOST_REQUIRE(o.count("blocks"));
			mArray blArray;
			vector<BlockInfo> vBiBlocks;
			vBiBlocks.push_back(biGenesisBlock);
			for (auto const& bl: o["blocks"].get_array())
			{
				mObject blObj = bl.get_obj();

				// get txs
				TransactionQueue txs;
				ZeroGasPricer gp;
				BOOST_REQUIRE(blObj.count("transactions"));
				for (auto const& txObj: blObj["transactions"].get_array())
				{
					mObject tx = txObj.get_obj();
					importer.importTransaction(tx);
					if (!txs.attemptImport(importer.m_transaction.rlp()))
						cnote << "failed importing transaction\n";
				}

				// write uncle list
				BlockQueue uncleBlockQueue;
				mArray aUncleList;
				vector<BlockInfo> vBiUncles;
				mObject uncleHeaderObj_pre;

				for (auto const& uHObj: blObj["uncleHeaders"].get_array())
				{
					mObject uncleHeaderObj = uHObj.get_obj();
					if (uncleHeaderObj.count("sameAsPreviousSibling"))
					{
						writeBlockHeaderToJson(uncleHeaderObj_pre, vBiUncles[vBiUncles.size()-1]);
						aUncleList.push_back(uncleHeaderObj_pre);
						vBiUncles.push_back(vBiUncles[vBiUncles.size()-1]);
						continue;
					}

					if (uncleHeaderObj.count("sameAsBlock"))
					{
						writeBlockHeaderToJson(uncleHeaderObj_pre, vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
						aUncleList.push_back(uncleHeaderObj_pre);
						vBiUncles.push_back(vBiBlocks[(size_t)toInt(uncleHeaderObj["sameAsBlock"])]);
						continue;
					}

					BlockInfo uncleBlockFromFields = constructBlock(uncleHeaderObj);

					// make uncle header valid
					uncleBlockFromFields.timestamp = (u256)time(0);
					if (vBiBlocks.size() > 2)
					{
						if (uncleBlockFromFields.number - 1 < vBiBlocks.size())
							uncleBlockFromFields.populateFromParent(vBiBlocks[(size_t)uncleBlockFromFields.number - 1]);
						else
							uncleBlockFromFields.populateFromParent(vBiBlocks[vBiBlocks.size() - 2]);
					}
					else
						continue;

					updatePoW(uncleBlockFromFields);
					writeBlockHeaderToJson(uncleHeaderObj, uncleBlockFromFields);

					aUncleList.push_back(uncleHeaderObj);
					vBiUncles.push_back(uncleBlockFromFields);

					cnote << "import uncle in blockQueue";
					RLPStream uncle = createFullBlockFromHeader(uncleBlockFromFields);
{'fraction_non_alphanumeric': 0.11170043492097168, 'fraction_numerical': 0.0032884268590219583, 'mean_word_length': 4.456018518518518, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2587175', 'n_tokens_mistral': 3599, 'n_tokens_neox': 3020, 'n_words': 694}