Skip to content

Commit b911929

Browse files
committed
perf: parse CCbTx once during block validation (check CbTx)
It combines CheckCbTx with other checks (CheckCbTxMerkleRoots and CheckCbTxBestChainlock)
1 parent d4f4173 commit b911929

File tree

3 files changed

+43
-34
lines changed

3 files changed

+43
-34
lines changed

src/evo/cbtx.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,8 @@
1919
#include <deploymentstatus.h>
2020

2121

22-
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state)
22+
bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationState& state)
2323
{
24-
if (tx.nType != TRANSACTION_COINBASE) {
25-
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-type");
26-
}
27-
28-
if (!tx.IsCoinBase()) {
29-
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-invalid");
30-
}
31-
32-
const auto opt_cbTx = GetTxPayload<CCbTx>(tx);
33-
if (!opt_cbTx) {
34-
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-payload");
35-
}
36-
const auto& cbTx = *opt_cbTx;
37-
3824
if (cbTx.nVersion == CCbTx::Version::INVALID || cbTx.nVersion >= CCbTx::Version::UNKNOWN) {
3925
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-version");
4026
}

src/evo/cbtx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class CCbTx
6464
};
6565
template<> struct is_serializable_enum<CCbTx::Version> : std::true_type {};
6666

67-
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state);
67+
bool CheckCbTx(const CCbTx& cbTx, const CBlockIndex* pindexPrev, TxValidationState& state);
6868

6969
bool CheckCbTxMerkleRoots(const CBlock& block, const CCbTx& cbTx, const CBlockIndex* pindex,
7070
const llmq::CQuorumBlockProcessor& quorum_block_processor, CSimplifiedMNList&& sml,

src/evo/specialtxman.cpp

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)