Replace account ID with ZIP-0032 key path in listaddresses output.

Account ID information is insufficiently granular to identify separate
pools of spend authority.
This commit is contained in:
Kris Nuttycombe 2021-10-19 20:04:21 -06:00
parent dc2c07bbde
commit ebab190fdf
7 changed files with 58 additions and 38 deletions

16
Cargo.lock generated
View File

@ -534,7 +534,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]]
name = "equihash"
version = "0.1.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"blake2b_simd",
"byteorder",
@ -543,7 +543,7 @@ dependencies = [
[[package]]
name = "f4jumble"
version = "0.0.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"blake2b_simd",
]
@ -1896,7 +1896,7 @@ dependencies = [
[[package]]
name = "zcash_address"
version = "0.0.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"bech32",
"blake2b_simd",
@ -1908,7 +1908,7 @@ dependencies = [
[[package]]
name = "zcash_encoding"
version = "0.0.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"byteorder",
"nonempty",
@ -1917,7 +1917,7 @@ dependencies = [
[[package]]
name = "zcash_history"
version = "0.2.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"bigint",
"blake2b_simd",
@ -1927,7 +1927,7 @@ dependencies = [
[[package]]
name = "zcash_note_encryption"
version = "0.0.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"blake2b_simd",
"byteorder",
@ -1942,7 +1942,7 @@ dependencies = [
[[package]]
name = "zcash_primitives"
version = "0.5.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"aes",
"bip0039",
@ -1976,7 +1976,7 @@ dependencies = [
[[package]]
name = "zcash_proofs"
version = "0.5.0"
source = "git+https://github.com/nuttycom/librustzcash.git?rev=86d4affe739170ab5ed9e69f5123938d12973fde#86d4affe739170ab5ed9e69f5123938d12973fde"
source = "git+https://github.com/zcash/librustzcash.git?rev=3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12#3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12"
dependencies = [
"bellman",
"blake2b_simd",

View File

@ -71,8 +71,8 @@ codegen-units = 1
ed25519-zebra = { git = "https://github.com/ZcashFoundation/ed25519-zebra.git", rev = "d3512400227a362d08367088ffaa9bd4142a69c7" }
incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" }
orchard = { git = "https://github.com/zcash/orchard.git", rev = "2c8241f25b943aa05203eacf9905db117c69bd29" }
zcash_address = { git = "https://github.com/nuttycom/librustzcash.git", rev = "86d4affe739170ab5ed9e69f5123938d12973fde" }
zcash_history = { git = "https://github.com/nuttycom/librustzcash.git", rev = "86d4affe739170ab5ed9e69f5123938d12973fde" }
zcash_note_encryption = { git = "https://github.com/nuttycom/librustzcash.git", rev = "86d4affe739170ab5ed9e69f5123938d12973fde" }
zcash_primitives = { git = "https://github.com/nuttycom/librustzcash.git", rev = "86d4affe739170ab5ed9e69f5123938d12973fde" }
zcash_proofs = { git = "https://github.com/nuttycom/librustzcash.git", rev = "86d4affe739170ab5ed9e69f5123938d12973fde" }
zcash_address = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
zcash_history = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }
zcash_proofs = { git = "https://github.com/zcash/librustzcash.git", rev = "3d7b9dc9aa14ecc8f95ed338b2d7876fac12fd12" }

View File

@ -135,3 +135,21 @@ TEST(ZIP32, TestVectors) {
m_1_2hv_3.DefaultAddress().d,
testing::ElementsAreArray({ 0x03, 0x0f, 0xfb, 0x26, 0x3a, 0x93, 0x9e, 0x23, 0x0e, 0x96, 0xdd }));
}
TEST(ZIP32, ParseZip32KeypathAccount) {
std::string sAccount = "m/32'/1234'/5'";
EXPECT_TRUE(libzcash::ParseZip32KeypathAccount(sAccount).has_value());
EXPECT_EQ(libzcash::ParseZip32KeypathAccount(sAccount).value(), 5);
sAccount = "m/32'/1234'/50'";
EXPECT_TRUE(libzcash::ParseZip32KeypathAccount(sAccount).has_value());
EXPECT_EQ(libzcash::ParseZip32KeypathAccount(sAccount).value(), 50);
sAccount = "m/32'/1234'/5'/0";
EXPECT_TRUE(libzcash::ParseZip32KeypathAccount(sAccount).has_value());
EXPECT_EQ(libzcash::ParseZip32KeypathAccount(sAccount).value(), 5);
sAccount = "m/32'/133'/2147483646'/1";
EXPECT_TRUE(libzcash::ParseZip32KeypathAccount(sAccount).has_value());
EXPECT_EQ(libzcash::ParseZip32KeypathAccount(sAccount).value(), 2147483646);
}

View File

@ -334,7 +334,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
" },\n"
" \"sapling\": [ -- each element in this list represents a set of diversified addresses derived from a single IVK. \n"
" {\n"
" \"zip32AccountId\": 0, -- optional field, not present for imported/watchonly sources,\n"
" \"zip32KeyPath\": \"m/32'/133'/0'\", -- optional field, not present for imported/watchonly sources,\n"
" \"addresses\": [\n"
" \"ztbx5DLDxa5ZLFTchHhoPNkKs57QzSyib6UqXpEdy76T1aUdFxJt1w9318Z8DJ73XzbnWHKEZP9Yjg712N5kMmP4QzS9iC9\",\n"
" ...\n"
@ -477,12 +477,10 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
UniValue sapling_obj(UniValue::VOBJ);
if (source == LegacyHDSeed) {
std::string hdKeypath = pwalletMain->mapSaplingZKeyMetadata[ivk].hdKeypath;
std::optional<unsigned long> accountId = libzcash::ParseZip32KeypathAccount(hdKeypath);
if (accountId.has_value()) {
sapling_obj.pushKV("zip32AccountId", (uint64_t) accountId.value());
if (source == LegacyHDSeed || source == MnemonicHDSeed) {
std::string hdKeyPath = pwalletMain->mapSaplingZKeyMetadata[ivk].hdKeypath;
if (hdKeyPath != "") {
sapling_obj.pushKV("zip32KeyPath", hdKeyPath);
}
}

View File

@ -831,34 +831,34 @@ BOOST_AUTO_TEST_CASE(rpc_wallet_z_getnewaddress) {
auto listarr = list.get_array();
bool sproutCountMatch = false;
bool saplingExtfvksMatch = false;
bool saplingAccount0 = false;
bool saplingAccount1 = false;
bool saplingSpendAuth0 = false;
bool saplingSpendAuth1 = false;
bool saplingCountMismatch = true;
for (auto a : listarr.getValues()) {
auto source = find_value(a.get_obj(), "source");
if (source.get_str() == "legacy_random") {
auto sprout_obj = find_value(a.get_obj(), "sprout").get_obj();
auto sprout_addrs = find_value(sprout_obj, "addresses").get_array();
sproutCountMatch = (sprout_addrs.size() == 1);
auto sproutObj = find_value(a.get_obj(), "sprout").get_obj();
auto sproutAddrs = find_value(sproutObj, "addresses").get_array();
sproutCountMatch = (sproutAddrs.size() == 1);
}
if (source.get_str() == "legacy_hdseed") {
auto sapling_addr_sets = find_value(a.get_obj(), "sapling").get_array();
saplingExtfvksMatch = (sapling_addr_sets.size() == 2);
for (auto sapling_obj : sapling_addr_sets.getValues()) {
auto sapling_account = find_value(sapling_obj, "zip32AccountId").get_int();
saplingAccount0 |= (sapling_account == 0);
saplingAccount1 |= (sapling_account == 1);
auto sapling_addrs = find_value(sapling_obj, "addresses").get_array();
saplingCountMismatch &= (sapling_addrs.size() != 1);
for (auto saplingObj : sapling_addr_sets.getValues()) {
auto keypath = find_value(saplingObj, "zip32KeyPath").get_str();
saplingSpendAuth0 |= (keypath == "m/32'/133'/2147483646'/0");
saplingSpendAuth1 |= (keypath == "m/32'/133'/2147483646'/1");
auto saplingAddrs = find_value(saplingObj, "addresses").get_array();
saplingCountMismatch &= (saplingAddrs.size() != 1);
}
}
}
BOOST_CHECK(sproutCountMatch);
BOOST_CHECK(saplingExtfvksMatch);
BOOST_CHECK(!saplingCountMismatch);
BOOST_CHECK(saplingAccount0);
BOOST_CHECK(saplingAccount1);
BOOST_CHECK(saplingSpendAuth0);
BOOST_CHECK(saplingSpendAuth1);
}
}

View File

@ -124,10 +124,10 @@ std::optional<SaplingPaymentAddress> CWallet::GenerateNewLegacySaplingZKey() {
auto seedOpt = GetMnemonicSeed();
if (seedOpt.has_value()) {
auto seed = seedOpt.value();
if (!legacyHDChain.has_value()) {
legacyHDChain = CHDChain(seed.Fingerprint(), GetTime());
if (!mnemonicHDChain.has_value()) {
mnemonicHDChain = CHDChain(seed.Fingerprint(), GetTime());
}
CHDChain& hdChain = legacyHDChain.value();
CHDChain& hdChain = mnemonicHDChain.value();
// loop until we find an unused address index
while (true) {
@ -249,8 +249,12 @@ std::optional<CPubKey> CWallet::GenerateNewKey()
{
AssertLockHeld(cs_wallet); // mapKeyMetadata
auto seedOpt = GetMnemonicSeed();
CHDChain& hdChain = mnemonicHDChain.value();
if (seedOpt.has_value()) {
if (!mnemonicHDChain.has_value()) {
mnemonicHDChain = CHDChain(seedOpt.value().Fingerprint(), GetTime());
}
CHDChain& hdChain = mnemonicHDChain.value();
// All mnemonic seeds are checked at construction to ensure that we can obtain
// a valid spending key for the account ZCASH_LEGACY_ACCOUNT;
// therefore, the `value()` call here is safe.

View File

@ -378,7 +378,7 @@ std::optional<ZcashdUnifiedAddress> UnifiedFullViewingKey::Address(diversifier_i
}
std::optional<unsigned long> ParseZip32KeypathAccount(const std::string& keyPath) {
std::regex pattern("m/32'/[0-9]+'/([0-9]+)'");
std::regex pattern("m/32'/[0-9]+'/([0-9]+)'.*");
std::smatch matches;
if (std::regex_match(keyPath, matches, pattern)) {
return stoul(matches[1]);