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.
5 #include <bench/bench.h>
7 #if defined(HAVE_CONSENSUS_LIB)
8 #include <script/bitcoinconsensus.h>
10 #include <script/script.h>
11 #include <script/sign.h>
16 // FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp.
17 static CMutableTransaction
BuildCreditingTransaction(const CScript
& scriptPubKey
)
19 CMutableTransaction txCredit
;
20 txCredit
.nVersion
= 1;
21 txCredit
.nLockTime
= 0;
22 txCredit
.vin
.resize(1);
23 txCredit
.vout
.resize(1);
24 txCredit
.vin
[0].prevout
.SetNull();
25 txCredit
.vin
[0].scriptSig
= CScript() << CScriptNum(0) << CScriptNum(0);
26 txCredit
.vin
[0].nSequence
= CTxIn::SEQUENCE_FINAL
;
27 txCredit
.vout
[0].scriptPubKey
= scriptPubKey
;
28 txCredit
.vout
[0].nValue
= 1;
33 // FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp.
34 static CMutableTransaction
BuildSpendingTransaction(const CScript
& scriptSig
, const CMutableTransaction
& txCredit
)
36 CMutableTransaction txSpend
;
38 txSpend
.nLockTime
= 0;
39 txSpend
.vin
.resize(1);
40 txSpend
.vout
.resize(1);
41 txSpend
.vin
[0].prevout
.hash
= txCredit
.GetHash();
42 txSpend
.vin
[0].prevout
.n
= 0;
43 txSpend
.vin
[0].scriptSig
= scriptSig
;
44 txSpend
.vin
[0].nSequence
= CTxIn::SEQUENCE_FINAL
;
45 txSpend
.vout
[0].scriptPubKey
= CScript();
46 txSpend
.vout
[0].nValue
= txCredit
.vout
[0].nValue
;
51 // Microbenchmark for verification of a basic P2WPKH script. Can be easily
52 // modified to measure performance of other types of scripts.
53 static void VerifyScriptBench(benchmark::State
& state
)
55 const int flags
= SCRIPT_VERIFY_WITNESS
| SCRIPT_VERIFY_P2SH
;
56 const int witnessversion
= 0;
60 static const std::array
<unsigned char, 32> vchKey
= {
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
65 key
.Set(vchKey
.begin(), vchKey
.end(), false);
66 CPubKey pubkey
= key
.GetPubKey();
68 CHash160().Write(pubkey
.begin(), pubkey
.size()).Finalize(pubkeyHash
.begin());
71 CScript scriptPubKey
= CScript() << witnessversion
<< ToByteVector(pubkeyHash
);
73 CScript witScriptPubkey
= CScript() << OP_DUP
<< OP_HASH160
<< ToByteVector(pubkeyHash
) << OP_EQUALVERIFY
<< OP_CHECKSIG
;
74 CTransaction txCredit
= BuildCreditingTransaction(scriptPubKey
);
75 CMutableTransaction txSpend
= BuildSpendingTransaction(scriptSig
, txCredit
);
76 CScriptWitness
& witness
= txSpend
.vin
[0].scriptWitness
;
77 witness
.stack
.emplace_back();
78 key
.Sign(SignatureHash(witScriptPubkey
, txSpend
, 0, SIGHASH_ALL
, txCredit
.vout
[0].nValue
, SIGVERSION_WITNESS_V0
), witness
.stack
.back(), 0);
79 witness
.stack
.back().push_back(static_cast<unsigned char>(SIGHASH_ALL
));
80 witness
.stack
.push_back(ToByteVector(pubkey
));
83 while (state
.KeepRunning()) {
85 bool success
= VerifyScript(
86 txSpend
.vin
[0].scriptSig
,
87 txCredit
.vout
[0].scriptPubKey
,
88 &txSpend
.vin
[0].scriptWitness
,
90 MutableTransactionSignatureChecker(&txSpend
, 0, txCredit
.vout
[0].nValue
),
92 assert(err
== SCRIPT_ERR_OK
);
95 #if defined(HAVE_CONSENSUS_LIB)
96 CDataStream
stream(SER_NETWORK
, PROTOCOL_VERSION
);
98 int csuccess
= bitcoinconsensus_verify_script_with_amount(
99 txCredit
.vout
[0].scriptPubKey
.data(),
100 txCredit
.vout
[0].scriptPubKey
.size(),
101 txCredit
.vout
[0].nValue
,
102 (const unsigned char*)stream
.data(), stream
.size(), 0, flags
, nullptr);
103 assert(csuccess
== 1);
108 BENCHMARK(VerifyScriptBench
);