Make evident the relationship between chainparams and key IO.

This commit is contained in:
Kris Nuttycombe 2020-07-09 16:53:54 -06:00
parent 8121e874e2
commit 07ff0d19a0
32 changed files with 607 additions and 422 deletions

View File

@ -240,9 +240,11 @@ static void MutateTxAddOutAddr(CMutableTransaction& tx, const std::string& strIn
if (!ParseMoney(strValue, value))
throw std::runtime_error("invalid TX output value");
KeyIO keyIO(Params());
// extract and validate ADDRESS
std::string strAddr = strInput.substr(pos + 1, std::string::npos);
CTxDestination destination = DecodeDestination(strAddr);
CTxDestination destination = keyIO.DecodeDestination(strAddr);
if (!IsValidDestination(destination)) {
throw std::runtime_error("invalid TX output address");
}
@ -399,10 +401,12 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput)
UniValue keysObj = registers["privatekeys"];
fGivenKeys = true;
KeyIO keyIO(Params());
for (size_t kidx = 0; kidx < keysObj.size(); kidx++) {
if (!keysObj[kidx].isStr())
throw std::runtime_error("privatekey not a std::string");
CKey key = DecodeSecret(keysObj[kidx].getValStr());
CKey key = keyIO.DecodeSecret(keysObj[kidx].getValStr());
if (!key.IsValid()) {
throw std::runtime_error("privatekey not valid");
}

View File

@ -127,6 +127,48 @@ public:
consensus.nFundingPeriodLength = consensus.nPostBlossomSubsidyHalvingInterval / 48;
// guarantees the first 2 characters, when base58 encoded, are "t1"
keyInfo.base58Prefixes[PUBKEY_ADDRESS] = {0x1C,0xB8};
// guarantees the first 2 characters, when base58 encoded, are "t3"
keyInfo.base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBD};
// the first character, when base58 encoded, is "5" or "K" or "L" (as in Bitcoin)
keyInfo.base58Prefixes[SECRET_KEY] = {0x80};
// do not rely on these BIP32 prefixes; they are not specified and may change
keyInfo.base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x88,0xB2,0x1E};
keyInfo.base58Prefixes[EXT_SECRET_KEY] = {0x04,0x88,0xAD,0xE4};
// guarantees the first 2 characters, when base58 encoded, are "zc"
keyInfo.base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0x9A};
// guarantees the first 4 characters, when base58 encoded, are "ZiVK"
keyInfo.base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3};
// guarantees the first 2 characters, when base58 encoded, are "SK"
keyInfo.base58Prefixes[ZCSPENDING_KEY] = {0xAB,0x36};
keyInfo.bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zs";
keyInfo.bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviews";
keyInfo.bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks";
keyInfo.bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-main";
keyInfo.bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviews";
// TODO: This `if` can be removed once canopy activation height is set.
if (consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
std::vector<std::string> addresses(48, "");
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_ECC,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
addresses);
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_ZF,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
addresses);
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_MG,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
addresses);
}
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("000000000000000000000000000000000000000000000000017e73a331fae01c");
@ -157,28 +199,6 @@ public:
vSeeds.push_back(CDNSSeedData("zfnd.org", "mainnet.seeder.zfnd.org")); // Zcash Foundation
vSeeds.push_back(CDNSSeedData("yolo.money", "mainnet.is.yolo.money")); // gtank
// guarantees the first 2 characters, when base58 encoded, are "t1"
base58Prefixes[PUBKEY_ADDRESS] = {0x1C,0xB8};
// guarantees the first 2 characters, when base58 encoded, are "t3"
base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBD};
// the first character, when base58 encoded, is "5" or "K" or "L" (as in Bitcoin)
base58Prefixes[SECRET_KEY] = {0x80};
// do not rely on these BIP32 prefixes; they are not specified and may change
base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x88,0xB2,0x1E};
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x88,0xAD,0xE4};
// guarantees the first 2 characters, when base58 encoded, are "zc"
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0x9A};
// guarantees the first 4 characters, when base58 encoded, are "ZiVK"
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAB,0xD3};
// guarantees the first 2 characters, when base58 encoded, are "SK"
base58Prefixes[ZCSPENDING_KEY] = {0xAB,0x36};
bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zs";
bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviews";
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks";
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-main";
bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviews";
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
fMiningRequiresPeers = true;
@ -336,20 +356,46 @@ public:
consensus.nFundingPeriodLength = consensus.nPostBlossomSubsidyHalvingInterval / 48;
// guarantees the first 2 characters, when base58 encoded, are "tm"
keyInfo.base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25};
// guarantees the first 2 characters, when base58 encoded, are "t2"
keyInfo.base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA};
// the first character, when base58 encoded, is "9" or "c" (as in Bitcoin)
keyInfo.base58Prefixes[SECRET_KEY] = {0xEF};
// do not rely on these BIP32 prefixes; they are not specified and may change
keyInfo.base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF};
keyInfo.base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
// guarantees the first 2 characters, when base58 encoded, are "zt"
keyInfo.base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
// guarantees the first 4 characters, when base58 encoded, are "ZiVt"
keyInfo.base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
// guarantees the first 2 characters, when base58 encoded, are "ST"
keyInfo.base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};
keyInfo.bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "ztestsapling";
keyInfo.bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviewtestsapling";
keyInfo.bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivktestsapling";
keyInfo.bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-test";
keyInfo.bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviewtestsapling";
// TODO: This `if` can be removed once canopy activation height is set.
if (consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight != Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT) {
std::vector<std::string> addresses(48, "");
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_ECC,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
{/*TODO*/});
addresses);
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_ZF,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
{/*TODO*/});
addresses);
consensus.AddZIP207FundingStream(
keyInfo,
Consensus::FS_ZIP214_MG,
consensus.vUpgrades[Consensus::UPGRADE_CANOPY].nActivationHeight, 2726400,
{/*TODO*/});
addresses);
}
// On testnet we activate this rule 6 blocks after Blossom activation. From block 299188 and
@ -395,28 +441,6 @@ public:
vSeeds.push_back(CDNSSeedData("zfnd.org", "testnet.seeder.zfnd.org")); // Zcash Foundation
vSeeds.push_back(CDNSSeedData("yolo.money", "testnet.is.yolo.money")); // gtank
// guarantees the first 2 characters, when base58 encoded, are "tm"
base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25};
// guarantees the first 2 characters, when base58 encoded, are "t2"
base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA};
// the first character, when base58 encoded, is "9" or "c" (as in Bitcoin)
base58Prefixes[SECRET_KEY] = {0xEF};
// do not rely on these BIP32 prefixes; they are not specified and may change
base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
// guarantees the first 2 characters, when base58 encoded, are "zt"
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
// guarantees the first 4 characters, when base58 encoded, are "ZiVt"
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
// guarantees the first 2 characters, when base58 encoded, are "ST"
base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};
bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "ztestsapling";
bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviewtestsapling";
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivktestsapling";
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-test";
bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviewtestsapling";
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));
fMiningRequiresPeers = true;
@ -517,6 +541,23 @@ public:
consensus.nFundingPeriodLength = consensus.nPostBlossomSubsidyHalvingInterval / 48;
// Defined funding streams can be enabled with node config flags.
// These prefixes are the same as the testnet prefixes
keyInfo.base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25};
keyInfo.base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA};
keyInfo.base58Prefixes[SECRET_KEY] = {0xEF};
// do not rely on these BIP32 prefixes; they are not specified and may change
keyInfo.base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF};
keyInfo.base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
keyInfo.base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
keyInfo.base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
keyInfo.base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};
keyInfo.bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zregtestsapling";
keyInfo.bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviewregtestsapling";
keyInfo.bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivkregtestsapling";
keyInfo.bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-regtest";
keyInfo.bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviewregtestsapling";
// The best chain should have at least this much work.
consensus.nMinimumChainWork = uint256S("0x00");
@ -552,22 +593,6 @@ public:
0,
0
};
// These prefixes are the same as the testnet prefixes
base58Prefixes[PUBKEY_ADDRESS] = {0x1D,0x25};
base58Prefixes[SCRIPT_ADDRESS] = {0x1C,0xBA};
base58Prefixes[SECRET_KEY] = {0xEF};
// do not rely on these BIP32 prefixes; they are not specified and may change
base58Prefixes[EXT_PUBLIC_KEY] = {0x04,0x35,0x87,0xCF};
base58Prefixes[EXT_SECRET_KEY] = {0x04,0x35,0x83,0x94};
base58Prefixes[ZCPAYMENT_ADDRRESS] = {0x16,0xB6};
base58Prefixes[ZCVIEWING_KEY] = {0xA8,0xAC,0x0C};
base58Prefixes[ZCSPENDING_KEY] = {0xAC,0x08};
bech32HRPs[SAPLING_PAYMENT_ADDRESS] = "zregtestsapling";
bech32HRPs[SAPLING_FULL_VIEWING_KEY] = "zviewregtestsapling";
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivkregtestsapling";
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-regtest";
bech32HRPs[SAPLING_EXTENDED_FVK] = "zxviewregtestsapling";
// Founders reward script expects a vector of 2-of-3 multisig addresses
vFoundersRewardAddress = { "t2FwcEhFdNXuFMv1tcYwaBJtYVtMj8b1uTg" };
@ -659,7 +684,8 @@ std::string CChainParams::GetFoundersRewardAddressAtHeight(int nHeight) const {
CScript CChainParams::GetFoundersRewardScriptAtHeight(int nHeight) const {
assert(nHeight > 0 && nHeight <= consensus.GetLastFoundersRewardBlockHeight(nHeight));
CTxDestination address = DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str());
KeyIO keyIO(*this);
CTxDestination address = keyIO.DecodeDestination(GetFoundersRewardAddressAtHeight(nHeight).c_str());
assert(IsValidDestination(address));
assert(IsScriptDestination(address));
CScriptID scriptID = boost::get<CScriptID>(address); // address is a boost variant

View File

@ -32,6 +32,15 @@ struct CCheckpointData {
double fTransactionsPerDay;
};
class CBaseKeyInfo : public Consensus::KeyInfo {
public:
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; }
std::vector<unsigned char> base58Prefixes[Consensus::KeyInfo::MAX_BASE58_TYPES];
std::string bech32HRPs[Consensus::KeyInfo::MAX_BECH32_TYPES];
};
/**
* CChainParams defines various tweakable parameters of a given instance of the
* Bitcoin system. There are three: the main network on which people trade goods
@ -39,33 +48,9 @@ struct CCheckpointData {
* a regression test mode which is intended for private networks only. It has
* minimal difficulty to ensure that blocks can be found instantly.
*/
class CChainParams
class CChainParams: public Consensus::KeyInfo
{
public:
enum Base58Type {
PUBKEY_ADDRESS,
SCRIPT_ADDRESS,
SECRET_KEY,
EXT_PUBLIC_KEY,
EXT_SECRET_KEY,
ZCPAYMENT_ADDRRESS,
ZCSPENDING_KEY,
ZCVIEWING_KEY,
MAX_BASE58_TYPES
};
enum Bech32Type {
SAPLING_PAYMENT_ADDRESS,
SAPLING_FULL_VIEWING_KEY,
SAPLING_INCOMING_VIEWING_KEY,
SAPLING_EXTENDED_SPEND_KEY,
SAPLING_EXTENDED_FVK,
MAX_BECH32_TYPES
};
const Consensus::Params& GetConsensus() const { return consensus; }
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
@ -93,8 +78,12 @@ public:
/** Return the BIP70 network string (main, test or regtest) */
std::string NetworkIDString() const { return strNetworkID; }
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; }
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const {
return keyInfo.Base58Prefix(type);
}
const std::string& Bech32HRP(Bech32Type type) const {
return keyInfo.Bech32HRP(type);
}
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
const CCheckpointData& Checkpoints() const { return checkpointData; }
/** Return the founder's reward address and script for a given block height */
@ -113,8 +102,7 @@ protected:
int nDefaultPort = 0;
uint64_t nPruneAfterHeight = 0;
std::vector<CDNSSeedData> vSeeds;
std::vector<unsigned char> base58Prefixes[MAX_BASE58_TYPES];
std::string bech32HRPs[MAX_BECH32_TYPES];
CBaseKeyInfo keyInfo;
std::string strNetworkID;
std::string strCurrencyUnits;
uint32_t bip44CoinType;

View File

