mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-17 13:22:03 +01:00
optimization: look for NULL prevouts in the sorted values
For the 2 input case we simply check them both, like we did with equality. For the general case, we take advantage of sorting, making invalid value detection constant time instead of linear in the worst case. > cmake -B build -DBUILD_BENCH=ON -DCMAKE_BUILD_TYPE=Release && cmake --build build -j$(nproc) && build/src/bench/bench_bitcoin -filter='CheckBlockBench|DuplicateInputs|ProcessTransactionBench' -min-time=10000 > C++ compiler .......................... AppleClang 16.0.0.16000026 | ns/block | block/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 179,971.00 | 5,556.45 | 0.3% | 11.02 | `CheckBlockBench` | ns/op | op/s | err% | total | benchmark |--------------------:|--------------------:|--------:|----------:|:---------- | 963,177.98 | 1,038.23 | 1.7% | 10.92 | `DuplicateInputs` | 9,410.90 | 106,259.75 | 0.3% | 11.01 | `ProcessTransactionBench` > C++ compiler .......................... GNU 13.3.0 | ns/block | block/s | err% | ins/block | cyc/block | IPC | bra/block | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 834,855.94 | 1,197.81 | 0.0% | 6,518,548.86 | 2,656,039.78 | 2.454 | 919,160.84 | 1.5% | 10.78 | `CheckBlockBench` | ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 4,261,492.75 | 234.66 | 0.0% | 17,379,823.40 | 13,559,793.33 | 1.282 | 4,265,714.28 | 3.4% | 11.00 | `DuplicateInputs` | 55,819.53 | 17,914.88 | 0.1% | 227,828.15 | 177,520.09 | 1.283 | 15,184.36 | 0.4% | 10.91 | `ProcessTransactionBench`
This commit is contained in:
parent
cd94cd7de4
commit
9a3397456d
@ -44,25 +44,27 @@ bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
|
||||
}
|
||||
}
|
||||
} else if (tx.vin.size() == 2) {
|
||||
if (tx.vin[0].prevout == tx.vin[1].prevout) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
if (tx.vin[0].prevout.IsNull() || tx.vin[1].prevout.IsNull()) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
|
||||
}
|
||||
} else {
|
||||
if (tx.vin.size() == 2) {
|
||||
if (tx.vin[0].prevout == tx.vin[1].prevout) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
} else {
|
||||
std::vector<COutPoint> sortedPrevouts;
|
||||
sortedPrevouts.reserve(tx.vin.size());
|
||||
for (const auto& txin : tx.vin) {
|
||||
sortedPrevouts.push_back(txin.prevout);
|
||||
}
|
||||
std::sort(sortedPrevouts.begin(), sortedPrevouts.end());
|
||||
if (std::ranges::adjacent_find(sortedPrevouts) != sortedPrevouts.end()) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
std::vector<COutPoint> sortedPrevouts;
|
||||
sortedPrevouts.reserve(tx.vin.size());
|
||||
for (const auto& txin : tx.vin) {
|
||||
sortedPrevouts.push_back(txin.prevout);
|
||||
}
|
||||
std::sort(sortedPrevouts.begin(), sortedPrevouts.end());
|
||||
if (std::ranges::adjacent_find(sortedPrevouts) != sortedPrevouts.end()) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
|
||||
for (const auto& txin : tx.vin) {
|
||||
if (txin.prevout.IsNull()) {
|
||||
for (const auto& in : sortedPrevouts) {
|
||||
if (!in.hash.IsNull()) break; // invalid values can only be at the beginning
|
||||
if (in.IsNull()) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user