You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

script_P2SH_tests.cpp 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // Copyright (c) 2012-2013 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.
  4. #include "key.h"
  5. #include "keystore.h"
  6. #include "main.h"
  7. #include "script/script.h"
  8. #include "script/script_error.h"
  9. #include "script/sign.h"
  10. #include "test/test_bitcoin.h"
  11. #ifdef ENABLE_WALLET
  12. #include "wallet/wallet_ismine.h"
  13. #endif
  14. #include <vector>
  15. #include <boost/test/unit_test.hpp>
  16. using namespace std;
  17. // Helpers:
  18. static std::vector<unsigned char>
  19. Serialize(const CScript& s)
  20. {
  21. std::vector<unsigned char> sSerialized(s);
  22. return sSerialized;
  23. }
  24. static bool
  25. Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
  26. {
  27. // Create dummy to/from transactions:
  28. CMutableTransaction txFrom;
  29. txFrom.vout.resize(1);
  30. txFrom.vout[0].scriptPubKey = scriptPubKey;
  31. CMutableTransaction txTo;
  32. txTo.vin.resize(1);
  33. txTo.vout.resize(1);
  34. txTo.vin[0].prevout.n = 0;
  35. txTo.vin[0].prevout.hash = txFrom.GetHash();
  36. txTo.vin[0].scriptSig = scriptSig;
  37. txTo.vout[0].nValue = 1;
  38. return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0), &err);
  39. }
  40. BOOST_FIXTURE_TEST_SUITE(script_P2SH_tests, BasicTestingSetup)
  41. BOOST_AUTO_TEST_CASE(sign)
  42. {
  43. LOCK(cs_main);
  44. // Pay-to-script-hash looks like this:
  45. // scriptSig: <sig> <sig...> <serialized_script>
  46. // scriptPubKey: HASH160 <hash> EQUAL
  47. // Test SignSignature() (and therefore the version of Solver() that signs transactions)
  48. CBasicKeyStore keystore;
  49. CKey key[4];
  50. for (int i = 0; i < 4; i++)
  51. {
  52. key[i].MakeNewKey(true);
  53. keystore.AddKey(key[i]);
  54. }
  55. // 8 Scripts: checking all combinations of
  56. // different keys, straight/P2SH, pubkey/pubkeyhash
  57. CScript standardScripts[4];
  58. standardScripts[0] << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
  59. standardScripts[1] = GetScriptForDestination(key[1].GetPubKey().GetID());
  60. standardScripts[2] << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
  61. standardScripts[3] = GetScriptForDestination(key[2].GetPubKey().GetID());
  62. CScript evalScripts[4];
  63. for (int i = 0; i < 4; i++)
  64. {
  65. keystore.AddCScript(standardScripts[i]);
  66. evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i]));
  67. }
  68. CMutableTransaction txFrom; // Funding transaction:
  69. string reason;
  70. txFrom.vout.resize(8);
  71. for (int i = 0; i < 4; i++)
  72. {
  73. txFrom.vout[i].scriptPubKey = evalScripts[i];
  74. txFrom.vout[i].nValue = COIN;
  75. txFrom.vout[i+4].scriptPubKey = standardScripts[i];
  76. txFrom.vout[i+4].nValue = COIN;
  77. }
  78. BOOST_CHECK(IsStandardTx(txFrom, reason));
  79. CMutableTransaction txTo[8]; // Spending transactions
  80. for (int i = 0; i < 8; i++)
  81. {
  82. txTo[i].vin.resize(1);
  83. txTo[i].vout.resize(1);
  84. txTo[i].vin[0].prevout.n = i;
  85. txTo[i].vin[0].prevout.hash = txFrom.GetHash();
  86. txTo[i].vout[0].nValue = 1;
  87. #ifdef ENABLE_WALLET
  88. BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
  89. #endif
  90. }
  91. for (int i = 0; i < 8; i++)
  92. {
  93. BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
  94. }
  95. // All of the above should be OK, and the txTos have valid signatures
  96. // Check to make sure signature verification fails if we use the wrong ScriptSig:
  97. for (int i = 0; i < 8; i++)
  98. for (int j = 0; j < 8; j++)
  99. {
  100. CScript sigSave = txTo[i].vin[0].scriptSig;
  101. txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
  102. bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)();
  103. if (i == j)
  104. BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
  105. else
  106. BOOST_CHECK_MESSAGE(!sigOK, strprintf("VerifySignature %d %d", i, j));
  107. txTo[i].vin[0].scriptSig = sigSave;
  108. }
  109. }
  110. BOOST_AUTO_TEST_CASE(norecurse)
  111. {
  112. ScriptError err;
  113. // Make sure only the outer pay-to-script-hash does the
  114. // extra-validation thing:
  115. CScript invalidAsScript;
  116. invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE;
  117. CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript));
  118. CScript scriptSig;
  119. scriptSig << Serialize(invalidAsScript);
  120. // Should not verify, because it will try to execute OP_INVALIDOPCODE
  121. BOOST_CHECK(!Verify(scriptSig, p2sh, true, err));
  122. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_BAD_OPCODE, ScriptErrorString(err));
  123. // Try to recur, and verification should succeed because
  124. // the inner HASH160 <> EQUAL should only check the hash:
  125. CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh));
  126. CScript scriptSig2;
  127. scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
  128. BOOST_CHECK(Verify(scriptSig2, p2sh2, true, err));
  129. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
  130. }
  131. BOOST_AUTO_TEST_CASE(set)
  132. {
  133. LOCK(cs_main);
  134. // Test the CScript::Set* methods
  135. CBasicKeyStore keystore;
  136. CKey key[4];
  137. std::vector<CPubKey> keys;
  138. for (int i = 0; i < 4; i++)
  139. {
  140. key[i].MakeNewKey(true);
  141. keystore.AddKey(key[i]);
  142. keys.push_back(key[i].GetPubKey());
  143. }
  144. CScript inner[4];
  145. inner[0] = GetScriptForDestination(key[0].GetPubKey().GetID());
  146. inner[1] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
  147. inner[2] = GetScriptForMultisig(1, std::vector<CPubKey>(keys.begin(), keys.begin()+2));
  148. inner[3] = GetScriptForMultisig(2, std::vector<CPubKey>(keys.begin(), keys.begin()+3));
  149. CScript outer[4];
  150. for (int i = 0; i < 4; i++)
  151. {
  152. outer[i] = GetScriptForDestination(CScriptID(inner[i]));
  153. keystore.AddCScript(inner[i]);
  154. }
  155. CMutableTransaction txFrom; // Funding transaction:
  156. string reason;
  157. txFrom.vout.resize(4);
  158. for (int i = 0; i < 4; i++)
  159. {
  160. txFrom.vout[i].scriptPubKey = outer[i];
  161. txFrom.vout[i].nValue = CENT;
  162. }
  163. BOOST_CHECK(IsStandardTx(txFrom, reason));
  164. CMutableTransaction txTo[4]; // Spending transactions
  165. for (int i = 0; i < 4; i++)
  166. {
  167. txTo[i].vin.resize(1);
  168. txTo[i].vout.resize(1);
  169. txTo[i].vin[0].prevout.n = i;
  170. txTo[i].vin[0].prevout.hash = txFrom.GetHash();
  171. txTo[i].vout[0].nValue = 1*CENT;
  172. txTo[i].vout[0].scriptPubKey = inner[i];
  173. #ifdef ENABLE_WALLET
  174. BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
  175. #endif
  176. }
  177. for (int i = 0; i < 4; i++)
  178. {
  179. BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0), strprintf("SignSignature %d", i));
  180. BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
  181. }
  182. }
  183. BOOST_AUTO_TEST_CASE(is)
  184. {
  185. // Test CScript::IsPayToScriptHash()
  186. uint160 dummy;
  187. CScript p2sh;
  188. p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL;
  189. BOOST_CHECK(p2sh.IsPayToScriptHash());
  190. // Not considered pay-to-script-hash if using one of the OP_PUSHDATA opcodes:
  191. static const unsigned char direct[] = { OP_HASH160, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
  192. BOOST_CHECK(CScript(direct, direct+sizeof(direct)).IsPayToScriptHash());
  193. static const unsigned char pushdata1[] = { OP_HASH160, OP_PUSHDATA1, 20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
  194. BOOST_CHECK(!CScript(pushdata1, pushdata1+sizeof(pushdata1)).IsPayToScriptHash());
  195. static const unsigned char pushdata2[] = { OP_HASH160, OP_PUSHDATA2, 20,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
  196. BOOST_CHECK(!CScript(pushdata2, pushdata2+sizeof(pushdata2)).IsPayToScriptHash());
  197. static const unsigned char pushdata4[] = { OP_HASH160, OP_PUSHDATA4, 20,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, OP_EQUAL };
  198. BOOST_CHECK(!CScript(pushdata4, pushdata4+sizeof(pushdata4)).IsPayToScriptHash());
  199. CScript not_p2sh;
  200. BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
  201. not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << ToByteVector(dummy) << OP_EQUAL;
  202. BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
  203. not_p2sh.clear(); not_p2sh << OP_NOP << ToByteVector(dummy) << OP_EQUAL;
  204. BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
  205. not_p2sh.clear(); not_p2sh << OP_HASH160 << ToByteVector(dummy) << OP_CHECKSIG;
  206. BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
  207. }
  208. BOOST_AUTO_TEST_CASE(switchover)
  209. {
  210. // Test switch over code
  211. CScript notValid;
  212. ScriptError err;
  213. notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
  214. CScript scriptSig;
  215. scriptSig << Serialize(notValid);
  216. CScript fund = GetScriptForDestination(CScriptID(notValid));
  217. // Validation should succeed under old rules (hash is correct):
  218. BOOST_CHECK(Verify(scriptSig, fund, false, err));
  219. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
  220. // Fail under new:
  221. BOOST_CHECK(!Verify(scriptSig, fund, true, err));
  222. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EQUALVERIFY, ScriptErrorString(err));
  223. }
  224. BOOST_AUTO_TEST_CASE(AreInputsStandard)
  225. {
  226. LOCK(cs_main);
  227. CCoinsView coinsDummy;
  228. CCoinsViewCache coins(&coinsDummy);
  229. CBasicKeyStore keystore;
  230. CKey key[6];
  231. vector<CPubKey> keys;
  232. for (int i = 0; i < 6; i++)
  233. {
  234. key[i].MakeNewKey(true);
  235. keystore.AddKey(key[i]);
  236. }
  237. for (int i = 0; i < 3; i++)
  238. keys.push_back(key[i].GetPubKey());
  239. CMutableTransaction txFrom;
  240. txFrom.vout.resize(7);
  241. // First three are standard:
  242. CScript pay1 = GetScriptForDestination(key[0].GetPubKey().GetID());
  243. keystore.AddCScript(pay1);
  244. CScript pay1of3 = GetScriptForMultisig(1, keys);
  245. txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1)); // P2SH (OP_CHECKSIG)
  246. txFrom.vout[0].nValue = 1000;
  247. txFrom.vout[1].scriptPubKey = pay1; // ordinary OP_CHECKSIG
  248. txFrom.vout[1].nValue = 2000;
  249. txFrom.vout[2].scriptPubKey = pay1of3; // ordinary OP_CHECKMULTISIG
  250. txFrom.vout[2].nValue = 3000;
  251. // vout[3] is complicated 1-of-3 AND 2-of-3
  252. // ... that is OK if wrapped in P2SH:
  253. CScript oneAndTwo;
  254. oneAndTwo << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << ToByteVector(key[2].GetPubKey());
  255. oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY;
  256. oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey()) << ToByteVector(key[4].GetPubKey()) << ToByteVector(key[5].GetPubKey());
  257. oneAndTwo << OP_3 << OP_CHECKMULTISIG;
  258. keystore.AddCScript(oneAndTwo);
  259. txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo));
  260. txFrom.vout[3].nValue = 4000;
  261. // vout[4] is max sigops:
  262. CScript fifteenSigops; fifteenSigops << OP_1;
  263. for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++)
  264. fifteenSigops << ToByteVector(key[i%3].GetPubKey());
  265. fifteenSigops << OP_15 << OP_CHECKMULTISIG;
  266. keystore.AddCScript(fifteenSigops);
  267. txFrom.vout[4].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops));
  268. txFrom.vout[4].nValue = 5000;
  269. // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS
  270. CScript sixteenSigops; sixteenSigops << OP_16 << OP_CHECKMULTISIG;
  271. keystore.AddCScript(sixteenSigops);
  272. txFrom.vout[5].scriptPubKey = GetScriptForDestination(CScriptID(fifteenSigops));
  273. txFrom.vout[5].nValue = 5000;
  274. CScript twentySigops; twentySigops << OP_CHECKMULTISIG;
  275. keystore.AddCScript(twentySigops);
  276. txFrom.vout[6].scriptPubKey = GetScriptForDestination(CScriptID(twentySigops));
  277. txFrom.vout[6].nValue = 6000;
  278. coins.ModifyCoins(txFrom.GetHash())->FromTx(txFrom, 0);
  279. CMutableTransaction txTo;
  280. txTo.vout.resize(1);
  281. txTo.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
  282. txTo.vin.resize(5);
  283. for (int i = 0; i < 5; i++)
  284. {
  285. txTo.vin[i].prevout.n = i;
  286. txTo.vin[i].prevout.hash = txFrom.GetHash();
  287. }
  288. BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0));
  289. BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1));
  290. BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
  291. // SignSignature doesn't know how to sign these. We're
  292. // not testing validating signatures, so just create
  293. // dummy signatures that DO include the correct P2SH scripts:
  294. txTo.vin[3].scriptSig << OP_11 << OP_11 << static_cast<vector<unsigned char> >(oneAndTwo);
  295. txTo.vin[4].scriptSig << static_cast<vector<unsigned char> >(fifteenSigops);
  296. BOOST_CHECK(::AreInputsStandard(txTo, coins));
  297. // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
  298. BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
  299. // Make sure adding crap to the scriptSigs makes them non-standard:
  300. for (int i = 0; i < 3; i++)
  301. {
  302. CScript t = txTo.vin[i].scriptSig;
  303. txTo.vin[i].scriptSig = (CScript() << 11) + t;
  304. BOOST_CHECK(!::AreInputsStandard(txTo, coins));
  305. txTo.vin[i].scriptSig = t;
  306. }
  307. CMutableTransaction txToNonStd1;
  308. txToNonStd1.vout.resize(1);
  309. txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
  310. txToNonStd1.vout[0].nValue = 1000;
  311. txToNonStd1.vin.resize(1);
  312. txToNonStd1.vin[0].prevout.n = 5;
  313. txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();
  314. txToNonStd1.vin[0].scriptSig << static_cast<vector<unsigned char> >(sixteenSigops);
  315. BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins));
  316. BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U);
  317. CMutableTransaction txToNonStd2;
  318. txToNonStd2.vout.resize(1);
  319. txToNonStd2.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
  320. txToNonStd2.vout[0].nValue = 1000;
  321. txToNonStd2.vin.resize(1);
  322. txToNonStd2.vin[0].prevout.n = 6;
  323. txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();
  324. txToNonStd2.vin[0].scriptSig << static_cast<vector<unsigned char> >(twentySigops);
  325. BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins));
  326. BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U);
  327. }
  328. BOOST_AUTO_TEST_SUITE_END()