@ -142,18 +142,21 @@ namespace Consensus {
FundingStream FundingStream::ParseFundingStream(
const Consensus::Params& params,
const Consensus::KeyInfo& keyInfo,
const int startHeight,
const int endHeight,
const std::vector<std::string>& strAddresses)
{
KeyIO keyIO(keyInfo);
// Parse the address strings into concrete types.
std::vector<FundingStreamAddress> addresses;
for (auto addr : strAddresses) {
auto taddr = DecodeDestination(addr);
auto taddr = keyIO.DecodeDestination(addr);
if (IsValidDestination(taddr)) {
addresses.push_back(GetScriptForDestination(taddr));
} else {
auto zaddr = DecodePaymentAddress(addr);
auto zaddr = keyIO.DecodePaymentAddress(addr);
// If the string is not a valid transparent or Sapling address, we will
// throw here.
@ -166,12 +169,13 @@ namespace Consensus {
};
void Params::AddZIP207FundingStream(
const Consensus::KeyInfo& keyInfo,
FundingStreamIndex idx,
int startHeight,
int endHeight,
const std::vector<std::string>& strAddresses)
{
vFundingStreams[idx] = FundingStream::ParseFundingStream(*this, startHeight, endHeight, strAddresses);
vFundingStreams[idx] = FundingStream::ParseFundingStream(*this, keyInfo, startHeight, endHeight, strAddresses);
};
FundingStreamAddress FundingStream::RecipientAddress(const Consensus::Params& params, int nHeight) const

View File

@ -101,6 +101,37 @@ enum FundingStreamError {
INSUFFICIENT_ADDRESSES,
};
class KeyInfo
{
public:
enum Base58Type {
PUBKEY_ADDRESS,
SCRIPT_ADDRESS,
SECRET_KEY,
EXT_PUBLIC_KEY,
EXT_SECRET_KEY,
ZCPAYMENT_ADDRRESS,
ZCSPENDING_KEY,
ZCVIEWING_KEY,
MAX_BASE58_TYPES
};
enum Bech32Type {
SAPLING_PAYMENT_ADDRESS,
SAPLING_FULL_VIEWING_KEY,
SAPLING_INCOMING_VIEWING_KEY,
SAPLING_EXTENDED_SPEND_KEY,
SAPLING_EXTENDED_FVK,
MAX_BECH32_TYPES
};
virtual const std::vector<unsigned char>& Base58Prefix(Base58Type type) const =0;
virtual const std::string& Bech32HRP(Bech32Type type) const =0;
};
class FundingStream
{
private:
@ -123,6 +154,7 @@ public:
static FundingStream ParseFundingStream(
const Consensus::Params& params,
const Consensus::KeyInfo& keyInfo,
const int startHeight,
const int endHeight,
const std::vector<std::string>& strAddresses);
@ -209,6 +241,7 @@ struct Params {
int nFundingPeriodLength;
boost::optional<FundingStream> vFundingStreams[MAX_FUNDING_STREAMS];
void AddZIP207FundingStream(
const Consensus::KeyInfo& keyInfo,
FundingStreamIndex idx,
int startHeight,
int endHeight,

View File

@ -142,9 +142,10 @@ void ScriptPubKeyToUniv(const CScript& scriptPubKey,
out.pushKV("reqSigs", nRequired);
out.pushKV("type", GetTxnOutputType(type));
KeyIO keyIO(Params());
UniValue a(UniValue::VARR);
for (const CTxDestination& addr : addresses) {
a.push_back(EncodeDestination(addr));
a.push_back(keyIO.EncodeDestination(addr));
}
out.pushKV("addresses", a);
}

View File

@ -42,6 +42,7 @@ TEST(FoundersRewardTest, create_testnet_2of3multisig) {
pubkeys.resize(3);
CPubKey newKey;
std::vector<std::string> addresses;
KeyIO keyIO(Params());
for (int i = 0; i < numKeys; i++) {
ASSERT_TRUE(pWallet->GetKeyFromPool(newKey));
pubkeys[0] = newKey;
@ -61,7 +62,7 @@ TEST(FoundersRewardTest, create_testnet_2of3multisig) {
pWallet->AddCScript(result);
pWallet->SetAddressBook(innerID, "", "receive");
std::string address = EncodeDestination(innerID);
std::string address = keyIO.EncodeDestination(innerID);
addresses.push_back(address);
}
@ -239,19 +240,22 @@ TEST(FundingStreamsRewardTest, Zip207Distribution) {
int minHeight = GetLastFoundersRewardHeight(consensus) + 1;
KeyIO keyIO(Params());
auto sk = libzcash::SaplingSpendingKey(uint256());
for (int idx = Consensus::FIRST_FUNDING_STREAM; idx < Consensus::MAX_FUNDING_STREAMS; idx++) {
// we can just use the same addresses for all streams, all we're trying to do here
// is validate that the streams add up to the 20% of block reward.
auto shieldedAddr = keyIO.EncodePaymentAddress(sk.default_address());
UpdateFundingStreamParameters(
(Consensus::FundingStreamIndex) idx,
Consensus::FundingStream::ParseFundingStream(
consensus,
Params(),
minHeight,
minHeight + 12,
{
"t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi",
EncodePaymentAddress(sk.default_address())
shieldedAddr,
}
)
);
@ -278,15 +282,18 @@ TEST(FundingStreamsRewardTest, ParseFundingStream) {
int minHeight = GetLastFoundersRewardHeight(consensus) + 1;
KeyIO keyIO(Params());
auto sk = libzcash::SaplingSpendingKey(uint256());
auto shieldedAddr = keyIO.EncodePaymentAddress(sk.default_address());
ASSERT_THROW(
Consensus::FundingStream::ParseFundingStream(
consensus,
Params(),
minHeight,
minHeight + 13,
{
"t2UNzUUx8mWBCRYPRezvA363EYXyEpHokyi",
EncodePaymentAddress(sk.default_address())
shieldedAddr,
}
),
std::runtime_error

View File

@ -9,18 +9,19 @@
TEST(Keys, EncodeAndDecodeSapling)
{
SelectParams(CBaseChainParams::MAIN);
KeyIO keyIO(Params());
auto m = GetTestMasterSaplingSpendingKey();
for (uint32_t i = 0; i < 1000; i++) {
auto sk = m.Derive(i);
{
std::string sk_string = EncodeSpendingKey(sk);
std::string sk_string = keyIO.EncodeSpendingKey(sk);
EXPECT_EQ(
sk_string.substr(0, 24),
Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY));
auto spendingkey2 = DecodeSpendingKey(sk_string);
auto spendingkey2 = keyIO.DecodeSpendingKey(sk_string);
EXPECT_TRUE(IsValidSpendingKey(spendingkey2));
ASSERT_TRUE(boost::get<libzcash::SaplingExtendedSpendingKey>(&spendingkey2) != nullptr);
@ -29,12 +30,12 @@ TEST(Keys, EncodeAndDecodeSapling)
}
{
auto extfvk = sk.ToXFVK();
std::string vk_string = EncodeViewingKey(extfvk);
std::string vk_string = keyIO.EncodeViewingKey(extfvk);
EXPECT_EQ(
vk_string.substr(0, 7),
Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_FVK));
auto viewingkey2 = DecodeViewingKey(vk_string);
auto viewingkey2 = keyIO.DecodeViewingKey(vk_string);
EXPECT_TRUE(IsValidViewingKey(viewingkey2));
ASSERT_TRUE(boost::get<libzcash::SaplingExtendedFullViewingKey>(&viewingkey2) != nullptr);
@ -44,12 +45,12 @@ TEST(Keys, EncodeAndDecodeSapling)
{
auto addr = sk.DefaultAddress();
std::string addr_string = EncodePaymentAddress(addr);
std::string addr_string = keyIO.EncodePaymentAddress(addr);
EXPECT_EQ(
addr_string.substr(0, 2),
Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS));
auto paymentaddr2 = DecodePaymentAddress(addr_string);
auto paymentaddr2 = keyIO.DecodePaymentAddress(addr_string);
EXPECT_TRUE(IsValidPaymentAddress(paymentaddr2));
ASSERT_TRUE(boost::get<libzcash::SaplingPaymentAddress>(&paymentaddr2) != nullptr);

View File

@ -1039,12 +1039,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
KeyIO keyIO(chainparams);
#ifdef ENABLE_MINING
if (mapArgs.count("-mineraddress")) {
CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]);
CTxDestination addr = keyIO.DecodeDestination(mapArgs["-mineraddress"]);
if (!IsValidDestination(addr)) {
// Try a Sapling address
auto zaddr = DecodePaymentAddress(mapArgs["-mineraddress"]);
auto zaddr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
if (!IsValidPaymentAddress(zaddr) ||
boost::get<libzcash::SaplingPaymentAddress>(&zaddr) == nullptr)
{
@ -1127,7 +1128,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
std::vector<std::string> vStreamAddrs;
boost::split(vStreamAddrs, vStreamParams[3], boost::is_any_of(","));
auto fs = Consensus::FundingStream::ParseFundingStream(Params().GetConsensus(), nStartHeight, nEndHeight, vStreamAddrs);
auto fs = Consensus::FundingStream::ParseFundingStream(
Params().GetConsensus(), Params(), nStartHeight, nEndHeight, vStreamAddrs);
UpdateFundingStreamParameters((Consensus::FundingStreamIndex) nFundingStreamId, fs);
}
@ -1586,12 +1588,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
#ifdef ENABLE_WALLET
bool minerAddressInLocalWallet = false;
if (pwalletMain) {
CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]);
CTxDestination addr = keyIO.DecodeDestination(mapArgs["-mineraddress"]);
if (IsValidDestination(addr)) {
CKeyID keyID = boost::get<CKeyID>(addr);
minerAddressInLocalWallet = pwalletMain->HaveKey(keyID);
} else {
auto zaddr = DecodePaymentAddress(mapArgs["-mineraddress"]);
auto zaddr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
minerAddressInLocalWallet = boost::apply_visitor(
HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr);
}

View File

@ -22,21 +22,21 @@ namespace
class DestinationEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
const Consensus::KeyInfo& keyInfo;
public:
DestinationEncoder(const CChainParams& params) : m_params(params) {}
DestinationEncoder(const Consensus::KeyInfo& keyInfo) : keyInfo(keyInfo) {}
std::string operator()(const CKeyID& id) const
{
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::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);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
@ -44,43 +44,19 @@ public:
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();
}
class PaymentAddressEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
const Consensus::KeyInfo& keyInfo;
public:
PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
PaymentAddressEncoder(const Consensus::KeyInfo& keyInfo) : keyInfo(keyInfo) {}
std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zaddr;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCPAYMENT_ADDRRESS);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::ZCPAYMENT_ADDRRESS);
data.insert(data.end(), ss.begin(), ss.end());
return EncodeBase58Check(data);
}
@ -95,7 +71,7 @@ public:
// See calculation comment below
data.reserve((seraddr.size() * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, seraddr.begin(), seraddr.end());
return bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS), data);
return bech32::Encode(keyInfo.Bech32HRP(Consensus::KeyInfo::SAPLING_PAYMENT_ADDRESS), data);
}
std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
@ -104,16 +80,16 @@ public:
class ViewingKeyEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
const Consensus::KeyInfo& keyInfo;
public:
ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
ViewingKeyEncoder(const Consensus::KeyInfo& keyInfo) : keyInfo(keyInfo) {}
std::string operator()(const libzcash::SproutViewingKey& vk) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << vk;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCVIEWING_KEY);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::ZCVIEWING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
@ -130,7 +106,7 @@ public:
// See calculation comment below
data.reserve((serkey.size() * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_EXTENDED_FVK), data);
std::string ret = bech32::Encode(keyInfo.Bech32HRP(Consensus::KeyInfo::SAPLING_EXTENDED_FVK), data);
memory_cleanse(serkey.data(), serkey.size());
memory_cleanse(data.data(), data.size());
return ret;
@ -142,16 +118,16 @@ public:
class SpendingKeyEncoder : public boost::static_visitor<std::string>
{
private:
const CChainParams& m_params;
const Consensus::KeyInfo& keyInfo;
public:
SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
SpendingKeyEncoder(const Consensus::KeyInfo& keyInfo) : keyInfo(keyInfo) {}
std::string operator()(const libzcash::SproutSpendingKey& zkey) const
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << zkey;
std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::ZCSPENDING_KEY);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::ZCSPENDING_KEY);
data.insert(data.end(), ss.begin(), ss.end());
std::string ret = EncodeBase58Check(data);
memory_cleanse(data.data(), data.size());
@ -168,7 +144,7 @@ public:
// See calculation comment below
data.reserve((serkey.size() * 8 + 4) / 5);
ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
std::string ret = bech32::Encode(m_params.Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY), data);
std::string ret = bech32::Encode(keyInfo.Bech32HRP(Consensus::KeyInfo::SAPLING_EXTENDED_SPEND_KEY), data);
memory_cleanse(serkey.data(), serkey.size());
memory_cleanse(data.data(), data.size());
return ret;
@ -186,12 +162,36 @@ const size_t ConvertedSaplingExtendedFullViewingKeySize = (ZIP32_XFVK_SIZE * 8 +
const size_t ConvertedSaplingExtendedSpendingKeySize = (ZIP32_XSK_SIZE * 8 + 4) / 5;
} // namespace
CKey DecodeSecret(const std::string& str)
CTxDestination KeyIO::DecodeDestination(const std::string& str)
{
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 = keyInfo.Base58Prefix(Consensus::KeyInfo::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 = keyInfo.Base58Prefix(Consensus::KeyInfo::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();
};
CKey KeyIO::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);
const std::vector<unsigned char>& privkey_prefix = keyInfo.Base58Prefix(Consensus::KeyInfo::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();
@ -202,10 +202,10 @@ CKey DecodeSecret(const std::string& str)
return key;
}
std::string EncodeSecret(const CKey& key)
std::string KeyIO::EncodeSecret(const CKey& key)
{
assert(key.IsValid());
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::SECRET_KEY);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::SECRET_KEY);
data.insert(data.end(), key.begin(), key.end());
if (key.IsCompressed()) {
data.push_back(1);
@ -215,12 +215,12 @@ std::string EncodeSecret(const CKey& key)
return ret;
}
CExtPubKey DecodeExtPubKey(const std::string& str)
CExtPubKey KeyIO::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);
const std::vector<unsigned char>& prefix = keyInfo.Base58Prefix(Consensus::KeyInfo::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());
}
@ -228,9 +228,9 @@ CExtPubKey DecodeExtPubKey(const std::string& str)
return key;
}
std::string EncodeExtPubKey(const CExtPubKey& key)
std::string KeyIO::EncodeExtPubKey(const CExtPubKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_PUBLIC_KEY);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::EXT_PUBLIC_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
@ -238,12 +238,12 @@ std::string EncodeExtPubKey(const CExtPubKey& key)
return ret;
}
CExtKey DecodeExtKey(const std::string& str)
CExtKey KeyIO::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);
const std::vector<unsigned char>& prefix = keyInfo.Base58Prefix(Consensus::KeyInfo::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());
}
@ -251,9 +251,9 @@ CExtKey DecodeExtKey(const std::string& str)
return key;
}
std::string EncodeExtKey(const CExtKey& key)
std::string KeyIO::EncodeExtKey(const CExtKey& key)
{
std::vector<unsigned char> data = Params().Base58Prefix(CChainParams::EXT_SECRET_KEY);
std::vector<unsigned char> data = keyInfo.Base58Prefix(Consensus::KeyInfo::EXT_SECRET_KEY);
size_t size = data.size();
data.resize(size + BIP32_EXTKEY_SIZE);
key.Encode(data.data() + size);
@ -262,40 +262,31 @@ std::string EncodeExtKey(const CExtKey& key)
return ret;
}
std::string EncodeDestination(const CTxDestination& dest)
std::string KeyIO::EncodeDestination(const CTxDestination& dest)
{
return boost::apply_visitor(DestinationEncoder(Params()), dest);
return boost::apply_visitor(DestinationEncoder(keyInfo), dest);
}
CTxDestination DecodeDestination(const std::string& str)
bool KeyIO::IsValidDestinationString(const std::string& str)
{
return DecodeDestination(str, Params());
return IsValidDestination(DecodeDestination(str));
}
bool IsValidDestinationString(const std::string& str, const CChainParams& params)
std::string KeyIO::EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
{
return IsValidDestination(DecodeDestination(str, params));
}
bool IsValidDestinationString(const std::string& str)
{
return IsValidDestinationString(str, Params());
}
std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
{
return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
return boost::apply_visitor(PaymentAddressEncoder(keyInfo), zaddr);
}
template<typename T1, typename T2, typename T3>
T1 DecodeAny(
const Consensus::KeyInfo& keyInfo,
const std::string& str,
std::pair<CChainParams::Base58Type, size_t> sprout,
std::pair<CChainParams::Bech32Type, size_t> sapling)
std::pair<Consensus::KeyInfo::Base58Type, size_t> sprout,
std::pair<Consensus::KeyInfo::Bech32Type, size_t> sapling)
{
std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = Params().Base58Prefix(sprout.first);
const std::vector<unsigned char>& prefix = keyInfo.Base58Prefix(sprout.first);
if ((data.size() == sprout.second + prefix.size()) &&
std::equal(prefix.begin(), prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + prefix.size(), data.end());
@ -310,7 +301,7 @@ T1 DecodeAny(
data.clear();
auto bech = bech32::Decode(str);
if (bech.first == Params().Bech32HRP(sapling.first) &&
if (bech.first == keyInfo.Bech32HRP(sapling.first) &&
bech.second.size() == sapling.second) {
// Bech32 decoding
data.reserve((bech.second.size() * 5) / 8);
@ -327,50 +318,53 @@ T1 DecodeAny(
return libzcash::InvalidEncoding();
}
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str)
libzcash::PaymentAddress KeyIO::DecodePaymentAddress(const std::string& str)
{
return DecodeAny<libzcash::PaymentAddress,
libzcash::SproutPaymentAddress,
libzcash::SaplingPaymentAddress>(
keyInfo,
str,
std::make_pair(CChainParams::ZCPAYMENT_ADDRRESS, libzcash::SerializedSproutPaymentAddressSize),
std::make_pair(CChainParams::SAPLING_PAYMENT_ADDRESS, ConvertedSaplingPaymentAddressSize)
std::make_pair(Consensus::KeyInfo::ZCPAYMENT_ADDRRESS, libzcash::SerializedSproutPaymentAddressSize),
std::make_pair(Consensus::KeyInfo::SAPLING_PAYMENT_ADDRESS, ConvertedSaplingPaymentAddressSize)
);
}
bool IsValidPaymentAddressString(const std::string& str) {
bool KeyIO::IsValidPaymentAddressString(const std::string& str) {
return IsValidPaymentAddress(DecodePaymentAddress(str));
}
std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
std::string KeyIO::EncodeViewingKey(const libzcash::ViewingKey& vk)
{
return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
return boost::apply_visitor(ViewingKeyEncoder(keyInfo), vk);
}
libzcash::ViewingKey DecodeViewingKey(const std::string& str)
libzcash::ViewingKey KeyIO::DecodeViewingKey(const std::string& str)
{
return DecodeAny<libzcash::ViewingKey,
libzcash::SproutViewingKey,
libzcash::SaplingExtendedFullViewingKey>(
keyInfo,
str,
std::make_pair(CChainParams::ZCVIEWING_KEY, libzcash::SerializedSproutViewingKeySize),
std::make_pair(CChainParams::SAPLING_EXTENDED_FVK, ConvertedSaplingExtendedFullViewingKeySize)
std::make_pair(Consensus::KeyInfo::ZCVIEWING_KEY, libzcash::SerializedSproutViewingKeySize),
std::make_pair(Consensus::KeyInfo::SAPLING_EXTENDED_FVK, ConvertedSaplingExtendedFullViewingKeySize)
);
}
std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
std::string KeyIO::EncodeSpendingKey(const libzcash::SpendingKey& zkey)
{
return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
return boost::apply_visitor(SpendingKeyEncoder(keyInfo), zkey);
}
libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
libzcash::SpendingKey KeyIO::DecodeSpendingKey(const std::string& str)
{
return DecodeAny<libzcash::SpendingKey,
libzcash::SproutSpendingKey,
libzcash::SaplingExtendedSpendingKey>(
keyInfo,
str,
std::make_pair(CChainParams::ZCSPENDING_KEY, libzcash::SerializedSproutSpendingKeySize),
std::make_pair(CChainParams::SAPLING_EXTENDED_SPEND_KEY, ConvertedSaplingExtendedSpendingKeySize)
std::make_pair(Consensus::KeyInfo::ZCSPENDING_KEY, libzcash::SerializedSproutSpendingKeySize),
std::make_pair(Consensus::KeyInfo::SAPLING_EXTENDED_SPEND_KEY, ConvertedSaplingExtendedSpendingKeySize)
);
}

View File

@ -15,27 +15,35 @@
#include <string>
CKey DecodeSecret(const std::string& str);
std::string EncodeSecret(const CKey& key);
class KeyIO {
private:
const Consensus::KeyInfo& keyInfo;
CExtKey DecodeExtKey(const std::string& str);
std::string EncodeExtKey(const CExtKey& extkey);
CExtPubKey DecodeExtPubKey(const std::string& str);
std::string EncodeExtPubKey(const CExtPubKey& extpubkey);
public:
KeyIO(const Consensus::KeyInfo& keyInfo): keyInfo(keyInfo) { }
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);
CKey DecodeSecret(const std::string& str);
std::string EncodeSecret(const CKey& key);
std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr);
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str);
bool IsValidPaymentAddressString(const std::string& str);
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 EncodeViewingKey(const libzcash::ViewingKey& vk);
libzcash::ViewingKey DecodeViewingKey(const std::string& str);
std::string EncodeDestination(const CTxDestination& dest);
CTxDestination DecodeDestination(const std::string& str);
std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey);
libzcash::SpendingKey DecodeSpendingKey(const std::string& str);
bool IsValidDestinationString(const std::string& str);
std::string EncodePaymentAddress(const libzcash::PaymentAddress& zaddr);
libzcash::PaymentAddress DecodePaymentAddress(const std::string& str);
bool IsValidPaymentAddressString(const std::string& str);
std::string EncodeViewingKey(const libzcash::ViewingKey& vk);
libzcash::ViewingKey DecodeViewingKey(const std::string& str);
std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey);
libzcash::SpendingKey DecodeSpendingKey(const std::string& str);
};
#endif // BITCOIN_KEYIO_H

