Skip to content

Commit ab48c5e

Browse files
NicolasDoriersipa
authored andcommitted
Unit test for sighash caching
1 parent d2c5d04 commit ab48c5e

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

src/test/transaction_tests.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "test/test_bitcoin.h"
88

99
#include "clientversion.h"
10+
#include "checkqueue.h"
1011
#include "consensus/validation.h"
1112
#include "core_io.h"
1213
#include "key.h"
@@ -421,6 +422,86 @@ void ReplaceRedeemScript(CScript& script, const CScript& redeemScript)
421422
script = PushAll(stack);
422423
}
423424

425+
BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
426+
CMutableTransaction mtx;
427+
mtx.nVersion = 1;
428+
429+
CKey key;
430+
key.MakeNewKey(false);
431+
CBasicKeyStore keystore;
432+
keystore.AddKeyPubKey(key, key.GetPubKey());
433+
CKeyID hash = key.GetPubKey().GetID();
434+
CScript scriptPubKey = CScript() << OP_0 << std::vector<unsigned char>(hash.begin(), hash.end());
435+
436+
vector<int> sigHashes;
437+
sigHashes.push_back(SIGHASH_NONE | SIGHASH_ANYONECANPAY);
438+
sigHashes.push_back(SIGHASH_SINGLE | SIGHASH_ANYONECANPAY);
439+
sigHashes.push_back(SIGHASH_ALL | SIGHASH_ANYONECANPAY);
440+
sigHashes.push_back(SIGHASH_NONE);
441+
sigHashes.push_back(SIGHASH_SINGLE);
442+
sigHashes.push_back(SIGHASH_ALL);
443+
444+
// create a big transaction of 4500 inputs signed by the same key
445+
for(uint32_t ij = 0; ij < 4500; ij++) {
446+
uint32_t i = mtx.vin.size();
447+
uint256 prevId;
448+
prevId.SetHex("0000000000000000000000000000000000000000000000000000000000000100");
449+
COutPoint outpoint(prevId, i);
450+
451+
mtx.vin.resize(mtx.vin.size() + 1);
452+
mtx.vin[i].prevout = outpoint;
453+
mtx.vin[i].scriptSig = CScript();
454+
455+
mtx.vout.resize(mtx.vout.size() + 1);
456+
mtx.vout[i].nValue = 1000;
457+
mtx.vout[i].scriptPubKey = CScript() << OP_1;
458+
}
459+
460+
// sign all inputs
461+
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
462+
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()));
463+
assert(hashSigned);
464+
}
465+
466+
CTransaction tx;
467+
CDataStream ssout(SER_NETWORK, PROTOCOL_VERSION);
468+
WithOrVersion(&ssout, 0) << mtx;
469+
WithOrVersion(&ssout, 0) >> tx;
470+
471+
// check all inputs concurrently, with the cache
472+
CachedHashes cachedHashes(tx);
473+
boost::thread_group threadGroup;
474+
CCheckQueue<CScriptCheck> scriptcheckqueue(128);
475+
CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
476+
477+
for (int i=0; i<20; i++)
478+
threadGroup.create_thread(boost::bind(&CCheckQueue<CScriptCheck>::Thread, boost::ref(scriptcheckqueue)));
479+
480+
CCoins coins;
481+
coins.nVersion = 1;
482+
coins.fCoinBase = false;
483+
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
484+
CTxOut txout;
485+
txout.nValue = 1000;
486+
txout.scriptPubKey = scriptPubKey;
487+
coins.vout.push_back(txout);
488+
}
489+
490+
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
491+
std::vector<CScriptCheck> vChecks;
492+
CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &cachedHashes);
493+
vChecks.push_back(CScriptCheck());
494+
check.swap(vChecks.back());
495+
control.Add(vChecks);
496+
}
497+
498+
bool controlCheck = control.Wait();
499+
assert(controlCheck);
500+
501+
threadGroup.interrupt_all();
502+
threadGroup.join_all();
503+
}
504+
424505
BOOST_AUTO_TEST_CASE(test_witness)
425506
{
426507
CBasicKeyStore keystore, keystore2;

0 commit comments

Comments
 (0)