Skip to content

Commit 71bc39e

Browse files
committed
Merge #9049: Remove duplicatable duplicate-input check from CheckTransaction
e2b3fb3 Optimize vInOutPoints insertion a bit (Matt Corallo) eecffe5 Remove redundant duplicate-input check from CheckTransaction (Matt Corallo) b2e178a Add deserialize + CheckBlock benchmarks, and a full block hex (Matt Corallo)
2 parents e536499 + e2b3fb3 commit 71bc39e

File tree

5 files changed

+82
-11
lines changed

5 files changed

+82
-11
lines changed

src/Makefile.bench.include

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ bin_PROGRAMS += bench/bench_bitcoin
66
BENCH_SRCDIR = bench
77
BENCH_BINARY = bench/bench_bitcoin$(EXEEXT)
88

9+
RAW_TEST_FILES = \
10+
bench/data/block413567.raw
11+
GENERATED_TEST_FILES = $(RAW_TEST_FILES:.raw=.raw.h)
912

1013
bench_bench_bitcoin_SOURCES = \
1114
bench/bench_bitcoin.cpp \
1215
bench/bench.cpp \
1316
bench/bench.h \
17+
bench/checkblock.cpp \
1418
bench/Examples.cpp \
1519
bench/rollingbloom.cpp \
1620
bench/crypto_hash.cpp \
@@ -20,6 +24,8 @@ bench_bench_bitcoin_SOURCES = \
2024
bench/base58.cpp \
2125
bench/lockedpool.cpp
2226

27+
nodist_bench_bench_bitcoin_SOURCES = $(GENERATED_TEST_FILES)
28+
2329
bench_bench_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CLFAGS) $(EVENT_PTHREADS_CFLAGS) -I$(builddir)/bench/
2430
bench_bench_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
2531
bench_bench_bitcoin_LDADD = \
@@ -45,14 +51,23 @@ endif
4551
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
4652
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
4753

48-
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno
54+
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_TEST_FILES)
4955

5056
CLEANFILES += $(CLEAN_BITCOIN_BENCH)
5157

58+
bench/checkblock.cpp: bench/data/block413567.raw.h
59+
5260
bitcoin_bench: $(BENCH_BINARY)
5361

5462
bench: $(BENCH_BINARY) FORCE
5563
$(BENCH_BINARY)
5664

5765
bitcoin_bench_clean : FORCE
5866
rm -f $(CLEAN_BITCOIN_BENCH) $(bench_bench_bitcoin_OBJECTS) $(BENCH_BINARY)
67+
68+
%.raw.h: %.raw
69+
@$(MKDIR_P) $(@D)
70+
@echo "static unsigned const char $(*F)[] = {" >> $@
71+
@$(HEXDUMP) -v -e '8/1 "0x%02x, "' -e '"\n"' $< | $(SED) -e 's/0x ,//g' >> $@
72+
@echo "};" >> $@
73+
@echo "Generated $@"

src/bench/checkblock.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) 2016 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include "bench.h"
6+
7+
#include "chainparams.h"
8+
#include "main.h"
9+
#include "consensus/validation.h"
10+
11+
namespace block_bench {
12+
#include "bench/data/block413567.raw.h"
13+
}
14+
15+
// These are the two major time-sinks which happen after we have fully received
16+
// a block off the wire, but before we can relay the block on to peers using
17+
// compact block relay.
18+
19+
static void DeserializeBlockTest(benchmark::State& state)
20+
{
21+
CDataStream stream((const char*)block_bench::block413567,
22+
(const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
23+
SER_NETWORK, PROTOCOL_VERSION);
24+
char a;
25+
stream.write(&a, 1); // Prevent compaction
26+
27+
while (state.KeepRunning()) {
28+
CBlock block;
29+
stream >> block;
30+
assert(stream.Rewind(sizeof(block_bench::block413567)));
31+
}
32+
}
33+
34+
static void DeserializeAndCheckBlockTest(benchmark::State& state)
35+
{
36+
CDataStream stream((const char*)block_bench::block413567,
37+
(const char*)&block_bench::block413567[sizeof(block_bench::block413567)],
38+
SER_NETWORK, PROTOCOL_VERSION);
39+
char a;
40+
stream.write(&a, 1); // Prevent compaction
41+
42+
Consensus::Params params = Params(CBaseChainParams::MAIN).GetConsensus();
43+
44+
while (state.KeepRunning()) {
45+
CBlock block; // Note that CBlock caches its checked state, so we need to recreate it here
46+
stream >> block;
47+
assert(stream.Rewind(sizeof(block_bench::block413567)));
48+
49+
CValidationState state;
50+
assert(CheckBlock(block, state, params));
51+
}
52+
}
53+
54+
BENCHMARK(DeserializeBlockTest);
55+
BENCHMARK(DeserializeAndCheckBlockTest);

src/bench/data/block413567.raw

976 KB
Binary file not shown.

src/main.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
11041104

11051105

11061106

1107-
bool CheckTransaction(const CTransaction& tx, CValidationState &state)
1107+
bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
11081108
{
11091109
// Basic checks that don't depend on any context
11101110
if (tx.vin.empty())
@@ -1128,13 +1128,14 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
11281128
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
11291129
}
11301130

1131-
// Check for duplicate inputs
1132-
set<COutPoint> vInOutPoints;
1133-
for (const auto& txin : tx.vin)
1134-
{
1135-
if (vInOutPoints.count(txin.prevout))
1136-
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
1137-
vInOutPoints.insert(txin.prevout);
1131+
// Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
1132+
if (fCheckDuplicateInputs) {
1133+
set<COutPoint> vInOutPoints;
1134+
for (const auto& txin : tx.vin)
1135+
{
1136+
if (!vInOutPoints.insert(txin.prevout).second)
1137+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
1138+
}
11381139
}
11391140

11401141
if (tx.IsCoinBase())
@@ -3461,7 +3462,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
34613462

34623463
// Check transactions
34633464
for (const auto& tx : block.vtx)
3464-
if (!CheckTransaction(tx, state))
3465+
if (!CheckTransaction(tx, state, false))
34653466
return state.Invalid(false, state.GetRejectCode(), state.GetRejectReason(),
34663467
strprintf("Transaction check failed (tx hash %s) %s", tx.GetHash().ToString(), state.GetDebugMessage()));
34673468

src/main.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight);
343343
/** Transaction validation functions */
344344

345345
/** Context-independent validity checks */
346-
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
346+
bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
347347

348348
namespace Consensus {
349349

0 commit comments

Comments
 (0)