示例#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;
}