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