Skip to content

Commit b225010

Browse files
committed
Merge #11372: Address encoding cleanup
92f1f8b Split off key_io_tests from base58_tests (Pieter Wuille) 119b0f8 Split key_io (address/key encodings) off from base58 (Pieter Wuille) ebfe217 Stop using CBase58Data for ext keys (Pieter Wuille) 32e69fa Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille) Pull request description: This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting. This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic. Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
2 parents 29088b1 + 92f1f8b commit b225010

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+484
-574
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ BITCOIN_CORE_H = \
105105
indirectmap.h \
106106
init.h \
107107
key.h \
108+
key_io.h \
108109
keystore.h \
109110
dbwrapper.h \
110111
limitedmap.h \
@@ -327,6 +328,7 @@ libbitcoin_common_a_SOURCES = \
327328
core_read.cpp \
328329
core_write.cpp \
329330
key.cpp \
331+
key_io.cpp \
330332
keystore.cpp \
331333
netaddress.cpp \
332334
netbase.cpp \

src/Makefile.test.include

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ TEST_SRCDIR = test
99
TEST_BINARY=test/test_bitcoin$(EXEEXT)
1010

1111
JSON_TEST_FILES = \
12-
test/data/script_tests.json \
13-
test/data/base58_keys_valid.json \
1412
test/data/base58_encode_decode.json \
15-
test/data/base58_keys_invalid.json \
13+
test/data/key_io_valid.json \
14+
test/data/key_io_invalid.json \
15+
test/data/script_tests.json \
16+
test/data/sighash.json \
1617
test/data/tx_invalid.json \
17-
test/data/tx_valid.json \
18-
test/data/sighash.json
18+
test/data/tx_valid.json
1919

2020
RAW_TEST_FILES =
2121

@@ -45,6 +45,7 @@ BITCOIN_TESTS =\
4545
test/DoS_tests.cpp \
4646
test/getarg_tests.cpp \
4747
test/hash_tests.cpp \
48+
test/key_io_tests.cpp \
4849
test/key_tests.cpp \
4950
test/limitedmap_tests.cpp \
5051
test/dbwrapper_tests.cpp \

src/base58.cpp

Lines changed: 0 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,12 @@
44

55
#include <base58.h>
66

7-
#include <bech32.h>
87
#include <hash.h>
9-
#include <script/script.h>
108
#include <uint256.h>
11-
#include <utilstrencodings.h>
129

13-
#include <boost/variant/apply_visitor.hpp>
14-
#include <boost/variant/static_visitor.hpp>
15-
16-
#include <algorithm>
1710
#include <assert.h>
1811
#include <string.h>
1912

20-
2113
/** All alphanumeric characters except for "0", "I", "O", and "l" */
2214
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
2315

