Auto merge of #3242 - str4d:3058-key-encoding-refactor, r=str4d

Key encoding refactor

Includes code cherry-picked from the following upstream PRs:

- bitcoin/bitcoin#11372
  - Only the first three commits (the fourth commit depends on #2390)

Part of #3058.
This commit is contained in:
Homu
2018-05-11 12:21:29 -07:00
34 changed files with 520 additions and 638 deletions

View File

@@ -152,6 +152,7 @@ BITCOIN_CORE_H = \
httpserver.h \
init.h \
key.h \
key_io.h \
keystore.h \
dbwrapper.h \
limitedmap.h \
@@ -368,6 +369,7 @@ libbitcoin_common_a_SOURCES = \
core_write.cpp \
hash.cpp \
key.cpp \
key_io.cpp \
keystore.cpp \
netbase.cpp \
primitives/block.cpp \

View File

@@ -4,21 +4,12 @@
#include "base58.h"
#include "hash.h"
#include "script/script.h"
#include "uint256.h"
#include <hash.h>
#include <uint256.h>
#include "version.h"
#include "streams.h"
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <algorithm>
#include <assert.h>
#include <string.h>
/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
@@ -143,227 +134,3 @@ bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRe
{
return DecodeBase58Check(str.c_str(), vchRet);
}
CBase58Data::CBase58Data()
{
vchVersion.clear();
vchData.clear();
}
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const void* pdata, size_t nSize)
{
vchVersion = vchVersionIn;
vchData.resize(nSize);
if (!vchData.empty())
memcpy(vchData.data(), pdata, nSize);
}
void CBase58Data::SetData(const std::vector<unsigned char>& vchVersionIn, const unsigned char* pbegin, const unsigned char* pend)
{
SetData(vchVersionIn, (void*)pbegin, pend - pbegin);
}
bool CBase58Data::SetString(const char* psz, unsigned int nVersionBytes)
{
std::vector<unsigned char> vchTemp;
bool rc58 = DecodeBase58Check(psz, vchTemp);
if ((!rc58) || (vchTemp.size() < nVersionBytes)) {
vchData.clear();
vchVersion.clear();
return false;
}
vchVersion.assign(vchTemp.begin(), vchTemp.begin() + nVersionBytes);
vchData.resize(vchTemp.size() - nVersionBytes);
if (!vchData.empty())
memcpy(vchData.data(), vchTemp.data() + nVersionBytes, vchData.size());
memory_cleanse(vchTemp.data(), vchTemp.size());
return true;
}
bool CBase58Data::SetString(const std::string& str, unsigned int nVersionBytes)
{
return SetString(str.c_str(), nVersionBytes);
}
std::string CBase58Data::ToString() const
{
std::vector<unsigned char> vch = vchVersion;
vch.insert(vch.end(), vchData.begin(), vchData.end());
return EncodeBase58Check(vch);
}
int CBase58Data::CompareTo(const CBase58Data& b58) const
{
if (vchVersion < b58.vchVersion)
return -1;
if (vchVersion > b58.vchVersion)
return 1;
if (vchData < b58.vchData)
return -1;
if (vchData > b58.vchData)
return 1;
return 0;
}
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 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();
}
} // namespace
void CBitcoinSecret::SetKey(const CKey& vchSecret)
{
assert(vchSecret.IsValid());
SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
if (vchSecret.IsCompressed())
vchData.push_back(1);
}
CKey CBitcoinSecret::GetKey()
{
CKey ret;
assert(vchData.size() >= 32);
ret.Set(vchData.begin(), vchData.begin() + 32, vchData.size() > 32 && vchData[32] == 1);
return ret;
}
bool CBitcoinSecret::IsValid() const
{
bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
bool fCorrectVersion = vchVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
return fExpectedFormat && fCorrectVersion;
}
bool CBitcoinSecret::SetString(const char* pszSecret)
{
return CBase58Data::SetString(pszSecret, 1) && IsValid();
}
bool CBitcoinSecret::SetString(const std::string& strSecret)
{
return SetString(strSecret.c_str());
}
std::string EncodeDestination(const CTxDestination& dest)
{
return boost::apply_visitor(DestinationEncoder(Params()), dest);
}
CTxDestination DecodeDestination(const std::string& str)
{
return DecodeDestination(str, Params());
}
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
{
return IsValidDestination(DecodeDestination(str, params));
}
bool IsValidDestinationString(const std::string& str)
{
return IsValidDestinationString(str, Params());
}
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
bool CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Set(const DATA_TYPE& addr)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << addr;
std::vector<unsigned char> addrSerialized(ss.begin(), ss.end());
assert(addrSerialized.size() == SER_SIZE);
SetData(Params().Base58Prefix(PREFIX), &addrSerialized[0], SER_SIZE);
return true;
}
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
DATA_TYPE CZCEncoding<DATA_TYPE, PREFIX, SER_SIZE>::Get() const
{
if (vchData.size() != SER_SIZE) {
throw std::runtime_error(
PrependName(" is invalid")
);
}
if (vchVersion != Params().Base58Prefix(PREFIX)) {
throw std::runtime_error(
PrependName(" is for wrong network type")
);
}
std::vector<unsigned char> serialized(vchData.begin(), vchData.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
DATA_TYPE ret;
ss >> ret;
return ret;
}
// Explicit instantiations for libzcash::PaymentAddress
template bool CZCEncoding<libzcash::PaymentAddress,
CChainParams::ZCPAYMENT_ADDRRESS,
libzcash::SerializedPaymentAddressSize>::Set(const libzcash::PaymentAddress& addr);
template libzcash::PaymentAddress CZCEncoding<libzcash::PaymentAddress,
CChainParams::ZCPAYMENT_ADDRRESS,
libzcash::SerializedPaymentAddressSize>::Get() const;
// Explicit instantiations for libzcash::ViewingKey
template bool CZCEncoding<libzcash::ViewingKey,
CChainParams::ZCVIEWING_KEY,
libzcash::SerializedViewingKeySize>::Set(const libzcash::ViewingKey& vk);
template libzcash::ViewingKey CZCEncoding<libzcash::ViewingKey,
CChainParams::ZCVIEWING_KEY,
libzcash::SerializedViewingKeySize>::Get() const;
// Explicit instantiations for libzcash::SpendingKey
template bool CZCEncoding<libzcash::SpendingKey,
CChainParams::ZCSPENDING_KEY,
libzcash::SerializedSpendingKeySize>::Set(const libzcash::SpendingKey& sk);
template libzcash::SpendingKey CZCEncoding<libzcash::SpendingKey,
CChainParams::ZCSPENDING_KEY,
libzcash::SerializedSpendingKeySize>::Get() const;

View File

@@ -14,13 +14,6 @@
#ifndef BITCOIN_BASE58_H
#define BITCOIN_BASE58_H
#include "chainparams.h"
#include "key.h"
#include "pubkey.h"
#include "script/standard.h"
#include "support/allocators/zeroafterfree.h"
#include "zcash/Address.hpp"
#include <string>
#include <vector>
@@ -57,139 +50,12 @@ std::string EncodeBase58Check(const std::vector<unsigned char>& vchIn);
* Decode a base58-encoded string (psz) that includes a checksum into a byte
* vector (vchRet), return true if decoding is successful
*/
inline bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
bool DecodeBase58Check(const char* psz, std::vector<unsigned char>& vchRet);
/**
* Decode a base58-encoded string (str) that includes a checksum into a byte
* vector (vchRet), return true if decoding is successful
*/
inline bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
/**
* Base class for all base58-encoded data
*/
class CBase58Data
{
protected:
//! the version byte(s)
std::vector<unsigned char> vchVersion;
//! the actually encoded data
typedef std::vector<unsigned char, zero_after_free_allocator<unsigned char> > vector_uchar;
vector_uchar vchData;
CBase58Data();
void SetData(const std::vector<unsigned char> &vchVersionIn, const void* pdata, size_t nSize);
void SetData(const std::vector<unsigned char> &vchVersionIn, const unsigned char *pbegin, const unsigned char *pend);
public:
bool SetString(const char* psz, unsigned int nVersionBytes);
bool SetString(const std::string& str, unsigned int nVersionBytes);
std::string ToString() const;
int CompareTo(const CBase58Data& b58) const;
bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
bool operator> (const CBase58Data& b58) const { return CompareTo(b58) > 0; }
};
template<class DATA_TYPE, CChainParams::Base58Type PREFIX, size_t SER_SIZE>
class CZCEncoding : public CBase58Data {
protected:
virtual std::string PrependName(const std::string& s) const = 0;
public:
bool Set(const DATA_TYPE& addr);
DATA_TYPE Get() const;
};
class CZCPaymentAddress : public CZCEncoding<libzcash::PaymentAddress, CChainParams::ZCPAYMENT_ADDRRESS, libzcash::SerializedPaymentAddressSize> {
protected:
std::string PrependName(const std::string& s) const { return "payment address" + s; }
public:
CZCPaymentAddress() {}
CZCPaymentAddress(const std::string& strAddress) { SetString(strAddress.c_str(), 2); }
CZCPaymentAddress(const libzcash::PaymentAddress& addr) { Set(addr); }
};
class CZCViewingKey : public CZCEncoding<libzcash::ViewingKey, CChainParams::ZCVIEWING_KEY, libzcash::SerializedViewingKeySize> {
protected:
std::string PrependName(const std::string& s) const { return "viewing key" + s; }
public:
CZCViewingKey() {}
CZCViewingKey(const std::string& strViewingKey) { SetString(strViewingKey.c_str(), 3); }
CZCViewingKey(const libzcash::ViewingKey& vk) { Set(vk); }
};
class CZCSpendingKey : public CZCEncoding<libzcash::SpendingKey, CChainParams::ZCSPENDING_KEY, libzcash::SerializedSpendingKeySize> {
protected:
std::string PrependName(const std::string& s) const { return "spending key" + s; }
public:
CZCSpendingKey() {}
CZCSpendingKey(const std::string& strAddress) { SetString(strAddress.c_str(), 2); }
CZCSpendingKey(const libzcash::SpendingKey& addr) { Set(addr); }
};
/**
* A base58-encoded secret key
*/
class CBitcoinSecret : public CBase58Data
{
public:
void SetKey(const CKey& vchSecret);
CKey GetKey();
bool IsValid() const;
bool SetString(const char* pszSecret);
bool SetString(const std::string& strSecret);
CBitcoinSecret(const CKey& vchSecret) { SetKey(vchSecret); }
CBitcoinSecret() {}
};
template<typename K, int Size, CChainParams::Base58Type Type> class CBitcoinExtKeyBase : public CBase58Data
{
public:
void SetKey(const K &key) {
unsigned char vch[Size];
key.Encode(vch);
SetData(Params().Base58Prefix(Type), vch, vch+Size);
}
K GetKey() {
K ret;
if (vchData.size() == Size) {
// If base58 encoded data does not hold an ext key, return a !IsValid() key
ret.Decode(vchData.data());
}
return ret;
}
CBitcoinExtKeyBase(const K &key) {
SetKey(key);
}
CBitcoinExtKeyBase(const std::string& strBase58c) {
SetString(strBase58c.c_str(), Params().Base58Prefix(Type).size());
}
CBitcoinExtKeyBase() {}
};
typedef CBitcoinExtKeyBase<CExtKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_SECRET_KEY> CBitcoinExtKey;
typedef CBitcoinExtKeyBase<CExtPubKey, BIP32_EXTKEY_SIZE, CChainParams::EXT_PUBLIC_KEY> CBitcoinExtPubKey;
std::string EncodeDestination(const CTxDestination& dest);
CTxDestination DecodeDestination(const std::string& str);
bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
bool DecodeBase58Check(const std::string& str, std::vector<unsigned char>& vchRet);
#endif // BITCOIN_BASE58_H

View File

@@ -2,12 +2,12 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "clientversion.h"
#include "coins.h"
#include "consensus/consensus.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "key_io.h"
#include "keystore.h"
#include "primitives/transaction.h"
#include "script/script.h"
@@ -400,12 +400,10 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput)
for (size_t kidx = 0; kidx < keysObj.size(); kidx++) {
if (!keysObj[kidx].isStr())
throw std::runtime_error("privatekey not a std::string");
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(keysObj[kidx].getValStr());
if (!fGood)
CKey key = DecodeSecret(keysObj[kidx].getValStr());
if (!key.IsValid()) {
throw std::runtime_error("privatekey not valid");
CKey key = vchSecret.GetKey();
}
tempKeystore.AddKey(key);
}

