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

New component: zcash_address crate #352

Merged
merged 18 commits into from
Jun 6, 2021
Merged

New component: zcash_address crate #352

merged 18 commits into from
Jun 6, 2021

Conversation

str4d
Copy link
Contributor

@str4d str4d commented Mar 8, 2021

The idea is that zcash_address encapsulates parsing and serialization logic for Zcash address encodings, in such a way that downstream users:

  • get automatic parsing support for future Zcash address formats simply by upgrading the dependency;
  • get separate error messages for "invalid / unknown" vs "unsupported" addresses.
    • From past experience, these error messages are often just directly displayed to the user, so this helps to inform the user about why the address they pasted is not working.

Part of #371.

@codecov
Copy link

codecov bot commented Mar 8, 2021

Codecov Report

Merging #352 (1af7b01) into master (05bd98b) will decrease coverage by 0.29%.
The diff coverage is 36.42%.

❗ Current head 1af7b01 differs from pull request most recent head af02e11. Consider uploading reports for the commit af02e11 to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #352      +/-   ##
==========================================
- Coverage   64.46%   64.17%   -0.30%     
==========================================
  Files          73       72       -1     
  Lines        7229     7212      -17     
==========================================
- Hits         4660     4628      -32     
- Misses       2569     2584      +15     
Impacted Files Coverage Δ
components/zcash_address/src/convert.rs 0.00% <0.00%> (ø)
components/zcash_address/src/lib.rs 0.00% <0.00%> (ø)
components/zcash_address/src/encoding.rs 50.49% <50.49%> (ø)
zcash_client_backend/src/address.rs 63.15% <0.00%> (-15.79%) ⬇️
zcash_client_backend/src/zip321.rs 63.66% <0.00%> (-5.32%) ⬇️
zcash_client_sqlite/src/lib.rs 51.69% <0.00%> (-2.93%) ⬇️
zcash_primitives/src/consensus.rs 19.44% <0.00%> (-2.78%) ⬇️
...sh_primitives/src/transaction/components/amount.rs 43.75% <0.00%> (-2.09%) ⬇️
zcash_history/src/node_data.rs 64.81% <0.00%> (-1.54%) ⬇️
zcash_history/src/tree.rs 59.83% <0.00%> (-0.98%) ⬇️
... and 58 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6fab0c8...af02e11. Read the comment docs.

