Changeset View
Changeset View
Standalone View
Standalone View
src/test/script_tests.cpp
Show First 20 Lines • Show All 304 Lines • ▼ Show 20 Lines | public: | ||||
TestBuilder &Push(const CScript &_script) { | TestBuilder &Push(const CScript &_script) { | ||||
DoPush(std::vector<uint8_t>(_script.begin(), _script.end())); | DoPush(std::vector<uint8_t>(_script.begin(), _script.end())); | ||||
return *this; | return *this; | ||||
} | } | ||||
TestBuilder &PushSig(const CKey &key, int nHashType = SIGHASH_ALL, | TestBuilder &PushSig(const CKey &key, int nHashType = SIGHASH_ALL, | ||||
unsigned int lenR = 32, unsigned int lenS = 32, | unsigned int lenR = 32, unsigned int lenS = 32, | ||||
Amount amount = 0) { | Amount amount = Amount(0)) { | ||||
uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount); | uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount); | ||||
std::vector<uint8_t> vchSig, r, s; | std::vector<uint8_t> vchSig, r, s; | ||||
uint32_t iter = 0; | uint32_t iter = 0; | ||||
do { | do { | ||||
key.Sign(hash, vchSig, iter++); | key.Sign(hash, vchSig, iter++); | ||||
if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { | if ((lenS == 33) != (vchSig[5 + vchSig[3]] == 33)) { | ||||
NegateSignatureS(vchSig); | NegateSignatureS(vchSig); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | TestBuilder &Test() { | ||||
comment, scriptError, nValue); | comment, scriptError, nValue); | ||||
*this = copy; | *this = copy; | ||||
return *this; | return *this; | ||||
} | } | ||||
UniValue GetJSON() { | UniValue GetJSON() { | ||||
DoPush(); | DoPush(); | ||||
UniValue array(UniValue::VARR); | UniValue array(UniValue::VARR); | ||||
if (nValue != 0) { | if (nValue != Amount(0)) { | ||||
UniValue amount(UniValue::VARR); | UniValue amount(UniValue::VARR); | ||||
amount.push_back(ValueFromAmount(nValue)); | amount.push_back(ValueFromAmount(nValue)); | ||||
array.push_back(amount); | array.push_back(amount); | ||||
} | } | ||||
array.push_back(FormatScript(spendTx.vin[0].scriptSig)); | array.push_back(FormatScript(spendTx.vin[0].scriptSig)); | ||||
array.push_back(FormatScript(creditTx->vout[0].scriptPubKey)); | array.push_back(FormatScript(creditTx->vout[0].scriptPubKey)); | ||||
array.push_back(FormatScriptFlags(flags)); | array.push_back(FormatScriptFlags(flags)); | ||||
▲ Show 20 Lines • Show All 632 Lines • ▼ Show 20 Lines | tests.push_back( | ||||
.PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | .PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | ||||
TEST_AMOUNT)); | TEST_AMOUNT)); | ||||
tests.push_back( | tests.push_back( | ||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | ||||
"P2PK INVALID AMOUNT", SCRIPT_ENABLE_SIGHASH_FORKID, false, | "P2PK INVALID AMOUNT", SCRIPT_ENABLE_SIGHASH_FORKID, false, | ||||
TEST_AMOUNT) | TEST_AMOUNT) | ||||
.PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | .PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | ||||
TEST_AMOUNT + 1) | TEST_AMOUNT + Amount(1)) | ||||
.ScriptError(SCRIPT_ERR_EVAL_FALSE)); | .ScriptError(SCRIPT_ERR_EVAL_FALSE)); | ||||
tests.push_back( | tests.push_back( | ||||
TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | TestBuilder(CScript() << ToByteVector(keys.pubkey0) << OP_CHECKSIG, | ||||
"P2PK INVALID FORKID", SCRIPT_VERIFY_STRICTENC, false, | "P2PK INVALID FORKID", SCRIPT_VERIFY_STRICTENC, false, | ||||
TEST_AMOUNT) | TEST_AMOUNT) | ||||
.PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | .PushSig(keys.key0, SIGHASH_ALL | SIGHASH_FORKID, 32, 32, | ||||
TEST_AMOUNT) | TEST_AMOUNT) | ||||
.ScriptError(SCRIPT_ERR_ILLEGAL_FORKID)); | .ScriptError(SCRIPT_ERR_ILLEGAL_FORKID)); | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(script_json_test) { | ||||
// scripts. | // scripts. | ||||
UniValue tests = read_json(std::string( | UniValue tests = read_json(std::string( | ||||
json_tests::script_tests, | json_tests::script_tests, | ||||
json_tests::script_tests + sizeof(json_tests::script_tests))); | json_tests::script_tests + sizeof(json_tests::script_tests))); | ||||
for (unsigned int idx = 0; idx < tests.size(); idx++) { | for (unsigned int idx = 0; idx < tests.size(); idx++) { | ||||
UniValue test = tests[idx]; | UniValue test = tests[idx]; | ||||
std::string strTest = test.write(); | std::string strTest = test.write(); | ||||
Amount nValue = 0; | Amount nValue(0); | ||||
unsigned int pos = 0; | unsigned int pos = 0; | ||||
if (test.size() > 0 && test[pos].isArray()) { | if (test.size() > 0 && test[pos].isArray()) { | ||||
nValue = AmountFromValue(test[pos][0]); | nValue = AmountFromValue(test[pos][0]); | ||||
pos++; | pos++; | ||||
} | } | ||||
// Allow size > 3; extra stuff ignored (useful for comments) | // Allow size > 3; extra stuff ignored (useful for comments) | ||||
if (test.size() < 4 + pos) { | if (test.size() < 4 + pos) { | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | BOOST_CHECK(EvalScript( | ||||
pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), | pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), | ||||
SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); | SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), &err)); | ||||
BOOST_CHECK(pushdata4Stack == directStack); | BOOST_CHECK(pushdata4Stack == directStack); | ||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); | BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); | ||||
} | } | ||||
CScript sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, | CScript sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, | ||||
CTransaction transaction) { | CTransaction transaction) { | ||||
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0); | uint256 hash = | ||||
SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, Amount(0)); | |||||
CScript result; | CScript result; | ||||
// | // | ||||
// NOTE: CHECKMULTISIG has an unfortunate bug; it requires one extra item on | // NOTE: CHECKMULTISIG has an unfortunate bug; it requires one extra item on | ||||
// the stack, before the signatures. Putting OP_0 on the stack is the | // the stack, before the signatures. Putting OP_0 on the stack is the | ||||
// workaround; fixing the bug would mean splitting the block chain (old | // workaround; fixing the bug would mean splitting the block chain (old | ||||
// clients would not accept new CHECKMULTISIG transactions, and vice-versa) | // clients would not accept new CHECKMULTISIG transactions, and vice-versa) | ||||
// | // | ||||
Show All 22 Lines | BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12) { | ||||
key2.MakeNewKey(false); | key2.MakeNewKey(false); | ||||
key3.MakeNewKey(true); | key3.MakeNewKey(true); | ||||
CScript scriptPubKey12; | CScript scriptPubKey12; | ||||
scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) | scriptPubKey12 << OP_1 << ToByteVector(key1.GetPubKey()) | ||||
<< ToByteVector(key2.GetPubKey()) << OP_2 | << ToByteVector(key2.GetPubKey()) << OP_2 | ||||
<< OP_CHECKMULTISIG; | << OP_CHECKMULTISIG; | ||||
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12, 0); | CMutableTransaction txFrom12 = | ||||
BuildCreditingTransaction(scriptPubKey12, Amount(0)); | |||||
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); | CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12); | ||||
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); | CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12); | ||||
BOOST_CHECK(VerifyScript( | BOOST_CHECK(VerifyScript( | ||||
goodsig1, scriptPubKey12, flags, | goodsig1, scriptPubKey12, flags, | ||||
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), | MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), | ||||
&err)); | &err)); | ||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); | BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err)); | ||||
txTo12.vout[0].nValue = 2; | txTo12.vout[0].nValue = Amount(2); | ||||
BOOST_CHECK(!VerifyScript( | BOOST_CHECK(!VerifyScript( | ||||
goodsig1, scriptPubKey12, flags, | goodsig1, scriptPubKey12, flags, | ||||
MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), | MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), | ||||
&err)); | &err)); | ||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); | BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err)); | ||||
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); | CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12); | ||||
BOOST_CHECK(VerifyScript( | BOOST_CHECK(VerifyScript( | ||||
Show All 19 Lines | BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23) { | ||||
key4.MakeNewKey(false); | key4.MakeNewKey(false); | ||||
CScript scriptPubKey23; | CScript scriptPubKey23; | ||||
scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) | scriptPubKey23 << OP_2 << ToByteVector(key1.GetPubKey()) | ||||
<< ToByteVector(key2.GetPubKey()) | << ToByteVector(key2.GetPubKey()) | ||||
<< ToByteVector(key3.GetPubKey()) << OP_3 | << ToByteVector(key3.GetPubKey()) << OP_3 | ||||
<< OP_CHECKMULTISIG; | << OP_CHECKMULTISIG; | ||||
CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23, 0); | CMutableTransaction txFrom23 = | ||||
BuildCreditingTransaction(scriptPubKey23, Amount(0)); | |||||
CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); | CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23); | ||||
std::vector<CKey> keys; | std::vector<CKey> keys; | ||||
keys.push_back(key1); | keys.push_back(key1); | ||||
keys.push_back(key2); | keys.push_back(key2); | ||||
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); | CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23); | ||||
BOOST_CHECK(VerifyScript( | BOOST_CHECK(VerifyScript( | ||||
goodsig1, scriptPubKey23, flags, | goodsig1, scriptPubKey23, flags, | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | BOOST_CHECK(!VerifyScript( | ||||
MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), | MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), | ||||
&err)); | &err)); | ||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, | BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, | ||||
ScriptErrorString(err)); | ScriptErrorString(err)); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(script_combineSigs) { | BOOST_AUTO_TEST_CASE(script_combineSigs) { | ||||
// Test the CombineSignatures function | // Test the CombineSignatures function | ||||
Amount amount = 0; | Amount amount(0); | ||||
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()), 0); | GetScriptForDestination(keys[0].GetPubKey().GetID()), Amount(0)); | ||||
CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom); | CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom); | ||||
CScript &scriptPubKey = txFrom.vout[0].scriptPubKey; | CScript &scriptPubKey = txFrom.vout[0].scriptPubKey; | ||||
CScript &scriptSig = txTo.vin[0].scriptSig; | CScript &scriptSig = txTo.vin[0].scriptSig; | ||||
SignatureData empty; | SignatureData empty; | ||||
SignatureData combined = CombineSignatures( | SignatureData combined = CombineSignatures( | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | ||||
empty, empty); | empty, empty); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(script_combineSigs) { | ||||
BOOST_CHECK(combined.scriptSig == scriptSig); | BOOST_CHECK(combined.scriptSig == scriptSig); | ||||
combined = CombineSignatures( | combined = CombineSignatures( | ||||
scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), | ||||
empty, SignatureData(scriptSig)); | empty, SignatureData(scriptSig)); | ||||
BOOST_CHECK(combined.scriptSig == 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, txTo, 0, SIGHASH_ALL, 0); | uint256 hash1 = | ||||
SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, Amount(0)); | |||||
BOOST_CHECK(keys[0].Sign(hash1, sig1)); | BOOST_CHECK(keys[0].Sign(hash1, sig1)); | ||||
sig1.push_back(SIGHASH_ALL); | sig1.push_back(SIGHASH_ALL); | ||||
std::vector<uint8_t> sig2; | std::vector<uint8_t> sig2; | ||||
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0); | uint256 hash2 = | ||||
SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, Amount(0)); | |||||
BOOST_CHECK(keys[1].Sign(hash2, sig2)); | BOOST_CHECK(keys[1].Sign(hash2, sig2)); | ||||
sig2.push_back(SIGHASH_NONE); | sig2.push_back(SIGHASH_NONE); | ||||
std::vector<uint8_t> sig3; | std::vector<uint8_t> sig3; | ||||
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0); | uint256 hash3 = | ||||
SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, Amount(0)); | |||||
BOOST_CHECK(keys[2].Sign(hash3, sig3)); | BOOST_CHECK(keys[2].Sign(hash3, sig3)); | ||||
sig3.push_back(SIGHASH_SINGLE); | sig3.push_back(SIGHASH_SINGLE); | ||||
// 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; | ||||
▲ Show 20 Lines • Show All 325 Lines • Show Last 20 Lines |