| 986 | } |
| 987 | |
| 988 | bool ConnectBlock(CBlock &block, CCacheWrapper &cw, CBlockIndex *pIndex, CValidationState &state, bool fJustCheck) { |
| 989 | AssertLockHeld(cs_main); |
| 990 | |
| 991 | auto bm = MAKE_BENCHMARK("ConnectBlock"); |
| 992 | bool isGensisBlock = (block.GetHeight() == 0) && (block.GetHash() == SysCfg().GetGenesisBlockHash()); |
| 993 | |
| 994 | // Check it again in case a previous version let a bad block in |
| 995 | if (!isGensisBlock && !CheckBlock(block, state, cw, !fJustCheck, !fJustCheck)) |
| 996 | return state.DoS(100, ERRORMSG(" check block error"), REJECT_INVALID, "check-block-error"); |
| 997 | |
| 998 | if (!fJustCheck) { |
| 999 | // Verify that the cache's current state corresponds to the previous block |
| 1000 | uint256 hashPrevBlock = pIndex->pprev == nullptr ? uint256() : pIndex->pprev->GetBlockHash(); |
| 1001 | if (hashPrevBlock != cw.blockCache.GetBestBlockHash()) { |
| 1002 | LogPrint(BCLog::INFO, "[%d] hashPrevBlock=%s, bestblock=%s\n", pIndex->height, hashPrevBlock.GetHex(), |
| 1003 | cw.blockCache.GetBestBlockHash().GetHex()); |
| 1004 | |
| 1005 | assert(hashPrevBlock == cw.blockCache.GetBestBlockHash()); |
| 1006 | } |
| 1007 | } |
| 1008 | |
| 1009 | // Special case for the genesis block, skipping connection of its transactions. |
| 1010 | if (isGensisBlock) { |
| 1011 | if (!ProcessGenesisBlock(block, cw, pIndex, state)) { |
| 1012 | return state.DoS(100, ERRORMSG("[0] process genesis block error"), |
| 1013 | REJECT_INVALID, "process genesis-block-error"); |
| 1014 | } |
| 1015 | return true; |
| 1016 | } |
| 1017 | |
| 1018 | // In stable coin genesis, need to verify txid for every transaction in block. |
| 1019 | if (block.GetHeight() == SysCfg().GetVer2GenesisHeight()) { |
| 1020 | assert(block.vptx.size() == 4); |
| 1021 | |
| 1022 | vector<string> ScoinTxIDs = IniCfg().GetStableCoinGenesisTxid(SysCfg().NetworkID()); |
| 1023 | assert(ScoinTxIDs.size() == 3); |
| 1024 | for (int32_t index = 0; index < 3; ++index) { |
| 1025 | LogPrint(BCLog::INFO, "stable coin genesis block, txid actual: %s, should be: %s, in detail: %s\n", |
| 1026 | block.vptx[index + 1]->GetHash().GetHex(), ScoinTxIDs[index], |
| 1027 | block.vptx[index + 1]->ToString(cw.accountCache)); |
| 1028 | |
| 1029 | assert(block.vptx[index + 1]->nTxType == UCOIN_MINT_TX); |
| 1030 | if (SysCfg().NetworkID() == MAIN_NET) { |
| 1031 | assert(block.vptx[index + 1]->GetHash() == uint256S(ScoinTxIDs[index])); |
| 1032 | } |
| 1033 | } |
| 1034 | } |
| 1035 | |
| 1036 | VoteDelegate curDelegate; |
| 1037 | uint32_t totalDelegateNum; |
| 1038 | if (!VerifyRewardTx(&block, cw, curDelegate, totalDelegateNum)) |
| 1039 | return state.DoS(100, ERRORMSG("[%d] verify reward tx error", block.GetHeight()), REJECT_INVALID, "bad-reward-tx"); |
| 1040 | |
| 1041 | CBlockUndo blockUndo; |
| 1042 | std::vector<pair<uint256, CDiskTxPos> > vPos; |
| 1043 | vPos.reserve(block.vptx.size()); |
| 1044 | |
| 1045 | CDiskTxPos pos(pIndex->GetBlockPos(), GetSizeOfCompactSize(block.vptx.size()), CTxCord(pIndex->height, 0)); |
no test coverage detected