/ src / addresstype.cpp
addresstype.cpp
  1  // Copyright (c) 2023 The Bitcoin Core developers
  2  // Distributed under the MIT software license, see the accompanying
  3  // file COPYING or https://www.opensource.org/licenses/mit-license.php.
  4  
  5  #include <addresstype.h>
  6  
  7  #include <crypto/sha256.h>
  8  #include <hash.h>
  9  #include <pubkey.h>
 10  #include <script/script.h>
 11  #include <script/solver.h>
 12  #include <uint256.h>
 13  #include <util/hash_type.h>
 14  
 15  #include <cassert>
 16  #include <vector>
 17  
 18  typedef std::vector<unsigned char> valtype;
 19  
 20  ScriptHash::ScriptHash(const CScript& in) : BaseHash(Hash160(in)) {}
 21  ScriptHash::ScriptHash(const CScriptID& in) : BaseHash{in} {}
 22  
 23  PKHash::PKHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
 24  PKHash::PKHash(const CKeyID& pubkey_id) : BaseHash(pubkey_id) {}
 25  
 26  WitnessV0KeyHash::WitnessV0KeyHash(const CPubKey& pubkey) : BaseHash(pubkey.GetID()) {}
 27  WitnessV0KeyHash::WitnessV0KeyHash(const PKHash& pubkey_hash) : BaseHash{pubkey_hash} {}
 28  
 29  CKeyID ToKeyID(const PKHash& key_hash)
 30  {
 31      return CKeyID{uint160{key_hash}};
 32  }
 33  
 34  CKeyID ToKeyID(const WitnessV0KeyHash& key_hash)
 35  {
 36      return CKeyID{uint160{key_hash}};
 37  }
 38  
 39  CScriptID ToScriptID(const ScriptHash& script_hash)
 40  {
 41      return CScriptID{uint160{script_hash}};
 42  }
 43  
 44  WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
 45  {
 46      CSHA256().Write(in.data(), in.size()).Finalize(begin());
 47  }
 48  
 49  bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
 50  {
 51      std::vector<valtype> vSolutions;
 52      TxoutType whichType = Solver(scriptPubKey, vSolutions);
 53  
 54      switch (whichType) {
 55      case TxoutType::PUBKEY: {
 56          CPubKey pubKey(vSolutions[0]);
 57          if (!pubKey.IsValid()) {
 58              addressRet = CNoDestination(scriptPubKey);
 59          } else {
 60              addressRet = PubKeyDestination(pubKey);
 61          }
 62          return false;
 63      }
 64      case TxoutType::PUBKEYHASH: {
 65          addressRet = PKHash(uint160(vSolutions[0]));
 66          return true;
 67      }
 68      case TxoutType::SCRIPTHASH: {
 69          addressRet = ScriptHash(uint160(vSolutions[0]));
 70          return true;
 71      }
 72      case TxoutType::WITNESS_V0_KEYHASH: {
 73          WitnessV0KeyHash hash;
 74          std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
 75          addressRet = hash;
 76          return true;
 77      }
 78      case TxoutType::WITNESS_V0_SCRIPTHASH: {
 79          WitnessV0ScriptHash hash;
 80          std::copy(vSolutions[0].begin(), vSolutions[0].end(), hash.begin());
 81          addressRet = hash;
 82          return true;
 83      }
 84      case TxoutType::WITNESS_V1_TAPROOT: {
 85          WitnessV1Taproot tap;
 86          std::copy(vSolutions[0].begin(), vSolutions[0].end(), tap.begin());
 87          addressRet = tap;
 88          return true;
 89      }
 90      case TxoutType::WITNESS_UNKNOWN: {
 91          addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
 92          return true;
 93      }
 94      case TxoutType::MULTISIG:
 95      case TxoutType::NULL_DATA:
 96      case TxoutType::NONSTANDARD:
 97          addressRet = CNoDestination(scriptPubKey);
 98          return false;
 99      } // no default case, so the compiler can warn about missing cases
100      assert(false);
101  }
102  
103  namespace {
104  class CScriptVisitor
105  {
106  public:
107      CScript operator()(const CNoDestination& dest) const
108      {
109          return dest.GetScript();
110      }
111  
112      CScript operator()(const PubKeyDestination& dest) const
113      {
114          return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG;
115      }
116  
117      CScript operator()(const PKHash& keyID) const
118      {
119          return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
120      }
121  
122      CScript operator()(const ScriptHash& scriptID) const
123      {
124          return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
125      }
126  
127      CScript operator()(const WitnessV0KeyHash& id) const
128      {
129          return CScript() << OP_0 << ToByteVector(id);
130      }
131  
132      CScript operator()(const WitnessV0ScriptHash& id) const
133      {
134          return CScript() << OP_0 << ToByteVector(id);
135      }
136  
137      CScript operator()(const WitnessV1Taproot& tap) const
138      {
139          return CScript() << OP_1 << ToByteVector(tap);
140      }
141  
142      CScript operator()(const WitnessUnknown& id) const
143      {
144          return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
145      }
146  };
147  
148  class ValidDestinationVisitor
149  {
150  public:
151      bool operator()(const CNoDestination& dest) const { return false; }
152      bool operator()(const PubKeyDestination& dest) const { return false; }
153      bool operator()(const PKHash& dest) const { return true; }
154      bool operator()(const ScriptHash& dest) const { return true; }
155      bool operator()(const WitnessV0KeyHash& dest) const { return true; }
156      bool operator()(const WitnessV0ScriptHash& dest) const { return true; }
157      bool operator()(const WitnessV1Taproot& dest) const { return true; }
158      bool operator()(const WitnessUnknown& dest) const { return true; }
159  };
160  } // namespace
161  
162  CScript GetScriptForDestination(const CTxDestination& dest)
163  {
164      return std::visit(CScriptVisitor(), dest);
165  }
166  
167  bool IsValidDestination(const CTxDestination& dest) {
168      return std::visit(ValidDestinationVisitor(), dest);
169  }