Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sapling support to z_importkey, z_exportkey #3392

Merged
merged 4 commits into from
Jul 30, 2018

Conversation

arcalinea
Copy link
Contributor

Add Sapling support to z_importkey and z_exportkey

@arcalinea arcalinea added A-wallet Area: Wallet A-rpc-interface Area: RPC interface NU1-sapling Network upgrade: Sapling-specific tasks labels Jul 12, 2018
@arcalinea arcalinea added this to the v2.0.0 milestone Jul 12, 2018
@arcalinea arcalinea self-assigned this Jul 12, 2018
}

return EncodeSpendingKey(sk);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move all this into a boost::static_visitor<SpendingKey>. See #3345 for an example. Then this function would become:

...
    auto sk = boost::apply_visitor(GetSpendingKeyForPaymentAddress(pwalletMain), address);
    return EncodeSpendingKey(sk);
}

It should be fine to throw inside the visitor.

return NullUniValue;
// Sapling support
bool isValidKey = boost::get<libzcash::SproutSpendingKey>(&spendingkey) != nullptr || boost::get<libzcash::SaplingSpendingKey>(&spendingkey) != nullptr;
assert(isValidKey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's already an IsValidSpendingKey(spendingkey) check above here, so these two lines can be removed.

if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
} else {
auto sk = boost::get<libzcash::SaplingSpendingKey>(spendingkey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move these sections into a boost::static_visitor<bool>, with the boolean indicating whether we should return early (from inside the fIgnoreExistingKey check). This function would become:

...
auto keyExists = boost::apply_visitor(AddSpendingKeyToWallet(pwalletMain), spendingkey);
if (keyExists) {
    return NullUniValue;
}
// whenever a key is imported, ...
...

return EncodeSpendingKey(k);
// Sapling support
bool isValidAddr = boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr || boost::get<libzcash::SaplingPaymentAddress>(&address) != nullptr;
assert(isValidAddr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's already an IsValidPayamentAddress(address) check above here, so these two lines can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But despite that, there was an assert there before that address was not nullptr. Why should we remove it now?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert was there specifically so that we would get a crash if someone tried to use a Sapling address before support was added. Now that GetSpendingKeyForPaymentAddress is implemented, we don't need these explicit nullptr checks, because if we ever add a new address type, all the boost::static_visitors will immediately start complaining that they aren't covering all cases 🙂

So please remove these two lines.

Copy link
Contributor

@str4d str4d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The removal of the nullptr checks is blocking.

throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet");
}

m_wallet->mapSaplingZKeyMetadata[addr].nCreateTime = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we should think about how this metadata is used, and whether it should index on addr or fvk.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will it still be used on addresses? Not a lot of instances in the code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this data is stored in order to figure out when rescanning how many blocks can be skipped (that won't contain transactions for any of the known addresses). So I think it makes sense to store SaplingFullViewingKey instead of SaplingPaymentAddress, as fvk uniquely corresponds to the key that will be used to scan (both for incoming transactions, and in future for recovering outgoing transaction data). However, this is entirely an in-memory decision, so we can just make an issue, and handle it later (when we update ScanForWalletTransactions() to catch all Sapling (and Sprout) transactions without needing to reindex).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed issue

}
}

bool operator()(const libzcash::InvalidEncoding& no) const { return true; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably fine; or you could throw an error here (this case should never be triggered, as we call IsValidSpendingKey() first which ensures that spendingkey is not an InvalidEncoding, so getting here would be an implementation error).

return EncodeSpendingKey(k);
// Sapling support
bool isValidAddr = boost::get<libzcash::SproutPaymentAddress>(&address) != nullptr || boost::get<libzcash::SaplingPaymentAddress>(&address) != nullptr;
assert(isValidAddr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert was there specifically so that we would get a crash if someone tried to use a Sapling address before support was added. Now that GetSpendingKeyForPaymentAddress is implemented, we don't need these explicit nullptr checks, because if we ever add a new address type, all the boost::static_visitors will immediately start complaining that they aren't covering all cases 🙂

So please remove these two lines.

@mdr0id mdr0id requested a review from gtank July 23, 2018 18:29
Copy link
Contributor

@str4d str4d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash the final cleanup commit into the second-to-last commit. Otherwise, ACK 🙂

throw JSONRPCError(RPC_WALLET_ERROR, "Error adding spending key to wallet");
}

m_wallet->mapSaplingZKeyMetadata[addr].nCreateTime = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, this data is stored in order to figure out when rescanning how many blocks can be skipped (that won't contain transactions for any of the known addresses). So I think it makes sense to store SaplingFullViewingKey instead of SaplingPaymentAddress, as fvk uniquely corresponds to the key that will be used to scan (both for incoming transactions, and in future for recovering outgoing transaction data). However, this is entirely an in-memory decision, so we can just make an issue, and handle it later (when we update ScanForWalletTransactions() to catch all Sapling (and Sprout) transactions without needing to reindex).

@bitcartel
Copy link
Contributor

@arcalinea I'm reviewing right now; can you push the cleanup per @str4d's review? Thanks.

@bitcartel bitcartel force-pushed the sapling_z_importexport_keys branch from a728d52 to 501de64 Compare July 30, 2018 01:46
Copy link
Contributor

@bitcartel bitcartel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I squashed the last two commits into one per str4d's review comment, rebased on master (clean) and force pushed.

@bitcartel
Copy link
Contributor

@zkbot r+

@zkbot
Copy link
Contributor

zkbot commented Jul 30, 2018

📌 Commit 501de64 has been approved by bitcartel

@zkbot
Copy link
Contributor

zkbot commented Jul 30, 2018

⌛ Testing commit 501de64 with merge 28a8d1d...

zkbot added a commit that referenced this pull request Jul 30, 2018
Add Sapling support to z_importkey, z_exportkey

Add Sapling support to `z_importkey` and `z_exportkey`
@zkbot
Copy link
Contributor

zkbot commented Jul 30, 2018

☀️ Test successful - pr-merge
Approved by: bitcartel
Pushing 28a8d1d to master...

@zkbot zkbot merged commit 501de64 into zcash:master Jul 30, 2018
@str4d str4d mentioned this pull request Jul 30, 2018
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-rpc-interface Area: RPC interface A-wallet Area: Wallet NU1-sapling Network upgrade: Sapling-specific tasks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants