Line data Source code
1 : // Copyright (c) 2014-2019 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #include "key_io.h"
6 :
7 : #include "base58.h"
8 : #include "script/script.h"
9 : #include <boost/variant/apply_visitor.hpp>
10 : #include <boost/variant/static_visitor.hpp>
11 :
12 : #include <assert.h>
13 : #include <string.h>
14 : #include <algorithm>
15 :
16 : namespace
17 : {
18 : class DestinationEncoder : public boost::static_visitor<std::string>
19 : {
20 : private:
21 : const CChainParams& m_params;
22 : const CChainParams::Base58Type m_addrType;
23 :
24 : public:
25 1990161 : explicit DestinationEncoder(const CChainParams& params, const CChainParams::Base58Type _addrType = CChainParams::PUBKEY_ADDRESS) : m_params(params), m_addrType(_addrType) {}
26 :
27 1990068 : std::string operator()(const CKeyID& id) const
28 : {
29 1990068 : std::vector<unsigned char> data = m_params.Base58Prefix(m_addrType);
30 1990068 : data.insert(data.end(), id.begin(), id.end());
31 3980136 : return EncodeBase58Check(data);
32 : }
33 :
34 0 : std::string operator()(const CExchangeKeyID& id) const
35 : {
36 0 : std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::EXCHANGE_ADDRESS);
37 0 : data.insert(data.end(), id.begin(), id.end());
38 0 : return EncodeBase58Check(data);
39 : }
40 :
41 93 : std::string operator()(const CScriptID& id) const
42 : {
43 93 : std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
44 93 : data.insert(data.end(), id.begin(), id.end());
45 186 : return EncodeBase58Check(data);
46 : }
47 :
48 0 : std::string operator()(const CNoDestination& no) const { return ""; }
49 : };
50 :
51 9813 : CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, bool& isStaking, bool& isExchange)
52 : {
53 19626 : std::vector<unsigned char> data;
54 9813 : uint160 hash;
55 9813 : if (DecodeBase58Check(str, data, 23)) {
56 : // base58-encoded PIVX addresses.
57 : // Public-key-hash-addresses have version 30 (or 139 testnet).
58 : // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
59 8397 : const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
60 8397 : if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
61 8225 : std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
62 8225 : return CKeyID(hash);
63 : }
64 : // Exchange Transparent addresses have version 31
65 172 : const std::vector<unsigned char>& exchange_pubkey_prefix = params.Base58Prefix(CChainParams::EXCHANGE_ADDRESS);
66 172 : if (data.size() == hash.size() + exchange_pubkey_prefix.size() && std::equal(exchange_pubkey_prefix.begin(), exchange_pubkey_prefix.end(), data.begin())) {
67 5 : isExchange = true;
68 5 : std::copy(data.begin() + exchange_pubkey_prefix.size(), data.end(), hash.begin());
69 5 : return CExchangeKeyID(hash);
70 : }
71 : // Public-key-hash-coldstaking-addresses have version 63 (or 73 testnet).
72 167 : const std::vector<unsigned char>& staking_prefix = params.Base58Prefix(CChainParams::STAKING_ADDRESS);
73 167 : if (data.size() == hash.size() + staking_prefix.size() && std::equal(staking_prefix.begin(), staking_prefix.end(), data.begin())) {
74 97 : isStaking = true;
75 97 : std::copy(data.begin() + staking_prefix.size(), data.end(), hash.begin());
76 97 : return CKeyID(hash);
77 : }
78 : // Script-hash-addresses have version 13 (or 19 testnet).
79 : // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
80 70 : const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
81 70 : if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
82 62 : std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
83 62 : return CScriptID(hash);
84 : }
85 : }
86 1424 : return CNoDestination();
87 : }
88 :
89 : } // anon namespace
90 :
91 257 : std::string EncodeDestination(const CTxDestination& dest, bool isStaking, bool isExchange)
92 : {
93 257 : return isExchange ? EncodeDestination(dest, CChainParams::EXCHANGE_ADDRESS) : (isStaking ? EncodeDestination(dest, CChainParams::STAKING_ADDRESS) : EncodeDestination(dest, CChainParams::PUBKEY_ADDRESS));
94 : }
95 :
96 1990161 : std::string EncodeDestination(const CTxDestination& dest, const CChainParams::Base58Type addrType)
97 : {
98 1990161 : return boost::apply_visitor(DestinationEncoder(Params(), addrType), dest);
99 : }
100 :
101 7968 : CTxDestination DecodeDestination(const std::string& str)
102 : {
103 7968 : bool isStaking;
104 7968 : bool isExchange;
105 7968 : return DecodeDestination(str, Params(), isStaking, isExchange);
106 : }
107 :
108 1845 : CTxDestination DecodeDestination(const std::string& str, bool& isStaking, bool& isExchange)
109 : {
110 1845 : return DecodeDestination(str, Params(), isStaking, isExchange);
111 : }
112 :
113 0 : bool IsValidDestinationString(const std::string& str, bool fStaking, const CChainParams& params)
114 : {
115 0 : bool isStaking = false;
116 0 : bool isExchange = false;
117 0 : return IsValidDestination(DecodeDestination(str, params, isStaking, isExchange)) && (isStaking == fStaking);
118 : }
119 :
120 0 : bool IsValidDestinationString(const std::string& str, bool isStaking)
121 : {
122 0 : return IsValidDestinationString(str, isStaking, Params());
123 : }
124 :
125 : namespace KeyIO {
126 :
127 1243 : CKey DecodeSecret(const std::string &str) {
128 1243 : CKey key;
129 1243 : std::vector<unsigned char> data;
130 1243 : if (DecodeBase58Check(str, data, 34)) {
131 1205 : const std::vector<unsigned char> &privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
132 1205 : if ((data.size() == 32 + privkey_prefix.size() ||
133 1205 : (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
134 1171 : std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
135 1165 : bool compressed = data.size() == 33 + privkey_prefix.size();
136 1165 : key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
137 : }
138 : }
139 1243 : if (!data.empty()) {
140 1205 : memory_cleanse(data.data(), data.size());
141 : }
142 2458 : return key;
143 : }
144 :
145 2047 : std::string EncodeSecret(const CKey &key) {
146 2047 : assert(key.IsValid());
147 2047 : std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
148 4094 : data.insert(data.end(), key.begin(), key.end());
149 2047 : if (key.IsCompressed()) {
150 2035 : data.push_back(1);
151 : }
152 2047 : std::string ret = EncodeBase58Check(data);
153 2047 : memory_cleanse(data.data(), data.size());
154 4094 : return ret;
155 : }
156 :
157 39 : CExtKey DecodeExtKey(const std::string &str) {
158 39 : CExtKey key;
159 39 : std::vector<unsigned char> data;
160 39 : if (DecodeBase58Check(str, data, 78)) {
161 39 : const std::vector<unsigned char> &prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
162 39 : if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() &&
163 39 : std::equal(prefix.begin(), prefix.end(), data.begin())) {
164 34 : key.Decode(data.data() + prefix.size());
165 : }
166 : }
167 78 : return key;
168 : }
169 :
170 20 : std::string EncodeExtKey(const CExtKey &key) {
171 20 : std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
172 20 : size_t size = data.size();
173 20 : data.resize(size + BIP32_EXTKEY_SIZE);
174 20 : key.Encode(data.data() + size);
175 20 : std::string ret = EncodeBase58Check(data);
176 20 : memory_cleanse(data.data(), data.size());
177 40 : return ret;
178 : }
179 :
180 39 : CExtPubKey DecodeExtPubKey(const std::string& str)
181 : {
182 39 : CExtPubKey key;
183 39 : std::vector<unsigned char> data;
184 39 : if (DecodeBase58Check(str, data, 78)) {
185 39 : const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
186 39 : if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
187 19 : key.Decode(data.data() + prefix.size());
188 : }
189 : }
190 78 : return key;
191 : }
192 :
193 14 : std::string EncodeExtPubKey(const CExtPubKey& key)
194 : {
195 14 : std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
196 14 : size_t size = data.size();
197 14 : data.resize(size + BIP32_EXTKEY_SIZE);
198 14 : key.Encode(data.data() + size);
199 14 : std::string ret = EncodeBase58Check(data);
200 28 : return ret;
201 : }
202 :
203 : }// namespace
|