@@ -46,8 +46,16 @@ static bool CheckSpecialTxInner(CDeterministicMNManager& dmnman, llmq::CQuorumSn
4646 return CheckProUpRegTx (dmnman, tx, pindexPrev, state, view, check_sigs);
4747 case TRANSACTION_PROVIDER_UPDATE_REVOKE:
4848 return CheckProUpRevTx (dmnman, tx, pindexPrev, state, check_sigs);
49- case TRANSACTION_COINBASE:
50- return CheckCbTx (tx, pindexPrev, state);
49+ case TRANSACTION_COINBASE: {
50+ if (!tx.IsCoinBase ()) {
51+ return state.Invalid (TxValidationResult::TX_CONSENSUS, " bad-cbtx-invalid" );
52+ }
53+ if (const auto opt_cbTx = GetTxPayload<CCbTx>(tx)) {
54+ return CheckCbTx (*opt_cbTx, pindexPrev, state);
55+ } else {
56+ return state.Invalid (TxValidationResult::TX_CONSENSUS, " bad-cbtx-payload" );
57+ }
58+ }
5159 case TRANSACTION_QUORUM_COMMITMENT:
5260 return llmq::CheckLLMQCommitment (dmnman, qsnapman, chainman, tx, pindexPrev, state);
5361 case TRANSACTION_MNHF_SIGNAL:
@@ -136,15 +144,45 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB
136144 static int64_t nTimeMerkle = 0 ;
137145 static int64_t nTimeCbTxCL = 0 ;
138146 static int64_t nTimeMnehf = 0 ;
147+ static int64_t nTimePayload = 0 ;
148+
149+ int64_t nTime0 = GetTimeMicros ();
150+
151+ std::optional<CCbTx> opt_cbTx{std::nullopt };
152+ if (block.vtx .size () > 0 && block.vtx [0 ]->nType == TRANSACTION_COINBASE) {
153+ const auto & tx = block.vtx [0 ];
154+ if (!tx->IsCoinBase ()) {
155+ return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cbtx-invalid" );
156+ }
157+ if (opt_cbTx = GetTxPayload<CCbTx>(*tx); opt_cbTx) {
158+ TxValidationState tx_state;
159+ if (!CheckCbTx (*opt_cbTx, pindex->pprev , tx_state)) {
160+ assert (tx_state.GetResult () == TxValidationResult::TX_CONSENSUS ||
161+ tx_state.GetResult () == TxValidationResult::TX_BAD_SPECIAL);
162+ return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason (),
163+ strprintf (" Special Transaction check failed (tx hash %s) %s" ,
164+ tx->GetHash ().ToString (), tx_state.GetDebugMessage ()));
165+ }
166+ } else {
167+ return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cbtx-payload" );
168+ }
169+ }
139170
140171 int64_t nTime1 = GetTimeMicros ();
172+ nTimePayload += nTime1 - nTime0;
173+ LogPrint (BCLog::BENCHMARK, " - GetTxPayload: %.2fms [%.2fs]\n " , 0.001 * (nTime1 - nTime0),
174+ nTimePayload * 0.000001 );
141175
142176 const CCreditPool creditPool = m_cpoolman.GetCreditPool (pindex->pprev , m_consensus_params);
143177 if (DeploymentActiveAt (*pindex, m_consensus_params, Consensus::DEPLOYMENT_V20)) {
144178 LogPrint (BCLog::CREDITPOOL, " CSpecialTxProcessor::%s -- CCreditPool is %s\n " , __func__, creditPool.ToString ());
145179 }
146180
147- for (const auto & ptr_tx : block.vtx ) {
181+ for (size_t i = 0 ; i < block.vtx .size (); ++i) {
182+ // we validated CCbTx above, starts from the 2nd transaction
183+ if (i == 0 && block.vtx [i]->nType == TRANSACTION_COINBASE) continue ;
184+
185+ const auto ptr_tx = block.vtx [i];
148186 TxValidationState tx_state;
149187 // At this moment CheckSpecialTx() and ProcessSpecialTx() may fail by 2 possible ways:
150188 // consensus failures and "TX_BAD_SPECIAL"
@@ -194,21 +232,7 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB
194232 LogPrint (BCLog::BENCHMARK, " - m_dmnman: %.2fms [%.2fs]\n " , 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001 );
195233
196234 int64_t nTime5{nTime4};
197-
198235 if (fCheckCbTxMerkleRoots && block.vtx [0 ]->nType == TRANSACTION_COINBASE) {
199- int64_t nTime1_cbtx = GetTimeMicros ();
200-
201- const auto opt_cbTx = GetTxPayload<CCbTx>(*block.vtx [0 ]);
202- if (!opt_cbTx) {
203- return state.Invalid (BlockValidationResult::BLOCK_CONSENSUS, " bad-cbtx-payload" );
204- }
205- static int64_t nTimePayload = 0 ;
206-
207- int64_t nTime2_cbtx = GetTimeMicros ();
208- nTimePayload += nTime2_cbtx - nTime1_cbtx;
209- LogPrint (BCLog::BENCHMARK, " - GetTxPayload: %.2fms [%.2fs]\n " ,
210- 0.001 * (nTime2_cbtx - nTime1_cbtx), nTimePayload * 0.000001 );
211-
212236 if (!CheckCbTxMerkleRoots (block, *opt_cbTx, pindex, m_qblockman, CSimplifiedMNList (mn_list), state)) {
213237 // pass the state returned by the function above
214238 return false ;
@@ -220,7 +244,6 @@ bool CSpecialTxProcessor::ProcessSpecialTxsInBlock(const CBlock& block, const CB
220244 LogPrint (BCLog::BENCHMARK, " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n " , 0.001 * (nTime5 - nTime4),
221245 nTimeMerkle * 0.000001 );
222246
223-
224247 if (!CheckCbTxBestChainlock (*opt_cbTx, pindex, m_clhandler, state)) {
225248 // pass the state returned by the function above
226249 return false ;
0 commit comments