/src/test/multisig_tests.cpp

https://github.com/superbitcoin/SuperBitcoin · C++ · 245 lines · 202 code · 37 blank · 6 comment · 27 complexity · 8c8d73b8faf61906e7f6926fbcb67bd5 MD5 · raw file

  1. // Copyright (c) 2011-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.
  4. #include "wallet/key.h"
  5. #include "wallet/keystore.h"
  6. #include "sbtccore/transaction/policy.h"
  7. #include "script/script.h"
  8. #include "script/script_error.h"
  9. #include "script/interpreter.h"
  10. #include "script/sign.h"
  11. #include "script/ismine.h"
  12. #include "uint256.h"
  13. #include "test/test_bitcoin.h"
  14. #include <boost/test/unit_test.hpp>
  15. BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
  16. CScript
  17. sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, int whichIn)
  18. {
  19. uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
  20. CScript result;
  21. result << OP_0; // CHECKMULTISIG bug workaround
  22. for (const CKey &key : keys)
  23. {
  24. std::vector<unsigned char> vchSig;
  25. BOOST_CHECK(key.Sign(hash, vchSig));
  26. vchSig.push_back((unsigned char)SIGHASH_ALL);
  27. result << vchSig;
  28. }
  29. return result;
  30. }
  31. BOOST_AUTO_TEST_CASE(multisig_verify)
  32. {
  33. unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
  34. ScriptError err;
  35. CKey key[4];
  36. CAmount amount = 0;
  37. for (int i = 0; i < 4; i++)
  38. key[i].MakeNewKey(true);
  39. CScript a_and_b;
  40. a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  41. << OP_CHECKMULTISIG;
  42. CScript a_or_b;
  43. a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  44. << OP_CHECKMULTISIG;
  45. CScript escrow;
  46. escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey())
  47. << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
  48. CMutableTransaction txFrom; // Funding transaction
  49. txFrom.vout.resize(3);
  50. txFrom.vout[0].scriptPubKey = a_and_b;
  51. txFrom.vout[1].scriptPubKey = a_or_b;
  52. txFrom.vout[2].scriptPubKey = escrow;
  53. CMutableTransaction txTo[3]; // Spending transaction
  54. for (int i = 0; i < 3; i++)
  55. {
  56. txTo[i].vin.resize(1);
  57. txTo[i].vout.resize(1);
  58. txTo[i].vin[0].prevout.n = i;
  59. txTo[i].vin[0].prevout.hash = txFrom.GetHash();
  60. txTo[i].vout[0].nValue = 1;
  61. }
  62. std::vector<CKey> keys;
  63. CScript s;
  64. // Test a AND b:
  65. keys.assign(1, key[0]);
  66. keys.push_back(key[1]);
  67. s = sign_multisig(a_and_b, keys, txTo[0], 0);
  68. BOOST_CHECK(VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount),
  69. &err));
  70. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
  71. for (int i = 0; i < 4; i++)
  72. {
  73. keys.assign(1, key[i]);
  74. s = sign_multisig(a_and_b, keys, txTo[0], 0);
  75. BOOST_CHECK_MESSAGE(
  76. !VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount),
  77. &err), strprintf("a&b 1: %d", i));
  78. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
  79. keys.assign(1, key[1]);
  80. keys.push_back(key[i]);
  81. s = sign_multisig(a_and_b, keys, txTo[0], 0);
  82. BOOST_CHECK_MESSAGE(
  83. !VerifyScript(s, a_and_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount),
  84. &err), strprintf("a&b 2: %d", i));
  85. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
  86. }
  87. // Test a OR b:
  88. for (int i = 0; i < 4; i++)
  89. {
  90. keys.assign(1, key[i]);
  91. s = sign_multisig(a_or_b, keys, txTo[1], 0);
  92. if (i == 0 || i == 1)
  93. {
  94. BOOST_CHECK_MESSAGE(
  95. VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount),
  96. &err), strprintf("a|b: %d", i));
  97. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
  98. } else
  99. {
  100. BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, nullptr, flags,
  101. MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err),
  102. strprintf("a|b: %d", i));
  103. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
  104. }
  105. }
  106. s.clear();
  107. s << OP_0 << OP_1;
  108. BOOST_CHECK(!VerifyScript(s, a_or_b, nullptr, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount),
  109. &err));
  110. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
  111. for (int i = 0; i < 4; i++)
  112. for (int j = 0; j < 4; j++)
  113. {
  114. keys.assign(1, key[i]);
  115. keys.push_back(key[j]);
  116. s = sign_multisig(escrow, keys, txTo[2], 0);
  117. if (i < j && i < 3 && j < 3)
  118. {
  119. BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, nullptr, flags,
  120. MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err),
  121. strprintf("escrow 1: %d %d", i, j));
  122. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
  123. } else
  124. {
  125. BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, nullptr, flags,
  126. MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err),
  127. strprintf("escrow 2: %d %d", i, j));
  128. BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
  129. }
  130. }
  131. }
  132. BOOST_AUTO_TEST_CASE(multisig_IsStandard)
  133. {
  134. CKey key[4];
  135. for (int i = 0; i < 4; i++)
  136. key[i].MakeNewKey(true);
  137. txnouttype whichType;
  138. CScript a_and_b;
  139. a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  140. << OP_CHECKMULTISIG;
  141. BOOST_CHECK(::IsStandard(a_and_b, whichType));
  142. CScript a_or_b;
  143. a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  144. << OP_CHECKMULTISIG;
  145. BOOST_CHECK(::IsStandard(a_or_b, whichType));
  146. CScript escrow;
  147. escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey())
  148. << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
  149. BOOST_CHECK(::IsStandard(escrow, whichType));
  150. CScript one_of_four;
  151. one_of_four << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey())
  152. << ToByteVector(key[2].GetPubKey()) << ToByteVector(key[3].GetPubKey()) << OP_4 << OP_CHECKMULTISIG;
  153. BOOST_CHECK(!::IsStandard(one_of_four, whichType));
  154. CScript malformed[6];
  155. malformed[0] << OP_3 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  156. << OP_CHECKMULTISIG;
  157. malformed[1] << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_3
  158. << OP_CHECKMULTISIG;
  159. malformed[2] << OP_0 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  160. << OP_CHECKMULTISIG;
  161. malformed[3] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_0
  162. << OP_CHECKMULTISIG;
  163. malformed[4] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey())
  164. << OP_CHECKMULTISIG;
  165. malformed[5] << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey());
  166. for (int i = 0; i < 6; i++)
  167. BOOST_CHECK(!::IsStandard(malformed[i], whichType));
  168. }
  169. BOOST_AUTO_TEST_CASE(multisig_Sign)
  170. {
  171. // Test SignSignature() (and therefore the version of Solver() that signs transactions)
  172. CBasicKeyStore keystore;
  173. CKey key[4];
  174. for (int i = 0; i < 4; i++)
  175. {
  176. key[i].MakeNewKey(true);
  177. keystore.AddKey(key[i]);
  178. }
  179. CScript a_and_b;
  180. a_and_b << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  181. << OP_CHECKMULTISIG;
  182. CScript a_or_b;
  183. a_or_b << OP_1 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey()) << OP_2
  184. << OP_CHECKMULTISIG;
  185. CScript escrow;
  186. escrow << OP_2 << ToByteVector(key[0].GetPubKey()) << ToByteVector(key[1].GetPubKey())
  187. << ToByteVector(key[2].GetPubKey()) << OP_3 << OP_CHECKMULTISIG;
  188. CMutableTransaction txFrom; // Funding transaction
  189. txFrom.vout.resize(3);
  190. txFrom.vout[0].scriptPubKey = a_and_b;
  191. txFrom.vout[1].scriptPubKey = a_or_b;
  192. txFrom.vout[2].scriptPubKey = escrow;
  193. CMutableTransaction txTo[3]; // Spending transaction
  194. for (int i = 0; i < 3; i++)
  195. {
  196. txTo[i].vin.resize(1);
  197. txTo[i].vout.resize(1);
  198. txTo[i].vin[0].prevout.n = i;
  199. txTo[i].vin[0].prevout.hash = txFrom.GetHash();
  200. txTo[i].vout[0].nValue = 1;
  201. }
  202. for (int i = 0; i < 3; i++)
  203. {
  204. BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL | SIGHASH_SBTC_FORK),
  205. strprintf("SignSignature %d", i));
  206. }
  207. }
  208. BOOST_AUTO_TEST_SUITE_END()