View File

@@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "key_io.h"
#include "main.h"
#include "crypto/equihash.h"
@@ -13,8 +14,6 @@
#include <boost/assign/list_of.hpp>
#include "base58.h"
#include "chainparamsseeds.h"
static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, uint32_t nTime, const uint256& nNonce, const std::vector<unsigned char>& nSolution, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)

View File

@@ -4,7 +4,7 @@
#include "core_io.h"
#include "base58.h"
#include "key_io.h"
#include "primitives/transaction.h"
#include "script/script.h"
#include "script/standard.h"

View File

@@ -1,8 +1,8 @@
#include "httprpc.h"
#include "base58.h"
#include "chainparams.h"
#include "httpserver.h"
#include "key_io.h"
#include "rpcprotocol.h"
#include "rpcserver.h"
#include "random.h"

View File

@@ -11,9 +11,6 @@
#include "crypto/common.h"
#include "addrman.h"
#include "amount.h"
#ifdef ENABLE_MINING
#include "base58.h"
#endif
#include "checkpoints.h"
#include "compat/sanity.h"
#include "consensus/upgrades.h"
@@ -21,6 +18,9 @@
#include "httpserver.h"
#include "httprpc.h"
#include "key.h"
#ifdef ENABLE_MINING
#include "key_io.h"
#endif
#include "main.h"
#include "metrics.h"
#include "miner.h"

254
src/key_io.cpp Normal file
View File

