Branch data Line data Source code
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 : 0 : std::optional<OutputType> ParseOutputType(const std::string& type)
25 : : {
26 [ # # ]: 0 : if (type == OUTPUT_TYPE_STRING_LEGACY) {
27 : 0 : return OutputType::LEGACY;
28 [ # # ]: 0 : } else if (type == OUTPUT_TYPE_STRING_P2SH_SEGWIT) {
29 : 0 : return OutputType::P2SH_SEGWIT;
30 [ # # ]: 0 : } else if (type == OUTPUT_TYPE_STRING_BECH32) {
31 : 0 : return OutputType::BECH32;
32 [ # # ]: 0 : } else if (type == OUTPUT_TYPE_STRING_BECH32M) {
33 : 0 : return OutputType::BECH32M;
34 : : }
35 : 0 : return std::nullopt;
36 : : }
37 : :
38 : 875 : const std::string& FormatOutputType(OutputType type)
39 : : {
40 [ + + + - : 875 : switch (type) {
- + ]
41 : : case OutputType::LEGACY: return OUTPUT_TYPE_STRING_LEGACY;
42 : 72 : case OutputType::P2SH_SEGWIT: return OUTPUT_TYPE_STRING_P2SH_SEGWIT;
43 : 659 : case OutputType::BECH32: return OUTPUT_TYPE_STRING_BECH32;
44 : 72 : case OutputType::BECH32M: return OUTPUT_TYPE_STRING_BECH32M;
45 : 0 : case OutputType::UNKNOWN: return OUTPUT_TYPE_STRING_UNKNOWN;
46 : : } // no default case, so the compiler can warn about missing cases
47 : 0 : assert(false);
48 : : }
49 : :
50 : 2 : CTxDestination GetDestinationForKey(const CPubKey& key, OutputType type)
51 : : {
52 [ + + - ]: 2 : switch (type) {
53 : 1 : case OutputType::LEGACY: return PKHash(key);
54 : 1 : case OutputType::P2SH_SEGWIT:
55 : 1 : case OutputType::BECH32: {
56 [ - + ]: 1 : if (!key.IsCompressed()) return PKHash(key);
57 [ + - ]: 1 : CTxDestination witdest = WitnessV0KeyHash(key);
58 [ + - ]: 1 : CScript witprog = GetScriptForDestination(witdest);
59 [ - + ]: 1 : if (type == OutputType::P2SH_SEGWIT) {
60 [ # # ]: 0 : return ScriptHash(witprog);
61 : : } else {
62 : 1 : return witdest;
63 : : }
64 : 1 : }
65 : 0 : case OutputType::BECH32M:
66 : 0 : 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 : 0 : assert(false);
69 : : }
70 : :
71 : 1 : std::vector<CTxDestination> GetAllDestinationsForKey(const CPubKey& key)
72 : : {
73 : 1 : PKHash keyid(key);
74 [ + - ]: 1 : CTxDestination p2pkh{keyid};
75 [ + - ]: 1 : if (key.IsCompressed()) {
76 [ + - ]: 1 : CTxDestination segwit = WitnessV0KeyHash(keyid);
77 [ + - + - ]: 1 : CTxDestination p2sh = ScriptHash(GetScriptForDestination(segwit));
78 [ + - ]: 1 : return Vector(std::move(p2pkh), std::move(p2sh), std::move(segwit));
79 : 1 : } else {
80 [ # # ]: 0 : return Vector(std::move(p2pkh));
81 : : }
82 : 1 : }
83 : :
84 : 0 : CTxDestination AddAndGetDestinationForScript(FlatSigningProvider& keystore, const CScript& script, OutputType type)
85 : : {
86 : : // Add script to keystore
87 : 0 : keystore.scripts.emplace(CScriptID(script), script);
88 : :
89 [ # # # ]: 0 : switch (type) {
90 : 0 : case OutputType::LEGACY:
91 : 0 : return ScriptHash(script);
92 : 0 : case OutputType::P2SH_SEGWIT:
93 : 0 : case OutputType::BECH32: {
94 [ # # ]: 0 : CTxDestination witdest = WitnessV0ScriptHash(script);
95 [ # # ]: 0 : CScript witprog = GetScriptForDestination(witdest);
96 : : // Add the redeemscript, so that P2WSH and P2SH-P2WSH outputs are recognized as ours.
97 [ # # # # ]: 0 : keystore.scripts.emplace(CScriptID(witprog), witprog);
98 [ # # ]: 0 : if (type == OutputType::BECH32) {
99 : 0 : return witdest;
100 : : } else {
101 [ # # ]: 0 : return ScriptHash(witprog);
102 : : }
103 : 0 : }
104 : 0 : case OutputType::BECH32M:
105 : 0 : 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 : 0 : assert(false);
108 : : }
109 : :
110 : 124 : std::optional<OutputType> OutputTypeFromDestination(const CTxDestination& dest) {
111 [ + - ]: 124 : if (std::holds_alternative<PKHash>(dest) ||
112 [ - + ]: 124 : std::holds_alternative<ScriptHash>(dest)) {
113 : 0 : return OutputType::LEGACY;
114 : : }
115 [ - + ]: 124 : if (std::holds_alternative<WitnessV0KeyHash>(dest) ||
116 [ # # ]: 0 : std::holds_alternative<WitnessV0ScriptHash>(dest)) {
117 : 124 : return OutputType::BECH32;
118 : : }
119 [ # # ]: 0 : if (std::holds_alternative<WitnessV1Taproot>(dest) ||
120 [ # # ]: 0 : std::holds_alternative<WitnessUnknown>(dest)) {
121 : 0 : return OutputType::BECH32M;
122 : : }
123 : 0 : return std::nullopt;
124 : : }
|