Browse Source

Add Sapling support to z_getnewaddress and z_listaddresses

pull/4/head
Jack Grigg 6 years ago
parent
commit
eec85c4388
No known key found for this signature in database GPG Key ID: 1B8D649257DB0829
  1. 1
      qa/pull-tester/rpc-tests.sh
  2. 85
      qa/rpc-tests/wallet_addresses.py
  3. 61
      src/wallet/rpcwallet.cpp

1
qa/pull-tester/rpc-tests.sh

@ -23,6 +23,7 @@ testScripts=(
'wallet_overwintertx.py'
'wallet_nullifiers.py'
'wallet_1941.py'
'wallet_addresses.py'
'listtransactions.py'
'mempool_resurrect_test.py'
'txn_doublespend.py'

85
qa/rpc-tests/wallet_addresses.py

@ -0,0 +1,85 @@
#!/usr/bin/env python2
# Copyright (c) 2018 The Zcash developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal, start_nodes
# Test wallet address behaviour across network upgradesa\
class WalletAddressesTest(BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, [[
'-nuparams=5ba81b19:202', # Overwinter
'-nuparams=76b809bb:204', # Sapling
]] * 4)
def run_test(self):
def addr_checks(default_type):
# Check default type
addr = self.nodes[0].z_getnewaddress()
res = self.nodes[0].z_validateaddress(addr)
assert(res['isvalid'])
assert(res['ismine'])
assert_equal(res['type'], default_type)
assert(addr in self.nodes[0].z_listaddresses())
# Check explicit Sprout type
addr = self.nodes[0].z_getnewaddress('sprout')
res = self.nodes[0].z_validateaddress(addr)
assert(res['isvalid'])
assert(res['ismine'])
assert_equal(res['type'], 'sprout')
assert(addr in self.nodes[0].z_listaddresses())
# Check explicit Sapling type
addr = self.nodes[0].z_getnewaddress('sapling')
res = self.nodes[0].z_validateaddress(addr)
assert(res['isvalid'])
assert(res['ismine'])
assert_equal(res['type'], 'sapling')
assert(addr in self.nodes[0].z_listaddresses())
# Sanity-check the test harness
assert_equal(self.nodes[0].getblockcount(), 200)
# Current height = 200 -> Sprout
# Default address type is Sprout
print "Testing height 200 (Sprout)"
addr_checks('sprout')
self.nodes[0].generate(1)
self.sync_all()
# Current height = 201 -> Sprout
# Default address type is Sprout
print "Testing height 201 (Sprout)"
addr_checks('sprout')
self.nodes[0].generate(1)
self.sync_all()
# Current height = 202 -> Overwinter
# Default address type is Sprout
print "Testing height 202 (Overwinter)"
addr_checks('sprout')
self.nodes[0].generate(1)
self.sync_all()
# Current height = 203 -> Overwinter
# Default address type is Sprout
print "Testing height 203 (Overwinter)"
addr_checks('sprout')
self.nodes[0].generate(1)
self.sync_all()
# Current height = 204 -> Sapling
# Default address type is Sprout
print "Testing height 204 (Sapling)"
addr_checks('sprout')
if __name__ == '__main__':
WalletAddressesTest().main()

61
src/wallet/rpcwallet.cpp

@ -42,6 +42,9 @@ using namespace std;
using namespace libzcash;
const std::string ADDR_TYPE_SPROUT = "sprout";
const std::string ADDR_TYPE_SAPLING = "sapling";
extern UniValue TxJoinSplitToJSON(const CTransaction& tx);
int64_t nWalletUnlockTime;
@ -3100,15 +3103,21 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
if (!EnsureWalletIsAvailable(fHelp))
return NullUniValue;
if (fHelp || params.size() > 0)
std::string defaultType = ADDR_TYPE_SPROUT;
if (fHelp || params.size() > 1)
throw runtime_error(
"z_getnewaddress\n"
"\nReturns a new zaddr for receiving payments.\n"
"z_getnewaddress ( type )\n"
"\nReturns a new shielded address for receiving payments.\n"
"\nWith no arguments, returns a Sprout address.\n"
"\nArguments:\n"
"1. \"type\" (string, optional, default=\"" + defaultType + "\") The type of address. One of [\""
+ ADDR_TYPE_SPROUT + "\", \"" + ADDR_TYPE_SAPLING + "\"].\n"
"\nResult:\n"
"\"zcashaddress\" (string) The new zaddr\n"
"\"zcashaddress\" (string) The new shielded address.\n"
"\nExamples:\n"
+ HelpExampleCli("z_getnewaddress", "")
+ HelpExampleCli("z_getnewaddress", ADDR_TYPE_SAPLING)
+ HelpExampleRpc("z_getnewaddress", "")
);
@ -3116,8 +3125,18 @@ UniValue z_getnewaddress(const UniValue& params, bool fHelp)
EnsureWalletIsUnlocked();
auto zaddr = pwalletMain->GenerateNewZKey();
return EncodePaymentAddress(zaddr);
auto addrType = defaultType;
if (params.size() > 0) {
addrType = params[0].get_str();
}
if (addrType == ADDR_TYPE_SPROUT) {
return EncodePaymentAddress(pwalletMain->GenerateNewZKey());
} else if (addrType == ADDR_TYPE_SAPLING) {
return EncodePaymentAddress(pwalletMain->GenerateNewSaplingZKey());
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid address type");
}
}
@ -3129,7 +3148,7 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
if (fHelp || params.size() > 1)
throw runtime_error(
"z_listaddresses ( includeWatchonly )\n"
"\nReturns the list of zaddr belonging to the wallet.\n"
"\nReturns the list of Sprout and Sapling shielded addresses belonging to the wallet.\n"
"\nArguments:\n"
"1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
"\nResult:\n"
@ -3150,12 +3169,28 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
}
UniValue ret(UniValue::VARR);
// TODO: Add Sapling support
std::set<libzcash::SproutPaymentAddress> addresses;
pwalletMain->GetPaymentAddresses(addresses);
for (auto addr : addresses ) {
if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
ret.push_back(EncodePaymentAddress(addr));
{
std::set<libzcash::SproutPaymentAddress> addresses;
pwalletMain->GetPaymentAddresses(addresses);
for (auto addr : addresses ) {
if (fIncludeWatchonly || pwalletMain->HaveSpendingKey(addr)) {
ret.push_back(EncodePaymentAddress(addr));
}
}
}
{
std::set<libzcash::SaplingPaymentAddress> addresses;
pwalletMain->GetSaplingPaymentAddresses(addresses);
libzcash::SaplingIncomingViewingKey ivk;
libzcash::SaplingFullViewingKey fvk;
for (auto addr : addresses ) {
if (fIncludeWatchonly || (
pwalletMain->GetSaplingIncomingViewingKey(addr, ivk) &&
pwalletMain->GetSaplingFullViewingKey(ivk, fvk) &&
pwalletMain->HaveSaplingSpendingKey(fvk)
)) {
ret.push_back(EncodePaymentAddress(addr));
}
}
}
return ret;

Loading…
Cancel
Save