@@ -0,0 +1,254 @@
// Copyright (c) 2014-2016 The Bitcoin Core developers
// Copyright (c) 2016-2018 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <key_io.h>
#include <base58.h>
#include <bech32.h>
#include <script/script.h>
#include <utilstrencodings.h>
#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <assert.h>
#include <string.h>
#include <algorithm>
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 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();
}
} // namespace
CKey DecodeSecret(const std::string& str)
{
CKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& privkey_prefix = Params().Base58Prefix(CChainParams::SECRET_KEY);
if ((data.size() == 32 + privkey_prefix.size() || (data.size() == 33 + privkey_prefix.size() && data.back() == 1)) &&
std::equal(privkey_prefix.begin(), privkey_prefix.end(), data.begin())) {
bool compressed = data.size() == 33 + privkey_prefix.size();
key.Set(data.begin() + privkey_prefix.size(), data.begin() + privkey_prefix.size() + 32, compressed);
}
}
memory_cleanse(data.data(), data.size());
return key;
}
std::string EncodeSecret(const CKey& key)
{
assert(key.IsValid());
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
data.insert(data.end(), key.begin(), key.end());
if (key.IsCompressed()) {
data.push_back(1);
}
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
CExtPubKey DecodeExtPubKey(const std::string& str)
{
CExtPubKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
key.Decode(data.data() + prefix.size());
}
}
return key;
}
std::string EncodeExtPubKey(const CExtPubKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
std::string ret = EncodeBase58Check(data);
return ret;
}
CExtKey DecodeExtKey(const std::string& str)
{
CExtKey key;
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
if (data.size() == BIP32_EXTKEY_SIZE + prefix.size() && std::equal(prefix.begin(), prefix.end(), data.begin())) {
key.Decode(data.data() + prefix.size());
}
}
return key;
}
std::string EncodeExtKey(const CExtKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
std::string EncodeDestination(const CTxDestination& dest)
{
return boost::apply_visitor(DestinationEncoder(Params()), dest);
}
CTxDestination DecodeDestination(const std::string& str)
{
return DecodeDestination(str, Params());
}
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
{
return IsValidDestination(DecodeDestination(str, params));
}
bool IsValidDestinationString(const std::string& str)
{
return IsValidDestinationString(str, Params());
}
std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
data.insert(data.end(), ss.begin(), ss.end());
return EncodeBase58Check(data);
}
boost::optional<libzcash::PaymentAddress> DecodePaymentAddress(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& zaddr_prefix = Params().Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
if ((data.size() == libzcash::SerializedPaymentAddressSize + zaddr_prefix.size()) &&
std::equal(zaddr_prefix.begin(), zaddr_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + zaddr_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::PaymentAddress ret;
ss >> ret;
return ret;
}
}
return boost::none;
}
std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << vk;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
boost::optional<libzcash::ViewingKey> DecodeViewingKey(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& vk_prefix = Params().Base58Prefix(CChainParams::ZCVIEWING_KEY);
if ((data.size() == libzcash::SerializedViewingKeySize + vk_prefix.size()) &&
std::equal(vk_prefix.begin(), vk_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + vk_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::ViewingKey ret;
ss >> ret;
memory_cleanse(serialized.data(), serialized.size());
memory_cleanse(data.data(), data.size());
return ret;
}
}
memory_cleanse(data.data(), data.size());
return boost::none;
}
std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zkey;
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
return ret;
}
boost::optional<libzcash::SpendingKey> DecodeSpendingKey(const std::string& str)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& zkey_prefix = Params().Base58Prefix(CChainParams::ZCSPENDING_KEY);
if ((data.size() == libzcash::SerializedSpendingKeySize + zkey_prefix.size()) &&
std::equal(zkey_prefix.begin(), zkey_prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + zkey_prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
libzcash::SpendingKey ret;
ss >> ret;
memory_cleanse(serialized.data(), serialized.size());
memory_cleanse(data.data(), data.size());
return ret;
}
}
memory_cleanse(data.data(), data.size());
return boost::none;
}

40
src/key_io.h Normal file
View File

@@ -0,0 +1,40 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2016-2018 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEYIO_H
#define BITCOIN_KEYIO_H
#include <chainparams.h>
#include <key.h>
#include <pubkey.h>
#include <script/standard.h>
#include <zcash/Address.hpp>
#include <string>
CKey DecodeSecret(const std::string& str);
std::string EncodeSecret(const CKey& key);
CExtKey DecodeExtKey(const std::string& str);
std::string EncodeExtKey(const CExtKey& extkey);
CExtPubKey DecodeExtPubKey(const std::string& str);
std::string EncodeExtPubKey(const CExtPubKey& extpubkey);
std::string EncodeDestination(const CTxDestination& dest);
CTxDestination DecodeDestination(const std::string& str);
bool IsValidDestinationString(const std::string& str);
bool IsValidDestinationString(const std::string& str, const CChainParams& params);
std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr);
boost::optional<libzcash::PaymentAddress> DecodePaymentAddress(const std::string& str);
std::string EncodeViewingKey(const libzcash::ViewingKey& vk);
boost::optional<libzcash::ViewingKey> DecodeViewingKey(const std::string& str);
std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey);
boost::optional<libzcash::SpendingKey> DecodeSpendingKey(const std::string& str);
#endif // BITCOIN_KEYIO_H

View File

@@ -9,7 +9,6 @@
#endif
#include "amount.h"
#include "base58.h"
#include "chainparams.h"
#include "consensus/consensus.h"
#include "consensus/upgrades.h"
@@ -18,6 +17,7 @@
#include "crypto/equihash.h"
#endif
#include "hash.h"
#include "key_io.h"
#include "main.h"
#include "metrics.h"
#include "net.h"

View File

@@ -3,11 +3,13 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "paymentdisclosure.h"
#include "key_io.h"
#include "util.h"
std::string PaymentDisclosureInfo::ToString() const {
return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=<omitted>, address=%s)",
version, esk.ToString(), CZCPaymentAddress(zaddr).ToString());
version, esk.ToString(), EncodePaymentAddress(zaddr));
}
std::string PaymentDisclosure::ToString() const {
@@ -17,7 +19,7 @@ std::string PaymentDisclosure::ToString() const {
std::string PaymentDisclosurePayload::ToString() const {
return strprintf("PaymentDisclosurePayload(version=%d, esk=%s, txid=%s, js=%d, n=%d, address=%s, message=%s)",
version, esk.ToString(), txid.ToString(), js, n, CZCPaymentAddress(zaddr).ToString(), message);
version, esk.ToString(), txid.ToString(), js, n, EncodePaymentAddress(zaddr), message);
}
PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const PaymentDisclosureKey &key, const PaymentDisclosureInfo &info, const std::string &message)

View File

