<commit_before>/**
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/consensus/miner.hpp>
#include <metaverse/blockchain/block_chain.hpp>
#include <metaverse/blockchain/block_chain_impl.hpp>
#include <metaverse/blockchain/validate_block.hpp>
#include <metaverse/node/p2p_node.hpp>

#include <algorithm>
#include <functional>
#include <system_error>
#include <boost/thread.hpp>
#include <metaverse/consensus/miner/MinerAux.h>
#include <metaverse/consensus/libdevcore/BasicType.h>
#include <metaverse/bitcoin/chain/script/operation.hpp>
#include <metaverse/bitcoin/config/hash160.hpp>
#include <metaverse/bitcoin/wallet/ec_public.hpp>
#include <metaverse/bitcoin/constants.hpp>
#include <metaverse/blockchain/validate_block.hpp>

#define LOG_HEADER "consensus"
using namespace std;

namespace libbitcoin{
namespace consensus{
typedef boost::tuple<double, double, int64_t, miner::transaction_ptr> transaction_priority;

miner::miner(p2p_node& node) : node_(node), state_(state::init_), setting_(node_.chain_impl().chain_settings())
{
    if (setting_.use_testnet_rules){
        bc::HeaderAux::set_as_testnet();
    }
}

miner::~miner()
{
	stop();
}

bool miner::get_transaction(std::vector<transaction_ptr>& transactions)
{
	boost::mutex mutex;
	mutex.lock();
	auto f = [&transactions, &mutex](const error_code& code, const vector<transaction_ptr>& transactions_) -> void
	{
		transactions = transactions_;
		mutex.unlock();
	};
	node_.pool().fetch(f);

	boost::unique_lock<boost::mutex> lock(mutex);

	if(transactions.empty() == false) {
		set<hash_digest> sets;
		for(auto i = transactions.begin(); i != transactions.end(); ) {
			auto& tx = **i;
			auto hash = (*i)->hash();

			if (tx.version >= transaction_version::check_output_script) {
        		for(auto& output : tx.outputs){
            		if(output.script.pattern() == script_pattern::non_standard) {
#ifdef MVS_DEBUG
            			log::error(LOG_HEADER) << "transaction output script error! tx:" << tx.to_string(1);
#endif
						node_.pool().delete_tx(hash);
						i = transactions.erase(i);
						continue;
            		}
        		}
			}

			if(sets.find(hash) == sets.end()){
				sets.insert(hash);
				++i;
			} else {
				i = transactions.erase(i);	
			}
		}
	}
	return transactions.empty() == false;
}

bool miner::script_hash_signature_operations_count(size_t &count, chain::input& input, vector<transaction_ptr>& transactions)
{
	const auto& previous_output = input.previous_output;
	transaction previous_tx;
	boost::uint64_t h;
	if(node_.chain_impl().get_transaction(previous_tx, h, input.previous_output.hash) == false){
		bool found = false;
		for(auto& tx : transactions)
		{
			if(input.previous_output.hash == tx->hash()){
				previous_tx = *tx;
				found = true;
			}<commit_msg>fix: wrong looping in miner::get_transaction<commit_after>/**
 * Copyright (c) 2016-2018 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/consensus/miner.hpp>
#include <metaverse/blockchain/block_chain.hpp>
#include <metaverse/blockchain/block_chain_impl.hpp>
#include <metaverse/blockchain/validate_block.hpp>
#include <metaverse/node/p2p_node.hpp>

#include <algorithm>
#include <functional>
#include <system_error>
#include <boost/thread.hpp>
#include <metaverse/consensus/miner/MinerAux.h>
#include <metaverse/consensus/libdevcore/BasicType.h>
#include <metaverse/bitcoin/chain/script/operation.hpp>
#include <metaverse/bitcoin/config/hash160.hpp>
#include <metaverse/bitcoin/wallet/ec_public.hpp>
#include <metaverse/bitcoin/constants.hpp>
#include <metaverse/blockchain/validate_block.hpp>

#define LOG_HEADER "consensus"
using namespace std;

namespace libbitcoin{
namespace consensus{
typedef boost::tuple<double, double, int64_t, miner::transaction_ptr> transaction_priority;

miner::miner(p2p_node& node) : node_(node), state_(state::init_), setting_(node_.chain_impl().chain_settings())
{
    if (setting_.use_testnet_rules){
        bc::HeaderAux::set_as_testnet();
    }
}

miner::~miner()
{
	stop();
}

bool miner::get_transaction(std::vector<transaction_ptr>& transactions)
{
	boost::mutex mutex;
	mutex.lock();
	auto f = [&transactions, &mutex](const error_code& code, const vector<transaction_ptr>& transactions_) -> void
	{
		transactions = transactions_;
		mutex.unlock();
	};
	node_.pool().fetch(f);

	boost::unique_lock<boost::mutex> lock(mutex);

	if(transactions.empty() == false) {
		set<hash_digest> sets;
		for(auto i = transactions.begin(); i != transactions.end(); ) {
			auto& tx = **i;
			auto hash = tx.hash();
			auto output_script_is_ok = true;

			if (tx.version >= transaction_version::check_output_script) {
        		for(auto& output : tx.outputs){
            		if(output.script.pattern() == script_pattern::non_standard) {
#ifdef MVS_DEBUG
            			log::error(LOG_HEADER) << "transaction output script error! tx:" << tx.to_string(1);
#endif
						node_.pool().delete_tx(hash);
						output_script_is_ok = false;
						break;
            		}
        		}
			}

			if (output_script_is_ok || (sets.find(hash) == sets.end())) {
				sets.insert(hash);
				++i;
			} else {
				i = transactions.erase(i);	
			}
		}
	}
	return transactions.empty() == false;
}

bool miner::script_hash_signature_operations_count(size_t &count, chain::input& input, vector<transaction_ptr>& transactions)
{
	const auto& previous_output = input.previous_output;
	transaction previous_tx;
	boost::uint64_t h;
	if (node_.chain_impl().get_transaction(previous_tx, h, previous_output.hash) == false) {
		bool found = false;
		for(auto& tx : transactions)
		{
			if (previous_output.hash == tx->hash()) {
				previous_tx = *tx;
				found = true;
				break;
			}
{'fraction_non_alphanumeric': 0.12732790729755827, 'fraction_numerical': 0.0052421023589460615, 'mean_word_length': 4.467571644042232, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 56, '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': '6315888', 'n_tokens_mistral': 2432, 'n_tokens_neox': 2285, 'n_words': 580}