@@ -151,227 +143,3 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
151143
{
152144
return DecodeBase58Check(str.c_str(), vchRet);
153145
}
154-
155-
CBase58Data::CBase58Data()
156-
{
157-
vchVersion.clear();
158-
vchData.clear();
159-
}
160-
161-
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
162-
{
163-
vchVersion = vchVersionIn;
164-
vchData.resize(nSize);
165-
if (!vchData.empty())
166-
memcpy(vchData.data(), pdata, nSize);
167-
}
168-
169-
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
170-
{
171-
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
172-
}
173-
174-
bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
175-
{
176-
std::vector<unsigned char> vchTemp;
177-
bool rc58 = DecodeBase58Check(psz, vchTemp);
178-
if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
179-
vchData.clear();
180-
vchVersion.clear();
181-
return false;
182-
}
183-
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
184-
vchData.resize(vchTemp.size() - nVersionBytes);
185-
if (!vchData.empty())
186-
memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
187-
memory_cleanse(vchTemp.data(), vchTemp.size());
188-
return true;
189-
}
190-
191-
bool CBase58Data::SetString(const std::string& str)
192-
{
193-
return SetString(str.c_str());
194-
}
195-
196-
std::string CBase58Data::ToString() const
197-
{
198-
std::vector<unsigned char> vch = vchVersion;
199-
vch.insert(vch.end(), vchData.begin(), vchData.end());
200-
return EncodeBase58Check(vch);
201-
}
202-
203-
int CBase58Data::CompareTo(const CBase58Data& b58) const
204-
{
205-
if (vchVersion < b58.vchVersion)
206-
return -1;
207-
if (vchVersion > b58.vchVersion)
208-
return 1;
209-
if (vchData < b58.vchData)
210-
return -1;
211-
if (vchData > b58.vchData)
212-
return 1;
213-
return 0;
214-
}
215-
216-
namespace
217-
{
218-
class DestinationEncoder : public boost::static_visitor<std::string>
219-
{
220-
private:
221-
const CChainParams& m_params;
222-
223-
public:
224-
DestinationEncoder(const CChainParams& params) : m_params(params) {}
225-
226-
std::string operator()(const CKeyID& id) const
227-
{
228-
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
229-
data.insert(data.end(), id.begin(), id.end());
230-
return EncodeBase58Check(data);
231-
}
232-
233-
std::string operator()(const CScriptID& id) const
234-
{
235-
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
236-
data.insert(data.end(), id.begin(), id.end());
237-
return EncodeBase58Check(data);
238-
}
239-
240-
std::string operator()(const WitnessV0KeyHash& id) const
241-
{
242-
std::vector<unsigned char> data = {0};
243-
ConvertBits<8, 5, true>(data, id.begin(), id.end());
244-
return bech32::Encode(m_params.Bech32HRP(), data);
245-
}
246-
247-
std::string operator()(const WitnessV0ScriptHash& id) const
248-
{
249-
std::vector<unsigned char> data = {0};
250-
ConvertBits<8, 5, true>(data, id.begin(), id.end());
251-
return bech32::Encode(m_params.Bech32HRP(), data);
252-
}
253-
254-
std::string operator()(const WitnessUnknown& id) const
255-
{
256-
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
257-
return {};
258-
}
259-
std::vector<unsigned char> data = {(unsigned char)id.version};
260-
ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
261-
return bech32::Encode(m_params.Bech32HRP(), data);
262-
}
263-
264-
std::string operator()(const CNoDestination& no) const { return {}; }
265-
};
266-
267-
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
268-
{
269-
std::vector<unsigned char> data;
270-
uint160 hash;
271-
if (DecodeBase58Check(str, data)) {
272-
// base58-encoded Bitcoin addresses.
273-
// Public-key-hash-addresses have version 0 (or 111 testnet).
274-
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
275-
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
276-
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
277-
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
278-
return CKeyID(hash);
279-
}
280-
// Script-hash-addresses have version 5 (or 196 testnet).
281-
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
282-
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
283-
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
284-
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
285-
return CScriptID(hash);
286-
}
287-
}
288-
data.clear();
289-
auto bech = bech32::Decode(str);
290-
if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
291-
// Bech32 decoding
292-
int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
293-
// The rest of the symbols are converted witness program bytes.
294-
if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
295-
if (version == 0) {
296-
{
297-
WitnessV0KeyHash keyid;
298-
if (data.size() == keyid.size()) {
299-
std::copy(data.begin(), data.end(), keyid.begin());
300-
return keyid;
301-
}
302-
}
303-
{
304-
WitnessV0ScriptHash scriptid;
305-
if (data.size() == scriptid.size()) {
306-
std::copy(data.begin(), data.end(), scriptid.begin());
307-
return scriptid;
308-
}
309-
}
310-
return CNoDestination();
311-
}
312-
if (version > 16 || data.size() < 2 || data.size() > 40) {
313-
return CNoDestination();
314-
}
315-
WitnessUnknown unk;
316-
unk.version = version;
317-
std::copy(data.begin(), data.end(), unk.program);
318-
unk.length = data.size();
319-
return unk;
320-
}
321-
}
322-
return CNoDestination();
323-
}
324-
} // namespace
325-
326-
void CBitcoinSecret::SetKey(const CKey& vchSecret)
327-
{
328-
assert(vchSecret.IsValid());
329-
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
330-
if (vchSecret.IsCompressed())
331-
vchData.push_back(1);
332-
}
333-
334-
CKey CBitcoinSecret::GetKey()
335-
{
336-
CKey ret;
337-
assert(vchData.size() >= 32);
338-
ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
339-
return ret;
340-
}
341-
342-
bool CBitcoinSecret::IsValid() const
343-
{
344-
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
345-
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
346-
return fExpectedFormat && fCorrectVersion;
347-
}
348-
349-
bool CBitcoinSecret::SetString(const char* pszSecret)
350-
{
351-
return CBase58Data::SetString(pszSecret) && IsValid();
352-
}
353-
354-
bool CBitcoinSecret::SetString(const std::string& strSecret)
355-
{
356-
return SetString(strSecret.c_str());
357-
}
358-
359-
std::string EncodeDestination(const CTxDestination& dest)
360-
{
361-
return boost::apply_visitor(DestinationEncoder(Params()), dest);
362-
}
363-
364-
CTxDestination DecodeDestination(const std::string& str)
365-
{
366-
return DecodeDestination(str, Params());
367-
}
368-
369-
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
370-
{
371-
return IsValidDestination(DecodeDestination(str, params));
372-
}
373-
374-
bool IsValidDestinationString(const std::string& str)
375-
{
376-
return IsValidDestinationString(str, Params());
377-
}

0 commit comments

Comments
 (0)