@@ -3,9 +3,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "clientversion.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "net.h"
#include "netbase.h"
@@ -235,27 +235,23 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp)
LOCK(cs_main);
#endif
bool isValid = false;
bool isMine = false;
std::string payingKey, transmissionKey;
string strAddress = params[0].get_str();
try {
CZCPaymentAddress address(strAddress);
libzcash::PaymentAddress addr = address.Get();
auto isValid = DecodePaymentAddress(strAddress);
if (isValid) {
libzcash::PaymentAddress addr = *isValid;
#ifdef ENABLE_WALLET
isMine = pwalletMain->HaveSpendingKey(addr);
#endif
payingKey = addr.a_pk.GetHex();
transmissionKey = addr.pk_enc.GetHex();
isValid = true;
} catch (std::runtime_error e) {
// address is invalid, nop here as isValid is false.
}
UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("isvalid", isValid));
ret.push_back(Pair("isvalid", static_cast<bool>(isValid)));
if (isValid)
{
ret.push_back(Pair("address", strAddress));

View File

@@ -3,11 +3,11 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
#include "key_io.h"
#include "keystore.h"
#include "main.h"
#include "merkleblock.h"
@@ -777,13 +777,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
UniValue keys = params[2].get_array();
for (size_t idx = 0; idx < keys.size(); idx++) {
UniValue k = keys[idx];
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(k.get_str());
if (!fGood)
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
CKey key = vchSecret.GetKey();
CKey key = DecodeSecret(k.get_str());
if (!key.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
tempKeystore.AddKey(key);
}
}

View File

@@ -5,8 +5,8 @@
#include "rpcserver.h"
#include "base58.h"
#include "init.h"
#include "key_io.h"
#include "random.h"
#include "sync.h"
#include "ui_interface.h"

View File

@@ -9,6 +9,7 @@
#include "data/base58_keys_valid.json.h"
#include "key.h"
#include "key_io.h"
#include "script/script.h"
#include "test/test_bitcoin.h"
#include "uint256.h"
@@ -78,7 +79,7 @@ BOOST_AUTO_TEST_CASE(base58_DecodeBase58)
BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
{
UniValue tests = read_json(std::string(json_tests::base58_keys_valid, json_tests::base58_keys_valid + sizeof(json_tests::base58_keys_valid)));
CBitcoinSecret secret;
CKey privkey;
CTxDestination destination;
SelectParams(CBaseChainParams::MAIN);
@@ -102,9 +103,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
if (isPrivkey) {
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
// Must be valid private key
BOOST_CHECK_MESSAGE(secret.SetString(exp_base58string), "!SetString:"+ strTest);
BOOST_CHECK_MESSAGE(secret.IsValid(), "!IsValid:" + strTest);
CKey privkey = secret.GetKey();
privkey = DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(privkey.IsValid(), "!IsValid:" + strTest);
BOOST_CHECK_MESSAGE(privkey.IsCompressed() == isCompressed, "compressed mismatch:" + strTest);
BOOST_CHECK_MESSAGE(privkey.size() == exp_payload.size() && std::equal(privkey.begin(), privkey.end(), exp_payload.begin()), "key mismatch:" + strTest);
@@ -119,8 +119,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
// Public key must be invalid private key
secret.SetString(exp_base58string);
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
privkey = DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest);
}
}
}
@@ -153,9 +153,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
CKey key;
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
assert(key.IsValid());
CBitcoinSecret secret;
secret.SetKey(key);
BOOST_CHECK_MESSAGE(secret.ToString() == exp_base58string, "result mismatch: " + strTest);
BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
} else {
CTxDestination dest;
CScript exp_script(exp_payload.begin(), exp_payload.end());
@@ -172,7 +170,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
BOOST_AUTO_TEST_CASE(base58_keys_invalid)
{
UniValue tests = read_json(std::string(json_tests::base58_keys_invalid, json_tests::base58_keys_invalid + sizeof(json_tests::base58_keys_invalid))); // Negative testcases
CBitcoinSecret secret;
CKey privkey;
CTxDestination destination;
for (size_t idx = 0; idx < tests.size(); idx++) {
@@ -188,8 +186,8 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
// must be invalid as public and as private key
destination = DecodeDestination(exp_base58string);
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey:" + strTest);
secret.SetString(exp_base58string);
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid privkey:" + strTest);
privkey = DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey:" + strTest);
}
}

View File

@@ -4,8 +4,8 @@
#include <boost/test/unit_test.hpp>
#include "base58.h"
#include "key.h"
#include "key_io.h"
#include "uint256.h"
#include "util.h"
#include "utilstrencodings.h"
@@ -90,20 +90,12 @@ void RunTest(const TestVector &test) {
pubkey.Encode(data);
// Test private key
CBitcoinExtKey b58key; b58key.SetKey(key);
BOOST_CHECK(b58key.ToString() == derive.prv);
CBitcoinExtKey b58keyDecodeCheck(derive.prv);
CExtKey checkKey = b58keyDecodeCheck.GetKey();
assert(checkKey == key); //ensure a base58 decoded key also matches
BOOST_CHECK(EncodeExtKey(key) == derive.prv);
BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
// Test public key
CBitcoinExtPubKey b58pubkey; b58pubkey.SetKey(pubkey);
BOOST_CHECK(b58pubkey.ToString() == derive.pub);
CBitcoinExtPubKey b58PubkeyDecodeCheck(derive.pub);
CExtPubKey checkPubKey = b58PubkeyDecodeCheck.GetKey();
assert(checkPubKey == pubkey); //ensure a base58 decoded pubkey also matches
BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
// Derive new keys
CExtKey keyNew;

View File

@@ -4,9 +4,9 @@
#include "bloom.h"
#include "base58.h"
#include "clientversion.h"
#include "key.h"
#include "key_io.h"
#include "merkleblock.h"
#include "random.h"
#include "serialize.h"
@@ -86,11 +86,8 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
{
string strSecret = string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
CBitcoinSecret vchSecret;
BOOST_CHECK(vchSecret.SetString(strSecret));
CKey key = vchSecret.GetKey();
std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
CKey key = DecodeSecret(strSecret);
CPubKey pubkey = key.GetPubKey();
vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());

View File

@@ -4,7 +4,7 @@
#include "key.h"
#include "base58.h"
#include "key_io.h"
#include "script/script.h"
#include "uint256.h"
#include "util.h"
@@ -65,21 +65,16 @@ BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(key_test1)
{
CBitcoinSecret bsecret1, bsecret2, bsecret1C, bsecret2C, baddress1;
BOOST_CHECK( bsecret1.SetString (strSecret1));
BOOST_CHECK( bsecret2.SetString (strSecret2));
BOOST_CHECK( bsecret1C.SetString(strSecret1C));
BOOST_CHECK( bsecret2C.SetString(strSecret2C));
BOOST_CHECK(!baddress1.SetString(strAddressBad));
CKey key1 = bsecret1.GetKey();
BOOST_CHECK(key1.IsCompressed() == false);
CKey key2 = bsecret2.GetKey();
BOOST_CHECK(key2.IsCompressed() == false);
CKey key1C = bsecret1C.GetKey();
BOOST_CHECK(key1C.IsCompressed() == true);
CKey key2C = bsecret2C.GetKey();
BOOST_CHECK(key2C.IsCompressed() == true);
CKey key1 = DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
CKey key2 = DecodeSecret(strSecret2);
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
CKey key1C = DecodeSecret(strSecret1C);
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
CKey key2C = DecodeSecret(strSecret2C);
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
CKey bad_key = DecodeSecret(strAddressBad);
BOOST_CHECK(!bad_key.IsValid());
CPubKey pubkey1 = key1. GetPubKey();
CPubKey pubkey2 = key2. GetPubKey();
@@ -195,28 +190,28 @@ BOOST_AUTO_TEST_CASE(zc_address_test)
for (size_t i = 0; i < 1000; i++) {
auto sk = SpendingKey::random();
{
CZCSpendingKey spendingkey(sk);
string sk_string = spendingkey.ToString();
string sk_string = EncodeSpendingKey(sk);
BOOST_CHECK(sk_string[0] == 'S');
BOOST_CHECK(sk_string[1] == 'K');
CZCSpendingKey spendingkey2(sk_string);
SpendingKey sk2 = spendingkey2.Get();
auto spendingkey2 = DecodeSpendingKey(sk_string);
BOOST_ASSERT(static_cast<bool>(spendingkey2));
SpendingKey sk2 = *spendingkey2;
BOOST_CHECK(sk.inner() == sk2.inner());
}
{
auto addr = sk.address();
CZCPaymentAddress paymentaddr(addr);
string addr_string = paymentaddr.ToString();
std::string addr_string = EncodePaymentAddress(addr);
BOOST_CHECK(addr_string[0] == 'z');
BOOST_CHECK(addr_string[1] == 'c');
CZCPaymentAddress paymentaddr2(addr_string);
auto paymentaddr2 = DecodePaymentAddress(addr_string);
BOOST_ASSERT(static_cast<bool>(paymentaddr2));
PaymentAddress addr2 = paymentaddr2.Get();
PaymentAddress addr2 = *paymentaddr2;
BOOST_CHECK(addr.a_pk == addr2.a_pk);
BOOST_CHECK(addr.pk_enc == addr2.pk_enc);
}

View File

@@ -5,7 +5,7 @@
#include "rpcserver.h"
#include "rpcclient.h"
#include "base58.h"
#include "key_io.h"
#include "netbase.h"
#include "utilstrencodings.h"

View File

@@ -5,7 +5,7 @@
#include "rpcserver.h"
#include "rpcclient.h"
#include "base58.h"
#include "key_io.h"
#include "main.h"
#include "wallet/wallet.h"
@@ -386,7 +386,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
BOOST_CHECK(addrs.size()==0);
// wallet should have one key
CZCPaymentAddress paymentAddress = pwalletMain->GenerateNewZKey();
auto addr = pwalletMain->GenerateNewZKey();
pwalletMain->GetPaymentAddresses(addrs);
BOOST_CHECK(addrs.size()==1);
@@ -411,12 +411,11 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
BOOST_CHECK_NO_THROW(CallRPC(string("z_exportwallet ") + tmpfilename.string()));
auto addr = paymentAddress.Get();
libzcash::SpendingKey key;
BOOST_CHECK(pwalletMain->GetSpendingKey(addr, key));
std::string s1 = paymentAddress.ToString();
std::string s2 = CZCSpendingKey(key).ToString();
std::string s1 = EncodePaymentAddress(addr);
std::string s2 = EncodeSpendingKey(key);
// There's no way to really delete a private key so we will read in the
// exported wallet file and search for the spending key and payment address.
@@ -459,8 +458,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
// create a random key locally
auto testSpendingKey = libzcash::SpendingKey::random();
auto testPaymentAddress = testSpendingKey.address();
std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString();
std::string testKey = CZCSpendingKey(testSpendingKey).ToString();
std::string testAddr = EncodePaymentAddress(testPaymentAddress);
std::string testKey = EncodeSpendingKey(testSpendingKey);
// create test data using the random key
std::string format_str = "# Wallet dump created by Zcash v0.11.2.0.z8-9155cc6-dirty (2016-08-11 11:37:00 -0700)\n"
@@ -498,15 +497,13 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
BOOST_CHECK(addrs.size()==1);
// check that we have the spending key for the address
CZCPaymentAddress address(testAddr);
auto addr = address.Get();
auto addr = *DecodePaymentAddress(testAddr);
BOOST_CHECK(pwalletMain->HaveSpendingKey(addr));
// Verify the spending key is the same as the test data
libzcash::SpendingKey k;
BOOST_CHECK(pwalletMain->GetSpendingKey(addr, k));
CZCSpendingKey spendingkey(k);
BOOST_CHECK_EQUAL(testKey, spendingkey.ToString());
BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k));
}
@@ -530,7 +527,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// error if invalid args
auto sk = libzcash::SpendingKey::random();
std::string prefix = std::string("z_importkey ") + CZCSpendingKey(sk).ToString() + " yes ";
std::string prefix = std::string("z_importkey ") + EncodeSpendingKey(sk) + " yes ";
BOOST_CHECK_THROW(CallRPC(prefix + "-1"), runtime_error);
BOOST_CHECK_THROW(CallRPC(prefix + "2147483647"), runtime_error); // allowed, but > height of active chain tip
BOOST_CHECK_THROW(CallRPC(prefix + "2147483648"), runtime_error); // not allowed, > int32 used for nHeight
@@ -546,8 +543,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// create a random key locally
auto testSpendingKey = libzcash::SpendingKey::random();
auto testPaymentAddress = testSpendingKey.address();
std::string testAddr = CZCPaymentAddress(testPaymentAddress).ToString();
std::string testKey = CZCSpendingKey(testSpendingKey).ToString();
std::string testAddr = EncodePaymentAddress(testPaymentAddress);
std::string testKey = EncodeSpendingKey(testSpendingKey);
BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testKey));
BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testAddr));
BOOST_CHECK_EQUAL(retValue.get_str(), testKey);
@@ -566,7 +563,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// Make new addresses for the set
for (int i=0; i<n2; i++) {
myaddrs.insert((pwalletMain->GenerateNewZKey()).ToString());
myaddrs.insert(EncodePaymentAddress(pwalletMain->GenerateNewZKey()));
}
// Verify number of addresses stored in wallet is n1+n2
@@ -593,8 +590,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// Add one more address
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_getnewaddress"));
std::string newaddress = retValue.get_str();
CZCPaymentAddress pa(newaddress);
auto newAddr = pa.Get();
auto newAddr = *DecodePaymentAddress(newaddress);
BOOST_CHECK(pwalletMain->HaveSpendingKey(newAddr));
// Check if too many args
@@ -916,8 +912,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
std::fill(v.begin(),v.end(), 'A');
std::string badmemo(v.begin(), v.end());
CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = pa.ToString();
auto pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
BOOST_CHECK_THROW(CallRPC(string("z_sendmany tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ ")
+ "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), runtime_error);
@@ -952,7 +948,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(mtx, "INVALID", recipients, {}, 1) );
} catch (const UniValue& objError) {
BOOST_CHECK( find_error(objError, "payment address is invalid"));
BOOST_CHECK( find_error(objError, "Invalid from address"));
}
// Testnet payment addresses begin with 'zt'. This test detects an incorrect prefix.
@@ -960,7 +956,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
std::vector<SendManyRecipient> recipients = { SendManyRecipient("dummy",1.0, "") };
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_sendmany(mtx, "zcMuhvq8sEkHALuSU2i4NbNQxshSAYrpCExec45ZjtivYPbuiFPwk6WHy4SvsbeZ4siy1WheuRGjtaJmoD1J8bFqNXhsG6U", recipients, {}, 1) );
} catch (const UniValue& objError) {
BOOST_CHECK( find_error(objError, "payment address is for wrong network type"));
BOOST_CHECK( find_error(objError, "Invalid from address"));
}
// Note: The following will crash as a google test because AsyncRPCOperation_sendmany
@@ -994,8 +990,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
// add keys manually
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
std::string taddr1 = retValue.get_str();
CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = pa.ToString();
auto pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
// there are no utxos to spend
{
@@ -1392,7 +1388,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_parameters)
std::vector<ShieldCoinbaseUTXO> inputs = { ShieldCoinbaseUTXO{uint256(),0,0} };
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_shieldcoinbase(mtx, inputs, mainnetzaddr, 1) );
} catch (const UniValue& objError) {
BOOST_CHECK( find_error(objError, "payment address is for wrong network type"));
BOOST_CHECK( find_error(objError, "Invalid to address"));
}
}
@@ -1417,8 +1413,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals)
mapArgs["-mempooltxinputlimit"] = "1";
// Add keys manually
CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
std::string zaddr = pa.ToString();
auto pa = pwalletMain->GenerateNewZKey();
std::string zaddr = EncodePaymentAddress(pa);
// Supply 2 inputs when mempool limit is 1
{
@@ -1542,8 +1538,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
std::vector<char> v (2 * (ZC_MEMO_SIZE+1)); // x2 for hexadecimal string format
std::fill(v.begin(),v.end(), 'A');
std::string badmemo(v.begin(), v.end());
CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = pa.ToString();
auto pa = pwalletMain->GenerateNewZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
BOOST_CHECK_THROW(CallRPC(string("z_mergetoaddress [\"tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ\"] ")
+ zaddr1 + " 0.0001 100 100 " + badmemo), runtime_error);
@@ -1590,7 +1586,7 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_parameters)
std::shared_ptr<AsyncRPCOperation> operation( new AsyncRPCOperation_mergetoaddress(mtx, inputs, {}, mainnetzaddr, 1) );
BOOST_FAIL("Should have caused an error");
} catch (const UniValue& objError) {
BOOST_CHECK( find_error(objError, "payment address is for wrong network type"));
BOOST_CHECK( find_error(objError, "Invalid recipient address"));
}
}
@@ -1613,8 +1609,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
// Add keys manually
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
MergeToAddressRecipient taddr1(retValue.get_str(), "");
CZCPaymentAddress pa = pwalletMain->GenerateNewZKey();
MergeToAddressRecipient zaddr1(pa.ToString(), "DEADBEEF");
auto pa = pwalletMain->GenerateNewZKey();
MergeToAddressRecipient zaddr1(EncodePaymentAddress(pa), "DEADBEEF");
// Supply 2 inputs when mempool limit is 1
{

View File

@@ -8,6 +8,7 @@
#include "asyncrpcqueue.h"
#include "core_io.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "miner.h"
#include "net.h"
@@ -78,14 +79,12 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
isToZaddr_ = false;
if (!isToTaddr_) {
CZCPaymentAddress address(std::get<0>(recipient));
try {
PaymentAddress addr = address.Get();
auto address = DecodePaymentAddress(std::get<0>(recipient));
if (address) {
isToZaddr_ = true;
toPaymentAddress_ = addr;
} catch (const std::runtime_error& e) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what());
toPaymentAddress_ = *address;
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address");
}
}
@@ -857,8 +856,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
CZCPaymentAddress address(zaddr);
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString());
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END