View File

@ -645,9 +645,11 @@ class MinerAddressScript : public CReserveScript
void GetMinerAddress(MinerAddress &minerAddress)
{
KeyIO keyIO(Params());
// Try a transparent address first
auto mAddrArg = GetArg("-mineraddress", "");
CTxDestination addr = DecodeDestination(mAddrArg);
CTxDestination addr = keyIO.DecodeDestination(mAddrArg);
if (IsValidDestination(addr)) {
boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
CKeyID keyID = boost::get<CKeyID>(addr);
@ -656,7 +658,7 @@ void GetMinerAddress(MinerAddress &minerAddress)
minerAddress = mAddr;
} else {
// Try a Sapling address
auto zaddr = DecodePaymentAddress(mAddrArg);
auto zaddr = keyIO.DecodePaymentAddress(mAddrArg);
if (IsValidPaymentAddress(zaddr)) {
if (boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
minerAddress = boost::get<libzcash::SaplingPaymentAddress>(zaddr);

View File

@ -143,6 +143,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
result.pushKV("version", block.nVersion);
result.pushKV("merkleroot", block.hashMerkleRoot.GetHex());
KeyIO keyIO(Params());
UniValue deltas(UniValue::VARR);
for (unsigned int i = 0; i < block.vtx.size(); i++) {
const CTransaction &tx = block.vtx[i];
@ -165,7 +166,7 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
}
CTxDestination dest = DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash);
if (IsValidDestination(dest)) {
delta.pushKV("address", EncodeDestination(dest));
delta.pushKV("address", keyIO.EncodeDestination(dest));
}
delta.pushKV("satoshis", -1 * spentInfo.satoshis);
delta.pushKV("index", (int)j);
@ -190,9 +191,9 @@ UniValue blockToDeltasJSON(const CBlock& block, const CBlockIndex* blockindex)
dest = CKeyID(addrhash);
}
if (IsValidDestination(dest)) {
delta.pushKV("address", EncodeDestination(dest));
delta.pushKV("address", keyIO.EncodeDestination(dest));
}
delta.pushKV("address", EncodeDestination(dest));
delta.pushKV("address", keyIO.EncodeDestination(dest));
delta.pushKV("satoshis", out.nValue);
delta.pushKV("index", (int)k);

View File

@ -905,7 +905,7 @@ UniValue getblocksubsidy(const UniValue& params, bool fHelp)
auto elems = Consensus::GetActiveFundingStreams(nHeight, consensus);
for (auto elem : elems) {
CAmount value = elem.Value(nBlockSubsidy);
fundingstreams.pushKV(elem.recipient, value);
fundingstreams.pushKV(elem.recipient, (double) value / COIN);
nMinerReward -= value;
}
result.pushKV("fundingstreams", fundingstreams);

View File

@ -127,6 +127,7 @@ public:
}
UniValue operator()(const CScriptID &scriptID) const {
KeyIO keyIO(Params());
UniValue obj(UniValue::VOBJ);
CScript subscript;
obj.pushKV("isscript", true);
@ -139,7 +140,7 @@ public:
obj.pushKV("hex", HexStr(subscript.begin(), subscript.end()));
UniValue a(UniValue::VARR);
for (const CTxDestination& addr : addresses) {
a.push_back(EncodeDestination(addr));
a.push_back(keyIO.EncodeDestination(addr));
}
obj.pushKV("addresses", a);
if (whichType == TX_MULTISIG)
@ -180,14 +181,15 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
LOCK(cs_main);
#endif
CTxDestination dest = DecodeDestination(params[0].get_str());
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
bool isValid = IsValidDestination(dest);
UniValue ret(UniValue::VOBJ);
ret.pushKV("isvalid", isValid);
if (isValid)
{
std::string currentAddress = EncodeDestination(dest);
std::string currentAddress = keyIO.EncodeDestination(dest);
ret.pushKV("address", currentAddress);
CScript scriptPubKey = GetScriptForDestination(dest);
@ -271,8 +273,9 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp)
LOCK(cs_main);
#endif
KeyIO keyIO(Params());
string strAddress = params[0].get_str();
auto address = DecodePaymentAddress(strAddress);
auto address = keyIO.DecodePaymentAddress(strAddress);
bool isValid = IsValidPaymentAddress(address);
UniValue ret(UniValue::VOBJ);
@ -304,6 +307,9 @@ CScript _createmultisig_redeemScript(const UniValue& params)
"(got %u keys, but need at least %d to redeem)", keys.size(), nRequired));
if (keys.size() > 16)
throw runtime_error("Number of addresses involved in the multisignature address creation > 16\nReduce the number");
KeyIO keyIO(Params());
std::vector<CPubKey> pubkeys;
pubkeys.resize(keys.size());
for (unsigned int i = 0; i < keys.size(); i++)
@ -311,7 +317,7 @@ CScript _createmultisig_redeemScript(const UniValue& params)
const std::string& ks = keys[i].get_str();
#ifdef ENABLE_WALLET
// Case 1: Bitcoin address and we have full public key:
CTxDestination dest = DecodeDestination(ks);
CTxDestination dest = keyIO.DecodeDestination(ks);
if (pwalletMain && IsValidDestination(dest)) {
const CKeyID *keyID = boost::get<CKeyID>(&dest);
if (!keyID) {
@ -385,8 +391,9 @@ UniValue createmultisig(const UniValue& params, bool fHelp)
CScript inner = _createmultisig_redeemScript(params);
CScriptID innerID(inner);
KeyIO keyIO(Params());
UniValue result(UniValue::VOBJ);
result.pushKV("address", EncodeDestination(innerID));
result.pushKV("address", keyIO.EncodeDestination(innerID));
result.pushKV("redeemScript", HexStr(inner.begin(), inner.end()));
return result;
@ -421,7 +428,8 @@ UniValue verifymessage(const UniValue& params, bool fHelp)
string strSign = params[1].get_str();
string strMessage = params[2].get_str();
CTxDestination destination = DecodeDestination(strAddress);
KeyIO keyIO(Params());
CTxDestination destination = keyIO.DecodeDestination(strAddress);
if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
@ -506,10 +514,11 @@ UniValue getexperimentalfeatures(const UniValue& params, bool fHelp)
static bool getAddressFromIndex(
int type, const uint160 &hash, std::string &address)
{
KeyIO keyIO(Params());
if (type == CScript::P2SH) {
address = EncodeDestination(CScriptID(hash));
address = keyIO.EncodeDestination(CScriptID(hash));
} else if (type == CScript::P2PKH) {
address = EncodeDestination(CKeyID(hash));
address = keyIO.EncodeDestination(CKeyID(hash));
} else {
return false;
}
@ -560,8 +569,10 @@ static bool getAddressesFromParams(
} else {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address");
}
KeyIO keyIO(Params());
for (const auto& it : param_addresses) {
CTxDestination address = DecodeDestination(it);
CTxDestination address = keyIO.DecodeDestination(it);
uint160 hashBytes;
int type = 0;
if (!getIndexKey(address, hashBytes, type)) {

View File

@ -51,9 +51,10 @@ void ScriptPubKeyToJSON(const CScript& scriptPubKey, UniValue& out, bool fInclud
out.pushKV("reqSigs", nRequired);
out.pushKV("type", GetTxnOutputType(type));
KeyIO keyIO(Params());
UniValue a(UniValue::VARR);
for (const CTxDestination& addr : addresses) {
a.push_back(EncodeDestination(addr));
a.push_back(keyIO.EncodeDestination(addr));
}
out.pushKV("addresses", a);
}
@ -161,6 +162,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
if (tx.fOverwintered) {
entry.pushKV("expiryheight", (int64_t)tx.nExpiryHeight);
}
KeyIO keyIO(Params());
UniValue vin(UniValue::VARR);
BOOST_FOREACH(const CTxIn& txin, tx.vin) {
UniValue in(UniValue::VOBJ);
@ -184,7 +187,7 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry)
CTxDestination dest =
DestFromAddressHash(spentInfo.addressType, spentInfo.addressHash);
if (IsValidDestination(dest)) {
in.pushKV("address", EncodeDestination(dest));
in.pushKV("address", keyIO.EncodeDestination(dest));
}
}
}
@ -585,10 +588,11 @@ UniValue createrawtransaction(const UniValue& params, bool fHelp)
rawTx.vin.push_back(in);
}
KeyIO keyIO(Params());
std::set<CTxDestination> destinations;
vector<string> addrList = sendTo.getKeys();
for (const std::string& name_ : addrList) {
CTxDestination destination = DecodeDestination(name_);
CTxDestination destination = keyIO.DecodeDestination(name_);
if (!IsValidDestination(destination)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
}
@ -740,7 +744,8 @@ UniValue decodescript(const UniValue& params, bool fHelp)
}
ScriptPubKeyToJSON(script, r, false);
r.pushKV("p2sh", EncodeDestination(CScriptID(script)));
KeyIO keyIO(Params());
r.pushKV("p2sh", keyIO.EncodeDestination(CScriptID(script)));
return r;
}
@ -865,6 +870,8 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long
}
KeyIO keyIO(Params());
bool fGivenKeys = false;
CBasicKeyStore tempKeystore;
if (params.size() > 2 && !params[2].isNull()) {
@ -872,7 +879,7 @@ 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];
CKey key = DecodeSecret(k.get_str());
CKey key = keyIO.DecodeSecret(k.get_str());
if (!key.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
tempKeystore.AddKey(key);

View File

@ -100,26 +100,28 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
} else {
SelectParams(CBaseChainParams::MAIN);
}
KeyIO keyIO(Params());
if (isPrivkey) {
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
// Must be valid private key
privkey = DecodeSecret(exp_base58string);
privkey = keyIO.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);
// Private key must be invalid public key
destination = DecodeDestination(exp_base58string);
destination = keyIO.DecodeDestination(exp_base58string);
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid privkey as pubkey:" + strTest);
} else {
// Must be valid public key
destination = DecodeDestination(exp_base58string);
destination = keyIO.DecodeDestination(exp_base58string);
CScript script = GetScriptForDestination(destination);
BOOST_CHECK_MESSAGE(IsValidDestination(destination), "!IsValid:" + strTest);
BOOST_CHECK_EQUAL(HexStr(script), HexStr(exp_payload));
// Public key must be invalid private key
privkey = DecodeSecret(exp_base58string);
privkey = keyIO.DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid pubkey as privkey:" + strTest);
}
}
@ -148,17 +150,19 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
} else {
SelectParams(CBaseChainParams::MAIN);
}
KeyIO keyIO(Params());
if (isPrivkey) {
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
CKey key;
key.Set(exp_payload.begin(), exp_payload.end(), isCompressed);
assert(key.IsValid());
BOOST_CHECK_MESSAGE(EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
BOOST_CHECK_MESSAGE(keyIO.EncodeSecret(key) == exp_base58string, "result mismatch: " + strTest);
} else {
CTxDestination dest;
CScript exp_script(exp_payload.begin(), exp_payload.end());
ExtractDestination(exp_script, dest);
std::string address = EncodeDestination(dest);
std::string address = keyIO.EncodeDestination(dest);
BOOST_CHECK_EQUAL(address, exp_base58string);
}
}
@ -173,6 +177,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
CKey privkey;
CTxDestination destination;
KeyIO keyIO(Params());
for (size_t idx = 0; idx < tests.size(); idx++) {
UniValue test = tests[idx];
std::string strTest = test.write();
@ -184,9 +189,9 @@ BOOST_AUTO_TEST_CASE(base58_keys_invalid)
std::string exp_base58string = test[0].get_str();
// must be invalid as public and as private key
destination = DecodeDestination(exp_base58string);
destination = keyIO.DecodeDestination(exp_base58string);
BOOST_CHECK_MESSAGE(!IsValidDestination(destination), "IsValid pubkey:" + strTest);
privkey = DecodeSecret(exp_base58string);
privkey = keyIO.DecodeSecret(exp_base58string);
BOOST_CHECK_MESSAGE(!privkey.IsValid(), "IsValid privkey:" + strTest);
}
}

