Jim Posen
7 years ago
3 changed files with 386 additions and 91 deletions
@ -0,0 +1,385 @@
@@ -0,0 +1,385 @@
|
||||
// Copyright (c) 2017 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "key.h" |
||||
#include "script/script.h" |
||||
#include "script/script_error.h" |
||||
#include "script/standard.h" |
||||
#include "test/test_bitcoin.h" |
||||
|
||||
#include <boost/test/unit_test.hpp> |
||||
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(script_standard_tests, BasicTestingSetup) |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_Solver_success) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<std::vector<unsigned char> > solutions; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0])); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript))); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_1 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 4); |
||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({1})); |
||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); |
||||
BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1])); |
||||
BOOST_CHECK(solutions[3] == std::vector<unsigned char>({2})); |
||||
|
||||
s.clear(); |
||||
s << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
ToByteVector(pubkeys[2]) << |
||||
OP_3 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 5); |
||||
BOOST_CHECK(solutions[0] == std::vector<unsigned char>({2})); |
||||
BOOST_CHECK(solutions[1] == ToByteVector(pubkeys[0])); |
||||
BOOST_CHECK(solutions[2] == ToByteVector(pubkeys[1])); |
||||
BOOST_CHECK(solutions[3] == ToByteVector(pubkeys[2])); |
||||
BOOST_CHECK(solutions[4] == std::vector<unsigned char>({3})); |
||||
|
||||
// TX_NULL_DATA
|
||||
solutions.clear(); |
||||
s.clear(); |
||||
s << OP_RETURN << |
||||
std::vector<unsigned char>({0}) << |
||||
std::vector<unsigned char>({75}) << |
||||
std::vector<unsigned char>({255}); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_NULL_DATA); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 0); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
solutions.clear(); |
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_KEYHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID())); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&redeemScript[0], redeemScript.size()).Finalize(scriptHash.begin()); |
||||
|
||||
solutions.clear(); |
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(scriptHash); |
||||
BOOST_CHECK(Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_WITNESS_V0_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(solutions.size(), 1); |
||||
BOOST_CHECK(solutions[0] == ToByteVector(scriptHash)); |
||||
|
||||
// TX_NONSTANDARD
|
||||
solutions.clear(); |
||||
s.clear(); |
||||
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_NONSTANDARD); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure) |
||||
{ |
||||
CKey key; |
||||
CPubKey pubkey; |
||||
key.MakeNewKey(true); |
||||
pubkey = key.GetPubKey(); |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<std::vector<unsigned char> > solutions; |
||||
|
||||
// TX_PUBKEY with incorrectly sized pubkey
|
||||
s.clear(); |
||||
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_PUBKEYHASH with incorrectly sized key hash
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_SCRIPTHASH with incorrectly sized script hash
|
||||
s.clear(); |
||||
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG 0/2
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG 2/1
|
||||
s.clear(); |
||||
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG n = 2 with 1 pubkey
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_MULTISIG n = 1 with 0 pubkeys
|
||||
s.clear(); |
||||
s << OP_1 << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_NULL_DATA with other opcodes
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD; |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_WITNESS with unknown version
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey); |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
|
||||
// TX_WITNESS with incorrect program size
|
||||
s.clear(); |
||||
s << OP_0 << std::vector<unsigned char>(19, 0x01); |
||||
BOOST_CHECK(!Solver(s, whichType, solutions)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination) |
||||
{ |
||||
CKey key; |
||||
CPubKey pubkey; |
||||
key.MakeNewKey(true); |
||||
pubkey = key.GetPubKey(); |
||||
|
||||
CScript s; |
||||
CTxDestination address; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkey) << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CKeyID>(&address) && |
||||
*boost::get<CKeyID>(&address) == pubkey.GetID()); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CKeyID>(&address) && |
||||
*boost::get<CKeyID>(&address) == pubkey.GetID()); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(ExtractDestination(s, address)); |
||||
BOOST_CHECK(boost::get<CScriptID>(&address) && |
||||
*boost::get<CScriptID>(&address) == CScriptID(redeemScript)); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_NULL_DATA
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkey); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(CScriptID(redeemScript)); |
||||
BOOST_CHECK(!ExtractDestination(s, address)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestinations) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript s; |
||||
txnouttype whichType; |
||||
std::vector<CTxDestination> addresses; |
||||
int nRequired; |
||||
|
||||
// TX_PUBKEY
|
||||
s.clear(); |
||||
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEY); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
|
||||
// TX_PUBKEYHASH
|
||||
s.clear(); |
||||
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_PUBKEYHASH); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
|
||||
// TX_SCRIPTHASH
|
||||
CScript redeemScript(s); // initialize with leftover P2PKH script
|
||||
s.clear(); |
||||
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_SCRIPTHASH); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 1); |
||||
BOOST_CHECK_EQUAL(nRequired, 1); |
||||
BOOST_CHECK(boost::get<CScriptID>(&addresses[0]) && |
||||
*boost::get<CScriptID>(&addresses[0]) == CScriptID(redeemScript)); |
||||
|
||||
// TX_MULTISIG
|
||||
s.clear(); |
||||
s << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
OP_2 << OP_CHECKMULTISIG; |
||||
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
BOOST_CHECK_EQUAL(whichType, TX_MULTISIG); |
||||
BOOST_CHECK_EQUAL(addresses.size(), 2); |
||||
BOOST_CHECK_EQUAL(nRequired, 2); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[0]) && |
||||
*boost::get<CKeyID>(&addresses[0]) == pubkeys[0].GetID()); |
||||
BOOST_CHECK(boost::get<CKeyID>(&addresses[1]) && |
||||
*boost::get<CKeyID>(&addresses[1]) == pubkeys[1].GetID()); |
||||
|
||||
// TX_NULL_DATA
|
||||
s.clear(); |
||||
s << OP_RETURN << std::vector<unsigned char>({75}); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
|
||||
// TX_WITNESS_V0_KEYHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
|
||||
// TX_WITNESS_V0_SCRIPTHASH
|
||||
s.clear(); |
||||
s << OP_0 << ToByteVector(CScriptID(redeemScript)); |
||||
BOOST_CHECK(!ExtractDestinations(s, whichType, addresses, nRequired)); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_GetScriptFor_) |
||||
{ |
||||
CKey keys[3]; |
||||
CPubKey pubkeys[3]; |
||||
for (int i = 0; i < 3; i++) { |
||||
keys[i].MakeNewKey(true); |
||||
pubkeys[i] = keys[i].GetPubKey(); |
||||
} |
||||
|
||||
CScript expected, result; |
||||
|
||||
// CKeyID
|
||||
expected.clear(); |
||||
expected << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
result = GetScriptForDestination(pubkeys[0].GetID()); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// CScriptID
|
||||
CScript redeemScript(result); |
||||
expected.clear(); |
||||
expected << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL; |
||||
result = GetScriptForDestination(CScriptID(redeemScript)); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// CNoDestination
|
||||
expected.clear(); |
||||
result = GetScriptForDestination(CNoDestination()); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForRawPubKey
|
||||
expected.clear(); |
||||
expected << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
result = GetScriptForRawPubKey(pubkeys[0]); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForMultisig
|
||||
expected.clear(); |
||||
expected << OP_2 << |
||||
ToByteVector(pubkeys[0]) << |
||||
ToByteVector(pubkeys[1]) << |
||||
ToByteVector(pubkeys[2]) << |
||||
OP_3 << OP_CHECKMULTISIG; |
||||
result = GetScriptForMultisig(2, std::vector<CPubKey>(pubkeys, pubkeys + 3)); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
// GetScriptForWitness
|
||||
CScript witnessScript; |
||||
|
||||
witnessScript << ToByteVector(pubkeys[0]) << OP_CHECKSIG; |
||||
expected.clear(); |
||||
expected << OP_0 << ToByteVector(pubkeys[0].GetID()); |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
witnessScript.clear(); |
||||
witnessScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG; |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
|
||||
witnessScript.clear(); |
||||
witnessScript << OP_1 << ToByteVector(pubkeys[0]) << OP_1 << OP_CHECKMULTISIG; |
||||
|
||||
uint256 scriptHash; |
||||
CSHA256().Write(&witnessScript[0], witnessScript.size()).Finalize(scriptHash.begin()); |
||||
|
||||
expected.clear(); |
||||
expected << OP_0 << ToByteVector(scriptHash); |
||||
result = GetScriptForWitness(witnessScript); |
||||
BOOST_CHECK(result == expected); |
||||
} |
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() |
Loading…
Reference in new issue