View File

@@ -7,7 +7,6 @@
#include "amount.h"
#include "asyncrpcoperation.h"
#include "base58.h"
#include "paymentdisclosure.h"
#include "primitives/transaction.h"
#include "wallet.h"

View File

@@ -8,6 +8,7 @@
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "net.h"
#include "netbase.h"
@@ -79,9 +80,9 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
isfromzaddr_ = false;
if (!isfromtaddr_) {
CZCPaymentAddress address(fromAddress);
try {
PaymentAddress addr = address.Get();
auto address = DecodePaymentAddress(fromAddress);
if (address) {
PaymentAddress addr = *address;
// We don't need to lock on the wallet as spending key related methods are thread-safe
SpendingKey key;
@@ -92,8 +93,8 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
isfromzaddr_ = true;
frompaymentaddress_ = addr;
spendingkey_ = key;
} catch (const std::runtime_error& e) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what());
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address");
}
}
@@ -467,7 +468,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
std::string hexMemo = std::get<2>(smr);
zOutputsDeque.pop_front();
PaymentAddress pa = CZCPaymentAddress(address).Get();
PaymentAddress pa = *DecodePaymentAddress(address);
JSOutput jso = JSOutput(pa, value);
if (hexMemo.size() > 0) {
jso.memo = get_memo_from_hex_string(hexMemo);
@@ -726,7 +727,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
assert(value==0);
info.vjsout.push_back(JSOutput()); // dummy output while we accumulate funds into a change note for vpub_new
} else {
PaymentAddress pa = CZCPaymentAddress(address).Get();
PaymentAddress pa = *DecodePaymentAddress(address);
JSOutput jso = JSOutput(pa, value);
if (hexMemo.size() > 0) {
jso.memo = get_memo_from_hex_string(hexMemo);
@@ -1080,8 +1081,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
CZCPaymentAddress address(zaddr);
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString());
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END

View File

@@ -7,7 +7,6 @@
#include "asyncrpcoperation.h"
#include "amount.h"
#include "base58.h"
#include "primitives/transaction.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Address.hpp"

View File

@@ -7,6 +7,7 @@
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "net.h"
#include "netbase.h"
@@ -71,11 +72,11 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
}
// Check the destination address is valid for this network i.e. not testnet being used on mainnet
CZCPaymentAddress address(toAddress);
try {
tozaddr_ = address.Get();
} catch (const std::runtime_error& e) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("runtime error: ") + e.what());
auto address = DecodePaymentAddress(toAddress);
if (address) {
tozaddr_ = *address;
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid to address");
}
// Log the context info
@@ -451,8 +452,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
CZCPaymentAddress address(zaddr);
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), address.ToString());
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END

