Add Sapling support to z_validateaddress

This commit is contained in:
Jack Grigg 2018-06-12 22:25:07 +12:00
parent 579ad3b13e
commit bea879157c
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829
2 changed files with 64 additions and 22 deletions

View File

@ -206,6 +206,43 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
} }
class DescribePaymentAddressVisitor : public boost::static_visitor<UniValue>
{
public:
UniValue operator()(const libzcash::InvalidEncoding &zaddr) const { return UniValue(UniValue::VOBJ); }
UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("type", "sprout"));
obj.push_back(Pair("payingkey", zaddr.a_pk.GetHex()));
obj.push_back(Pair("transmissionkey", zaddr.pk_enc.GetHex()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.push_back(Pair("ismine", pwalletMain->HaveSpendingKey(zaddr)));
}
#endif
return obj;
}
UniValue operator()(const libzcash::SaplingPaymentAddress &zaddr) const {
UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("type", "sapling"));
obj.push_back(Pair("diversifier", HexStr(zaddr.d)));
obj.push_back(Pair("diversifiedtransmissionkey", zaddr.pk_d.GetHex()));
#ifdef ENABLE_WALLET
if (pwalletMain) {
libzcash::SaplingIncomingViewingKey ivk;
libzcash::SaplingFullViewingKey fvk;
bool isMine = pwalletMain->GetSaplingIncomingViewingKey(zaddr, ivk) &&
pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
pwalletMain->HaveSaplingSpendingKey(fvk);
obj.push_back(Pair("ismine", isMine));
}
#endif
return obj;
}
};
UniValue z_validateaddress(const UniValue& params, bool fHelp) UniValue z_validateaddress(const UniValue& params, bool fHelp)
{ {
if (fHelp || params.size() != 1) if (fHelp || params.size() != 1)
@ -218,9 +255,12 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp)
"{\n" "{\n"
" \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
" \"address\" : \"zaddr\", (string) The z address validated\n" " \"address\" : \"zaddr\", (string) The z address validated\n"
" \"type\" : \"xxxx\", (string) \"sprout\" or \"sapling\"\n"
" \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
" \"payingkey\" : \"hex\", (string) The hex value of the paying key, a_pk\n" " \"payingkey\" : \"hex\", (string) [sprout] The hex value of the paying key, a_pk\n"
" \"transmissionkey\" : \"hex\", (string) The hex value of the transmission key, pk_enc\n" " \"transmissionkey\" : \"hex\", (string) [sprout] The hex value of the transmission key, pk_enc\n"
" \"diversifier\" : \"hex\", (string) [sapling] The hex value of the diversifier, d\n"
" \"diversifiedtransmissionkey\" : \"hex\", (string) [sapling] The hex value of pk_d\n"
"}\n" "}\n"
"\nExamples:\n" "\nExamples:\n"
@ -235,34 +275,17 @@ UniValue z_validateaddress(const UniValue& params, bool fHelp)
LOCK(cs_main); LOCK(cs_main);
#endif #endif
bool isMine = false;
std::string payingKey, transmissionKey;
string strAddress = params[0].get_str(); string strAddress = params[0].get_str();
auto address = DecodePaymentAddress(strAddress); auto address = DecodePaymentAddress(strAddress);
bool isValid = IsValidPaymentAddress(address); bool isValid = IsValidPaymentAddress(address);
if (isValid) {
// TODO: Add Sapling support
assert(boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr);
libzcash::SproutPaymentAddress addr = boost::get<libzcash::SproutPaymentAddress>(address);
#ifdef ENABLE_WALLET
isMine = pwalletMain->HaveSpendingKey(addr);
#endif
payingKey = addr.a_pk.GetHex();
transmissionKey = addr.pk_enc.GetHex();
}
UniValue ret(UniValue::VOBJ); UniValue ret(UniValue::VOBJ);
ret.push_back(Pair("isvalid", static_cast<bool>(isValid))); ret.push_back(Pair("isvalid", isValid));
if (isValid) if (isValid)
{ {
ret.push_back(Pair("address", strAddress)); ret.push_back(Pair("address", strAddress));
ret.push_back(Pair("payingkey", payingKey)); UniValue detail = boost::apply_visitor(DescribePaymentAddressVisitor(), address);
ret.push_back(Pair("transmissionkey", transmissionKey)); ret.pushKVs(detail);
#ifdef ENABLE_WALLET
ret.push_back(Pair("ismine", isMine));
#endif
} }
return ret; return ret;
} }

View File

@ -359,6 +359,7 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress)
resultObj = retValue.get_obj(); resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool(); b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, true); BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
b = find_value(resultObj, "ismine").get_bool(); b = find_value(resultObj, "ismine").get_bool();
BOOST_CHECK_EQUAL(b, false); BOOST_CHECK_EQUAL(b, false);
@ -368,10 +369,28 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_validateaddress)
resultObj = retValue.get_obj(); resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool(); b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, true); BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sprout");
b = find_value(resultObj, "ismine").get_bool(); b = find_value(resultObj, "ismine").get_bool();
BOOST_CHECK_EQUAL(b, true); BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad"); BOOST_CHECK_EQUAL(find_value(resultObj, "payingkey").get_str(), "f5bb3c888ccc9831e3f6ba06e7528e26a312eec3acc1823be8918b6a3a5e20ad");
BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a"); BOOST_CHECK_EQUAL(find_value(resultObj, "transmissionkey").get_str(), "7a58c7132446564e6b810cf895c20537b3528357dc00150a8e201f491efa9c1a");
// This Sapling address is not valid, it belongs to another network
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress ztestsapling1knww2nyjc62njkard0jmx7hlsj6twxmxwprn7anvrv4dc2zxanl3nemc0qx2hvplxmd2uau8gyw"));
resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, false);
// This Sapling address is valid, but the spending key is not in this wallet
BOOST_CHECK_NO_THROW(retValue = CallRPC("z_validateaddress zs1z7rejlpsa98s2rrrfkwmaxu53e4ue0ulcrw0h4x5g8jl04tak0d3mm47vdtahatqrlkngh9slya"));
resultObj = retValue.get_obj();
b = find_value(resultObj, "isvalid").get_bool();
BOOST_CHECK_EQUAL(b, true);
BOOST_CHECK_EQUAL(find_value(resultObj, "type").get_str(), "sapling");
b = find_value(resultObj, "ismine").get_bool();
BOOST_CHECK_EQUAL(b, false);
BOOST_CHECK_EQUAL(find_value(resultObj, "diversifier").get_str(), "1787997c30e94f050c634d");
BOOST_CHECK_EQUAL(find_value(resultObj, "diversifiedtransmissionkey").get_str(), "34ed1f60f5db5763beee1ddbb37dd5f7e541d4d4fbdcc09fbfcc6b8e949bbe9d");
} }
/* /*