/ src / addresstype.cpp
addresstype.cpp
  1  // Copyright (c) 2023-present 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::ANCHOR: {
 91          addressRet = PayToAnchor();
 92          return true;
 93      }
 94      case TxoutType::WITNESS_UNKNOWN: {
 95          addressRet = WitnessUnknown{vSolutions[0][0], vSolutions[1]};
 96          return true;
 97      }
 98      case TxoutType::MULTISIG:
 99      case TxoutType::NULL_DATA:
100      case TxoutType::NONSTANDARD:
101          addressRet = CNoDestination(scriptPubKey);
102          return false;
103      } // no default case, so the compiler can warn about missing cases
104      assert(false);
105  }
106  
107  namespace {
108  class CScriptVisitor
109  {
110  public:
111      CScript operator()(const CNoDestination& dest) const
112      {
113          return dest.GetScript();
114      }
115  
116      CScript operator()(const PubKeyDestination& dest) const
117      {
118          return CScript() << ToByteVector(dest.GetPubKey()) << OP_CHECKSIG;
119      }
120  
121      CScript operator()(const PKHash& keyID) const
122      {
123          return CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
124      }
125  
126      CScript operator()(const ScriptHash& scriptID) const
127      {
128          return CScript() << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
129      }
130  
131      CScript operator()(const WitnessV0KeyHash& id) const
132      {
133          return CScript() << OP_0 << ToByteVector(id);
134      }
135  
136      CScript operator()(const WitnessV0ScriptHash& id) const
137      {
138          return CScript() << OP_0 << ToByteVector(id);
139      }
140  
141      CScript operator()(const WitnessV1Taproot& tap) const
142      {
143          return CScript() << OP_1 << ToByteVector(tap);
144      }
145  
146      CScript operator()(const WitnessUnknown& id) const
147      {
148          return CScript() << CScript::EncodeOP_N(id.GetWitnessVersion()) << id.GetWitnessProgram();
149      }
150  };
151  
152  class ValidDestinationVisitor
153  {
154  public:
155      bool operator()(const CNoDestination& dest) const { return false; }
156      bool operator()(const PubKeyDestination& dest) const { return false; }
157      bool operator()(const PKHash& dest) const { return true; }
158      bool operator()(const ScriptHash& dest) const { return true; }
159      bool operator()(const WitnessV0KeyHash& dest) const { return true; }
160      bool operator()(const WitnessV0ScriptHash& dest) const { return true; }
161      bool operator()(const WitnessV1Taproot& dest) const { return true; }
162      bool operator()(const WitnessUnknown& dest) const { return true; }
163  };
164  } // namespace
165  
166  CScript GetScriptForDestination(const CTxDestination& dest)
167  {
168      return std::visit(CScriptVisitor(), dest);
169  }
170  
171  bool IsValidDestination(const CTxDestination& dest) {
172      return std::visit(ValidDestinationVisitor(), dest);
173  }