/ src / outputtype.cpp
outputtype.cpp
  1  // Copyright (c) 2009-2010 Satoshi Nakamoto
  2  // Copyright (c) 2009-2022 The Bitcoin Core developers
  3  // Distributed under the MIT software license, see the accompanying
  4  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5  
  6  #include <outputtype.h>
  7  
  8  #include <pubkey.h>
  9  #include <script/script.h>
 10  #include <script/sign.h>
 11  #include <script/signingprovider.h>
 12  #include <util/vector.h>
 13  
 14  #include <assert.h>
 15  #include <optional>
 16  #include <string>
 17  
 18  static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
 19  static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
 20  static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
 21  static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m";
 22  static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown";
 23  
 24  std::optional<OutputType> ParseOutputType(const std::string& type)
 25  {
 26      if (type == OUTPUT_TYPE_STRING_LEGACY) {
 27          return OutputType::LEGACY;
 28      } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
 29          return OutputType::P2SH_SEGWIT;
 30      } else if (type == OUTPUT_TYPE_STRING_BECH32) {
 31          return OutputType::BECH32;
 32      } else if (type == OUTPUT_TYPE_STRING_BECH32M) {
 33          return OutputType::BECH32M;
 34      }
 35      return std::nullopt;
 36  }
 37  
 38  const std::string& FormatOutputType(OutputType type)
 39  {
 40      switch (type) {
 41      case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY;
 42      case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
 43      case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
 44      case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M;
 45      case OutputType::UNKNOWN: return OUTPUT_TYPE_STRING_UNKNOWN;
 46      } // no default case, so the compiler can warn about missing cases
 47      assert(false);
 48  }
 49  
 50  CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
 51  {
 52      switch (type) {
 53      case OutputType::LEGACY: return PKHash(key);
 54      case OutputType::P2SH_SEGWIT:
 55      case OutputType::BECH32: {
 56          if (!key.IsCompressed()) return PKHash(key);
 57          CTxDestination witdest = WitnessV0KeyHash(key);
 58          CScript witprog = GetScriptForDestination(witdest);
 59          if (type == OutputType::P2SH_SEGWIT) {
 60              return ScriptHash(witprog);
 61          } else {
 62              return witdest;
 63          }
 64      }
 65      case OutputType::BECH32M:
 66      case OutputType::UNKNOWN: {} // This function should never be used with BECH32M or UNKNOWN, so let it assert
 67      } // no default case, so the compiler can warn about missing cases
 68      assert(false);
 69  }
 70  
 71  std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
 72  {
 73      PKHash keyid(key);
 74      CTxDestination p2pkh{keyid};
 75      if (key.IsCompressed()) {
 76          CTxDestination segwit = WitnessV0KeyHash(keyid);
 77          CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit));
 78          return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit));
 79      } else {
 80          return Vector(std::move(p2pkh));
 81      }
 82  }
 83  
 84  CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore, const CScript& script, OutputType type)
 85  {
 86      // Add script to keystore
 87      keystore.AddCScript(script);
 88      // Note that scripts over 520 bytes are not yet supported.
 89      switch (type) {
 90      case OutputType::LEGACY:
 91          return ScriptHash(script);
 92      case OutputType::P2SH_SEGWIT:
 93      case OutputType::BECH32: {
 94          CTxDestination witdest = WitnessV0ScriptHash(script);
 95          CScript witprog = GetScriptForDestination(witdest);
 96          // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
 97          keystore.AddCScript(witprog);
 98          if (type == OutputType::BECH32) {
 99              return witdest;
100          } else {
101              return ScriptHash(witprog);
102          }
103      }
104      case OutputType::BECH32M:
105      case OutputType::UNKNOWN: {} // This function should not be used for BECH32M or UNKNOWN, so let it assert
106      } // no default case, so the compiler can warn about missing cases
107      assert(false);
108  }
109  
110  std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
111      if (std::holds_alternative<PKHash>(dest) ||
112          std::holds_alternative<ScriptHash>(dest)) {
113          return OutputType::LEGACY;
114      }
115      if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
116          std::holds_alternative<WitnessV0ScriptHash>(dest)) {
117          return OutputType::BECH32;
118      }
119      if (std::holds_alternative<WitnessV1Taproot>(dest) ||
120          std::holds_alternative<WitnessUnknown>(dest)) {
121          return OutputType::BECH32M;
122      }
123      return std::nullopt;
124  }