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.
7 #if defined(HAVE_CONSENSUS_LIB)
8 #include "script/bitcoinconsensus.h"
10 #include "script/script.h"
11 #include "script/sign.h"
14 // FIXME: Dedup with BuildCreditingTransaction in test/script_tests.cpp.
15 static CMutableTransaction
BuildCreditingTransaction(const CScript
& scriptPubKey
)
17 CMutableTransaction txCredit
;
18 txCredit
.nVersion
= 1;
19 txCredit
.nLockTime
= 0;
20 txCredit
.vin
.resize(1);
21 txCredit
.vout
.resize(1);
22 txCredit
.vin
[0].prevout
.SetNull();
23 txCredit
.vin
[0].scriptSig
= CScript() << CScriptNum(0) << CScriptNum(0);
24 txCredit
.vin
[0].nSequence
= CTxIn::SEQUENCE_FINAL
;
25 txCredit
.vout
[0].scriptPubKey
= scriptPubKey
;
26 txCredit
.vout
[0].nValue
= 1;
31 // FIXME: Dedup with BuildSpendingTransaction in test/script_tests.cpp.
32 static CMutableTransaction
BuildSpendingTransaction(const CScript
& scriptSig
, const CMutableTransaction
& txCredit
)
34 CMutableTransaction txSpend
;
36 txSpend
.nLockTime
= 0;
37 txSpend
.vin
.resize(1);
38 txSpend
.vout
.resize(1);
39 txSpend
.vin
[0].prevout
.hash
= txCredit
.GetHash();
40 txSpend
.vin
[0].prevout
.n
= 0;
41 txSpend
.vin
[0].scriptSig
= scriptSig
;
42 txSpend
.vin
[0].nSequence
= CTxIn::SEQUENCE_FINAL
;
43 txSpend
.vout
[0].scriptPubKey
= CScript();
44 txSpend
.vout
[0].nValue
= txCredit
.vout
[0].nValue
;
49 // Microbenchmark for verification of a basic P2WPKH script. Can be easily
50 // modified to measure performance of other types of scripts.
51 static void VerifyScriptBench(benchmark::State
& state
)
53 const int flags
= SCRIPT_VERIFY_WITNESS
| SCRIPT_VERIFY_P2SH
;
54 const int witnessversion
= 0;
58 const unsigned char vchKey
[32] = {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};
59 key
.Set(vchKey
, vchKey
+ 32, false);
60 CPubKey pubkey
= key
.GetPubKey();
62 CHash160().Write(pubkey
.begin(), pubkey
.size()).Finalize(pubkeyHash
.begin());
65 CScript scriptPubKey
= CScript() << witnessversion
<< ToByteVector(pubkeyHash
);
67 CScript witScriptPubkey
= CScript() << OP_DUP
<< OP_HASH160
<< ToByteVector(pubkeyHash
) << OP_EQUALVERIFY
<< OP_CHECKSIG
;
68 CTransaction txCredit
= BuildCreditingTransaction(scriptPubKey
);
69 CMutableTransaction txSpend
= BuildSpendingTransaction(scriptSig
, txCredit
);
70 CScriptWitness
& witness
= txSpend
.vin
[0].scriptWitness
;
71 witness
.stack
.emplace_back();
72 key
.Sign(SignatureHash(witScriptPubkey
, txSpend
, 0, SIGHASH_ALL
, txCredit
.vout
[0].nValue
, SIGVERSION_WITNESS_V0
), witness
.stack
.back(), 0);
73 witness
.stack
.back().push_back(static_cast<unsigned char>(SIGHASH_ALL
));
74 witness
.stack
.push_back(ToByteVector(pubkey
));
77 while (state
.KeepRunning()) {
79 bool success
= VerifyScript(
80 txSpend
.vin
[0].scriptSig
,
81 txCredit
.vout
[0].scriptPubKey
,
82 &txSpend
.vin
[0].scriptWitness
,
84 MutableTransactionSignatureChecker(&txSpend
, 0, txCredit
.vout
[0].nValue
),
86 assert(err
== SCRIPT_ERR_OK
);
89 #if defined(HAVE_CONSENSUS_LIB)
90 CDataStream
stream(SER_NETWORK
, PROTOCOL_VERSION
);
92 int csuccess
= bitcoinconsensus_verify_script_with_amount(
93 txCredit
.vout
[0].scriptPubKey
.data(),
94 txCredit
.vout
[0].scriptPubKey
.size(),
95 txCredit
.vout
[0].nValue
,
96 (const unsigned char*)stream
.data(), stream
.size(), 0, flags
, nullptr);
97 assert(csuccess
== 1);
102 BENCHMARK(VerifyScriptBench
);