View File

@@ -7,7 +7,6 @@
#include "asyncrpcoperation.h"
#include "amount.h"
#include "base58.h"
#include "primitives/transaction.h"
#include "zcash/JoinSplit.hpp"
#include "zcash/Address.hpp"

View File

@@ -25,12 +25,11 @@ TEST(wallet_zkeys_tests, store_and_load_zkeys) {
ASSERT_EQ(0, addrs.size());
// wallet should have one key
CZCPaymentAddress paymentAddress = wallet.GenerateNewZKey();
auto addr = wallet.GenerateNewZKey();
wallet.GetPaymentAddresses(addrs);
ASSERT_EQ(1, addrs.size());
// verify wallet has spending key for the address
auto addr = paymentAddress.Get();
ASSERT_TRUE(wallet.HaveSpendingKey(addr));
// manually add new spending key to wallet
@@ -289,22 +288,22 @@ TEST(wallet_zkeys_tests, write_cryptedzkey_direct_to_db) {
ASSERT_EQ(2, addrs.size());
// check we have entries for our payment addresses
ASSERT_TRUE(addrs.count(paymentAddress.Get()));
ASSERT_TRUE(addrs.count(paymentAddress2.Get()));
ASSERT_TRUE(addrs.count(paymentAddress));
ASSERT_TRUE(addrs.count(paymentAddress2));
// spending key is crypted, so we can't extract valid payment address
libzcash::SpendingKey keyOut;
wallet2.GetSpendingKey(paymentAddress.Get(), keyOut);
ASSERT_FALSE(paymentAddress.Get() == keyOut.address());
wallet2.GetSpendingKey(paymentAddress, keyOut);
ASSERT_FALSE(paymentAddress == keyOut.address());
// unlock wallet to get spending keys and verify payment addresses
wallet2.Unlock(strWalletPass);
wallet2.GetSpendingKey(paymentAddress.Get(), keyOut);
ASSERT_EQ(paymentAddress.Get(), keyOut.address());
wallet2.GetSpendingKey(paymentAddress, keyOut);
ASSERT_EQ(paymentAddress, keyOut.address());
wallet2.GetSpendingKey(paymentAddress2.Get(), keyOut);
ASSERT_EQ(paymentAddress2.Get(), keyOut.address());
wallet2.GetSpendingKey(paymentAddress2, keyOut);
ASSERT_EQ(paymentAddress2, keyOut.address());
ECC_Stop();
}

View File

@@ -2,9 +2,9 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "rpcserver.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "script/script.h"
#include "script/standard.h"
@@ -254,11 +254,8 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
// Check the payment address is valid
PaymentAddress zaddr = pd.payload.zaddr;
CZCPaymentAddress address;
if (!address.Set(zaddr)) {
errs.push_back("Payment disclosure refers to an invalid payment address");
} else {
o.push_back(Pair("paymentAddress", address.ToString()));
{
o.push_back(Pair("paymentAddress", EncodePaymentAddress(zaddr)));
try {
// Decrypt the note to get value and memo field

View File

@@ -2,7 +2,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "key_io.h"
#include "rpcserver.h"
#include "init.h"
#include "main.h"
@@ -112,13 +112,8 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
if (params.size() > 2)
fRescan = params[2].get_bool();
CBitcoinSecret vchSecret;
bool fGood = vchSecret.SetString(strSecret);
if (!fGood) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
CKey key = vchSecret.GetKey();
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Private key outside allowed range");
CKey key = DecodeSecret(strSecret);
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
@@ -300,16 +295,16 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
// Let's see if the address is a valid Zcash spending key
if (fImportZKeys) {
try {
CZCSpendingKey spendingkey(vstr[0]);
libzcash::SpendingKey key = spendingkey.Get();
auto spendingkey = DecodeSpendingKey(vstr[0]);
if (spendingkey) {
libzcash::SpendingKey key = *spendingkey;
libzcash::PaymentAddress addr = key.address();
if (pwalletMain->HaveSpendingKey(addr)) {
LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", CZCPaymentAddress(addr).ToString());
LogPrint("zrpc", "Skipping import of zaddr %s (key already present)\n", EncodePaymentAddress(addr));
continue;
}
int64_t nTime = DecodeDumpTime(vstr[1]);
LogPrint("zrpc", "Importing zaddr %s...\n", CZCPaymentAddress(addr).ToString());
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
if (!pwalletMain->AddZKey(key)) {
// Something went wrong
fGood = false;
@@ -318,17 +313,15 @@ UniValue importwallet_impl(const UniValue& params, bool fHelp, bool fImportZKeys
// Successfully imported zaddr. Now import the metadata.
pwalletMain->mapZKeyMetadata[addr].nCreateTime = nTime;
continue;
}
catch (const std::runtime_error &e) {
LogPrint("zrpc","Importing detected an error: %s\n", e.what());
} else {
LogPrint("zrpc", "Importing detected an error: invalid spending key. Trying as a transparent key...\n");
// Not a valid spending key, so carry on and see if it's a Zcash style address.
}
}
CBitcoinSecret vchSecret;
if (!vchSecret.SetString(vstr[0]))
CKey key = DecodeSecret(vstr[0]);
if (!key.IsValid())
continue;
CKey key = vchSecret.GetKey();
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
@@ -418,7 +411,7 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp)
if (!pwalletMain->GetKey(*keyID, vchSecret)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
}
return CBitcoinSecret(vchSecret).ToString();
return EncodeSecret(vchSecret);
}
@@ -522,11 +515,11 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
if (pwalletMain->mapAddressBook.count(keyid)) {
file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
file << strprintf("%s %s label=%s # addr=%s\n", EncodeSecret(key), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
} else if (setKeyPool.count(keyid)) {
file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
file << strprintf("%s %s reserve=1 # addr=%s\n", EncodeSecret(key), strTime, strAddr);
} else {
file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString(), strTime, strAddr);
file << strprintf("%s %s change=1 # addr=%s\n", EncodeSecret(key), strTime, strAddr);
}
}
}
@@ -542,7 +535,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fHelp, bool fDumpZKeys)
libzcash::SpendingKey key;
if (pwalletMain->GetSpendingKey(addr, key)) {
std::string strTime = EncodeDumpTime(pwalletMain->mapZKeyMetadata[addr].nCreateTime);
file << strprintf("%s %s # zaddr=%s\n", CZCSpendingKey(key).ToString(), strTime, CZCPaymentAddress(addr).ToString());
file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(key), strTime, EncodePaymentAddress(addr));
}
}
file << "\n";
@@ -620,8 +613,11 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
}
string strSecret = params[0].get_str();
CZCSpendingKey spendingkey(strSecret);
auto key = spendingkey.Get();
auto spendingkey = DecodeSpendingKey(strSecret);
if (!spendingkey) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
auto key = *spendingkey;
auto addr = key.address();
{
@@ -709,8 +705,11 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp)
}
string strVKey = params[0].get_str();
CZCViewingKey viewingkey(strVKey);
auto vkey = viewingkey.Get();
auto viewingkey = DecodeViewingKey(strVKey);
if (!viewingkey) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key");
}
auto vkey = *viewingkey;
auto addr = vkey.address();
{
@@ -766,15 +765,17 @@ UniValue z_exportkey(const UniValue& params, bool fHelp)
string strAddress = params[0].get_str();
CZCPaymentAddress address(strAddress);
auto addr = address.Get();
auto address = DecodePaymentAddress(strAddress);
if (!address) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
auto addr = *address;
libzcash::SpendingKey k;
if (!pwalletMain->GetSpendingKey(addr, k))
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private zkey for this zaddr");
CZCSpendingKey spendingkey(k);
return spendingkey.ToString();
return EncodeSpendingKey(k);
}
UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
@@ -802,8 +803,11 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
string strAddress = params[0].get_str();
CZCPaymentAddress address(strAddress);
auto addr = address.Get();
auto address = DecodePaymentAddress(strAddress);
if (!address) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
auto addr = *address;
libzcash::ViewingKey vk;
if (!pwalletMain->GetViewingKey(addr, vk)) {
@@ -814,6 +818,5 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
vk = k.viewing_key();
}
CZCViewingKey viewingkey(vk);
return viewingkey.ToString();
return EncodeViewingKey(vk);
}

