Beispiel #1
0
bool VerifyPosTx(CAccountViewCache &accView, const CBlock *pBlock, CTransactionDBCache &txCache, CScriptDBViewCache &scriptCache, bool bNeedRunTx) {
//	LogPrint("INFO", "VerifyPoxTx begin\n");
	uint64_t maxNonce = SysCfg().GetBlockMaxNonce(); //cacul times

	if (pBlock->GetNonce() > maxNonce) {
		return ERRORMSG("Nonce is larger than maxNonce");
	}

	if (pBlock->GetHashMerkleRoot() != pBlock->BuildMerkleTree()) {
		return ERRORMSG("hashMerkleRoot is error");
	}
	CAccountViewCache view(accView, true);
	CScriptDBViewCache scriptDBView(scriptCache, true);
	CAccount account;
	CRewardTransaction *prtx = (CRewardTransaction *) pBlock->vptx[0].get();
	if (view.GetAccount(prtx->account, account)) {
		if(!CheckSignScript(pBlock->SignatureHash(), pBlock->GetSignature(), account.PublicKey)) {
			if (!CheckSignScript(pBlock->SignatureHash(), pBlock->GetSignature(), account.MinerPKey)) {
//				LogPrint("ERROR", "block verify fail\r\n");
//				LogPrint("ERROR", "block hash:%s\n", pBlock->GetHash().GetHex());
//				LogPrint("ERROR", "signature block:%s\n", HexStr(pBlock->vSignature.begin(), pBlock->vSignature.end()));
				return ERRORMSG("Verify miner publickey signature error");
			}
		}
	} else {
		return ERRORMSG("AccountView have no the accountid");
	}

	//校验reward_tx 版本是否正确

	if (prtx->nVersion != nTxVersion2) {
		return ERRORMSG("CTransaction CheckTransction,tx version is not equal current version, (tx version %d: vs current %d)",
				prtx->nVersion, nTxVersion2);
	}


	if (bNeedRunTx) {
		int64_t nTotalFuel(0);
		uint64_t nTotalRunStep(0);
		for (unsigned int i = 1; i < pBlock->vptx.size(); i++) {
			shared_ptr<CBaseTransaction> pBaseTx = pBlock->vptx[i];
			if (uint256() != txCache.IsContainTx(pBaseTx->GetHash())) {
				return ERRORMSG("VerifyPosTx duplicate tx hash:%s", pBaseTx->GetHash().GetHex());
			}
			CTxUndo txundo;
			CValidationState state;
			if (CONTRACT_TX == pBaseTx->nTxType) {
				LogPrint("vm", "tx hash=%s VerifyPosTx run contract\n", pBaseTx->GetHash().GetHex());
			}
			pBaseTx->nFuelRate = pBlock->GetFuelRate();
			if (!pBaseTx->ExecuteTx(i, view, state, txundo, pBlock->GetHeight(), txCache, scriptDBView)) {
				return ERRORMSG("transaction UpdateAccount account error");
			}
			nTotalRunStep += pBaseTx->nRunStep;
			if(nTotalRunStep > MAX_BLOCK_RUN_STEP) {
				return ERRORMSG("block total run steps exceed max run step");
			}

			nTotalFuel += pBaseTx->GetFuel(pBlock->GetFuelRate());
			LogPrint("fuel", "VerifyPosTx total fuel:%d, tx fuel:%d runStep:%d fuelRate:%d txhash:%s \n",nTotalFuel, pBaseTx->GetFuel(pBlock->GetFuelRate()), pBaseTx->nRunStep, pBlock->GetFuelRate(), pBaseTx->GetHash().GetHex());
		}

		if(nTotalFuel != pBlock->GetFuel()) {
			return ERRORMSG("fuel value at block header calculate error");
		}

		if (view.GetAccount(prtx->account, account)) {
			//available acc
//     		cout << "check block hash:" << pBlock->SignatureHash().GetHex() << endl;
//			cout << "check signature:" << HexStr(pBlock->vSignature) << endl;
//			cout <<"account miner"<< account.ToString()<< endl;
			if(account.GetAccountPos(pBlock->GetHeight()) <= 0 || !account.IsMiner(pBlock->GetHeight()))
				return ERRORMSG("coindays of account dismatch, can't be miner, account info:%s", account.ToString());
		} else {
			LogPrint("ERROR", "AccountView have no the accountid\r\n");
			return false;
		}
	}

	uint256 prevblockhash = pBlock->GetHashPrevBlock();
	const uint256 targetHash = CBigNum().SetCompact(pBlock->GetBits()).getuint256(); //target hash difficult

	uint64_t posacc = account.GetAccountPos(pBlock->GetHeight());
/*
	arith_uint256 bnNew;
	bnNew.SetCompact(pBlock->nBits);
	string  timeFormat = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pBlock->nTime);
	LogPrint("coinday","height:%.10d, account:%-10s, coinday:%.10ld, difficulty=%.8lf,  time=%-20s, interval=%d\n", pBlock->nHeight, account.regID.ToString(), posacc/COIN/SysCfg().GetIntervalPos(), CaculateDifficulty(bnNew.GetCompact()), timeFormat,  pBlock->nTime-chainActive[pBlock->nHeight-1]->nTime);
*/
	if (posacc == 0) {
		return ERRORMSG("Account have no pos");
	}

	uint256 adjusthash = GetAdjustHash(targetHash, posacc, pBlock->GetHeight()-1); //adjust nbits

    //need compute this block proofofwork
	struct PosTxInfo postxinfo;
	postxinfo.nVersion = pBlock->GetVersion();
	postxinfo.hashPrevBlock = prevblockhash;
	postxinfo.hashMerkleRoot = account.GetHash();
	postxinfo.nValues = account.llValues;
	postxinfo.nTime = pBlock->GetTime();
	postxinfo.nNonce = pBlock->GetNonce();
	postxinfo.nHeight = pBlock->GetHeight();
	postxinfo.nFuel = pBlock->GetFuel();
	postxinfo.nFuelRate = pBlock->GetFuelRate();
	uint256 curhash = postxinfo.GetHash();

	LogPrint("miner", "Miner account info:%s\n", account.ToString());
	LogPrint("miner", "VerifyPosTx block hash:%s, postxinfo:%s\n", pBlock->GetHash().GetHex(), postxinfo.ToString().c_str());
	if(pBlock->GetHashPos() != curhash) {
		return ERRORMSG("PosHash Error: \n"
					" computer PoS hash:%s \n"
					" block PoS hash:%s\n", curhash.GetHex(),  pBlock->GetHashPos().GetHex());
	}
	if (UintToArith256(curhash) > UintToArith256(adjusthash)) {
		return ERRORMSG("Account ProofOfWorkLimit error: \n"
		           "   pos hash:%s \n"
		           "adjust hash:%s\r\n", curhash.GetHex(), adjusthash.GetHex());
	}

	return true;
}
Beispiel #2
0
bool CreatePosTx(const CBlockIndex *pPrevIndex, CBlock *pBlock, set<CKeyID>&setCreateKey, CAccountViewCache &view,
		CTransactionDBCache &txCache, CScriptDBViewCache &scriptCache) {
	set<CKeyID> setKeyID;
	setKeyID.clear();

	set<CAccount, CAccountComparator> setAcctInfo;

	{
		LOCK2(cs_main, pwalletMain->cs_wallet);

		if((unsigned int)(chainActive.Tip()->nHeight + 1) !=  pBlock->GetHeight())
			return false;
		pwalletMain->GetKeys(setKeyID, true);                         // first:get keyID from pwalletMain
		if (setKeyID.empty()) {
			return ERRORMSG("CreatePosTx setKeyID empty");
		}

		LogPrint("INFO","CreatePosTx block time:%d\n",  pBlock->GetTime());
		for(const auto &keyid:setKeyID) {                             //second:get account by keyID
			//find CAccount info by keyid
			if(setCreateKey.size()) {
				bool bfind = false;
				for(auto &item: setCreateKey){
					if(item == keyid){
						bfind = true;
						break;
					}
				}
				if (!bfind)
					continue;
			}
			CUserID userId = keyid;
			CAccount acctInfo;
			if (view.GetAccount(userId, acctInfo)) {     // check  acctInfo is or not allowed to mining ,
				//available
//				LogPrint("miner", "account info:regid=%s keyid=%s ncoinday=%lld isMiner=%d\n", acctInfo.regID.ToString(),
//						acctInfo.keyID.ToString(), acctInfo.GetAccountPos(pBlock->nHeight), acctInfo.IsMiner(pBlock->nHeight));
				if (acctInfo.IsRegister() && acctInfo.GetAccountPos(pBlock->GetHeight()) > 0 && acctInfo.IsMiner(pBlock->GetHeight())) {
					setAcctInfo.insert(std::move(acctInfo));
//					LogPrint("miner", "miner account info:%s\n", acctInfo.ToString());
				}
			}
		}
	}

	if (setAcctInfo.empty()) {
		setCreateKey.clear();
		LogPrint("INFO", "CreatePosTx setSecureAcc empty");
		return false;
	}

	uint64_t maxNonce = SysCfg().GetBlockMaxNonce(); //cacul times

	uint256 prevblockhash = pPrevIndex->GetBlockHash();
	const uint256 targetHash = CBigNum().SetCompact(pBlock->GetBits()).getuint256(); //target hash difficult
	set<CAccount, CAccountComparator>::iterator iterAcct = setAcctInfo.begin();
	for (;iterAcct!=setAcctInfo.end();++iterAcct) {                            //third: 根据不同的账户 ,去计算挖矿
		CAccount  &item = const_cast<CAccount&>(*iterAcct);
		uint64_t posacc = item.GetAccountPos(pBlock->GetHeight());
		if (0 == posacc) {  //have no pos
			LogPrint("ERROR", "CreatePosTx posacc zero\n");
			continue;
		}
		LogPrint("miner", "miner account:%s\n", item.ToString());
//		LogPrint("INFO", "target hash:%s\n", targetHash.ToString());
//		LogPrint("INFO", "posacc:%d\n", posacc);
		uint256 adjusthash = GetAdjustHash(targetHash, posacc, pBlock->GetHeight()-1); //adjust nbits
//		LogPrint("INFO", "adjusthash:%s\n", adjusthash.ToString());

		//need compute this block proofofwork
		struct PosTxInfo postxinfo;
		postxinfo.nVersion = pBlock->GetVersion();
		postxinfo.hashPrevBlock = prevblockhash;
		postxinfo.hashMerkleRoot = item.GetHash();
		postxinfo.nValues = item.llValues;
		postxinfo.nHeight = pBlock->GetHeight();
		postxinfo.nFuel = pBlock->GetFuel();
		postxinfo.nFuelRate = pBlock->GetFuelRate();
		postxinfo.nTime = pBlock->GetTime(); //max(pPrevIndex->GetMedianTimePast() + 1, GetAdjustedTime());
		unsigned int nNonce = 0;
		for (; nNonce < maxNonce; ++nNonce) {        //循环的 更改随机数,计算curhash看是否满足
			postxinfo.nNonce = nNonce;
			pBlock->SetNonce(nNonce);
			uint256 curhash = postxinfo.GetHash();

			if (UintToArith256(curhash) <= UintToArith256(adjusthash)) {
				CRegID regid;

				if (pAccountViewTip->GetRegId(item.keyID, regid)) {
					CRewardTransaction *prtx = (CRewardTransaction *) pBlock->vptx[0].get();
					prtx->account = regid;                                   //存矿工的 账户ID
					prtx->nHeight = pPrevIndex->nHeight+1;

					pBlock->SetHashMerkleRoot(pBlock->BuildMerkleTree());
					pBlock->SetHashPos(curhash);
					LogPrint("INFO", "find pos tx hash succeed: \n"
									  "   pos hash:%s \n"
									  "adjust hash:%s \r\n", curhash.GetHex(), adjusthash.GetHex());
					vector<unsigned char> vSign;
					if (pwalletMain->Sign(item.keyID, pBlock->SignatureHash(), vSign,
							item.MinerPKey.IsValid())) {
						LogPrint("INFO", "Create new block hash:%s\n", pBlock->GetHash().GetHex());
						LogPrint("miner", "Miner account info:%s\n", item.ToString());
						LogPrint("miner", "CreatePosTx block hash:%s, postxinfo:%s\n",pBlock->GetHash().GetHex(), postxinfo.ToString().c_str());
						pBlock->SetSignature(vSign);
						return true;
					} else {
						LogPrint("ERROR", "sign fail\r\n");
					}
				} else {
					LogPrint("ERROR", "GetKey fail or GetVec6 fail\r\n");
				}

			}
		}
	}

	return false;
}