raw
genesis                 1 #include <vector>
genesis 2 #include <boost/test/unit_test.hpp>
genesis 3 #include <boost/foreach.hpp>
genesis 4
genesis 5 #include "../main.h"
genesis 6 #include "../wallet.h"
genesis 7
genesis 8 using namespace std;
genesis 9 extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
genesis 10 extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, int nHashType);
genesis 11 extern bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, unsigned int nIn, int nHashType);
genesis 12
genesis 13 BOOST_AUTO_TEST_SUITE(script_tests)
genesis 14
genesis 15 BOOST_AUTO_TEST_CASE(script_PushData)
genesis 16 {
genesis 17 // Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
genesis 18 // the stack as the 1-75 opcodes do.
genesis 19 static const unsigned char direct[] = { 1, 0x5a };
genesis 20 static const unsigned char pushdata1[] = { OP_PUSHDATA1, 1, 0x5a };
genesis 21 static const unsigned char pushdata2[] = { OP_PUSHDATA2, 1, 0, 0x5a };
genesis 22 static const unsigned char pushdata4[] = { OP_PUSHDATA4, 1, 0, 0, 0, 0x5a };
genesis 23
genesis 24 vector<vector<unsigned char> > directStack;
genesis 25 BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), CTransaction(), 0, 0));
genesis 26
genesis 27 vector<vector<unsigned char> > pushdata1Stack;
genesis 28 BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), CTransaction(), 0, 0));
genesis 29 BOOST_CHECK(pushdata1Stack == directStack);
genesis 30
genesis 31 vector<vector<unsigned char> > pushdata2Stack;
genesis 32 BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), CTransaction(), 0, 0));
genesis 33 BOOST_CHECK(pushdata2Stack == directStack);
genesis 34
genesis 35 vector<vector<unsigned char> > pushdata4Stack;
genesis 36 BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), CTransaction(), 0, 0));
genesis 37 BOOST_CHECK(pushdata4Stack == directStack);
genesis 38 }
genesis 39
genesis 40 CScript
genesis 41 sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
genesis 42 {
genesis 43 uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL);
genesis 44
genesis 45 CScript result;
genesis 46 //
genesis 47 // NOTE: CHECKMULTISIG has an unfortunate bug; it requires
genesis 48 // one extra item on the stack, before the signatures.
genesis 49 // Putting OP_0 on the stack is the workaround;
genesis 50 // fixing the bug would mean splitting the blockchain (old
genesis 51 // clients would not accept new CHECKMULTISIG transactions,
genesis 52 // and vice-versa)
genesis 53 //
genesis 54 result << OP_0;
genesis 55 BOOST_FOREACH(CKey key, keys)
genesis 56 {
genesis 57 vector<unsigned char> vchSig;
genesis 58 BOOST_CHECK(key.Sign(hash, vchSig));
genesis 59 vchSig.push_back((unsigned char)SIGHASH_ALL);
genesis 60 result << vchSig;
genesis 61 }
genesis 62 return result;
genesis 63 }
genesis 64 CScript
genesis 65 sign_multisig(CScript scriptPubKey, CKey key, CTransaction transaction)
genesis 66 {
genesis 67 std::vector<CKey> keys;
genesis 68 keys.push_back(key);
genesis 69 return sign_multisig(scriptPubKey, keys, transaction);
genesis 70 }
genesis 71
genesis 72 BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
genesis 73 {
genesis 74 CKey key1, key2, key3;
genesis 75 key1.MakeNewKey();
genesis 76 key2.MakeNewKey();
genesis 77 key3.MakeNewKey();
genesis 78
genesis 79 CScript scriptPubKey12;
genesis 80 scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
genesis 81
genesis 82 CTransaction txFrom12;
genesis 83 txFrom12.vout.resize(1);
genesis 84 txFrom12.vout[0].scriptPubKey = scriptPubKey12;
genesis 85
genesis 86 CTransaction txTo12;
genesis 87 txTo12.vin.resize(1);
genesis 88 txTo12.vout.resize(1);
genesis 89 txTo12.vin[0].prevout.n = 0;
genesis 90 txTo12.vin[0].prevout.hash = txFrom12.GetHash();
genesis 91 txTo12.vout[0].nValue = 1;
genesis 92
genesis 93 CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
genesis 94 BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
genesis 95 txTo12.vout[0].nValue = 2;
genesis 96 BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
genesis 97
genesis 98 CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
genesis 99 BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, 0));
genesis 100
genesis 101 CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
genesis 102 BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, 0));
genesis 103 }
genesis 104
genesis 105 BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
genesis 106 {
genesis 107 CKey key1, key2, key3, key4;
genesis 108 key1.MakeNewKey();
genesis 109 key2.MakeNewKey();
genesis 110 key3.MakeNewKey();
genesis 111 key4.MakeNewKey();
genesis 112
genesis 113 CScript scriptPubKey23;
genesis 114 scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
genesis 115
genesis 116 CTransaction txFrom23;
genesis 117 txFrom23.vout.resize(1);
genesis 118 txFrom23.vout[0].scriptPubKey = scriptPubKey23;
genesis 119
genesis 120 CTransaction txTo23;
genesis 121 txTo23.vin.resize(1);
genesis 122 txTo23.vout.resize(1);
genesis 123 txTo23.vin[0].prevout.n = 0;
genesis 124 txTo23.vin[0].prevout.hash = txFrom23.GetHash();
genesis 125 txTo23.vout[0].nValue = 1;
genesis 126
genesis 127 std::vector<CKey> keys;
genesis 128 keys.push_back(key1); keys.push_back(key2);
genesis 129 CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 130 BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, 0));
genesis 131
genesis 132 keys.clear();
genesis 133 keys.push_back(key1); keys.push_back(key3);
genesis 134 CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 135 BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, 0));
genesis 136
genesis 137 keys.clear();
genesis 138 keys.push_back(key2); keys.push_back(key3);
genesis 139 CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 140 BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0));
genesis 141
genesis 142 keys.clear();
genesis 143 keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
genesis 144 CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 145 BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0));
genesis 146
genesis 147 keys.clear();
genesis 148 keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
genesis 149 CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 150 BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, 0));
genesis 151
genesis 152 keys.clear();
genesis 153 keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
genesis 154 CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 155 BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, 0));
genesis 156
genesis 157 keys.clear();
genesis 158 keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
genesis 159 CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 160 BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, 0));
genesis 161
genesis 162 keys.clear();
genesis 163 keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
genesis 164 CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 165 BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, 0));
genesis 166
genesis 167 keys.clear(); // Must have signatures
genesis 168 CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
genesis 169 BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, 0));
genesis 170 }
genesis 171
genesis 172
genesis 173 BOOST_AUTO_TEST_SUITE_END()