dash/src/test/script_standard_tests.cpp
Wladimir J. van der Laan 2d13a4b190 Merge #15452: Replace CScriptID and CKeyID in CTxDestination with dedicated types
78e407ad0c26190a22de1bc8ed900164a44a36c3 GetKeyBirthTimes should return key ids, not destinations (Gregory Sanders)
70946e7fee54323ce6a5ea8aeb377e2c7c790bc6 Replace CScriptID and CKeyID in CTxDestination with dedicated types (Gregory Sanders)

Pull request description:

  The current usage seems to be an overloading of meanings. `CScriptID` is used in the wallet as a lookup key, as well as a destination, and `CKeyID` likewise. Instead, have all destinations be dedicated types.

  New types:
  `CScriptID`->`ScriptHash`
  `CKeyID`->`PKHash`

ACKs for commit 78e407:
  ryanofsky:
    utACK 78e407ad0c26190a22de1bc8ed900164a44a36c3. Only changes are removing extra CScriptID()s and fixing the test case.
  Sjors:
    utACK 78e407a
  meshcollider:
    utACK 78e407ad0c

Tree-SHA512: 437f59fc3afb83a40540da3351507aef5aed44e3a7f15b01ddad6226854edeee762ff0b0ef336fe3654c4cd99a205cef175211de8b639abe1130c8a6313337b9
2023-02-10 23:34:57 +03:00

298 lines
10 KiB
C++

// 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/signingprovider.h>
#include <script/standard.h>
#include <test/util/setup_common.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;
std::vector<std::vector<unsigned char> > solutions;
// TxoutType::PUBKEY
s.clear();
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEY);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0]));
// TxoutType::PUBKEYHASH
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::PUBKEYHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(pubkeys[0].GetID()));
// TxoutType::SCRIPTHASH
CScript redeemScript(s); // initialize with leftover P2PKH script
s.clear();
s << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::SCRIPTHASH);
BOOST_CHECK_EQUAL(solutions.size(), 1U);
BOOST_CHECK(solutions[0] == ToByteVector(CScriptID(redeemScript)));
// TxoutType::MULTISIG
s.clear();
s << OP_1 <<
ToByteVector(pubkeys[0]) <<
ToByteVector(pubkeys[1]) <<
OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
BOOST_CHECK_EQUAL(solutions.size(), 4U);
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_EQUAL(Solver(s, solutions), TxoutType::MULTISIG);
BOOST_CHECK_EQUAL(solutions.size(), 5U);
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}));
// TxoutType::NULL_DATA
s.clear();
s << OP_RETURN <<
std::vector<unsigned char>({0}) <<
std::vector<unsigned char>({75}) <<
std::vector<unsigned char>({255});
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NULL_DATA);
BOOST_CHECK_EQUAL(solutions.size(), 0U);
// TxoutType::NONSTANDARD
s.clear();
s << OP_9 << OP_ADD << OP_11 << OP_EQUAL;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
}
BOOST_AUTO_TEST_CASE(script_standard_Solver_failure)
{
CKey key;
CPubKey pubkey;
key.MakeNewKey(true);
pubkey = key.GetPubKey();
CScript s;
std::vector<std::vector<unsigned char> > solutions;
// TxoutType::PUBKEY with incorrectly sized pubkey
s.clear();
s << std::vector<unsigned char>(30, 0x01) << OP_CHECKSIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::PUBKEYHASH with incorrectly sized key hash
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey) << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::SCRIPTHASH with incorrectly sized script hash
s.clear();
s << OP_HASH160 << std::vector<unsigned char>(21, 0x01) << OP_EQUAL;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::MULTISIG 0/2
s.clear();
s << OP_0 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::MULTISIG 2/1
s.clear();
s << OP_2 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::MULTISIG n = 2 with 1 pubkey
s.clear();
s << OP_1 << ToByteVector(pubkey) << OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::MULTISIG n = 1 with 0 pubkeys
s.clear();
s << OP_1 << OP_1 << OP_CHECKMULTISIG;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
// TxoutType::NULL_DATA with other opcodes
s.clear();
s << OP_RETURN << std::vector<unsigned char>({75}) << OP_ADD;
BOOST_CHECK_EQUAL(Solver(s, solutions), TxoutType::NONSTANDARD);
}
BOOST_AUTO_TEST_CASE(script_standard_ExtractDestination)
{
CKey key;
CPubKey pubkey;
key.MakeNewKey(true);
pubkey = key.GetPubKey();
CScript s;
CTxDestination address;
// TxoutType::PUBKEY
s.clear();
s << ToByteVector(pubkey) << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
BOOST_CHECK(std::get_if<PKHash>(&address) &&
*std::get_if<PKHash>(&address) == PKHash(pubkey));
// TxoutType::PUBKEYHASH
s.clear();
s << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK(ExtractDestination(s, address));
BOOST_CHECK(std::get_if<PKHash>(&address) &&
*std::get_if<PKHash>(&address) == PKHash(pubkey));
// TxoutType::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(std::get_if<ScriptHash>(&address) &&
*std::get_if<ScriptHash>(&address) == ScriptHash(redeemScript));
// TxoutType::MULTISIG
s.clear();
s << OP_1 << ToByteVector(pubkey) << OP_1 << OP_CHECKMULTISIG;
BOOST_CHECK(!ExtractDestination(s, address));
// TxoutType::NULL_DATA
s.clear();
s << OP_RETURN << std::vector<unsigned char>({75});
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;
TxoutType whichType;
std::vector<CTxDestination> addresses;
int nRequired;
// TxoutType::PUBKEY
s.clear();
s << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
BOOST_CHECK(ExtractDestinations(s, whichType, addresses, nRequired));
BOOST_CHECK_EQUAL(whichType, TxoutType::PUBKEY);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
*std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TxoutType::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, TxoutType::PUBKEYHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
*std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
// TxoutType::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, TxoutType::SCRIPTHASH);
BOOST_CHECK_EQUAL(addresses.size(), 1U);
BOOST_CHECK_EQUAL(nRequired, 1);
BOOST_CHECK(std::get_if<ScriptHash>(&addresses[0]) &&
*std::get_if<ScriptHash>(&addresses[0]) == ScriptHash(redeemScript));
// TxoutType::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, TxoutType::MULTISIG);
BOOST_CHECK_EQUAL(addresses.size(), 2U);
BOOST_CHECK_EQUAL(nRequired, 2);
BOOST_CHECK(std::get_if<PKHash>(&addresses[0]) &&
*std::get_if<PKHash>(&addresses[0]) == PKHash(pubkeys[0]));
BOOST_CHECK(std::get_if<PKHash>(&addresses[1]) &&
*std::get_if<PKHash>(&addresses[1]) == PKHash(pubkeys[1]));
// TxoutType::NULL_DATA
s.clear();
s << OP_RETURN << std::vector<unsigned char>({75});
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;
// PKHash
expected.clear();
expected << OP_DUP << OP_HASH160 << ToByteVector(PKHash(pubkeys[0])) << OP_EQUALVERIFY << OP_CHECKSIG;
result = GetScriptForDestination(PKHash(pubkeys[0]));
BOOST_CHECK(result == expected);
// ScriptHash
CScript redeemScript(result);
expected.clear();
expected << OP_HASH160 << ToByteVector(ScriptHash(redeemScript)) << OP_EQUAL;
result = GetScriptForDestination(ScriptHash(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);
}
BOOST_AUTO_TEST_SUITE_END()