@r3ld3v r3ld3v added this to the Core Sprint 2021-08 milestone Mar 8, 2021
@str4d str4d marked this pull request as ready for review March 12, 2021 22:24
_ => {
// Use some heuristics to try and guess whether this might be a Zcash
// address from the future:
// - Zcash HRPs always start with a 'z'.
Copy link
Contributor

@daira daira Mar 13, 2021

Choose a reason for hiding this comment

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

It's quite possible that we may want to add transparent address formats that use bech32[m] encoding. I would suggest that we allow "t" followed by any single character as an HRP for transparent addresses.

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK.

Is it intended that this be able to parse address bundles/unified addresses? I think the API is already compatible with that.

@str4d
Copy link
Contributor Author

str4d commented Mar 27, 2021

Yes; if/when we decide to use Unified Addresses, the Orchard key type would be replaced by UA parsing and serialization.

str4d added 9 commits May 20, 2021 14:54
This provides round-trip encoding for Zcash addresses.
This enables easy conversion of an encoded Zcash address to a target
type, with automatic handling of Zcash address types that are not
supported by the target.
This places parsing documentation front and centre, while also making
it clear that `str::parse` is the anticipated main entry point.
Using two separate `impl ZcashAddress` blocks resulted in separate
blocks in the documentation, which is unnecessary.
str4d added 3 commits May 20, 2021 22:50
This commit removes the now-undefined Orchard encoding logic, and adds
the general Bech32m encoding/decoding logic for Unified Addresses. The
internal data format of Unified Addresses is not correct in this commit.
@str4d
Copy link
Contributor Author

str4d commented May 25, 2021

  • Rebased PR.
  • Removed draft Orchard address encoding (which no longer exists).
  • Added initial Unified Address encoding.
  • Removed the future-address heuristics from this PR, as we now have the Unified Address format that we plan to use going forward.

I'm not sure whether this is the ideal API now that it includes UA support; I'm going to do some more thinking about it. But this should be mergeable as-is.

@str4d str4d added this to the Core Sprint 2021-20 milestone May 25, 2021
Copy link
Contributor

@nuttycom nuttycom left a comment

Choose a reason for hiding this comment

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

I think that the point at which f4jumble is being applied in the encoding process is incorrect. Otherwise, this looks good.

fn from_sprout(net: Network, data: sprout::Data) -> Self {
ZcashAddress {
net: if let Network::Regtest = net {
Network::Test
Copy link
Contributor

Choose a reason for hiding this comment

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

Does sprout not exist on regtest or something? Why is this different from sapling? As a third-party user, I think the impls that are written like this are rather surprising; if I pass in Network::Regtest and get back Network::Test I'll be rather confused as to what's going on.

Copy link
Contributor

Choose a reason for hiding this comment

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

Addendum: I later found the comment where Network::Regtest was defined; I think that the correct thing to do is handle the network values separately at the use site, not to rewrite them in this location.

components/zcash_address/src/kind/unified.rs Outdated Show resolved Hide resolved
components/zcash_address/src/kind/unified.rs Outdated Show resolved Hide resolved
str4d added 2 commits May 25, 2021 21:24
These need to be applied to the entire UA encoding, not to the encoding
of each individual receiver.
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2021 Electric Coin Company
Copy link
Contributor

Choose a reason for hiding this comment

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

Electric Coin Company, or "Zcash developers"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ECC (matches the license text in zcash_primitives/LICENSE-MIT which is where the F4Jumble impl was moved from, and also matches ECC having copyright assignment for the rest of the code I've written in this module).

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, but it'll need to be changed as soon as we get any external contributions, unless we intend to require copyright assignment (which we don't do for any of our other MIT/Apache code).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We've been accepting external contributions for quite some time with the rest of the repo licensed in this way. If there's a change that needs making, it should be made uniformly.

Copy link
Contributor

@daira daira Jun 3, 2021

Choose a reason for hiding this comment

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

We've been accepting external contributions for quite some time with the rest of the repo licensed in this way.

I think this is violating the external contributors' copyrights, strictly speaking.

If there's a change that needs making, it should be made uniformly.

Agreed. Filed #393.

Copy link
Contributor

@nuttycom nuttycom left a comment

Choose a reason for hiding this comment

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

utACK ff94f66

use super::{Address, Receiver};

prop_compose! {
fn uniform43()(a in uniform11(0u8..), b in uniform32(0u8..)) -> [u8; 43] {
Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, this is a nice technique for larger byte arrays, I should have thought of this before! I've used vec(any::<u8>(), size) before but then had to convert.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One downside to this is the separate halves shrink separately (though that's less of an issue here given that these addresses are composite types). In theory we can implement our own custom array sizes directly, but I couldn't figure out how to set up the UniformArrayStrategy type properly.

Comment on lines +110 to +113
fn from_sprout(net: Network, data: sprout::Data) -> Self;

fn from_sapling(net: Network, data: sapling::Data) -> Self;

Copy link
Contributor

Choose a reason for hiding this comment

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

New code is ideally supposed to be constructing only unified, P2SH, and P2PKH addresses, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True; I added these for maximum compatibility (so you could replace your current parsing and serialization stack with zcash_address), but I guess until the old addresses go away, devs can use their existing serialization code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't object to including them, but let's document that they are not preferred.

unified::MAINNET => Network::Main,
unified::TESTNET => Network::Test,
unified::REGTEST => Network::Regtest,
// We will not define new Bech32m address encodings.
Copy link
Contributor

@daira daira Jun 2, 2021

Choose a reason for hiding this comment

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

I think it's possible that we will. For instance, we may find a way to reduce the overhead currently imposed by the 16 bytes of redundancy, or some other way to mitigate address replacement attacks that doesn't use F4Jumble. Or there could be some cryptographic flaw in that design that we need to fix later.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mmk, I'll remove this comment. But since there's no way to predict how we might make that kind of change, I can't do what I was previously doing (returning ParseError::MaybeZcash).

Copy link
Contributor

@daira daira Jun 3, 2021

Choose a reason for hiding this comment

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

I think that we should reserve another Bech32m HRP for such purposes (just one for each network should be sufficient).

.chain(iter::repeat(0).take(PADDING_LEN))
.collect();

f4jumble::f4jumble(&encoded).unwrap()
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe this could panic if the length of encoded were greater than 16448 bytes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently there is no way to construct a unified::Address other than decoding one (which checks the length), so this cannot panic. When we add other constructors, we can similarly enforce correctness there.

Copy link
Contributor

@daira daira left a comment

Choose a reason for hiding this comment

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

utACK modulo previous comments.

@str4d str4d merged commit 2f3e498 into zcash:master Jun 6, 2021
@str4d str4d deleted the zcash_address branch June 6, 2021 23:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants