<commit_before>/*
 * ScriptCheck.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: ranger.shi
 */
#include "VmScriptRun.h"
#include "tx.h"
#include "util.h"
#include <boost/foreach.hpp>
CVmScriptRun::CVmScriptRun() {
	RawAccont.clear();
	NewAccont.clear();
	height = 0;
	m_ScriptDBTip = NULL;
	m_view = NULL;
	m_dblog = std::make_shared<std::vector<CScriptDBOperLog> >();
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetRawAccont() {
	return RawAccont;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetNewAccont() {
	return NewAccont;
}

bool CVmScriptRun::intial(shared_ptr<CBaseTransaction> & Tx, CAccountViewCache& view, int nheight) {

	m_output.clear();
	listTx = Tx;
	height = nheight;
	m_view = &view;
	vector<unsigned char> vScript;

	if (Tx.get()->nTxType != CONTRACT_TX) {
		LogPrint("ERROR", "%s\r\n", "err param");
		assert(0);
		return false;
	}

	CTransaction* secure = static_cast<CTransaction*>(Tx.get());
	if (!m_ScriptDBTip->GetScript(boost::get<CRegID>(secure->desUserId), vScript)) {
		LogPrint("ERROR", "Script is not Registed %s\r\n", boost::get<CRegID>(secure->desUserId).ToString());
		return false;
	}

	CDataStream stream(vScript, SER_DISK, CLIENT_VERSION);
	try {
		stream >> vmScript;
	} catch (exception& e) {
		LogPrint("ERROR", "%s\r\n", "CVmScriptRun::intial() Unserialize to vmScript error");
		throw runtime_error("CVmScriptRun::intial() Unserialize to vmScript error:" + string(e.what()));
	}

	if (vmScript.IsValid() == false){
		LogPrint("ERROR", "%s\r\n", "CVmScriptRun::intial() vmScript.IsValid error");
		return false;
	}

	pMcu = make_shared<CVir8051>(vmScript.Rom, secure->vContract);
	return true;
}

CVmScriptRun::~CVmScriptRun() {

}
tuple<bool, uint64_t, string> CVmScriptRun::run(shared_ptr<CBaseTransaction>& Tx, CAccountViewCache& view, CScriptDBViewCache& VmDB, int nheight,
		uint64_t nBurnFactor, uint64_t &uRunStep) {

	if(nBurnFactor == 0)
	{
		assert(0);
		return std::make_tuple (false, 0, string("VmScript nBurnFactor == 0 \n"));
	}
	m_ScriptDBTip = &VmDB;

	CTransaction* tx = static_cast<CTransaction*>(Tx.get());
	uint64_t maxstep = tx->llFees;///nBurnFactor;
	tuple<bool, uint64_t, string> mytuple;
	if (!intial(Tx, view, nheight)) {
		return std::make_tuple (false, 0, string("VmScript inital Failed\n"));

	}

	int64_t step = pMcu.get()->run(maxstep,this);
	if (0 == step) {
		return std::make_tuple(false, 0, string("VmScript run Failed\n"));
	} else if (-1 == step) {
		return std::make_tuple(false, 0, string("execure tx contranct run step exceed the max step limit\n"));
	}

	uRunStep = step;
	LogPrint("CONTRACT_TX", "tx:%s,step:%ld\n", tx->ToString(view), step);
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	Contractstream >> retvmcode;

	if (!CheckOperate(m_output)) {
		return std::make_tuple (false, 0, string("VmScript CheckOperate Failed \n"));

	}
	if (!OpeatorAccount(m_output, view)) {
		return std::make_tuple (false, 0, string("VmScript OpeatorAccount Failed\n"));
	}
	uint64_t spend = step*nBurnFactor;
	return std::make_tuple (true, spend, string("VmScript Sucess\n"));

}

shared_ptr<CAccount> CVmScriptRun::GetNewAccount(shared_ptr<CAccount>& vOldAccount) {
	if (NewAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = NewAccont.begin(); Iter != NewAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (temp.get()->keyID == vOldAccount.get()->keyID) {
			NewAccont.erase(Iter);
			return temp;
		}
	}
	return NULL;
}
shared_ptr<CAccount> CVmScriptRun::GetAccount(shared_ptr<CAccount>& Account) {
	if (RawAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = RawAccont.begin(); Iter != RawAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (Account.get()->keyID == temp.get()->keyID) {
			return temp;
		}
	}
	return NULL;
}
vector_unsigned_char CVmScriptRun::GetAccountID(CVmOperate value) {
	vector_unsigned_char accountid;
	//if (value.type == ACCOUNTID) {
	//	accountid.assign(value.accountid, value.accountid + 6);
	//} else if (value.type == KEYID) {
		//accountid.assign(value.accountid, value.accountid + 20);
	//}
	return accountid;
}
bool CVmScriptRun::CheckOperate(const vector<CVmOperate> &listoperate) const {
	// judge contract rulue
	uint64_t addmoey = 0, miusmoney = 0;
	uint64_t temp = 0;
	for (auto& it : listoperate) {

		if (it.opeatortype == ADD_FREE ) {
			memcpy(&temp,it.money,sizeof(it.money));
			addmoey += temp;
		}

		if (it.opeatortype == MINUS_FREE) {

			/// ӶǮʱ߶ȱڵǰtip߶
			if(it.outheight < height)
			{
				return false;
			}
			vector<unsigned char > accountid(it.accountid,it.accountid+sizeof(it.accountid));
			CRegID regId(accountid);
			CTransaction* secure = static_cast<CTransaction*>(listTx.get());
			/// current tx's script cant't mius other script's regid
			if(m_ScriptDBTip->HaveScript(regId) && regId != boost::get<CRegID>(secure->desUserId))
			{
				return false;
			}
			memcpy(&temp,it.money,sizeof(it.money));
			miusmoney += temp;
		}
		vector<unsigned char> accountid(it.accountid, it.accountid + sizeof(it.accountid));
		CRegID regId(accountid);
		if(regId.IsEmpty() || regId.getKeyID( *m_view) == uint160(0))
			return false;
		/// if account script id ,the it.opeatortype must be ADD_FREE or MINUS_FREE
		if (m_ScriptDBTip->HaveScript(regId)|| it.opeatortype != MINUS_FREE) {
			return false;
		}
	}
	if (addmoey != miusmoney)
	{
		return false;
	}
	return true;
}

shared_ptr<vector<CVmOperate>> CVmScriptRun::GetOperate() const {
	auto tem = make_shared<vector<CVmOperate>>();
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;<commit_msg>modify VmScriptRun.cpp<commit_after>/*
 * ScriptCheck.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: ranger.shi
 */
#include "VmScriptRun.h"
#include "tx.h"
#include "util.h"
#include <boost/foreach.hpp>
CVmScriptRun::CVmScriptRun() {
	RawAccont.clear();
	NewAccont.clear();
	height = 0;
	m_ScriptDBTip = NULL;
	m_view = NULL;
	m_dblog = std::make_shared<std::vector<CScriptDBOperLog> >();
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetRawAccont() {
	return RawAccont;
}
vector<shared_ptr<CAccount> > &CVmScriptRun::GetNewAccont() {
	return NewAccont;
}

bool CVmScriptRun::intial(shared_ptr<CBaseTransaction> & Tx, CAccountViewCache& view, int nheight) {

	m_output.clear();
	listTx = Tx;
	height = nheight;
	m_view = &view;
	vector<unsigned char> vScript;

	if (Tx.get()->nTxType != CONTRACT_TX) {
		LogPrint("ERROR", "%s\r\n", "err param");
		assert(0);
		return false;
	}

	CTransaction* secure = static_cast<CTransaction*>(Tx.get());
	if (!m_ScriptDBTip->GetScript(boost::get<CRegID>(secure->desUserId), vScript)) {
		LogPrint("ERROR", "Script is not Registed %s\r\n", boost::get<CRegID>(secure->desUserId).ToString());
		return false;
	}

	CDataStream stream(vScript, SER_DISK, CLIENT_VERSION);
	try {
		stream >> vmScript;
	} catch (exception& e) {
		LogPrint("ERROR", "%s\r\n", "CVmScriptRun::intial() Unserialize to vmScript error");
		throw runtime_error("CVmScriptRun::intial() Unserialize to vmScript error:" + string(e.what()));
	}

	if (vmScript.IsValid() == false){
		LogPrint("ERROR", "%s\r\n", "CVmScriptRun::intial() vmScript.IsValid error");
		return false;
	}

	pMcu = make_shared<CVir8051>(vmScript.Rom, secure->vContract);
	return true;
}

CVmScriptRun::~CVmScriptRun() {

}
tuple<bool, uint64_t, string> CVmScriptRun::run(shared_ptr<CBaseTransaction>& Tx, CAccountViewCache& view, CScriptDBViewCache& VmDB, int nheight,
		uint64_t nBurnFactor, uint64_t &uRunStep) {

	if(nBurnFactor == 0)
	{
		assert(0);
		return std::make_tuple (false, 0, string("VmScript nBurnFactor == 0 \n"));
	}
	m_ScriptDBTip = &VmDB;

	CTransaction* tx = static_cast<CTransaction*>(Tx.get());
	uint64_t maxstep = tx->llFees;///nBurnFactor;
	tuple<bool, uint64_t, string> mytuple;
	if (!intial(Tx, view, nheight)) {
		return std::make_tuple (false, 0, string("VmScript inital Failed\n"));

	}

	int64_t step = pMcu.get()->run(maxstep,this);
	if (0 == step) {
		return std::make_tuple(false, 0, string("VmScript run Failed\n"));
	} else if (-1 == step) {
		return std::make_tuple(false, 0, string("execure tx contranct run step exceed the max step limit\n"));
	}

	uRunStep = step;
	LogPrint("CONTRACT_TX", "tx:%s,step:%ld\n", tx->ToString(view), step);
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
	Contractstream >> retvmcode;

	if (!CheckOperate(m_output)) {
		return std::make_tuple (false, 0, string("VmScript CheckOperate Failed \n"));

	}
	if (!OpeatorAccount(m_output, view)) {
		return std::make_tuple (false, 0, string("VmScript OpeatorAccount Failed\n"));
	}
	uint64_t spend = step*nBurnFactor;
	return std::make_tuple (true, spend, string("VmScript Sucess\n"));

}

shared_ptr<CAccount> CVmScriptRun::GetNewAccount(shared_ptr<CAccount>& vOldAccount) {
	if (NewAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = NewAccont.begin(); Iter != NewAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (temp.get()->keyID == vOldAccount.get()->keyID) {
			NewAccont.erase(Iter);
			return temp;
		}
	}
	return NULL;
}
shared_ptr<CAccount> CVmScriptRun::GetAccount(shared_ptr<CAccount>& Account) {
	if (RawAccont.size() == 0)
		return NULL;
	vector<shared_ptr<CAccount> >::iterator Iter;
	for (Iter = RawAccont.begin(); Iter != RawAccont.end(); Iter++) {
		shared_ptr<CAccount> temp = *Iter;
		if (Account.get()->keyID == temp.get()->keyID) {
			return temp;
		}
	}
	return NULL;
}
vector_unsigned_char CVmScriptRun::GetAccountID(CVmOperate value) {
	vector_unsigned_char accountid;
	//if (value.type == ACCOUNTID) {
	//	accountid.assign(value.accountid, value.accountid + 6);
	//} else if (value.type == KEYID) {
		//accountid.assign(value.accountid, value.accountid + 20);
	//}
	return accountid;
}
bool CVmScriptRun::CheckOperate(const vector<CVmOperate> &listoperate) const {
	// judge contract rulue
	uint64_t addmoey = 0, miusmoney = 0;
	uint64_t temp = 0;
	for (auto& it : listoperate) {

		if (it.opeatortype == ADD_FREE ) {
			memcpy(&temp,it.money,sizeof(it.money));
			addmoey += temp;
		}

		if (it.opeatortype == MINUS_FREE) {

			vector<unsigned char > accountid(it.accountid,it.accountid+sizeof(it.accountid));
			CRegID regId(accountid);
			CTransaction* secure = static_cast<CTransaction*>(listTx.get());
			/// current tx's script cant't mius other script's regid
			if(m_ScriptDBTip->HaveScript(regId) && regId != boost::get<CRegID>(secure->desUserId))
			{
				return false;
			}
			memcpy(&temp,it.money,sizeof(it.money));
			miusmoney += temp;
		}
		vector<unsigned char> accountid(it.accountid, it.accountid + sizeof(it.accountid));
		CRegID regId(accountid);
		if(regId.IsEmpty() || regId.getKeyID( *m_view) == uint160(0))
			return false;
		//  app only be allowed minus self money
		if (!m_ScriptDBTip->HaveScript(regId) && it.opeatortype == MINUS_FREE) {
			return false;
		}
	}
	if (addmoey != miusmoney)
	{
		return false;
	}
	return true;
}

shared_ptr<vector<CVmOperate>> CVmScriptRun::GetOperate() const {
	auto tem = make_shared<vector<CVmOperate>>();
	shared_ptr<vector<unsigned char>> retData = pMcu.get()->GetRetData();
	CDataStream Contractstream(*retData.get(), SER_DISK, CLIENT_VERSION);
	vector<CVmOperate> retvmcode;
{'fraction_non_alphanumeric': 0.16238358054501553, 'fraction_numerical': 0.008968609865470852, 'mean_word_length': 5.2215665236051505, 'pattern_counts': {'":': 0, '<': 88, '<?xml version=': 0, '>': 129, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1335050', 'n_tokens_mistral': 4667, 'n_tokens_neox': 4357, 'n_words': 849}