diff --git a/src/base58.cpp b/src/base58.cpp --- a/src/base58.cpp +++ b/src/base58.cpp @@ -3,10 +3,12 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "base58.h" +#include "bech32.h" #include "hash.h" #include "script/script.h" #include "uint256.h" +#include "utilstrencodings.h" #include #include @@ -209,6 +211,10 @@ } namespace { + +const static int BECH32_VERSION_PUBKEY = 0; +const static int BECH32_VERISON_SCRIPT = 8; + class DestinationEncoder : public boost::static_visitor { private: const CChainParams &m_params; @@ -217,22 +223,48 @@ DestinationEncoder(const CChainParams ¶ms) : m_params(params) {} std::string operator()(const CKeyID &id) const { - std::vector data = - m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS); - data.insert(data.end(), id.begin(), id.end()); - return EncodeBase58Check(data); + std::vector data = { + static_cast(BECH32_VERSION_PUBKEY)}; + ConvertBits<8, 5, true>(data, id.begin(), id.end()); + return bech32::Encode(m_params.Bech32HRP(), data); } std::string operator()(const CScriptID &id) const { - std::vector data = - m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); - data.insert(data.end(), id.begin(), id.end()); - return EncodeBase58Check(data); + std::vector data = { + static_cast(BECH32_VERISON_SCRIPT)}; + ConvertBits<8, 5, true>(data, id.begin(), id.end()); + return bech32::Encode(m_params.Bech32HRP(), data); } std::string operator()(const CNoDestination &no) const { return ""; } }; +CTxDestination +DecodeBech32Addr(const std::pair> &bech, + const CChainParams ¶ms) { + + if (bech.first != params.Bech32HRP()) return CNoDestination{}; + + if (bech.second.empty()) return CNoDestination{}; + + std::vector data; + if (!ConvertBits<5, 8, false>(data, begin(bech.second) + 1, + end(bech.second))) + return CNoDestination(); + + if (data.size() != 20) return CNoDestination{}; + + uint160 hash; + memcpy(hash.begin(), &data[0], 20); + + int version = bech.second.at(0); + if (version == BECH32_VERSION_PUBKEY) return CKeyID(hash); + if (version == BECH32_VERISON_SCRIPT) return CScriptID(hash); + + // unknown version + return CNoDestination{}; +} + CTxDestination DecodeDestination(const std::string &str, const CChainParams ¶ms) { std::vector data; @@ -256,7 +288,7 @@ return CScriptID(hash); } } - return CNoDestination(); + return DecodeBech32Addr(bech32::Decode(str), params); } } // namespace diff --git a/src/chainparams.h b/src/chainparams.h --- a/src/chainparams.h +++ b/src/chainparams.h @@ -86,6 +86,7 @@ const std::vector &Base58Prefix(Base58Type type) const { return base58Prefixes[type]; } + const std::string &Bech32HRP() const { return bech32HDR; } const std::vector &FixedSeeds() const { return vFixedSeeds; } const CCheckpointData &Checkpoints() const { return checkpointData; } const ChainTxData &TxData() const { return chainTxData; } @@ -100,6 +101,7 @@ uint64_t nPruneAfterHeight; std::vector vSeeds; std::vector base58Prefixes[MAX_BASE58_TYPES]; + std::string bech32HDR; std::string strNetworkID; CBlock genesis; std::vector vFixedSeeds; diff --git a/src/chainparams.cpp b/src/chainparams.cpp --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -195,6 +195,7 @@ base58Prefixes[SECRET_KEY] = std::vector(1, 128); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4}; + bech32HDR = "cash"; vFixedSeeds = std::vector( pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); @@ -358,6 +359,7 @@ base58Prefixes[SECRET_KEY] = std::vector(1, 239); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; + bech32HDR = "test"; vFixedSeeds = std::vector( pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); @@ -474,6 +476,7 @@ base58Prefixes[SECRET_KEY] = std::vector(1, 239); base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x35, 0x87, 0xCF}; base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x35, 0x83, 0x94}; + bech32HDR = "reg"; } void UpdateBIP9Parameters(Consensus::DeploymentPos d, int64_t nStartTime,