1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 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 <script/standard.h>
13 #include <util/vector.h>
14 
15 #include <assert.h>
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 
ParseOutputType(const std::string & type,OutputType & output_type)23 bool ParseOutputType(const std::string& type, OutputType& output_type)
24 {
25     if (type == OUTPUT_TYPE_STRING_LEGACY) {
26         output_type = OutputType::LEGACY;
27         return true;
28     } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
29         output_type = OutputType::P2SH_SEGWIT;
30         return true;
31     } else if (type == OUTPUT_TYPE_STRING_BECH32) {
32         output_type = OutputType::BECH32;
33         return true;
34     } else if (type == OUTPUT_TYPE_STRING_BECH32M) {
35         output_type = OutputType::BECH32M;
36         return true;
37     }
38     return false;
39 }
40 
FormatOutputType(OutputType type)41 const std::string& FormatOutputType(OutputType type)
42 {
43     switch (type) {
44     case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY;
45     case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
46     case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
47     case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M;
48     } // no default case, so the compiler can warn about missing cases
49     assert(false);
50 }
51 
GetDestinationForKey(const CPubKey & key,OutputType type)52 CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
53 {
54     switch (type) {
55     case OutputType::LEGACY: return PKHash(key);
56     case OutputType::P2SH_SEGWIT:
57     case OutputType::BECH32: {
58         if (!key.IsCompressed()) return PKHash(key);
59         CTxDestination witdest = WitnessV0KeyHash(key);
60         CScript witprog = GetScriptForDestination(witdest);
61         if (type == OutputType::P2SH_SEGWIT) {
62             return ScriptHash(witprog);
63         } else {
64             return witdest;
65         }
66     }
67     case OutputType::BECH32M: {} // This function should never be used with BECH32M, so let it assert
68     } // no default case, so the compiler can warn about missing cases
69     assert(false);
70 }
71 
GetAllDestinationsForKey(const CPubKey & key)72 std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
73 {
74     PKHash keyid(key);
75     CTxDestination p2pkh{keyid};
76     if (key.IsCompressed()) {
77         CTxDestination segwit = WitnessV0KeyHash(keyid);
78         CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit));
79         return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit));
80     } else {
81         return Vector(std::move(p2pkh));
82     }
83 }
84 
AddAndGetDestinationForScript(FillableSigningProvider & keystore,const CScript & script,OutputType type)85 CTxDestination AddAndGetDestinationForScript(FillableSigningProvider& keystore, const CScript& script, OutputType type)
86 {
87     // Add script to keystore
88     keystore.AddCScript(script);
89     // Note that scripts over 520 bytes are not yet supported.
90     switch (type) {
91     case OutputType::LEGACY:
92         return ScriptHash(script);
93     case OutputType::P2SH_SEGWIT:
94     case OutputType::BECH32: {
95         CTxDestination witdest = WitnessV0ScriptHash(script);
96         CScript witprog = GetScriptForDestination(witdest);
97         // Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
98         if (!IsSolvable(keystore, witprog)) return ScriptHash(script);
99         // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
100         keystore.AddCScript(witprog);
101         if (type == OutputType::BECH32) {
102             return witdest;
103         } else {
104             return ScriptHash(witprog);
105         }
106     }
107     case OutputType::BECH32M: {} // This function should not be used for BECH32M, so let it assert
108     } // no default case, so the compiler can warn about missing cases
109     assert(false);
110 }
111 
OutputTypeFromDestination(const CTxDestination & dest)112 std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
113     if (std::holds_alternative<PKHash>(dest) ||
114         std::holds_alternative<ScriptHash>(dest)) {
115         return OutputType::LEGACY;
116     }
117     if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
118         std::holds_alternative<WitnessV0ScriptHash>(dest)) {
119         return OutputType::BECH32;
120     }
121     if (std::holds_alternative<WitnessV1Taproot>(dest) ||
122         std::holds_alternative<WitnessUnknown>(dest)) {
123         return OutputType::BECH32M;
124     }
125     return std::nullopt;
126 }
127