mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
Merge #19706: refactor: make EncodeBase58{Check} consume Spans
356988e200
util: make EncodeBase58Check consume Spans (Sebastian Falbesoner)f0fce0675d
util: make EncodeBase58 consume Spans (Sebastian Falbesoner) Pull request description: This PR improves the interfaces for the functions `EncodeBase58{Check}` by using Spans, in a similar fashion to e.g. PRs #19660, #19687. Note that on the master branch there are currently two versions of `EncodeBase58`: one that takes two pointers (marking begin and end) and another one that takes a `std::vector<unsigned char>` const-ref. The PR branch only leaves one generic Span-interface, both simplifying the interface and allowing more generic containers to be passed. The same is done for `EncodeBase58Check`, where only one interface existed but it's more generic now (e.g. a std::array can be directly passed, as done in the benchmarks). ACKs for top commit: laanwj: Code review ACK356988e200
Tree-SHA512: 47cfccdd7f3a2d4694bb8785e6e5fd756daee04ce1652ee59a7822e7e833b4a441ae9362b9bd67ea020d2b5b7d927629c9addb6abaa9881d8564fd3b1257f512
This commit is contained in:
commit
44ddcd887d
5 changed files with 18 additions and 30 deletions
|
@ -84,21 +84,21 @@ bool DecodeBase58(const char* psz, std::vector<unsigned char>& vch, int max_ret_
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
std::string EncodeBase58(Span<const unsigned char> input)
|
||||||
{
|
{
|
||||||
// Skip & count leading zeroes.
|
// Skip & count leading zeroes.
|
||||||
int zeroes = 0;
|
int zeroes = 0;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
while (pbegin != pend && *pbegin == 0) {
|
while (input.size() > 0 && input[0] == 0) {
|
||||||
pbegin++;
|
input = input.subspan(1);
|
||||||
zeroes++;
|
zeroes++;
|
||||||
}
|
}
|
||||||
// Allocate enough space in big-endian base58 representation.
|
// Allocate enough space in big-endian base58 representation.
|
||||||
int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
|
int size = input.size() * 138 / 100 + 1; // log(256) / log(58), rounded up.
|
||||||
std::vector<unsigned char> b58(size);
|
std::vector<unsigned char> b58(size);
|
||||||
// Process the bytes.
|
// Process the bytes.
|
||||||
while (pbegin != pend) {
|
while (input.size() > 0) {
|
||||||
int carry = *pbegin;
|
int carry = input[0];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// Apply "b58 = b58 * 256 + ch".
|
// Apply "b58 = b58 * 256 + ch".
|
||||||
for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
|
for (std::vector<unsigned char>::reverse_iterator it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
|
||||||
|
@ -109,7 +109,7 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||||
|
|
||||||
assert(carry == 0);
|
assert(carry == 0);
|
||||||
length = i;
|
length = i;
|
||||||
pbegin++;
|
input = input.subspan(1);
|
||||||
}
|
}
|
||||||
// Skip leading zeroes in base58 result.
|
// Skip leading zeroes in base58 result.
|
||||||
std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
|
std::vector<unsigned char>::iterator it = b58.begin() + (size - length);
|
||||||
|
@ -124,11 +124,6 @@ std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EncodeBase58(const std::vector<unsigned char>& vch)
|
|
||||||
{
|
|
||||||
return EncodeBase58(vch.data(), vch.data() + vch.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
|
bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len)
|
||||||
{
|
{
|
||||||
if (!ValidAsCString(str)) {
|
if (!ValidAsCString(str)) {
|
||||||
|
@ -137,10 +132,10 @@ bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, in
|
||||||
return DecodeBase58(str.c_str(), vchRet, max_ret_len);
|
return DecodeBase58(str.c_str(), vchRet, max_ret_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn)
|
std::string EncodeBase58Check(Span<const unsigned char> input)
|
||||||
{
|
{
|
||||||
// add 4-byte hash check to the end
|
// add 4-byte hash check to the end
|
||||||
std::vector<unsigned char> vch(vchIn);
|
std::vector<unsigned char> vch(input.begin(), input.end());
|
||||||
uint256 hash = Hash(vch);
|
uint256 hash = Hash(vch);
|
||||||
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
|
vch.insert(vch.end(), (unsigned char*)&hash, (unsigned char*)&hash + 4);
|
||||||
return EncodeBase58(vch);
|
return EncodeBase58(vch);
|
||||||
|
|
15
src/base58.h
15
src/base58.h
|
@ -15,20 +15,15 @@
|
||||||
#define BITCOIN_BASE58_H
|
#define BITCOIN_BASE58_H
|
||||||
|
|
||||||
#include <attributes.h>
|
#include <attributes.h>
|
||||||
|
#include <span.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a byte sequence as a base58-encoded string.
|
* Encode a byte span as a base58-encoded string
|
||||||
* pbegin and pend cannot be nullptr, unless both are.
|
|
||||||
*/
|
*/
|
||||||
std::string EncodeBase58(const unsigned char* pbegin, const unsigned char* pend);
|
std::string EncodeBase58(Span<const unsigned char> input);
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a byte vector as a base58-encoded string
|
|
||||||
*/
|
|
||||||
std::string EncodeBase58(const std::vector<unsigned char>& vch);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a base58-encoded string (psz) into a byte vector (vchRet).
|
* Decode a base58-encoded string (psz) into a byte vector (vchRet).
|
||||||
|
@ -44,9 +39,9 @@ NODISCARD bool DecodeBase58(const char* psz, std::vector<unsigned char>& vchRet,
|
||||||
NODISCARD bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
|
NODISCARD bool DecodeBase58(const std::string& str, std::vector<unsigned char>& vchRet, int max_ret_len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode a byte vector into a base58-encoded string, including checksum
|
* Encode a byte span into a base58-encoded string, including checksum
|
||||||
*/
|
*/
|
||||||
std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
|
std::string EncodeBase58Check(Span<const unsigned char> input);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode a base58-encoded string (psz) that includes a checksum into a byte
|
* Decode a base58-encoded string (psz) that includes a checksum into a byte
|
||||||
|
|
|
@ -20,7 +20,7 @@ static void Base58Encode(benchmark::Bench& bench)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
bench.batch(buff.size()).unit("byte").run([&] {
|
bench.batch(buff.size()).unit("byte").run([&] {
|
||||||
EncodeBase58(buff.data(), buff.data() + buff.size());
|
EncodeBase58(buff);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,8 @@ static void Base58CheckEncode(benchmark::Bench& bench)
|
||||||
200, 24
|
200, 24
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<unsigned char> vch;
|
|
||||||
vch.assign(buff.begin(), buff.end());
|
|
||||||
bench.batch(buff.size()).unit("byte").run([&] {
|
bench.batch(buff.size()).unit("byte").run([&] {
|
||||||
EncodeBase58Check(vch);
|
EncodeBase58Check(buff);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ static std::string DummyAddress(const CChainParams ¶ms)
|
||||||
std::vector<unsigned char> sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
std::vector<unsigned char> sourcedata = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
|
||||||
sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
|
sourcedata.insert(sourcedata.end(), dummydata, dummydata + sizeof(dummydata));
|
||||||
for(int i=0; i<256; ++i) { // Try every trailing byte
|
for(int i=0; i<256; ++i) { // Try every trailing byte
|
||||||
std::string s = EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size());
|
std::string s = EncodeBase58(sourcedata);
|
||||||
if (!IsValidDestinationString(s)) {
|
if (!IsValidDestinationString(s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(base58_EncodeBase58)
|
||||||
std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
|
std::vector<unsigned char> sourcedata = ParseHex(test[0].get_str());
|
||||||
std::string base58string = test[1].get_str();
|
std::string base58string = test[1].get_str();
|
||||||
BOOST_CHECK_MESSAGE(
|
BOOST_CHECK_MESSAGE(
|
||||||
EncodeBase58(sourcedata.data(), sourcedata.data() + sourcedata.size()) == base58string,
|
EncodeBase58(sourcedata) == base58string,
|
||||||
strTest);
|
strTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue