Skip to content

Commit

Permalink
Update EncodeDestination(), DecodeDestination() and IsValidDestination()
Browse files Browse the repository at this point in the history
An overview of commits that implement an initial switch from using
CBitcoinAddress to CTxDestination using bech32 (in line with Bitcoin's
implementation). A 80% implementation (not cleaned up) can be found in our archives:
- cevap/ion-old-v3@3b30fd0
- cevap/ion-old-v3@f8ee3a8
- cevap/ion-old-v3@7f87033
- cevap/ion-old-v3@f0d2206
- cevap/ion-old-v3@dbddc7b
- cevap/ion-old-v3@e834f27
- cevap/ion-old-v3@2c467e1
- cevap/ion-old-v3@ef36201
- cevap/ion-old-v3@3d6e391

Implementing this switch in full is future work, which needs:
- bitcoin#11117
- bitcoin#11167
- bitcoin#11372
  • Loading branch information
FornaxA authored and cevap committed Feb 6, 2021
1 parent ce3753a commit a45c5d4
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ BITCOIN_CORE_H = \
activemasternode.h \
addrman.h \
base58.h \
bech32.h \
bip38.h \
bloom.h \
blocksignature.h \
Expand Down Expand Up @@ -151,6 +152,7 @@ BITCOIN_CORE_H = \
invalid.h \
invalid_outpoints.json.h \
invalid_serials.json.h \
ionaddrenc.h \
kernel.h \
swifttx.h \
key.h \
Expand Down Expand Up @@ -571,10 +573,13 @@ libbitcoin_common_a_SOURCES = \
allocators.cpp \
amount.cpp \
base58.cpp \
bech32.cpp \
bip38.cpp \
chainparams.cpp \
coins.cpp \
compressor.cpp \
dstencode.cpp \
ionaddrenc.cpp \
primitives/block.cpp \
xion/deterministicmint.cpp \
primitives/transaction.cpp \
Expand Down
87 changes: 87 additions & 0 deletions src/base58.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,90 @@ bool CBitcoinSecret::SetString(const std::string& strSecret)
{
return SetString(strSecret.c_str());
}

namespace
{
class DestinationEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;

public:
DestinationEncoder(const CChainParams& params) : m_params(params) {}

std::string operator()(const CKeyID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}

std::string operator()(const CScriptID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}

/*
std::string operator()(const WitnessV0KeyHash& id) const
{
std::vector<unsigned char> data = {0};
ConvertBits<8, 5, true>(data, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessV0ScriptHash& id) const
{
std::vector<unsigned char> data = {0};
ConvertBits<8, 5, true>(data, id.begin(), id.end());
return bech32::Encode(m_params.Bech32HRP(), data);
}
std::string operator()(const WitnessUnknown& id) const
{
if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
return {};
}
std::vector<unsigned char> data = {(unsigned char)id.version};
ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
return bech32::Encode(m_params.Bech32HRP(), data);
}
*/
std::string operator()(const CNoDestination& no) const { return {}; }
};

CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
{
std::vector<unsigned char> data;
uint160 hash;
if (DecodeBase58Check(str, data)) {
// base58-encoded Bitcoin addresses.
// Public-key-hash-addresses have version 0 (or 111 testnet).
// The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
return CKeyID(hash);
}
// Script-hash-addresses have version 5 (or 196 testnet).
// The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
return CScriptID(hash);
}
}
return CNoDestination();
}
} // anon namespace

std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &params)
{
return boost::apply_visitor(DestinationEncoder(params), dest);
}

CTxDestination DecodeLegacyAddr(const std::string &str, const CChainParams &params)
{
return DecodeDestination(str, params);
}
6 changes: 6 additions & 0 deletions src/base58.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,10 @@ std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &);
/// Decode an old-style bitcoin address
CTxDestination DecodeLegacyAddr(const std::string &str, const CChainParams &);

/// Encode an old-style bitcoin address
std::string EncodeLegacyAddr(const CTxDestination &dest, const CChainParams &);

/// Decode an old-style bitcoin address
CTxDestination DecodeLegacyAddr(const std::string &str, const CChainParams &);

#endif // BITCOIN_BASE58_H
4 changes: 4 additions & 0 deletions src/script/standard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,7 @@ CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys)
script << CScript::EncodeOP_N(keys.size()) << OP_CHECKMULTISIG;
return script;
}

bool IsValidDestination(const CTxDestination& dest) {
return dest.which() != 0;
}
2 changes: 2 additions & 0 deletions src/script/standard.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ class CNoDestination {
* A CTxDestination is the internal data type encoded in a CBitcoinAddress
*/
typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
/** Check whether a CTxDestination is a CNoDestination. */
bool IsValidDestination(const CTxDestination& dest);

const char* GetTxnOutputType(txnouttype t);

Expand Down

0 comments on commit a45c5d4

Please sign in to comment.