Changeset View
Changeset View
Standalone View
Standalone View
src/cashaddrenc.cpp
- This file was added.
// Copyright (c) 2017 The Bitcoin developers | |||||
// Distributed under the MIT software license, see the accompanying | |||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
#include "cashaddrenc.h" | |||||
#include "cashaddr.h" | |||||
#include "chainparams.h" | |||||
#include "pubkey.h" | |||||
#include "script/script.h" | |||||
#include "utilstrencodings.h" | |||||
#include <boost/variant/static_visitor.hpp> | |||||
const uint8_t CASHADDR_VERSION_PUBKEY = 0; | |||||
const uint8_t CASHADDR_VERISON_SCRIPT = 8; | |||||
namespace { | |||||
// Implements encoding of CTxDestination using cashaddr. | |||||
class CashAddrEncoder : public boost::static_visitor<std::string> { | |||||
schancel: Does this basically operate as a closure then? | |||||
public: | |||||
CashAddrEncoder(const CChainParams &p); | |||||
std::string operator()(const CKeyID &id) const; | |||||
std::string operator()(const CScriptID &id) const; | |||||
std::string operator()(const CNoDestination &) const; | |||||
private: | |||||
const CChainParams ¶ms; | |||||
}; | |||||
CashAddrEncoder::CashAddrEncoder(const CChainParams &p) : params(p) {} | |||||
std::string CashAddrEncoder::operator()(const CKeyID &id) const { | |||||
std::vector<uint8_t> data = {CASHADDR_VERSION_PUBKEY}; | |||||
ConvertBits<8, 5, true>(data, id.begin(), id.end()); | |||||
return cashaddr::Encode(params.CashAddrPrefix(), data); | |||||
} | |||||
std::string CashAddrEncoder::operator()(const CScriptID &id) const { | |||||
std::vector<uint8_t> data = {CASHADDR_VERISON_SCRIPT}; | |||||
ConvertBits<8, 5, true>(data, id.begin(), id.end()); | |||||
deadalnixUnsubmitted Done Inline ActionsWe need to make sure we don't double pad when encoding/decoding. This needs more logic and a test for it. deadalnix: We need to make sure we don't double pad when encoding/decoding.
This needs more logic and a… | |||||
return cashaddr::Encode(params.CashAddrPrefix(), data); | |||||
} | |||||
std::string CashAddrEncoder::operator()(const CNoDestination &) const { | |||||
return ""; | |||||
} | |||||
} // anon ns | |||||
std::string EncodeCashAddr(const CTxDestination &dst, | |||||
const CChainParams ¶ms) { | |||||
return boost::apply_visitor(CashAddrEncoder(params), dst); | |||||
schancelUnsubmitted Not Done Inline ActionsWhat's the point of constructing this in such a way if we have a single-use function that takes params? schancel: What's the point of constructing this in such a way if we have a single-use function that takes… | |||||
dagurvalAuthorUnsubmitted Not Done Inline ActionsThis is how boost suggests working with boost::variants http://www.boost.org/doc/libs/1_64_0/doc/html/variant.html#variant.motivation dagurval: This is how boost suggests working with boost::variants http://www.boost. | |||||
} | |||||
CTxDestination DecodeCashAddr(const std::string &addrstr, | |||||
const CChainParams ¶ms) { | |||||
std::pair<std::string, std::vector<uint8_t>> cashaddr = | |||||
cashaddr::Decode(addrstr); | |||||
schancelUnsubmitted Not Done Inline ActionsThis was added in another patch already? schancel: This was added in another patch already? | |||||
if (cashaddr.first != params.CashAddrPrefix()) { | |||||
return CNoDestination{}; | |||||
} | |||||
if (cashaddr.second.empty()) { | |||||
return CNoDestination{}; | |||||
} | |||||
std::vector<unsigned char> data; | |||||
deadalnixUnsubmitted Done Inline ActionsPlease use uint8_t deadalnix: Please use uint8_t | |||||
if (!ConvertBits<5, 8, false>(data, begin(cashaddr.second) + 1, | |||||
end(cashaddr.second))) { | |||||
return CNoDestination(); | |||||
} | |||||
if (data.size() != 20) { | |||||
return CNoDestination{}; | |||||
} | |||||
uint160 hash; | |||||
memcpy(hash.begin(), &data[0], 20); | |||||
deadalnixUnsubmitted Not Done Inline ActionsI think it'd be preferable to use std::copy but not a big deal. deadalnix: I think it'd be preferable to use std::copy but not a big deal. | |||||
int version = cashaddr.second.at(0); | |||||
if (version == CASHADDR_VERSION_PUBKEY) { | |||||
return CKeyID(hash); | |||||
} | |||||
if (version == CASHADDR_VERISON_SCRIPT) { | |||||
return CScriptID(hash); | |||||
} | |||||
// unknown version | |||||
return CNoDestination{}; | |||||
} |
Does this basically operate as a closure then?