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; }