diff --git a/src/base58.cpp b/src/base58.cpp index c8091850..9649a681 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -7,6 +7,9 @@ #include "hash.h" #include "uint256.h" +#include "version.h" +#include "streams.h" + #include #include #include @@ -309,3 +312,38 @@ bool CBitcoinSecret::SetString(const std::string& strSecret) { return SetString(strSecret.c_str()); } + +const size_t serializedPaymentAddressSize = 64; + +bool CZCPaymentAddress::Set(const libzcash::PaymentAddress& addr) +{ + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << addr; + std::vector addrSerialized(ss.begin(), ss.end()); + assert(addrSerialized.size() == serializedPaymentAddressSize); + SetData(Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS), &addrSerialized[0], serializedPaymentAddressSize); + return true; +} + +libzcash::PaymentAddress CZCPaymentAddress::Get() const +{ + if (vchData.size() != serializedPaymentAddressSize) { + throw std::runtime_error( + "payment address is invalid" + ); + } + + if (vchVersion != Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS)) { + throw std::runtime_error( + "payment address is for wrong network type" + ); + } + + std::vector serialized(vchData.begin(), vchData.end()); + + CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); + libzcash::PaymentAddress ret; + ss >> ret; + return ret; +} + diff --git a/src/base58.h b/src/base58.h index 787979c8..27f564cc 100644 --- a/src/base58.h +++ b/src/base58.h @@ -20,6 +20,7 @@ #include "script/script.h" #include "script/standard.h" #include "support/allocators/zeroafterfree.h" +#include "zcash/Address.hpp" #include #include @@ -95,6 +96,17 @@ public: bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; } }; +class CZCPaymentAddress : public CBase58Data { +public: + bool Set(const libzcash::PaymentAddress& addr); + CZCPaymentAddress() {} + + CZCPaymentAddress(const std::string& strAddress) { SetString(strAddress.c_str(), 2); } + CZCPaymentAddress(const libzcash::PaymentAddress& addr) { Set(addr); } + + libzcash::PaymentAddress Get() const; +}; + /** 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. diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1e45243a..c73c68ce 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -105,6 +105,8 @@ public: base58Prefixes[SECRET_KEY] = std::vector(1,128); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container >(); + // guarantees the first two characters, when base58 encoded, are "zc" + base58Prefixes[ZCPAYMENT_ADDRRESS] = {22,154}; vFixedSeeds = std::vector(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main)); @@ -182,6 +184,7 @@ public: base58Prefixes[SECRET_KEY] = std::vector(1,239); base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container >(); base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x35)(0x83)(0x94).convert_to_container >(); + base58Prefixes[ZCPAYMENT_ADDRRESS] = {22,155}; vFixedSeeds = std::vector(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test)); diff --git a/src/chainparams.h b/src/chainparams.h index 7169c324..86d2dfb9 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -42,6 +42,8 @@ public: EXT_PUBLIC_KEY, EXT_SECRET_KEY, + ZCPAYMENT_ADDRRESS, + MAX_BASE58_TYPES }; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 0c7db257..a2027aec 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2634,11 +2634,8 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp) BOOST_FOREACH(const Pair& s, outputs) { - PaymentAddress addrTo; - { - CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION); - ssData >> addrTo; - } + CZCPaymentAddress pubaddr(s.name_); + PaymentAddress addrTo = pubaddr.Get(); CAmount nAmount = AmountFromValue(s.value_); vpourout.push_back(JSOutput(addrTo, nAmount)); @@ -2751,20 +2748,18 @@ Value zc_raw_keygen(const json_spirit::Array& params, bool fHelp) auto addr = k.address(); auto viewing_key = k.viewing_key(); - CDataStream pub(SER_NETWORK, PROTOCOL_VERSION); CDataStream priv(SER_NETWORK, PROTOCOL_VERSION); CDataStream viewing(SER_NETWORK, PROTOCOL_VERSION); - pub << addr; priv << k; viewing << viewing_key; - std::string pub_hex = HexStr(pub.begin(), pub.end()); + CZCPaymentAddress pubaddr(addr); std::string priv_hex = HexStr(priv.begin(), priv.end()); std::string viewing_hex = HexStr(viewing.begin(), viewing.end()); Object result; - result.push_back(Pair("zcaddress", pub_hex)); + result.push_back(Pair("zcaddress", pubaddr.ToString())); result.push_back(Pair("zcsecretkey", priv_hex)); result.push_back(Pair("zcviewingkey", viewing_hex)); return result;