addresstype.cpp raw

   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  }
 174