Changeset View
Changeset View
Standalone View
Standalone View
src/test/script_tests.cpp
Show First 20 Lines • Show All 2,539 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) { | ||||
BOOST_CHECK(!VerifyScript( | BOOST_CHECK(!VerifyScript( | ||||
badsig6, scriptPubKey23, gFlags, | badsig6, scriptPubKey23, gFlags, | ||||
TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), | TransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), | ||||
&err)); | &err)); | ||||
BOOST_CHECK_MESSAGE(err == ScriptError::INVALID_STACK_OPERATION, | BOOST_CHECK_MESSAGE(err == ScriptError::INVALID_STACK_OPERATION, | ||||
ScriptErrorString(err)); | ScriptErrorString(err)); | ||||
} | } | ||||
/* Wrapper around ProduceSignature to combine two scriptsigs */ | |||||
SignatureData CombineSignatures(const CTxOut &txout, | |||||
const CMutableTransaction &tx, | |||||
const SignatureData &scriptSig1, | |||||
const SignatureData &scriptSig2) { | |||||
SignatureData data; | |||||
data.MergeSignatureData(scriptSig1); | |||||
data.MergeSignatureData(scriptSig2); | |||||
ProduceSignature(DUMMY_SIGNING_PROVIDER, | |||||
MutableTransactionSignatureCreator(&tx, 0, txout.nValue), | |||||
txout.scriptPubKey, data); | |||||
return data; | |||||
} | |||||
BOOST_AUTO_TEST_CASE(script_combineSigs) { | BOOST_AUTO_TEST_CASE(script_combineSigs) { | ||||
// Test the CombineSignatures function | // Test the ProduceSignature's ability to combine signatures function | ||||
Amount amount = Amount::zero(); | |||||
CBasicKeyStore keystore; | CBasicKeyStore keystore; | ||||
std::vector<CKey> keys; | std::vector<CKey> keys; | ||||
std::vector<CPubKey> pubkeys; | std::vector<CPubKey> pubkeys; | ||||
for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
CKey key; | CKey key; | ||||
key.MakeNewKey(i % 2 == 1); | key.MakeNewKey(i % 2 == 1); | ||||
keys.push_back(key); | keys.push_back(key); | ||||
pubkeys.push_back(key.GetPubKey()); | pubkeys.push_back(key.GetPubKey()); | ||||
keystore.AddKey(key); | keystore.AddKey(key); | ||||
} | } | ||||
CMutableTransaction txFrom = BuildCreditingTransaction( | CMutableTransaction txFrom = BuildCreditingTransaction( | ||||
GetScriptForDestination(keys[0].GetPubKey().GetID()), Amount::zero()); | GetScriptForDestination(keys[0].GetPubKey().GetID()), Amount::zero()); | ||||
CMutableTransaction txTo = | CMutableTransaction txTo = | ||||
BuildSpendingTransaction(CScript(), CTransaction(txFrom)); | BuildSpendingTransaction(CScript(), CTransaction(txFrom)); | ||||
CScript &scriptPubKey = txFrom.vout[0].scriptPubKey; | CScript &scriptPubKey = txFrom.vout[0].scriptPubKey; | ||||
CScript &scriptSig = txTo.vin[0].scriptSig; | SignatureData scriptSig; | ||||
SignatureData empty; | SignatureData empty; | ||||
SignatureData combined = CombineSignatures( | SignatureData combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, empty, empty); | ||||
empty, empty); | |||||
BOOST_CHECK(combined.scriptSig.empty()); | BOOST_CHECK(combined.scriptSig.empty()); | ||||
// Single signature case: | // Single signature case: | ||||
SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); | SignSignature(keystore, CTransaction(txFrom), txTo, 0, | ||||
combined = CombineSignatures( | SigHashType().withForkId()); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); | ||||
SignatureData(scriptSig), empty); | combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); | ||||
BOOST_CHECK(combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
combined = CombineSignatures( | combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
empty, SignatureData(scriptSig)); | SignatureData scriptSigCopy = scriptSig; | ||||
BOOST_CHECK(combined.scriptSig == scriptSig); | |||||
CScript scriptSigCopy = scriptSig; | |||||
// Signing again will give a different, valid signature: | // Signing again will give a different, valid signature: | ||||
SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); | SignSignature(keystore, CTransaction(txFrom), txTo, 0, | ||||
combined = CombineSignatures( | SigHashType().withForkId()); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); | ||||
SignatureData(scriptSigCopy), SignatureData(scriptSig)); | combined = | ||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || | CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig); | ||||
combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || | ||||
combined.scriptSig == scriptSig.scriptSig); | |||||
// P2SH, single-signature case: | // P2SH, single-signature case: | ||||
CScript pkSingle; | CScript pkSingle; | ||||
pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; | pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG; | ||||
keystore.AddCScript(pkSingle); | keystore.AddCScript(pkSingle); | ||||
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); | scriptPubKey = GetScriptForDestination(CScriptID(pkSingle)); | ||||
SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); | SignSignature(keystore, CTransaction(txFrom), txTo, 0, | ||||
combined = CombineSignatures( | SigHashType().withForkId()); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); | ||||
SignatureData(scriptSig), empty); | combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); | ||||
BOOST_CHECK(combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
combined = CombineSignatures( | combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
empty, SignatureData(scriptSig)); | |||||
BOOST_CHECK(combined.scriptSig == scriptSig); | |||||
scriptSigCopy = scriptSig; | scriptSigCopy = scriptSig; | ||||
SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); | SignSignature(keystore, CTransaction(txFrom), txTo, 0, | ||||
combined = CombineSignatures( | SigHashType().withForkId()); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); | ||||
SignatureData(scriptSigCopy), SignatureData(scriptSig)); | combined = | ||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || | CombineSignatures(txFrom.vout[0], txTo, scriptSigCopy, scriptSig); | ||||
combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSigCopy.scriptSig || | ||||
// dummy scriptSigCopy with placeholder, should always choose | combined.scriptSig == scriptSig.scriptSig); | ||||
// non-placeholder: | |||||
scriptSigCopy = CScript() | |||||
<< OP_0 | |||||
<< std::vector<uint8_t>(pkSingle.begin(), pkSingle.end()); | |||||
combined = CombineSignatures( | |||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | |||||
SignatureData(scriptSigCopy), SignatureData(scriptSig)); | |||||
BOOST_CHECK(combined.scriptSig == scriptSig); | |||||
combined = CombineSignatures( | |||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | |||||
SignatureData(scriptSig), SignatureData(scriptSigCopy)); | |||||
BOOST_CHECK(combined.scriptSig == scriptSig); | |||||
// Hardest case: Multisig 2-of-3 | // Hardest case: Multisig 2-of-3 | ||||
scriptPubKey = GetScriptForMultisig(2, pubkeys); | scriptPubKey = GetScriptForMultisig(2, pubkeys); | ||||
keystore.AddCScript(scriptPubKey); | keystore.AddCScript(scriptPubKey); | ||||
SignSignature(keystore, CTransaction(txFrom), txTo, 0, SigHashType()); | SignSignature(keystore, CTransaction(txFrom), txTo, 0, | ||||
combined = CombineSignatures( | SigHashType().withForkId()); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptSig = DataFromTransaction(txTo, 0, txFrom.vout[0]); | ||||
SignatureData(scriptSig), empty); | combined = CombineSignatures(txFrom.vout[0], txTo, scriptSig, empty); | ||||
BOOST_CHECK(combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
combined = CombineSignatures( | combined = CombineSignatures(txFrom.vout[0], txTo, empty, scriptSig); | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | BOOST_CHECK(combined.scriptSig == scriptSig.scriptSig); | ||||
empty, SignatureData(scriptSig)); | |||||
BOOST_CHECK(combined.scriptSig == scriptSig); | |||||
// A couple of partially-signed versions: | // A couple of partially-signed versions: | ||||
std::vector<uint8_t> sig1; | std::vector<uint8_t> sig1; | ||||
uint256 hash1 = SignatureHash(scriptPubKey, CTransaction(txTo), 0, | uint256 hash1 = SignatureHash(scriptPubKey, CTransaction(txTo), 0, | ||||
SigHashType(), Amount::zero()); | SigHashType().withForkId(), Amount::zero()); | ||||
BOOST_CHECK(keys[0].SignECDSA(hash1, sig1)); | BOOST_CHECK(keys[0].SignECDSA(hash1, sig1)); | ||||
sig1.push_back(SIGHASH_ALL); | sig1.push_back(SIGHASH_ALL | SIGHASH_FORKID); | ||||
std::vector<uint8_t> sig2; | std::vector<uint8_t> sig2; | ||||
uint256 hash2 = SignatureHash( | uint256 hash2 = SignatureHash( | ||||
scriptPubKey, CTransaction(txTo), 0, | scriptPubKey, CTransaction(txTo), 0, | ||||
SigHashType().withBaseType(BaseSigHashType::NONE), Amount::zero()); | SigHashType().withBaseType(BaseSigHashType::NONE).withForkId(), | ||||
Amount::zero()); | |||||
BOOST_CHECK(keys[1].SignECDSA(hash2, sig2)); | BOOST_CHECK(keys[1].SignECDSA(hash2, sig2)); | ||||
sig2.push_back(SIGHASH_NONE); | sig2.push_back(SIGHASH_NONE | SIGHASH_FORKID); | ||||
std::vector<uint8_t> sig3; | std::vector<uint8_t> sig3; | ||||
uint256 hash3 = SignatureHash( | uint256 hash3 = SignatureHash( | ||||
scriptPubKey, CTransaction(txTo), 0, | scriptPubKey, CTransaction(txTo), 0, | ||||
SigHashType().withBaseType(BaseSigHashType::SINGLE), Amount::zero()); | SigHashType().withBaseType(BaseSigHashType::SINGLE).withForkId(), | ||||
Amount::zero()); | |||||
BOOST_CHECK(keys[2].SignECDSA(hash3, sig3)); | BOOST_CHECK(keys[2].SignECDSA(hash3, sig3)); | ||||
sig3.push_back(SIGHASH_SINGLE); | sig3.push_back(SIGHASH_SINGLE | SIGHASH_FORKID); | ||||
// Not fussy about order (or even existence) of placeholders or signatures: | // Not fussy about order (or even existence) of placeholders or signatures: | ||||
CScript partial1a = CScript() << OP_0 << sig1 << OP_0; | CScript partial1a = CScript() << OP_0 << sig1 << OP_0; | ||||
CScript partial1b = CScript() << OP_0 << OP_0 << sig1; | CScript partial1b = CScript() << OP_0 << OP_0 << sig1; | ||||
CScript partial2a = CScript() << OP_0 << sig2; | CScript partial2a = CScript() << OP_0 << sig2; | ||||
CScript partial2b = CScript() << sig2 << OP_0; | CScript partial2b = CScript() << sig2 << OP_0; | ||||
CScript partial3a = CScript() << sig3; | CScript partial3a = CScript() << sig3; | ||||
CScript partial3b = CScript() << OP_0 << OP_0 << sig3; | CScript partial3b = CScript() << OP_0 << OP_0 << sig3; | ||||
CScript partial3c = CScript() << OP_0 << sig3 << OP_0; | CScript partial3c = CScript() << OP_0 << sig3 << OP_0; | ||||
CScript complete12 = CScript() << OP_0 << sig1 << sig2; | CScript complete12 = CScript() << OP_0 << sig1 << sig2; | ||||
CScript complete13 = CScript() << OP_0 << sig1 << sig3; | CScript complete13 = CScript() << OP_0 << sig1 << sig3; | ||||
CScript complete23 = CScript() << OP_0 << sig2 << sig3; | CScript complete23 = CScript() << OP_0 << sig2 << sig3; | ||||
SignatureData partial1_sigs; | |||||
partial1_sigs.signatures.emplace(keys[0].GetPubKey().GetID(), | |||||
SigPair(keys[0].GetPubKey(), sig1)); | |||||
SignatureData partial2_sigs; | |||||
partial2_sigs.signatures.emplace(keys[1].GetPubKey().GetID(), | |||||
SigPair(keys[1].GetPubKey(), sig2)); | |||||
SignatureData partial3_sigs; | |||||
partial3_sigs.signatures.emplace(keys[2].GetPubKey().GetID(), | |||||
SigPair(keys[2].GetPubKey(), sig3)); | |||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial1_sigs); | ||||
SignatureData(partial1a), SignatureData(partial1b)); | |||||
BOOST_CHECK(combined.scriptSig == partial1a); | BOOST_CHECK(combined.scriptSig == partial1a); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs); | ||||
SignatureData(partial1a), SignatureData(partial2a)); | |||||
BOOST_CHECK(combined.scriptSig == complete12); | BOOST_CHECK(combined.scriptSig == complete12); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial1_sigs); | ||||
SignatureData(partial2a), SignatureData(partial1a)); | |||||
BOOST_CHECK(combined.scriptSig == complete12); | BOOST_CHECK(combined.scriptSig == complete12); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial1_sigs, partial2_sigs); | ||||
SignatureData(partial1b), SignatureData(partial2b)); | |||||
BOOST_CHECK(combined.scriptSig == complete12); | BOOST_CHECK(combined.scriptSig == complete12); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial1_sigs); | ||||
SignatureData(partial3b), SignatureData(partial1b)); | |||||
BOOST_CHECK(combined.scriptSig == complete13); | BOOST_CHECK(combined.scriptSig == complete13); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial2_sigs, partial3_sigs); | ||||
SignatureData(partial2a), SignatureData(partial3a)); | |||||
BOOST_CHECK(combined.scriptSig == complete23); | BOOST_CHECK(combined.scriptSig == complete23); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial2_sigs); | ||||
SignatureData(partial3b), SignatureData(partial2b)); | |||||
BOOST_CHECK(combined.scriptSig == complete23); | BOOST_CHECK(combined.scriptSig == complete23); | ||||
combined = CombineSignatures( | combined = | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | CombineSignatures(txFrom.vout[0], txTo, partial3_sigs, partial3_sigs); | ||||
SignatureData(partial3b), SignatureData(partial3a)); | |||||
BOOST_CHECK(combined.scriptSig == partial3c); | BOOST_CHECK(combined.scriptSig == partial3c); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(script_standard_push) { | BOOST_AUTO_TEST_CASE(script_standard_push) { | ||||
ScriptError err; | ScriptError err; | ||||
for (int i = 0; i < 67000; i++) { | for (int i = 0; i < 67000; i++) { | ||||
CScript script; | CScript script; | ||||
script << i; | script << i; | ||||
▲ Show 20 Lines • Show All 336 Lines • Show Last 20 Lines |