View File

@ -84,18 +84,19 @@ void RunTest(const TestVector &test) {
CExtPubKey pubkey;
key.SetMaster(&seed[0], seed.size());
pubkey = key.Neuter();
KeyIO keyIO(Params());
BOOST_FOREACH(const TestDerivation &derive, test.vDerive) {
unsigned char data[74];
key.Encode(data);
pubkey.Encode(data);
// Test private key
BOOST_CHECK(EncodeExtKey(key) == derive.prv);
BOOST_CHECK(DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
BOOST_CHECK(keyIO.EncodeExtKey(key) == derive.prv);
BOOST_CHECK(keyIO.DecodeExtKey(derive.prv) == key); //ensure a base58 decoded key also matches
// Test public key
BOOST_CHECK(EncodeExtPubKey(pubkey) == derive.pub);
BOOST_CHECK(DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
BOOST_CHECK(keyIO.EncodeExtPubKey(pubkey) == derive.pub);
BOOST_CHECK(keyIO.DecodeExtPubKey(derive.pub) == pubkey); //ensure a base58 decoded pubkey also matches
// Derive new keys
CExtKey keyNew;

View File

@ -86,8 +86,9 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_serialize_with_tweak)
BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
{
KeyIO keyIO(Params());
std::string strSecret = std::string("5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C");
CKey key = DecodeSecret(strSecret);
CKey key = keyIO.DecodeSecret(strSecret);
CPubKey pubkey = key.GetPubKey();
vector<unsigned char> vchPubKey(pubkey.begin(), pubkey.end());

View File

@ -46,6 +46,7 @@ void dumpKeyInfo(uint256 privkey)
memcpy(&sec[0], &secret[0], 32);
printf(" * secret (hex): %s\n", HexStr(sec).c_str());
KeyIO keyIO(Params());
for (int nCompressed=0; nCompressed<2; nCompressed++)
{
bool fCompressed = nCompressed == 1;
@ -57,7 +58,7 @@ void dumpKeyInfo(uint256 privkey)
key.SetSecret(secret, fCompressed);
vector<unsigned char> vchPubKey = key.GetPubKey();
printf(" * pubkey (hex): %s\n", HexStr(vchPubKey).c_str());
printf(" * address (base58): %s\n", EncodeDestination(vchPubKey).c_str());
printf(" * address (base58): %s\n", keyIO.EncodeDestination(vchPubKey).c_str());
}
}
#endif
@ -67,15 +68,16 @@ BOOST_FIXTURE_TEST_SUITE(key_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(key_test1)
{
CKey key1 = DecodeSecret(strSecret1);
KeyIO keyIO(Params());
CKey key1 = keyIO.DecodeSecret(strSecret1);
BOOST_CHECK(key1.IsValid() && !key1.IsCompressed());
CKey key2 = DecodeSecret(strSecret2);
CKey key2 = keyIO.DecodeSecret(strSecret2);
BOOST_CHECK(key2.IsValid() && !key2.IsCompressed());
CKey key1C = DecodeSecret(strSecret1C);
CKey key1C = keyIO.DecodeSecret(strSecret1C);
BOOST_CHECK(key1C.IsValid() && key1C.IsCompressed());
CKey key2C = DecodeSecret(strSecret2C);
CKey key2C = keyIO.DecodeSecret(strSecret2C);
BOOST_CHECK(key2C.IsValid() && key2C.IsCompressed());
CKey bad_key = DecodeSecret(strAddressBad);
CKey bad_key = keyIO.DecodeSecret(strAddressBad);
BOOST_CHECK(!bad_key.IsValid());
CPubKey pubkey1 = key1. GetPubKey();
@ -103,10 +105,10 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_CHECK(!key2C.VerifyPubKey(pubkey2));
BOOST_CHECK(key2C.VerifyPubKey(pubkey2C));
BOOST_CHECK(DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
BOOST_CHECK(DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
BOOST_CHECK(DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
BOOST_CHECK(DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
BOOST_CHECK(keyIO.DecodeDestination(addr1) == CTxDestination(pubkey1.GetID()));
BOOST_CHECK(keyIO.DecodeDestination(addr2) == CTxDestination(pubkey2.GetID()));
BOOST_CHECK(keyIO.DecodeDestination(addr1C) == CTxDestination(pubkey1C.GetID()));
BOOST_CHECK(keyIO.DecodeDestination(addr2C) == CTxDestination(pubkey2C.GetID()));
for (int n=0; n<16; n++)
{
@ -189,15 +191,16 @@ BOOST_AUTO_TEST_CASE(key_test1)
BOOST_AUTO_TEST_CASE(zc_address_test)
{
KeyIO keyIO(Params());
for (size_t i = 0; i < 1000; i++) {
auto sk = SproutSpendingKey::random();
{
string sk_string = EncodeSpendingKey(sk);
string sk_string = keyIO.EncodeSpendingKey(sk);
BOOST_CHECK(sk_string[0] == 'S');
BOOST_CHECK(sk_string[1] == 'K');
auto spendingkey2 = DecodeSpendingKey(sk_string);
auto spendingkey2 = keyIO.DecodeSpendingKey(sk_string);
BOOST_CHECK(IsValidSpendingKey(spendingkey2));
BOOST_ASSERT(boost::get<SproutSpendingKey>(&spendingkey2) != nullptr);
auto sk2 = boost::get<SproutSpendingKey>(spendingkey2);
@ -206,12 +209,12 @@ BOOST_AUTO_TEST_CASE(zc_address_test)
{
auto addr = sk.address();
std::string addr_string = EncodePaymentAddress(addr);
std::string addr_string = keyIO.EncodePaymentAddress(addr);
BOOST_CHECK(addr_string[0] == 'z');
BOOST_CHECK(addr_string[1] == 'c');
auto paymentaddr2 = DecodePaymentAddress(addr_string);
auto paymentaddr2 = keyIO.DecodePaymentAddress(addr_string);
BOOST_ASSERT(IsValidPaymentAddress(paymentaddr2));
BOOST_ASSERT(boost::get<SproutPaymentAddress>(&paymentaddr2) != nullptr);
@ -228,13 +231,14 @@ BOOST_AUTO_TEST_CASE(zs_address_test)
auto m = GetTestMasterSaplingSpendingKey();
KeyIO keyIO(Params());
for (uint32_t i = 0; i < 1000; i++) {
auto sk = m.Derive(i);
{
std::string sk_string = EncodeSpendingKey(sk);
std::string sk_string = keyIO.EncodeSpendingKey(sk);
BOOST_CHECK(sk_string.compare(0, 27, Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY)) == 0);
auto spendingkey2 = DecodeSpendingKey(sk_string);
auto spendingkey2 = keyIO.DecodeSpendingKey(sk_string);
BOOST_CHECK(IsValidSpendingKey(spendingkey2));
BOOST_ASSERT(boost::get<SaplingExtendedSpendingKey>(&spendingkey2) != nullptr);
@ -244,10 +248,10 @@ BOOST_AUTO_TEST_CASE(zs_address_test)
{
auto addr = sk.DefaultAddress();
std::string addr_string = EncodePaymentAddress(addr);
std::string addr_string = keyIO.EncodePaymentAddress(addr);
BOOST_CHECK(addr_string.compare(0, 15, Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS)) == 0);
auto paymentaddr2 = DecodePaymentAddress(addr_string);
auto paymentaddr2 = keyIO.DecodePaymentAddress(addr_string);
BOOST_CHECK(IsValidPaymentAddress(paymentaddr2));
BOOST_ASSERT(boost::get<SaplingPaymentAddress>(&paymentaddr2) != nullptr);

View File

@ -286,7 +286,8 @@ libzcash::SaplingExtendedSpendingKey GetTestMasterSaplingSpendingKey() {
}
CKey AddTestCKeyToKeyStore(CBasicKeyStore& keyStore) {
CKey tsk = DecodeSecret(T_SECRET_REGTEST);
KeyIO keyIO(Params());
CKey tsk = keyIO.DecodeSecret(T_SECRET_REGTEST);
keyStore.AddKey(tsk);
return tsk;
}

View File

@ -91,12 +91,13 @@ AsyncRPCOperation_mergetoaddress::AsyncRPCOperation_mergetoaddress(
builder_ = builder.get();
}
toTaddr_ = DecodeDestination(std::get<0>(recipient));
KeyIO keyIO(Params());
toTaddr_ = keyIO.DecodeDestination(std::get<0>(recipient));
isToTaddr_ = IsValidDestination(toTaddr_);
isToZaddr_ = false;
if (!isToTaddr_) {
auto address = DecodePaymentAddress(std::get<0>(recipient));
auto address = keyIO.DecodePaymentAddress(std::get<0>(recipient));
if (IsValidPaymentAddress(address)) {
isToZaddr_ = true;
toPaymentAddress_ = address;
@ -866,6 +867,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
arrOutputMap.push_back(static_cast<uint64_t>(outputMap[i]));
}
KeyIO keyIO(Params());
// !!! Payment disclosure START
unsigned char buffer[32] = {0};
@ -883,7 +885,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END

View File

@ -192,9 +192,10 @@ CAmount AsyncRPCOperation_saplingmigration::chooseAmount(const CAmount& availabl
// Unless otherwise specified, the migration destination address is the address for Sapling account 0
libzcash::SaplingPaymentAddress AsyncRPCOperation_saplingmigration::getMigrationDestAddress(const HDSeed& seed) {
KeyIO keyIO(Params());
if (mapArgs.count("-migrationdestaddress")) {
std::string migrationDestAddress = mapArgs["-migrationdestaddress"];
auto address = DecodePaymentAddress(migrationDestAddress);
auto address = keyIO.DecodePaymentAddress(migrationDestAddress);
auto saplingAddress = boost::get<libzcash::SaplingPaymentAddress>(&address);
assert(saplingAddress != nullptr); // This is checked in init.cpp
return *saplingAddress;

View File

@ -85,12 +85,14 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
builder_ = builder.get();
}
fromtaddr_ = DecodeDestination(fromAddress);
KeyIO keyIO(Params());
fromtaddr_ = keyIO.DecodeDestination(fromAddress);
isfromtaddr_ = IsValidDestination(fromtaddr_);
isfromzaddr_ = false;
if (!isfromtaddr_) {
auto address = DecodePaymentAddress(fromAddress);
auto address = keyIO.DecodePaymentAddress(fromAddress);
if (IsValidPaymentAddress(address)) {
// We don't need to lock on the wallet as spending key related methods are thread-safe
if (!boost::apply_visitor(HaveSpendingKeyForPaymentAddress(pwalletMain), address)) {
@ -343,6 +345,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
LogPrint("zrpcunsafe", "%s: private output: %s\n", getId(), FormatMoney(z_outputs_total));
LogPrint("zrpc", "%s: fee: %s\n", getId(), FormatMoney(minersFee));
KeyIO keyIO(Params());
/**
* SCENARIO #0
@ -424,7 +427,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
auto value = r.amount;
auto hexMemo = r.memo;
auto addr = DecodePaymentAddress(address);
auto addr = keyIO.DecodePaymentAddress(address);
assert(boost::get<libzcash::SaplingPaymentAddress>(&addr) != nullptr);
auto to = boost::get<libzcash::SaplingPaymentAddress>(addr);
@ -438,7 +441,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
auto outputAddress = r.address;
auto amount = r.amount;
auto address = DecodeDestination(outputAddress);
auto address = keyIO.DecodeDestination(outputAddress);
builder_.AddTransparentOutput(address, amount);
}
@ -583,7 +586,7 @@ bool AsyncRPCOperation_sendmany::main_impl() {
std::string hexMemo = smr.memo;
zOutputsDeque.pop_front();
PaymentAddress pa = DecodePaymentAddress(address);
PaymentAddress pa = keyIO.DecodePaymentAddress(address);
JSOutput jso = JSOutput(boost::get<libzcash::SproutPaymentAddress>(pa), value);
if (hexMemo.size() > 0) {
jso.memo = get_memo_from_hex_string(hexMemo);
@ -845,7 +848,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 = DecodePaymentAddress(address);
PaymentAddress pa = keyIO.DecodePaymentAddress(address);
// If we are here, we know we have no Sapling outputs.
JSOutput jso = JSOutput(boost::get<libzcash::SproutPaymentAddress>(pa), value);
if (hexMemo.size() > 0) {
@ -1145,6 +1148,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
arrOutputMap.push_back(static_cast<uint64_t>(outputMap[i]));
}
KeyIO keyIO(Params());
// !!! Payment disclosure START
unsigned char buffer[32] = {0};
@ -1162,7 +1166,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END
@ -1179,11 +1183,13 @@ void AsyncRPCOperation_sendmany::add_taddr_outputs_to_tx() {
CMutableTransaction rawTx(tx_);
KeyIO keyIO(Params());
for (SendManyRecipient & r : t_outputs_) {
std::string outputAddress = r.address;
CAmount nAmount = r.amount;
CTxDestination address = DecodeDestination(outputAddress);
CTxDestination address = keyIO.DecodeDestination(outputAddress);
if (!IsValidDestination(address)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid output address, not a valid taddr.");
}

View File

@ -74,7 +74,8 @@ AsyncRPCOperation_shieldcoinbase::AsyncRPCOperation_shieldcoinbase(
}
// Check the destination address is valid for this network i.e. not testnet being used on mainnet
auto address = DecodePaymentAddress(toAddress);
KeyIO keyIO(Params());
auto address = keyIO.DecodePaymentAddress(toAddress);
if (IsValidPaymentAddress(address)) {
tozaddr_ = address;
} else {
@ -386,6 +387,8 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
arrOutputMap.push_back(static_cast<uint64_t>(outputMap[i]));
}
KeyIO keyIO(Params());
// !!! Payment disclosure START
unsigned char buffer[32] = {0};
memcpy(&buffer[0], &joinSplitPrivKey_[0], 32); // private key in first half of 64 byte buffer
@ -402,7 +405,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
PaymentDisclosureInfo pdInfo = {PAYMENT_DISCLOSURE_VERSION_EXPERIMENTAL, esk, joinSplitPrivKey, zaddr};
paymentDisclosureData_.push_back(PaymentDisclosureKeyInfo(pdKey, pdInfo));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), EncodePaymentAddress(zaddr));
LogPrint("paymentdisclosure", "%s: Payment Disclosure: js=%d, n=%d, zaddr=%s\n", getId(), js_index, int(mapped_index), keyIO.EncodePaymentAddress(zaddr));
}
// !!! Payment disclosure END

View File

@ -8,8 +8,9 @@
#include "util.h"
std::string PaymentDisclosureInfo::ToString() const {
KeyIO keyIO(Params());
return strprintf("PaymentDisclosureInfo(version=%d, esk=%s, joinSplitPrivKey=<omitted>, address=%s)",
version, esk.ToString(), EncodePaymentAddress(zaddr));
version, esk.ToString(), keyIO.EncodePaymentAddress(zaddr));
}
std::string PaymentDisclosure::ToString() const {
@ -18,8 +19,9 @@ std::string PaymentDisclosure::ToString() const {
}
std::string PaymentDisclosurePayload::ToString() const {
KeyIO keyIO(Params());
return strprintf("PaymentDisclosurePayload(version=%d, esk=%s, txid=%s, js=%d, n=%d, address=%s, message=%s)",
version, esk.ToString(), txid.ToString(), js, n, EncodePaymentAddress(zaddr), message);
version, esk.ToString(), txid.ToString(), js, n, keyIO.EncodePaymentAddress(zaddr), message);
}
PaymentDisclosure::PaymentDisclosure(const uint256 &joinSplitPubKey, const PaymentDisclosureKey &key, const PaymentDisclosureInfo &info, const std::string &message)

View File

@ -250,10 +250,12 @@ UniValue z_validatepaymentdisclosure(const UniValue& params, bool fHelp)
errs.push_back("Payment disclosure signature does not match transaction signature");
}
KeyIO keyIO(Params());
// Check the payment address is valid
SproutPaymentAddress zaddr = pd.payload.zaddr;
{
o.pushKV("paymentAddress", EncodePaymentAddress(zaddr));
o.pushKV("paymentAddress", keyIO.EncodePaymentAddress(zaddr));
try {
// Decrypt the note to get value and memo field

View File

@ -116,7 +116,9 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
if (params.size() > 2)
fRescan = params[2].get_bool();
CKey key = DecodeSecret(strSecret);
KeyIO keyIO(Params());
CKey key = keyIO.DecodeSecret(strSecret);
if (!key.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key encoding");
CPubKey pubkey = key.GetPubKey();
@ -128,7 +130,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
// Don't throw error in case a key is already there
if (pwalletMain->HaveKey(vchAddress)) {
return EncodeDestination(vchAddress);
return keyIO.EncodeDestination(vchAddress);
}
pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1;
@ -144,7 +146,7 @@ UniValue importprivkey(const UniValue& params, bool fHelp)
}
}
return EncodeDestination(vchAddress);
return keyIO.EncodeDestination(vchAddress);
}
void ImportAddress(const CTxDestination& dest, const string& strLabel);
@ -227,7 +229,8 @@ UniValue importaddress(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
CTxDestination dest = DecodeDestination(params[0].get_str());
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
if (IsValidDestination(dest)) {
if (fP2SH) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Cannot use the p2sh flag with an address - use a script instead");
@ -373,6 +376,8 @@ UniValue importwallet_impl(const UniValue& params, bool fImportZKeys)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
KeyIO keyIO(Params());
pwalletMain->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
while (file.good()) {
pwalletMain->ShowProgress("", std::max(1, std::min(99, (int)(((double)file.tellg() / (double)nFilesize) * 100))));
@ -388,7 +393,7 @@ UniValue importwallet_impl(const UniValue& params, bool fImportZKeys)
// Let's see if the address is a valid Zcash spending key
if (fImportZKeys) {
auto spendingkey = DecodeSpendingKey(vstr[0]);
auto spendingkey = keyIO.DecodeSpendingKey(vstr[0]);
int64_t nTime = DecodeDumpTime(vstr[1]);
// Only include hdKeypath and seedFpStr if we have both
boost::optional<std::string> hdKeypath = (vstr.size() > 3) ? boost::optional<std::string>(vstr[2]) : boost::none;
@ -409,14 +414,14 @@ UniValue importwallet_impl(const UniValue& params, bool fImportZKeys)
}
}
CKey key = DecodeSecret(vstr[0]);
CKey key = keyIO.DecodeSecret(vstr[0]);
if (!key.IsValid())
continue;
CPubKey pubkey = key.GetPubKey();
assert(key.VerifyPubKey(pubkey));
CKeyID keyid = pubkey.GetID();
if (pwalletMain->HaveKey(keyid)) {
LogPrintf("Skipping import of %s (key already present)\n", EncodeDestination(keyid));
LogPrintf("Skipping import of %s (key already present)\n", keyIO.EncodeDestination(keyid));
continue;
}
int64_t nTime = DecodeDumpTime(vstr[1]);
@ -434,7 +439,7 @@ UniValue importwallet_impl(const UniValue& params, bool fImportZKeys)
fLabel = true;
}
}
LogPrintf("Importing %s...\n", EncodeDestination(keyid));
LogPrintf("Importing %s...\n", keyIO.EncodeDestination(keyid));
if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
fGood = false;
continue;
@ -489,8 +494,10 @@ UniValue dumpprivkey(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
KeyIO keyIO(Params());
std::string strAddress = params[0].get_str();
CTxDestination dest = DecodeDestination(strAddress);
CTxDestination dest = keyIO.DecodeDestination(strAddress);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -502,7 +509,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 EncodeSecret(vchSecret);
return keyIO.EncodeSecret(vchSecret);
}
@ -593,6 +600,8 @@ UniValue dumpwallet_impl(const UniValue& params, bool fDumpZKeys)
mapKeyBirth.clear();
std::sort(vKeyBirth.begin(), vKeyBirth.end());
KeyIO keyIO(Params());
// produce output
file << strprintf("# Wallet dump created by Zcash %s (%s)\n", CLIENT_BUILD, CLIENT_DATE);
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
@ -609,15 +618,15 @@ UniValue dumpwallet_impl(const UniValue& params, bool fDumpZKeys)
for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
const CKeyID &keyid = it->second;
std::string strTime = EncodeDumpTime(it->first);
std::string strAddr = EncodeDestination(keyid);
std::string strAddr = keyIO.EncodeDestination(keyid);
CKey key;
if (pwalletMain->GetKey(keyid, key)) {
if (pwalletMain->mapAddressBook.count(keyid)) {
file << strprintf("%s %s label=%s # addr=%s\n", EncodeSecret(key), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
file << strprintf("%s %s label=%s # addr=%s\n", keyIO.EncodeSecret(key), strTime, EncodeDumpString(pwalletMain->mapAddressBook[keyid].name), strAddr);
} else if (setKeyPool.count(keyid)) {
file << strprintf("%s %s reserve=1 # addr=%s\n", EncodeSecret(key), strTime, strAddr);
file << strprintf("%s %s reserve=1 # addr=%s\n", keyIO.EncodeSecret(key), strTime, strAddr);
} else {
file << strprintf("%s %s change=1 # addr=%s\n", EncodeSecret(key), strTime, strAddr);
file << strprintf("%s %s change=1 # addr=%s\n", keyIO.EncodeSecret(key), strTime, strAddr);
}
}
}
@ -633,7 +642,7 @@ UniValue dumpwallet_impl(const UniValue& params, bool fDumpZKeys)
libzcash::SproutSpendingKey key;
if (pwalletMain->GetSproutSpendingKey(addr, key)) {
std::string strTime = EncodeDumpTime(pwalletMain->mapSproutZKeyMetadata[addr].nCreateTime);
file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(key), strTime, EncodePaymentAddress(addr));
file << strprintf("%s %s # zaddr=%s\n", keyIO.EncodeSpendingKey(key), strTime, keyIO.EncodePaymentAddress(addr));
}
}
std::set<libzcash::SaplingPaymentAddress> saplingAddresses;
@ -649,9 +658,9 @@ UniValue dumpwallet_impl(const UniValue& params, bool fDumpZKeys)
std::string strTime = EncodeDumpTime(keyMeta.nCreateTime);
// Keys imported with z_importkey do not have zip32 metadata
if (keyMeta.hdKeypath.empty() || keyMeta.seedFp.IsNull()) {
file << strprintf("%s %s # zaddr=%s\n", EncodeSpendingKey(extsk), strTime, EncodePaymentAddress(addr));
file << strprintf("%s %s # zaddr=%s\n", keyIO.EncodeSpendingKey(extsk), strTime, keyIO.EncodePaymentAddress(addr));
} else {
file << strprintf("%s %s %s %s # zaddr=%s\n", EncodeSpendingKey(extsk), strTime, keyMeta.hdKeypath, keyMeta.seedFp.GetHex(), EncodePaymentAddress(addr));
file << strprintf("%s %s %s %s # zaddr=%s\n", keyIO.EncodeSpendingKey(extsk), strTime, keyMeta.hdKeypath, keyMeta.seedFp.GetHex(), keyIO.EncodePaymentAddress(addr));
}
}
}
@ -737,8 +746,9 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
}
KeyIO keyIO(Params());
string strSecret = params[0].get_str();
auto spendingkey = DecodeSpendingKey(strSecret);
auto spendingkey = keyIO.DecodeSpendingKey(strSecret);
if (!IsValidSpendingKey(spendingkey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
@ -746,7 +756,7 @@ UniValue z_importkey(const UniValue& params, bool fHelp)
auto addrInfo = boost::apply_visitor(libzcash::AddressInfoFromSpendingKey{}, spendingkey);
UniValue result(UniValue::VOBJ);
result.pushKV("type", addrInfo.first);
result.pushKV("address", EncodePaymentAddress(addrInfo.second));
result.pushKV("address", keyIO.EncodePaymentAddress(addrInfo.second));
// Sapling support
auto addResult = boost::apply_visitor(AddSpendingKeyToWallet(pwalletMain, Params().GetConsensus()), spendingkey);
@ -831,8 +841,9 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
}
KeyIO keyIO(Params());
string strVKey = params[0].get_str();
auto viewingkey = DecodeViewingKey(strVKey);
auto viewingkey = keyIO.DecodeViewingKey(strVKey);
if (!IsValidViewingKey(viewingkey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid viewing key");
}
@ -840,7 +851,7 @@ UniValue z_importviewingkey(const UniValue& params, bool fHelp)
auto addrInfo = boost::apply_visitor(libzcash::AddressInfoFromViewingKey{}, viewingkey);
UniValue result(UniValue::VOBJ);
result.pushKV("type", addrInfo.first);
result.pushKV("address", EncodePaymentAddress(addrInfo.second));
result.pushKV("address", keyIO.EncodePaymentAddress(addrInfo.second));
auto addResult = boost::apply_visitor(AddViewingKeyToWallet(pwalletMain), viewingkey);
if (addResult == SpendingKeyExists) {
@ -889,7 +900,8 @@ UniValue z_exportkey(const UniValue& params, bool fHelp)
string strAddress = params[0].get_str();
auto address = DecodePaymentAddress(strAddress);
KeyIO keyIO(Params());
auto address = keyIO.DecodePaymentAddress(strAddress);
if (!IsValidPaymentAddress(address)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
@ -899,7 +911,7 @@ UniValue z_exportkey(const UniValue& params, bool fHelp)
if (!sk) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private zkey for this zaddr");
}
return EncodeSpendingKey(sk.get());
return keyIO.EncodeSpendingKey(sk.get());
}
UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
@ -927,14 +939,15 @@ UniValue z_exportviewingkey(const UniValue& params, bool fHelp)
string strAddress = params[0].get_str();
auto address = DecodePaymentAddress(strAddress);
KeyIO keyIO(Params());
auto address = keyIO.DecodePaymentAddress(strAddress);
if (!IsValidPaymentAddress(address)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr");
}
auto vk = boost::apply_visitor(GetViewingKeyForPaymentAddress(pwalletMain), address);
if (vk) {
return EncodeViewingKey(vk.get());
return keyIO.EncodeViewingKey(vk.get());
} else {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet does not hold private key or viewing key for this zaddr");
}

View File

@ -168,7 +168,8 @@ UniValue getnewaddress(const UniValue& params, bool fHelp)
pwalletMain->SetAddressBook(keyID, strAccount, "receive");
return EncodeDestination(keyID);
KeyIO keyIO(Params());
return keyIO.EncodeDestination(keyID);
}
@ -236,7 +237,8 @@ UniValue getaccountaddress(const UniValue& params, bool fHelp)
UniValue ret(UniValue::VSTR);
ret = EncodeDestination(GetAccountAddress(strAccount));
KeyIO keyIO(Params());
ret = keyIO.EncodeDestination(GetAccountAddress(strAccount));
return ret;
}
@ -272,7 +274,8 @@ UniValue getrawchangeaddress(const UniValue& params, bool fHelp)
CKeyID keyID = vchPubKey.GetID();
return EncodeDestination(keyID);
KeyIO keyIO(Params());
return keyIO.EncodeDestination(keyID);
}
@ -295,7 +298,8 @@ UniValue setaccount(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
CTxDestination dest = DecodeDestination(params[0].get_str());
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -342,7 +346,8 @@ UniValue getaccount(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
CTxDestination dest = DecodeDestination(params[0].get_str());
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -381,13 +386,14 @@ UniValue getaddressesbyaccount(const UniValue& params, bool fHelp)
string strAccount = AccountFromValue(params[0]);
KeyIO keyIO(Params());
// Find all addresses that have the given account
UniValue ret(UniValue::VARR);
for (const std::pair<CTxDestination, CAddressBookData>& item : pwalletMain->mapAddressBook) {
const CTxDestination& dest = item.first;
const std::string& strName = item.second.name;
if (strName == strAccount) {
ret.push_back(EncodeDestination(dest));
ret.push_back(keyIO.EncodeDestination(dest));
}
}
return ret;
@ -455,7 +461,8 @@ UniValue sendtoaddress(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
CTxDestination dest = DecodeDestination(params[0].get_str());
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -513,6 +520,7 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
KeyIO keyIO(Params());
UniValue jsonGroupings(UniValue::VARR);
std::map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
for (const std::set<CTxDestination>& grouping : pwalletMain->GetAddressGroupings()) {
@ -520,7 +528,7 @@ UniValue listaddressgroupings(const UniValue& params, bool fHelp)
for (const CTxDestination& address : grouping)
{
UniValue addressInfo(UniValue::VARR);
addressInfo.push_back(EncodeDestination(address));
addressInfo.push_back(keyIO.EncodeDestination(address));
addressInfo.push_back(ValueFromAmount(balances[address]));
{
if (pwalletMain->mapAddressBook.find(address) != pwalletMain->mapAddressBook.end()) {
@ -567,7 +575,8 @@ UniValue signmessage(const UniValue& params, bool fHelp)
string strAddress = params[0].get_str();
string strMessage = params[1].get_str();
CTxDestination dest = DecodeDestination(strAddress);
KeyIO keyIO(Params());
CTxDestination dest = keyIO.DecodeDestination(strAddress);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
}
@ -621,8 +630,9 @@ UniValue getreceivedbyaddress(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
KeyIO keyIO(Params());
// Bitcoin address
CTxDestination dest = DecodeDestination(params[0].get_str());
CTxDestination dest = keyIO.DecodeDestination(params[0].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -960,8 +970,9 @@ UniValue sendfrom(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
KeyIO keyIO(Params());
std::string strAccount = AccountFromValue(params[0]);
CTxDestination dest = DecodeDestination(params[1].get_str());
CTxDestination dest = keyIO.DecodeDestination(params[1].get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Zcash address");
}
@ -1053,10 +1064,11 @@ UniValue sendmany(const UniValue& params, bool fHelp)
std::set<CTxDestination> destinations;
std::vector<CRecipient> vecSend;
KeyIO keyIO(Params());
CAmount totalAmount = 0;
std::vector<std::string> keys = sendTo.getKeys();
for (const std::string& name_ : keys) {
CTxDestination dest = DecodeDestination(name_);
CTxDestination dest = keyIO.DecodeDestination(name_);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + name_);
}
@ -1152,7 +1164,8 @@ UniValue addmultisigaddress(const UniValue& params, bool fHelp)
pwalletMain->AddCScript(inner);
pwalletMain->SetAddressBook(innerID, strAccount, "send");
return EncodeDestination(innerID);
KeyIO keyIO(Params());
return keyIO.EncodeDestination(innerID);
}
@ -1218,6 +1231,8 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
}
}
KeyIO keyIO(Params());
// Reply
UniValue ret(UniValue::VARR);
std::map<std::string, tallyitem> mapAccountTally;
@ -1250,7 +1265,7 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
UniValue obj(UniValue::VOBJ);
if(fIsWatchonly)
obj.pushKV("involvesWatchonly", true);
obj.pushKV("address", EncodeDestination(dest));
obj.pushKV("address", keyIO.EncodeDestination(dest));
obj.pushKV("account", strAccount);
obj.pushKV("amount", ValueFromAmount(nAmount));
obj.pushKV("amountZat", nAmount);
@ -1366,7 +1381,8 @@ UniValue listreceivedbyaccount(const UniValue& params, bool fHelp)
static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
{
if (IsValidDestination(dest)) {
entry.pushKV("address", EncodeDestination(dest));
KeyIO keyIO(Params());
entry.pushKV("address", keyIO.EncodeDestination(dest));
}
}
@ -2440,12 +2456,13 @@ UniValue listunspent(const UniValue& params, bool fHelp)
if (params.size() > 1)
nMaxDepth = params[1].get_int();
KeyIO keyIO(Params());
std::set<CTxDestination> destinations;
if (params.size() > 2) {
UniValue inputs = params[2].get_array();
for (size_t idx = 0; idx < inputs.size(); idx++) {
const UniValue& input = inputs[idx];
CTxDestination dest = DecodeDestination(input.get_str());
CTxDestination dest = keyIO.DecodeDestination(input.get_str());
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, std::string("Invalid Zcash address: ") + input.get_str());
}
@ -2477,7 +2494,7 @@ UniValue listunspent(const UniValue& params, bool fHelp)
entry.pushKV("generated", out.tx->IsCoinBase());
if (fValidAddress) {
entry.pushKV("address", EncodeDestination(address));
entry.pushKV("address", keyIO.EncodeDestination(address));
if (pwalletMain->mapAddressBook.count(address))
entry.pushKV("account", pwalletMain->mapAddressBook[address].name);
@ -2575,6 +2592,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
LOCK2(cs_main, pwalletMain->cs_wallet);
KeyIO keyIO(Params());
// User has supplied zaddrs to filter on
if (params.size() > 3) {
UniValue addresses = params[3].get_array();
@ -2590,7 +2608,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected string");
}
string address = o.get_str();
auto zaddr = DecodePaymentAddress(address);
auto zaddr = keyIO.DecodePaymentAddress(address);
if (!IsValidPaymentAddress(zaddr)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, address is not a valid zaddr: ") + address);
}
@ -2635,7 +2653,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
obj.pushKV("confirmations", entry.confirmations);
bool hasSproutSpendingKey = HaveSpendingKeyForPaymentAddress(pwalletMain)(entry.address);
obj.pushKV("spendable", hasSproutSpendingKey);
obj.pushKV("address", EncodePaymentAddress(entry.address));
obj.pushKV("address", keyIO.EncodePaymentAddress(entry.address));
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value())));
std::string data(entry.memo.begin(), entry.memo.end());
obj.pushKV("memo", HexStr(data));
@ -2652,7 +2670,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
obj.pushKV("confirmations", entry.confirmations);
bool hasSaplingSpendingKey = HaveSpendingKeyForPaymentAddress(pwalletMain)(entry.address);
obj.pushKV("spendable", hasSaplingSpendingKey);
obj.pushKV("address", EncodePaymentAddress(entry.address));
obj.pushKV("address", keyIO.EncodePaymentAddress(entry.address));
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); // note.value() is equivalent to plaintext.value()
obj.pushKV("memo", HexStr(entry.memo));
if (hasSaplingSpendingKey) {
@ -2914,7 +2932,8 @@ UniValue zc_raw_receive(const UniValue& params, bool fHelp)
LOCK(cs_main);
auto spendingkey = DecodeSpendingKey(params[0].get_str());
KeyIO keyIO(Params());
auto spendingkey = keyIO.DecodeSpendingKey(params[0].get_str());
if (!IsValidSpendingKey(spendingkey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
@ -3037,8 +3056,9 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
std::vector<SproutSpendingKey> keys;
std::vector<uint256> commitments;
KeyIO keyIO(Params());
for (const string& name_ : inputs.getKeys()) {
auto spendingkey = DecodeSpendingKey(inputs[name_].get_str());
auto spendingkey = keyIO.DecodeSpendingKey(inputs[name_].get_str());
if (!IsValidSpendingKey(spendingkey)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid spending key");
}
@ -3086,7 +3106,7 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
}
for (const string& name_ : outputs.getKeys()) {
auto addrTo = DecodePaymentAddress(name_);
auto addrTo = keyIO.DecodePaymentAddress(name_);
if (!IsValidPaymentAddress(addrTo)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid recipient address.");
}
@ -3206,10 +3226,11 @@ UniValue zc_raw_keygen(const UniValue& params, bool fHelp)
auto addr = k.address();
auto viewing_key = k.viewing_key();
KeyIO keyIO(Params());
UniValue result(UniValue::VOBJ);
result.pushKV("zcaddress", EncodePaymentAddress(addr));
result.pushKV("zcsecretkey", EncodeSpendingKey(k));
result.pushKV("zcviewingkey", EncodeViewingKey(viewing_key));
result.pushKV("zcaddress", keyIO.EncodePaymentAddress(addr));
result.pushKV("zcsecretkey", keyIO.EncodeSpendingKey(k));
result.pushKV("zcviewingkey", keyIO.EncodeViewingKey(viewing_key));
return result;
}
@ -3246,10 +3267,11 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
addrType = params[0].get_str();
}
KeyIO keyIO(Params());
if (addrType == ADDR_TYPE_SPROUT) {
return EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey());
return keyIO.EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey());
} else if (addrType == ADDR_TYPE_SAPLING) {
return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
return keyIO.EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");
}
@ -3284,13 +3306,14 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
fIncludeWatchonly = params[0].get_bool();
}
KeyIO keyIO(Params());
UniValue ret(UniValue::VARR);
{
std::set<libzcash::SproutPaymentAddress> addresses;
pwalletMain->GetSproutPaymentAddresses(addresses);
for (auto addr : addresses) {
if (fIncludeWatchonly || HaveSpendingKeyForPaymentAddress(pwalletMain)(addr)) {
ret.push_back(EncodePaymentAddress(addr));
ret.push_back(keyIO.EncodePaymentAddress(addr));
}
}
}
@ -3299,7 +3322,7 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
pwalletMain->GetSaplingPaymentAddresses(addresses);
for (auto addr : addresses) {
if (fIncludeWatchonly || HaveSpendingKeyForPaymentAddress(pwalletMain)(addr)) {
ret.push_back(EncodePaymentAddress(addr));
ret.push_back(keyIO.EncodePaymentAddress(addr));
}
}
}
@ -3311,8 +3334,9 @@ CAmount getBalanceTaddr(std::string transparentAddress, int minDepth=1, bool ign
vector<COutput> vecOutputs;
CAmount balance = 0;
KeyIO keyIO(Params());
if (transparentAddress.length() > 0) {
CTxDestination taddr = DecodeDestination(transparentAddress);
CTxDestination taddr = keyIO.DecodeDestination(transparentAddress);
if (!IsValidDestination(taddr)) {
throw std::runtime_error("invalid transparent address");
}
@ -3427,7 +3451,8 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
// Check that the from address is valid.
auto fromaddress = params[0].get_str();
auto zaddr = DecodePaymentAddress(fromaddress);
KeyIO keyIO(Params());
auto zaddr = keyIO.DecodePaymentAddress(fromaddress);
if (!IsValidPaymentAddress(zaddr)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid zaddr.");
}
@ -3530,13 +3555,14 @@ UniValue z_getbalance(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Minimum number of confirmations cannot be less than 0");
}
KeyIO keyIO(Params());
// Check that the from address is valid.
auto fromaddress = params[0].get_str();
bool fromTaddr = false;
CTxDestination taddr = DecodeDestination(fromaddress);
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
fromTaddr = IsValidDestination(taddr);
if (!fromTaddr) {
auto res = DecodePaymentAddress(fromaddress);
auto res = keyIO.DecodePaymentAddress(fromaddress);
if (!IsValidPaymentAddress(res)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
}
@ -3705,6 +3731,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
}
};
KeyIO keyIO(Params());
// Sprout spends
for (size_t i = 0; i < wtx.vJoinSplit.size(); ++i) {
for (size_t j = 0; j < wtx.vJoinSplit[i].nullifiers.size(); ++j) {
@ -3729,7 +3756,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
entry.pushKV("txidPrev", jsop.hash.GetHex());
entry.pushKV("jsPrev", (int)jsop.js);
entry.pushKV("jsOutputPrev", (int)jsop.n);
entry.pushKV("address", EncodePaymentAddress(pa));
entry.pushKV("address", keyIO.EncodePaymentAddress(pa));
entry.pushKV("value", ValueFromAmount(notePt.value()));
entry.pushKV("valueZat", notePt.value());
spends.push_back(entry);
@ -3749,7 +3776,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
entry.pushKV("type", ADDR_TYPE_SPROUT);
entry.pushKV("js", (int)jsop.js);
entry.pushKV("jsOutput", (int)jsop.n);
entry.pushKV("address", EncodePaymentAddress(pa));
entry.pushKV("address", keyIO.EncodePaymentAddress(pa));
entry.pushKV("value", ValueFromAmount(notePt.value()));
entry.pushKV("valueZat", notePt.value());
addMemo(entry, memo);
@ -3792,7 +3819,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
entry.pushKV("spend", (int)i);
entry.pushKV("txidPrev", op.hash.GetHex());
entry.pushKV("outputPrev", (int)op.n);
entry.pushKV("address", EncodePaymentAddress(pa));
entry.pushKV("address", keyIO.EncodePaymentAddress(pa));
entry.pushKV("value", ValueFromAmount(notePt.value()));
entry.pushKV("valueZat", notePt.value());
spends.push_back(entry);
@ -3831,7 +3858,7 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
entry.pushKV("type", ADDR_TYPE_SAPLING);
entry.pushKV("output", (int)op.n);
entry.pushKV("outgoing", isOutgoing);
entry.pushKV("address", EncodePaymentAddress(pa));
entry.pushKV("address", keyIO.EncodePaymentAddress(pa));
entry.pushKV("value", ValueFromAmount(notePt.value()));
entry.pushKV("valueZat", notePt.value());
addMemo(entry, memo);
@ -3997,10 +4024,11 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
auto fromaddress = params[0].get_str();
bool fromTaddr = false;
bool fromSapling = false;
CTxDestination taddr = DecodeDestination(fromaddress);
KeyIO keyIO(Params());
CTxDestination taddr = keyIO.DecodeDestination(fromaddress);
fromTaddr = IsValidDestination(taddr);
if (!fromTaddr) {
auto res = DecodePaymentAddress(fromaddress);
auto res = keyIO.DecodePaymentAddress(fromaddress);
if (!IsValidPaymentAddress(res)) {
// invalid
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or zaddr.");
@ -4049,9 +4077,9 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
string address = find_value(o, "address").get_str();
bool isZaddr = false;
CTxDestination taddr = DecodeDestination(address);
CTxDestination taddr = keyIO.DecodeDestination(address);
if (!IsValidDestination(taddr)) {
auto res = DecodePaymentAddress(address);
auto res = keyIO.DecodePaymentAddress(address);
if (IsValidPaymentAddress(res)) {
isZaddr = true;
@ -4153,7 +4181,7 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
size_t txsize = 0;
for (int i = 0; i < zaddrRecipients.size(); i++) {
auto address = zaddrRecipients[i].address;
auto res = DecodePaymentAddress(address);
auto res = keyIO.DecodePaymentAddress(address);
bool toSapling = boost::get<libzcash::SaplingPaymentAddress>(&res) != nullptr;
if (toSapling) {
mtx.vShieldedOutput.push_back(OutputDescription());
@ -4302,7 +4330,8 @@ UniValue z_getmigrationstatus(const UniValue& params, bool fHelp) {
// parameter is not set and no default address has yet been generated.
// Note: The following function may return the default address even if it has not been added to the wallet
auto destinationAddress = AsyncRPCOperation_saplingmigration::getMigrationDestAddress(pwalletMain->GetHDSeedForRPC());
migrationStatus.pushKV("destination_address", EncodePaymentAddress(destinationAddress));
KeyIO keyIO(Params());
migrationStatus.pushKV("destination_address", keyIO.EncodePaymentAddress(destinationAddress));
// The values of "unmigrated_amount" and "migrated_amount" MUST take into
// account failed transactions, that were not mined within their expiration
// height.
@ -4431,9 +4460,10 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
// Validate the from address
auto fromaddress = params[0].get_str();
bool isFromWildcard = fromaddress == "*";
KeyIO keyIO(Params());
CTxDestination taddr;
if (!isFromWildcard) {
taddr = DecodeDestination(fromaddress);
taddr = keyIO.DecodeDestination(fromaddress);
if (!IsValidDestination(taddr)) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid from address, should be a taddr or \"*\".");
}
@ -4441,7 +4471,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
// Validate the destination address
auto destaddress = params[1].get_str();
if (!IsValidPaymentAddressString(destaddress)) {
if (!keyIO.IsValidPaymentAddressString(destaddress)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
}
@ -4449,7 +4479,7 @@ UniValue z_shieldcoinbase(const UniValue& params, bool fHelp)
const bool canopyActive = Params().GetConsensus().NetworkUpgradeActive(nextBlockHeight, Consensus::UPGRADE_CANOPY);
if (canopyActive) {
auto decodeAddr = DecodePaymentAddress(destaddress);
auto decodeAddr = keyIO.DecodePaymentAddress(destaddress);
bool isToSproutZaddr = (boost::get<libzcash::SproutPaymentAddress>(&decodeAddr) != nullptr);
if (isToSproutZaddr) {
@ -4678,6 +4708,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
bool isFromNonSprout = false;
KeyIO keyIO(Params());
// Sources
for (const UniValue& o : addresses.getValues()) {
if (!o.isStr())
@ -4694,12 +4725,12 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
useAnySapling = true;
isFromNonSprout = true;
} else {
CTxDestination taddr = DecodeDestination(address);
CTxDestination taddr = keyIO.DecodeDestination(address);
if (IsValidDestination(taddr)) {
taddrs.insert(taddr);
isFromNonSprout = true;
} else {
auto zaddr = DecodePaymentAddress(address);
auto zaddr = keyIO.DecodePaymentAddress(address);
if (IsValidPaymentAddress(zaddr)) {
zaddrs.insert(zaddr);
if (boost::get<libzcash::SaplingPaymentAddress>(&zaddr) != nullptr) {
@ -4732,9 +4763,9 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
auto destaddress = params[1].get_str();
bool isToSproutZaddr = false;
bool isToSaplingZaddr = false;
CTxDestination taddr = DecodeDestination(destaddress);
CTxDestination taddr = keyIO.DecodeDestination(destaddress);
if (!IsValidDestination(taddr)) {
auto decodeAddr = DecodePaymentAddress(destaddress);
auto decodeAddr = keyIO.DecodePaymentAddress(destaddress);
if (IsValidPaymentAddress(decodeAddr)) {
if (boost::get<libzcash::SaplingPaymentAddress>(&decodeAddr) != nullptr) {
isToSaplingZaddr = true;

View File

@ -68,18 +68,19 @@ BOOST_AUTO_TEST_CASE(rpc_addmultisig)
// new, compressed:
const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
KeyIO keyIO(Params());
UniValue v;
CTxDestination address;
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
address = DecodeDestination(v.get_str());
address = keyIO.DecodeDestination(v.get_str());
BOOST_CHECK(IsValidDestination(address) && IsScriptDestination(address));
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
address = DecodeDestination(v.get_str());
address = keyIO.DecodeDestination(v.get_str());
BOOST_CHECK(IsValidDestination(address) && IsScriptDestination(address));
BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
address = DecodeDestination(v.get_str());
address = keyIO.DecodeDestination(v.get_str());
BOOST_CHECK(IsValidDestination(address) && IsScriptDestination(address));
BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
@ -122,9 +123,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
/*********************************
* setaccount
*********************************/
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " \"\""));
KeyIO keyIO(Params());
BOOST_CHECK_NO_THROW(CallRPC("setaccount " + keyIO.EncodeDestination(setaccountDemoAddress) + " \"\""));
/* Accounts are disabled */
BOOST_CHECK_THROW(CallRPC("setaccount " + EncodeDestination(setaccountDemoAddress) + " nullaccount"), runtime_error);
BOOST_CHECK_THROW(CallRPC("setaccount " + keyIO.EncodeDestination(setaccountDemoAddress) + " nullaccount"), runtime_error);
/* t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV is not owned by the test wallet. */
BOOST_CHECK_THROW(CallRPC("setaccount t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV nullaccount"), runtime_error);
BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
@ -136,7 +138,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
* getbalance
*********************************/
BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
BOOST_CHECK_THROW(CallRPC("getbalance " + EncodeDestination(demoAddress)), runtime_error);
BOOST_CHECK_THROW(CallRPC("getbalance " + keyIO.EncodeDestination(demoAddress)), runtime_error);
/*********************************
* listunspent
@ -178,10 +180,10 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
* listtransactions
*********************************/
BOOST_CHECK_NO_THROW(CallRPC("listtransactions"));
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress)));
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20"));
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " 20 0"));
BOOST_CHECK_THROW(CallRPC("listtransactions " + EncodeDestination(demoAddress) + " not_int"), runtime_error);
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + keyIO.EncodeDestination(demoAddress)));
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + keyIO.EncodeDestination(demoAddress) + " 20"));
BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + keyIO.EncodeDestination(demoAddress) + " 20 0"));
BOOST_CHECK_THROW(CallRPC("listtransactions " + keyIO.EncodeDestination(demoAddress) + " not_int"), runtime_error);
/*********************************
* listlockunspent
@ -218,33 +220,33 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
/* Accounts are deprecated */
BOOST_CHECK_THROW(CallRPC("getaccountaddress accountThatDoesntExists"), runtime_error);
BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
BOOST_CHECK(DecodeDestination(retValue.get_str()) == demoAddress);
BOOST_CHECK(keyIO.DecodeDestination(retValue.get_str()) == demoAddress);
/*********************************
* getaccount
*********************************/
BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
BOOST_CHECK_NO_THROW(CallRPC("getaccount " + EncodeDestination(demoAddress)));
BOOST_CHECK_NO_THROW(CallRPC("getaccount " + keyIO.EncodeDestination(demoAddress)));
/*********************************
* signmessage + verifymessage
*********************************/
BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + EncodeDestination(demoAddress) + " mymessage"));
BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + keyIO.EncodeDestination(demoAddress) + " mymessage"));
BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
/* Should throw error because this address is not loaded in the wallet */
BOOST_CHECK_THROW(CallRPC("signmessage t1h8SqgtM3QM5e2M8EzhhT1yL2PXXtA6oqe mymessage"), runtime_error);
/* missing arguments */
BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress)), runtime_error);
BOOST_CHECK_THROW(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str()), runtime_error);
BOOST_CHECK_THROW(CallRPC("verifymessage " + keyIO.EncodeDestination(demoAddress)), runtime_error);
BOOST_CHECK_THROW(CallRPC("verifymessage " + keyIO.EncodeDestination(demoAddress) + " " + retValue.get_str()), runtime_error);
/* Illegal address */
BOOST_CHECK_THROW(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1Gpg " + retValue.get_str() + " mymessage"), runtime_error);
/* wrong address */
BOOST_CHECK(CallRPC("verifymessage t1VtArtnn1dGPiD2WFfMXYXW5mHM3q1GpgV " + retValue.get_str() + " mymessage").get_bool() == false);
/* Correct address and signature but wrong message */
BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
BOOST_CHECK(CallRPC("verifymessage " + keyIO.EncodeDestination(demoAddress) + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
/* Correct address, message and signature*/
BOOST_CHECK(CallRPC("verifymessage " + EncodeDestination(demoAddress) + " " + retValue.get_str() + " mymessage").get_bool() == true);
BOOST_CHECK(CallRPC("verifymessage " + keyIO.EncodeDestination(demoAddress) + " " + retValue.get_str() + " mymessage").get_bool() == true);
/*********************************
* getaddressesbyaccount
@ -255,7 +257,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet)
BOOST_CHECK_EQUAL(4, arr.size());
bool notFound = true;
for (auto a : arr.getValues()) {
notFound &= DecodeDestination(a.get_str()) != demoAddress;
notFound &= keyIO.DecodeDestination(a.get_str()) != demoAddress;
}
BOOST_CHECK(!notFound);
@ -516,8 +518,9 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_exportwallet)
libzcash::SproutSpendingKey key;
BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, key));
std::string s1 = EncodePaymentAddress(addr);
std::string s2 = EncodeSpendingKey(key);
KeyIO keyIO(Params());
std::string s1 = keyIO.EncodePaymentAddress(addr);
std::string s2 = keyIO.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.
@ -557,11 +560,12 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
// error if too many args
BOOST_CHECK_THROW(CallRPC("z_importwallet toomany args"), runtime_error);
KeyIO keyIO(Params());
// create a random key locally
auto testSpendingKey = libzcash::SproutSpendingKey::random();
auto testPaymentAddress = testSpendingKey.address();
std::string testAddr = EncodePaymentAddress(testPaymentAddress);
std::string testKey = EncodeSpendingKey(testSpendingKey);
std::string testAddr = keyIO.EncodePaymentAddress(testPaymentAddress);
std::string testKey = keyIO.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"
@ -599,7 +603,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
BOOST_CHECK(addrs.size()==1);
// check that we have the spending key for the address
auto address = DecodePaymentAddress(testAddr);
auto address = keyIO.DecodePaymentAddress(testAddr);
BOOST_CHECK(IsValidPaymentAddress(address));
BOOST_ASSERT(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
auto addr = boost::get<libzcash::SproutPaymentAddress>(address);
@ -608,7 +612,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importwallet)
// Verify the spending key is the same as the test data
libzcash::SproutSpendingKey k;
BOOST_CHECK(pwalletMain->GetSproutSpendingKey(addr, k));
BOOST_CHECK_EQUAL(testKey, EncodeSpendingKey(k));
BOOST_CHECK_EQUAL(testKey, keyIO.EncodeSpendingKey(k));
}
@ -631,8 +635,9 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
BOOST_CHECK_THROW(CallRPC("z_exportkey toomany args"), runtime_error);
// error if invalid args
KeyIO keyIO(Params());
auto sk = libzcash::SproutSpendingKey::random();
std::string prefix = std::string("z_importkey ") + EncodeSpendingKey(sk) + " yes ";
std::string prefix = std::string("z_importkey ") + keyIO.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
@ -653,8 +658,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// create a random Sprout key locally
auto testSpendingKey = libzcash::SproutSpendingKey::random();
auto testPaymentAddress = testSpendingKey.address();
std::string testAddr = EncodePaymentAddress(testPaymentAddress);
std::string testKey = EncodeSpendingKey(testSpendingKey);
std::string testAddr = keyIO.EncodePaymentAddress(testPaymentAddress);
std::string testKey = keyIO.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);
@ -662,8 +667,8 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// create a random Sapling key locally
auto testSaplingSpendingKey = m.Derive(i);
auto testSaplingPaymentAddress = testSaplingSpendingKey.DefaultAddress();
std::string testSaplingAddr = EncodePaymentAddress(testSaplingPaymentAddress);
std::string testSaplingKey = EncodeSpendingKey(testSaplingSpendingKey);
std::string testSaplingAddr = keyIO.EncodePaymentAddress(testSaplingPaymentAddress);
std::string testSaplingKey = keyIO.EncodeSpendingKey(testSaplingSpendingKey);
BOOST_CHECK_NO_THROW(CallRPC(string("z_importkey ") + testSaplingKey));
BOOST_CHECK_NO_THROW(retValue = CallRPC(string("z_exportkey ") + testSaplingAddr));
BOOST_CHECK_EQUAL(retValue.get_str(), testSaplingKey);
@ -682,7 +687,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_importexport)
// Make new addresses for the set
for (int i=0; i<n2; i++) {
myaddrs.insert(EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey()));
myaddrs.insert(keyIO.EncodePaymentAddress(pwalletMain->GenerateNewSproutZKey()));
}
// Verify number of addresses stored in wallet is n1+n2
@ -729,17 +734,18 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_getnewaddress) {
pwalletMain->GenerateNewSeed();
}
KeyIO keyIO(Params());
// No parameter defaults to sapling address
addr = CallRPC("z_getnewaddress");
CheckHaveAddr<SaplingPaymentAddress>(DecodePaymentAddress(addr.get_str()));
CheckHaveAddr<SaplingPaymentAddress>(keyIO.DecodePaymentAddress(addr.get_str()));
// Passing 'sapling' should also work
addr = CallRPC("z_getnewaddress sapling");
CheckHaveAddr<SaplingPaymentAddress>(DecodePaymentAddress(addr.get_str()));
CheckHaveAddr<SaplingPaymentAddress>(keyIO.DecodePaymentAddress(addr.get_str()));
// Should also support sprout
addr = CallRPC("z_getnewaddress sprout");
CheckHaveAddr<SproutPaymentAddress>(DecodePaymentAddress(addr.get_str()));
CheckHaveAddr<SproutPaymentAddress>(keyIO.DecodePaymentAddress(addr.get_str()));
// Should throw on invalid argument
CheckRPCThrows("z_getnewaddress garbage", "Invalid address type");
@ -1062,7 +1068,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_parameters)
std::fill(v.begin(),v.end(), 'A');
std::string badmemo(v.begin(), v.end());
auto pa = pwalletMain->GenerateNewSproutZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
KeyIO keyIO(Params());
std::string zaddr1 = keyIO.EncodePaymentAddress(pa);
BOOST_CHECK_THROW(CallRPC(string("z_sendmany tmRr6yJonqGK23UVhrKuyvTpF8qxQQjKigJ ")
+ "[{\"address\":\"" + zaddr1 + "\", \"amount\":123.456}]"), runtime_error);
@ -1153,7 +1160,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_internals)
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
std::string taddr1 = retValue.get_str();
auto pa = pwalletMain->GenerateNewSproutZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
KeyIO keyIO(Params());
std::string zaddr1 = keyIO.EncodePaymentAddress(pa);
// there are no utxos to spend
{
@ -1351,11 +1359,12 @@ BOOST_AUTO_TEST_CASE(rpc_z_sendmany_taddr_to_sapling)
UniValue retValue;
KeyIO keyIO(Params());
// add keys manually
auto taddr = pwalletMain->GenerateNewKey().GetID();
std::string taddr1 = EncodeDestination(taddr);
std::string taddr1 = keyIO.EncodeDestination(taddr);
auto pa = pwalletMain->GenerateNewSaplingZKey();
std::string zaddr1 = EncodePaymentAddress(pa);
std::string zaddr1 = keyIO.EncodePaymentAddress(pa);
auto consensusParams = Params().GetConsensus();
retValue = CallRPC("getblockcount");
@ -1700,8 +1709,9 @@ BOOST_AUTO_TEST_CASE(rpc_z_shieldcoinbase_internals)
CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight + 1);
// Add keys manually
KeyIO keyIO(Params());
auto pa = pwalletMain->GenerateNewSproutZKey();
std::string zaddr = EncodePaymentAddress(pa);
std::string zaddr = keyIO.EncodePaymentAddress(pa);
// Insufficient funds
{
@ -1908,7 +1918,8 @@ BOOST_AUTO_TEST_CASE(rpc_z_mergetoaddress_internals)
BOOST_CHECK_NO_THROW(retValue = CallRPC("getnewaddress"));
MergeToAddressRecipient taddr1(retValue.get_str(), "");
auto pa = pwalletMain->GenerateNewSproutZKey();
MergeToAddressRecipient zaddr1(EncodePaymentAddress(pa), "DEADBEEF");
KeyIO keyIO(Params());
MergeToAddressRecipient zaddr1(keyIO.EncodePaymentAddress(pa), "DEADBEEF");
// Insufficient funds
{

View File

@ -465,9 +465,10 @@ bool CWallet::LoadCScript(const CScript& redeemScript)
/* A sanity check was added in pull #3843 to avoid adding redeemScripts
* that never can be redeemed. However, old wallets may still contain
* these. Do not add them to the wallet and warn. */
KeyIO keyIO(Params());
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
std::string strAddr = EncodeDestination(CScriptID(redeemScript));
std::string strAddr = keyIO.EncodeDestination(CScriptID(redeemScript));
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
return true;
@ -2271,13 +2272,14 @@ std::pair<SproutNotePlaintext, SproutPaymentAddress> CWalletTx::DecryptSproutNot
auto nd = this->mapSproutNoteData.at(jsop);
SproutPaymentAddress pa = nd.address;
KeyIO keyIO(Params());
// Get cached decryptor
ZCNoteDecryption decryptor;
if (!pwallet->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",
EncodePaymentAddress(pa)));
keyIO.EncodePaymentAddress(pa)));
}
auto hSig = this->vJoinSplit[jsop.js].h_sig(this->joinSplitPubKey);
@ -2294,12 +2296,12 @@ std::pair<SproutNotePlaintext, SproutPaymentAddress> CWalletTx::DecryptSproutNot
// Couldn't decrypt with this spending key
throw std::runtime_error(strprintf(
"Could not decrypt note for payment address %s",
EncodePaymentAddress(pa)));
keyIO.EncodePaymentAddress(pa)));
} catch (const std::exception &exc) {
// Unexpected failure
throw std::runtime_error(strprintf(
"Error while decrypting note for payment address %s: %s",
EncodePaymentAddress(pa), exc.what()));
keyIO.EncodePaymentAddress(pa), exc.what()));
}
}
@ -3955,22 +3957,24 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
}
NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
KeyIO keyIO(Params());
if (!fFileBacked)
return false;
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(EncodeDestination(address), strPurpose))
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(keyIO.EncodeDestination(address), strPurpose))
return false;
return CWalletDB(strWalletFile).WriteName(EncodeDestination(address), strName);
return CWalletDB(strWalletFile).WriteName(keyIO.EncodeDestination(address), strName);
}
bool CWallet::DelAddressBook(const CTxDestination& address)
{
KeyIO keyIO(Params());
{
LOCK(cs_wallet); // mapAddressBook
if(fFileBacked)
{
// Delete destdata tuples associated with address
std::string strAddress = EncodeDestination(address);
std::string strAddress = keyIO.EncodeDestination(address);
BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
{
CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
@ -3983,8 +3987,8 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
if (!fFileBacked)
return false;
CWalletDB(strWalletFile).ErasePurpose(EncodeDestination(address));
return CWalletDB(strWalletFile).EraseName(EncodeDestination(address));
CWalletDB(strWalletFile).ErasePurpose(keyIO.EncodeDestination(address));
return CWalletDB(strWalletFile).EraseName(keyIO.EncodeDestination(address));
}
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
@ -4558,7 +4562,8 @@ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, co
mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
if (!fFileBacked)
return true;
return CWalletDB(strWalletFile).WriteDestData(EncodeDestination(dest), key, value);
KeyIO keyIO(Params());
return CWalletDB(strWalletFile).WriteDestData(keyIO.EncodeDestination(dest), key, value);
}
bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
@ -4567,7 +4572,8 @@ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
return false;
if (!fFileBacked)
return true;
return CWalletDB(strWalletFile).EraseDestData(EncodeDestination(dest), key);
KeyIO keyIO(Params());
return CWalletDB(strWalletFile).EraseDestData(keyIO.EncodeDestination(dest), key);
}
bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
@ -4842,10 +4848,11 @@ bool CWallet::ParameterInteraction()
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);
KeyIO keyIO(Params());
// Check Sapling migration address if set and is a valid Sapling address
if (mapArgs.count("-migrationdestaddress")) {
std::string migrationDestAddress = mapArgs["-migrationdestaddress"];
libzcash::PaymentAddress address = DecodePaymentAddress(migrationDestAddress);
libzcash::PaymentAddress address = keyIO.DecodePaymentAddress(migrationDestAddress);
if (boost::get<libzcash::SaplingPaymentAddress>(&address) == nullptr) {
return UIError(_("-migrationdestaddress must be a valid Sapling address."));
}
@ -4957,8 +4964,9 @@ void CWallet::GetFilteredNotes(
{
std::set<PaymentAddress> filterAddresses;
KeyIO keyIO(Params());
if (address.length() > 0) {
filterAddresses.insert(DecodePaymentAddress(address));
filterAddresses.insert(keyIO.DecodePaymentAddress(address));
}
GetFilteredNotes(sproutEntries, saplingEntries, filterAddresses, minDepth, INT_MAX, ignoreSpent, requireSpendingKey);
@ -4981,6 +4989,7 @@ void CWallet::GetFilteredNotes(
{
LOCK2(cs_main, cs_wallet);
KeyIO keyIO(Params());
for (auto & p : mapWallet) {
CWalletTx wtx = p.second;
@ -5028,7 +5037,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", EncodePaymentAddress(pa)));
throw std::runtime_error(strprintf("Could not find note decryptor for payment address %s", keyIO.EncodePaymentAddress(pa)));
}
// determine amount of funds in the note
@ -5046,10 +5055,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", EncodePaymentAddress(pa)));
throw std::runtime_error(strprintf("Could not decrypt note for payment address %s", keyIO.EncodePaymentAddress(pa)));
} catch (const std::exception &exc) {
// Unexpected failure
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", EncodePaymentAddress(pa), exc.what()));
throw std::runtime_error(strprintf("Error while decrypting note for payment address %s: %s", keyIO.EncodePaymentAddress(pa), exc.what()));
}
}
@ -5236,8 +5245,9 @@ KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::InvalidEncoding&
KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
auto addr = sk.address();
KeyIO keyIO(Params());
if (log){
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(addr));
LogPrint("zrpc", "Importing zaddr %s...\n", keyIO.EncodePaymentAddress(addr));
}
if (m_wallet->HaveSproutSpendingKey(addr)) {
return KeyAlreadyExists;
@ -5252,9 +5262,10 @@ KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKe
KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
auto extfvk = sk.ToXFVK();
auto ivk = extfvk.fvk.in_viewing_key();
KeyIO keyIO(Params());
{
if (log){
LogPrint("zrpc", "Importing zaddr %s...\n", EncodePaymentAddress(sk.DefaultAddress()));
LogPrint("zrpc", "Importing zaddr %s...\n", keyIO.EncodePaymentAddress(sk.DefaultAddress()));
}
// Don't throw error in case a key is already there
if (m_wallet->HaveSaplingSpendingKey(extfvk)) {

View File

@ -458,6 +458,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
CWalletScanState &wss, string& strType, string& strErr)
{
try {
KeyIO keyIO(Params());
// Unserialize
// Taking advantage of the fact that pair serialization
// is just the two items serialized one after the other
@ -466,13 +468,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
string strAddress;
ssKey >> strAddress;
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].name;
ssValue >> pwallet->mapAddressBook[keyIO.DecodeDestination(strAddress)].name;
}
else if (strType == "purpose")
{
string strAddress;
ssKey >> strAddress;
ssValue >> pwallet->mapAddressBook[DecodeDestination(strAddress)].purpose;
ssValue >> pwallet->mapAddressBook[keyIO.DecodeDestination(strAddress)].purpose;
}
else if (strType == "tx")
{
@ -829,7 +831,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssKey >> strAddress;
ssKey >> strKey;
ssValue >> strValue;
if (!pwallet->LoadDestData(DecodeDestination(strAddress), strKey, strValue))
if (!pwallet->LoadDestData(keyIO.DecodeDestination(strAddress), strKey, strValue))
{
strErr = "Error reading wallet database: LoadDestData failed";
return false;