/ src / outputtype.cpp
outputtype.cpp
 1  // Copyright (c) 2009-2010 Satoshi Nakamoto
 2  // Copyright (c) 2009-present 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  
13  #include <cassert>
14  #include <optional>
15  #include <string>
16  
17  static const std::string OUTPUT_TYPE_STRING_LEGACY = "legacy";
18  static const std::string OUTPUT_TYPE_STRING_P2SH_SEGWIT = "p2sh-segwit";
19  static const std::string OUTPUT_TYPE_STRING_BECH32 = "bech32";
20  static const std::string OUTPUT_TYPE_STRING_BECH32M = "bech32m";
21  static const std::string OUTPUT_TYPE_STRING_UNKNOWN = "unknown";
22  
23  std::optional<OutputType> ParseOutputType(std::string_view type)
24  {
25      if (type == OUTPUT_TYPE_STRING_LEGACY) {
26          return OutputType::LEGACY;
27      } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
28          return OutputType::P2SH_SEGWIT;
29      } else if (type == OUTPUT_TYPE_STRING_BECH32) {
30          return OutputType::BECH32;
31      } else if (type == OUTPUT_TYPE_STRING_BECH32M) {
32          return OutputType::BECH32M;
33      }
34      return std::nullopt;
35  }
36  
37  const std::string& FormatOutputType(OutputType type)
38  {
39      switch (type) {
40      case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY;
41      case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
42      case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
43      case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M;
44      case OutputType::UNKNOWN: return OUTPUT_TYPE_STRING_UNKNOWN;
45      } // no default case, so the compiler can warn about missing cases
46      assert(false);
47  }
48  
49  std::string FormatAllOutputTypes()
50  {
51      return util::Join(OUTPUT_TYPES, ", ", [](const auto& i) { return "\"" + FormatOutputType(i) + "\""; });
52  }
53  
54  CTxDestination AddAndGetDestinationForScript(FlatSigningProvider& keystore, const CScript& script, OutputType type)
55  {
56      // Add script to keystore
57      keystore.scripts.emplace(CScriptID(script), script);
58  
59      switch (type) {
60      case OutputType::LEGACY:
61          return ScriptHash(script);
62      case OutputType::P2SH_SEGWIT:
63      case OutputType::BECH32: {
64          CTxDestination witdest = WitnessV0ScriptHash(script);
65          CScript witprog = GetScriptForDestination(witdest);
66          // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
67          keystore.scripts.emplace(CScriptID(witprog), witprog);
68          if (type == OutputType::BECH32) {
69              return witdest;
70          } else {
71              return ScriptHash(witprog);
72          }
73      }
74      case OutputType::BECH32M:
75      case OutputType::UNKNOWN: {} // This function should not be used for BECH32M or UNKNOWN, so let it assert
76      } // no default case, so the compiler can warn about missing cases
77      assert(false);
78  }
79  
80  std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
81      if (std::holds_alternative<PKHash>(dest) ||
82          std::holds_alternative<ScriptHash>(dest)) {
83          return OutputType::LEGACY;
84      }
85      if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
86          std::holds_alternative<WitnessV0ScriptHash>(dest)) {
87          return OutputType::BECH32;
88      }
89      if (std::holds_alternative<WitnessV1Taproot>(dest) ||
90          std::holds_alternative<WitnessUnknown>(dest)) {
91          return OutputType::BECH32M;
92      }
93      return std::nullopt;
94  }