View File

@@ -4,10 +4,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "amount.h"
#include "base58.h"
#include "consensus/upgrades.h"
#include "core_io.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "net.h"
#include "netbase.h"
@@ -2521,14 +2521,14 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
}
string address = o.get_str();
try {
CZCPaymentAddress zaddr(address);
libzcash::PaymentAddress addr = zaddr.Get();
auto zaddr = DecodePaymentAddress(address);
if (zaddr) {
libzcash::PaymentAddress addr = *zaddr;
if (!fIncludeWatchonly && !pwalletMain->HaveSpendingKey(addr)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, spending key for address does not belong to wallet: ") + address);
}
zaddrs.insert(addr);
} catch (const std::runtime_error&) {
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address);
}
@@ -2555,7 +2555,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
obj.push_back(Pair("jsoutindex", (int)entry.jsop.n));
obj.push_back(Pair("confirmations", entry.nHeight));
obj.push_back(Pair("spendable", pwalletMain->HaveSpendingKey(entry.address)));
obj.push_back(Pair("address", CZCPaymentAddress(entry.address).ToString()));
obj.push_back(Pair("address", EncodePaymentAddress(entry.address)));
obj.push_back(Pair("amount", ValueFromAmount(CAmount(entry.plaintext.value()))));
std::string data(entry.plaintext.memo().begin(), entry.plaintext.memo().end());
obj.push_back(Pair("memo", HexStr(data)));
@@ -2792,8 +2792,11 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
LOCK(cs_main);
CZCSpendingKey spendingkey(params[0].get_str());
SpendingKey k = spendingkey.Get();
auto spendingkey = DecodeSpendingKey(params[0].get_str());
if (!spendingkey) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
SpendingKey k = *spendingkey;
uint256 epk;
unsigned char nonce;
@@ -2903,8 +2906,11 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
std::vector<uint256> commitments;
for (const string& name_ : inputs.getKeys()) {
CZCSpendingKey spendingkey(inputs[name_].get_str());
SpendingKey k = spendingkey.Get();
auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
if (!spendingkey) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
SpendingKey k = *spendingkey;
keys.push_back(k);
@@ -2945,11 +2951,13 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
}
for (const string& name_ : outputs.getKeys()) {
CZCPaymentAddress pubaddr(name_);
PaymentAddress addrTo = pubaddr.Get();
auto addrTo = DecodePaymentAddress(name_);
if (!addrTo) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
}
CAmount nAmount = AmountFromValue(outputs[name_]);
vjsout.push_back(JSOutput(addrTo, nAmount));
vjsout.push_back(JSOutput(*addrTo, nAmount));
}
while (vjsout.size() < ZC_NUM_JS_OUTPUTS) {
@@ -3059,14 +3067,10 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
auto addr = k.address();
auto viewing_key = k.viewing_key();
CZCPaymentAddress pubaddr(addr);
CZCSpendingKey spendingkey(k);
CZCViewingKey viewingkey(viewing_key);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("zcaddress", pubaddr.ToString()));
result.push_back(Pair("zcsecretkey", spendingkey.ToString()));
result.push_back(Pair("zcviewingkey", viewingkey.ToString()));
result.push_back(Pair("zcaddress", EncodePaymentAddress(addr)));
result.push_back(Pair("zcsecretkey", EncodeSpendingKey(k)));
result.push_back(Pair("zcviewingkey", EncodeViewingKey(viewing_key)));
return result;
}
@@ -3092,9 +3096,8 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
CZCPaymentAddress pubaddr = pwalletMain->GenerateNewZKey();
std::string result = pubaddr.ToString();
return result;
auto zaddr = pwalletMain->GenerateNewZKey();
return EncodePaymentAddress(zaddr);
}
@@ -3131,7 +3134,7 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
pwalletMain->GetPaymentAddresses(addresses);
for (auto addr : addresses ) {
if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
ret.push_back(CZCPaymentAddress(addr).ToString());
ret.push_back(EncodePaymentAddress(addr));
}
}
return ret;
@@ -3228,15 +3231,12 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
// Check that the from address is valid.
auto fromaddress = params[0].get_str();
libzcash::PaymentAddress zaddr;
CZCPaymentAddress address(fromaddress);
try {
zaddr = address.Get();
} catch (const std::runtime_error&) {
auto zaddr = DecodePaymentAddress(fromaddress);
if (!zaddr) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
}
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
if (!(pwalletMain->HaveSpendingKey(*zaddr) || pwalletMain->HaveViewingKey(*zaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
}
@@ -3301,12 +3301,11 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
fromTaddr = IsValidDestination(taddr);
libzcash::PaymentAddress zaddr;
if (!fromTaddr) {
CZCPaymentAddress address(fromaddress);
try {
zaddr = address.Get();
} catch (const std::runtime_error&) {
auto res = DecodePaymentAddress(fromaddress);
if (!res) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
}
zaddr = *res;
if (!(pwalletMain->HaveSpendingKey(zaddr) || pwalletMain->HaveViewingKey(zaddr))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "From address does not belong to this node, zaddr spending key or viewing key not found.");
}
@@ -3537,13 +3536,12 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
fromTaddr = IsValidDestination(taddr);
libzcash::PaymentAddress zaddr;
if (!fromTaddr) {
CZCPaymentAddress address(fromaddress);
try {
zaddr = address.Get();
} catch (const std::runtime_error&) {
auto res = DecodePaymentAddress(fromaddress);
if (!res) {
// invalid
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
}
zaddr = *res;
}
// Check that we have the spending key
@@ -3581,11 +3579,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
bool isZaddr = false;
CTxDestination taddr = DecodeDestination(address);
if (!IsValidDestination(taddr)) {
try {
CZCPaymentAddress zaddr(address);
zaddr.Get();
if (DecodePaymentAddress(address)) {
isZaddr = true;
} catch (const std::runtime_error&) {
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ")+address );
}
}
@@ -3777,10 +3773,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
// Validate the destination address
auto destaddress = params[1].get_str();
try {
CZCPaymentAddress pa(destaddress);
libzcash::PaymentAddress zaddr = pa.Get();
} catch (const std::runtime_error&) {
if (!DecodePaymentAddress(destaddress)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
}
@@ -4021,13 +4014,13 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
taddrs.insert(taddr);
}
} else {
try {
CZCPaymentAddress zaddr(address);
auto zaddr = DecodePaymentAddress(address);
if (zaddr) {
// Ignore listed z-addrs if we are using all of them
if (!(useAny || useAnyNote)) {
zaddrs.insert(zaddr.Get());
zaddrs.insert(*zaddr);
}
} catch (const std::runtime_error&) {
} else {
throw JSONRPCError(
RPC_INVALID_PARAMETER,
string("Invalid parameter, unknown address format: ") + address);
@@ -4045,11 +4038,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
bool isToZaddr = false;
CTxDestination taddr = DecodeDestination(destaddress);
if (!IsValidDestination(taddr)) {
try {
CZCPaymentAddress zaddr(destaddress);
zaddr.Get();
if (DecodePaymentAddress(destaddress)) {
isToZaddr = true;
} catch (const std::runtime_error&) {
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
}
}

View File

@@ -5,13 +5,13 @@
#include "wallet/wallet.h"
#include "base58.h"
#include "checkpoints.h"
#include "coincontrol.h"
#include "consensus/upgrades.h"
#include "consensus/validation.h"
#include "consensus/consensus.h"
#include "init.h"
#include "key_io.h"
#include "main.h"
#include "net.h"
#include "script/script.h"
@@ -80,7 +80,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
}
// Generate a new spending key and return its public payment address
CZCPaymentAddress CWallet::GenerateNewZKey()
libzcash::PaymentAddress CWallet::GenerateNewZKey()
{
AssertLockHeld(cs_wallet); // mapZKeyMetadata
auto k = SpendingKey::random();
@@ -94,10 +94,9 @@ CZCPaymentAddress CWallet::GenerateNewZKey()
int64_t nCreationTime = GetTime();
mapZKeyMetadata[addr] = CKeyMetadata(nCreationTime);
CZCPaymentAddress pubaddr(addr);
if (!AddZKey(k))
throw std::runtime_error("CWallet::GenerateNewZKey(): AddZKey failed");
return pubaddr;
return addr;
}
// Add spending key to keystore and persist to disk
@@ -3716,7 +3715,7 @@ void CWallet::GetFilteredNotes(std::vector<CSproutNotePlaintextEntry> & outEntri
std::set<PaymentAddress> filterAddresses;
if (address.length() > 0) {
filterAddresses.insert(CZCPaymentAddress(address).Get());
filterAddresses.insert(*DecodePaymentAddress(address));
}
GetFilteredNotes(outEntries, filterAddresses, minDepth, ignoreSpent, ignoreUnspendable);
@@ -3779,7 +3778,7 @@ void CWallet::GetFilteredNotes(
ZCNoteDecryption decryptor;
if (!GetNoteDecryptor(pa, decryptor)) {
// Note decryptors are created when the wallet is loaded, so it should always exist
throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", CZCPaymentAddress(pa).ToString()));
throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa)));
}
// determine amount of funds in the note
@@ -3796,10 +3795,10 @@ void CWallet::GetFilteredNotes(
} catch (const note_decryption_failed &err) {
// Couldn't decrypt with this spending key
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString()));
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa)));
} catch (const std::exception &exc) {
// Unexpected failure
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", CZCPaymentAddress(pa).ToString(), exc.what()));
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
}
}
}
@@ -3855,7 +3854,7 @@ void CWallet::GetUnspentFilteredNotes(
ZCNoteDecryption decryptor;
if (!GetNoteDecryptor(pa, decryptor)) {
// Note decryptors are created when the wallet is loaded, so it should always exist
throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", CZCPaymentAddress(pa).ToString()));
throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", EncodePaymentAddress(pa)));
}
// determine amount of funds in the note
@@ -3872,10 +3871,10 @@ void CWallet::GetUnspentFilteredNotes(
} catch (const note_decryption_failed &err) {
// Couldn't decrypt with this spending key
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", CZCPaymentAddress(pa).ToString()));
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", EncodePaymentAddress(pa)));
} catch (const std::exception &exc) {
// Unexpected failure
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", CZCPaymentAddress(pa).ToString(), exc.what()));
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
}
}
}

View File

@@ -960,7 +960,7 @@ public:
* ZKeys
*/
//! Generates a new zaddr
CZCPaymentAddress GenerateNewZKey();
libzcash::PaymentAddress GenerateNewZKey();
//! Adds spending key to the store, and saves it to disk
bool AddZKey(const libzcash::SpendingKey &key);
//! Adds spending key to the store, without saving it to disk (used by LoadWallet)

View File

@@ -5,8 +5,8 @@
#include "wallet/walletdb.h"
#include "base58.h"
#include "consensus/validation.h"
#include "key_io.h"
#include "main.h"
#include "protocol.h"
#include "serialize.h"