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 Hash256 associated type #434

Merged
merged 3 commits into from
Jun 21, 2022
Merged

Conversation

sanket1729
Copy link
Member

  • Implement a new hash type that does not display/FromStr with DISPLAY_BACKWARD. Should we make this type upstream in bitcoin-hashes?
  • Remove the PkTranslator trait as it was causing conflicting implementations downstream.
  • Replace the above with more macros :(

@apoelstra
Copy link
Member

@sipa in your miniscript implementation, do you serialize hashes (e.g. in sha256(...) fragments) forward or backward?

@sipa
Copy link

sipa commented Jun 15, 2022

@apoelstra They're treated as byte arrays, so the order of 2-character-hex units is the same as the order of the bytes as they appear in the script.

@apoelstra
Copy link
Member

Perfect, thank you!

@apoelstra
Copy link
Member

Done reviewing 4ffabb7. ACK except for the one nit.

Arguably this should be two PRs -- the hash256 stuff in the first two commits looks unobjectionable (and it's not even breaking, since amusingly we previously had a shitload of manual byte-reversing logic..). The second two are potentially more controversial, since we introduce a macro-based API to simulate a trait hierarchy. Given the limitations of Rust's type system, I think this is the right approach, but it's definitely not a great user experience to need to know about these macros.... I guess we will just have to be careful to document them well.

nit: there are a typos in the last two commit messages

@apoelstra apoelstra closed this Jun 15, 2022
@apoelstra apoelstra reopened this Jun 15, 2022
@apoelstra
Copy link
Member

sorry, tried to click "comment" while scratching my arm and the mouse moved.

@sanket1729
Copy link
Member Author

@apoelstra split into two PRs.

The second two are potentially more controversial, since we introduce a macro-based API to simulate a trait hierarchy. Given the limitations of Rust's type system, I think this is the right approach, but it's definitely not a great user experience to need to know about these macros. I guess we will just have to be careful to document them well.

I will document them more carefully in the upcoming PR and will add a macro exporting. My plan is to add an example using the API after we are merged all the associated fields (ripemd160/hash160/older/after).

The users don't have to know about them, they still implement all of the methods, but it's annoying.

@sanket1729
Copy link
Member Author

The nightly formatter had configuration errors that were fixed in the first commit.

@sanket1729
Copy link
Member Author

@tcharding, it occurs to me that if rustfmt is breaking(two times now) in nightly. Perhaps we should switch to stable? Are the benefits of nightly worth it over stable?

We can give it a try for a few more weeks to test the stability. If it breaks again, we should consider moving back to the stable version.

@sanket1729 sanket1729 force-pushed the hash256 branch 2 times, most recently from 74392eb to b9f7a63 Compare June 15, 2022 22:01
@tcharding
Copy link
Member

tcharding commented Jun 16, 2022

@tcharding, it occurs to me that if rustfmt is breaking(two times now) in nightly. Perhaps we should switch to stable? Are the benefits of nightly worth it over stable?

The reason we moved to nightly was that many of the config options are not available on stable. With the current contention over using rustfmt in rust-bitcoin we need the nightly config options if we are to have any hope of enabling rustfmt there.

I do not think that 'breaking' is the correct term, rustfmt nighltly changes and our config file needed updating.

I have two suggestions

  1. Use a fixed version of nightly on CI and then update it manually periodically
  2. Every time rustfmt changes do a PR to fix it

I like (1) because I can do it as part of my routine work and then others are not inconvenienced by rustfmt. Devs could see the CI verison used and use the same one locally (if I can figure out an easy way to do so).

We can give it a try for a few more weeks to test the stability. If it breaks again, we should consider moving back to the stable version.

I think I answered this above, are you open to the suggestions? Sorry that rust-miniscript is taking a hit here because of rust-bitcoin.

@sanket1729
Copy link
Member Author

I like (1) because I can do it as part of my routine work and then others are not inconvenienced by rustfmt.

Thanks. I like (1) too. We are in agreement with the next steps.

Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

This can be rebased now that #424 has merged (the first 5 patches of this PR).

I'd prefer to see the rustfmt stuff as a separate PR so other open PRs could use it, I imagine everyone is going to have red in the CI pipeline because of this but its not that big a deal.

High level comment: seems like this DISPLAY_BACKWARDS const makes the types in bitcoin_hashes less usable. Perhaps it should be a field on the type so users can control the direction of the output? I had to hack around it once recently also.

Comment on lines 31 to 33
feature = "schemars",
schemars(schema_with = "crate::util::json_hex_string::len_32")
)]
Copy link
Member

Choose a reason for hiding this comment

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

We don't have schemars dependency, did you mean to add it? Will need the module in bitcoin_hashes/src/util.rs as well.

Copy link
Member

Choose a reason for hiding this comment

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

This is a fail in the tooling, compiler does not flag this and neither does clippy.

Copy link
Member Author

Choose a reason for hiding this comment

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

Wow, embarrassing copy-paste error here.

Copy link
Member

Choose a reason for hiding this comment

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

Lol, I should've also flagged this in review rather than shrugging "I guess we capitulated about supporting schemars at some point"

src/lib.rs Outdated
@@ -159,13 +159,18 @@ pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Ha
/// Used in the sha256 fragment
type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

/// The associated [`hash256::Hash`] type for this [`MiniscriptKey`] type.
/// Used in the sha256 fragment
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Used in the sha256 fragment
/// The associated [`hash256::Hash`] for this `MiniscriptKey`, used in the hash256 fragment.

If this form is agreeably, then could use it for the comment on Sha256 also.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@@ -43,6 +43,15 @@ impl Translator<String, bitcoin::PublicKey, ()> for StrKeyTranslator {
.unwrap();
Ok(hash)
}

fn hash256(&mut self, _hash256: &String) -> Result<hash256::Hash, ()> {
// hard coded value
Copy link
Member

Choose a reason for hiding this comment

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

This comment adds no value, we can see its a hard coded value. Perhaps comment why this value is used or don't comment at all.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removing the comment

x.reverse();
write!(f, "hash256({})", sha256d::Hash::from_inner(x))
}
Terminal::Hash256(ref h) => write!(f, "hash256({})", h), // reverse would handled correctly by rust-bitcoin
Copy link
Member

Choose a reason for hiding this comment

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

This comment is incorrect, right? We are handling the display here in this lib now, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, this comment is incorrect. Thanks for catching this!

x.reverse();
write!(f, "hash256({})", sha256d::Hash::from_inner(x))
}
Terminal::Hash256(ref h) => write!(f, "hash256({})", h), // reverse correctly handled upstream
Copy link
Member

Choose a reason for hiding this comment

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

And this one?

/// The associated [`hash256::Hash`] type for this [`MiniscriptKey`] type.
/// Used in the sha256 fragment
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

Copy link
Member

Choose a reason for hiding this comment

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

re: Hash, Sha256, and Hash256

From the docs on the trait its not really clear, at least to me, what is the relation between these three types. Two of them are named after fragments but one is not and they are all 'hashes' but there are other hash fragments as well. Can be add some documentation to try and help devs (cough me) to understand this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, this is indeed clarification now that we have multiple hashes. I will add some clarification here.

Copy link
Member

Choose a reason for hiding this comment

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

Sha256 and Hash256 are two of the five hash types supported by Script (the others are Sha1 (not supported by miniscript), Ripemd160 and Hash160). Meanwhile Hash is a trait from bitcoin_hashes which abstracts over all of these and allows feeding data into it.

(IIRC Hash is basically just a copy of io::Write but io::Write is std-only, for unclear reasons.)

Copy link
Member Author

Choose a reason for hiding this comment

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

@apoelstra , I think the Hash is @tcharding is talking about here is MiniscirptKey::Hash which is different from bitcoin_hashes::Hash.

The Hash represents the associated type corresponding to PkH fragment. Perhaps, with multiple hashes in the picture and considering #431 we should rename that to RawPkHash?

I think we should re-evaluate whether we even need a Pk::Hash type anymore. That can be useful for abstractions over RawPkH in the future when we have partial descriptors.

We can consider renaming that as a part of a separate PR.

Comment on lines 17 to 18
//! Functionality similar to `sha256d` Hash type in bitcoin, but the FromStr
//! `Display` are *NOT* REVERSE.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
//! Functionality similar to `sha256d` Hash type in bitcoin, but the FromStr
//! `Display` are *NOT* REVERSE.
//! This module is _identical_ in functionality to the `bitcoin_hashes::sha256d` hash type
//! but the `FromHex` and `ToHex` implementations use `DISPLAY_BACKWARDS = false`.

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed and also added a comment about FromStr and Display

@tcharding
Copy link
Member

Hey man, I'm not sure what the force push means, did you think this is ready for re-review? The schemars stuff is still in there.

@sanket1729 sanket1729 force-pushed the hash256 branch 2 times, most recently from f9f3e56 to 3685071 Compare June 17, 2022 02:16
Copy link
Member Author

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

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

Sorry about the previous push. This is ready for review now @tcharding

/// The associated [`hash256::Hash`] type for this [`MiniscriptKey`] type.
/// Used in the sha256 fragment
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;

Copy link
Member Author

Choose a reason for hiding this comment

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

@apoelstra , I think the Hash is @tcharding is talking about here is MiniscirptKey::Hash which is different from bitcoin_hashes::Hash.

The Hash represents the associated type corresponding to PkH fragment. Perhaps, with multiple hashes in the picture and considering #431 we should rename that to RawPkHash?

I think we should re-evaluate whether we even need a Pk::Hash type anymore. That can be useful for abstractions over RawPkH in the future when we have partial descriptors.

We can consider renaming that as a part of a separate PR.

@@ -43,6 +43,15 @@ impl Translator<String, bitcoin::PublicKey, ()> for StrKeyTranslator {
.unwrap();
Ok(hash)
}

fn hash256(&mut self, _hash256: &String) -> Result<hash256::Hash, ()> {
// hard coded value
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing the comment

@sanket1729
Copy link
Member Author

@apoelstra, let's try to merge #431 before this.

@apoelstra
Copy link
Member

Yeah, renaming MiniscriptKey::Hash sounds like a good idea :)

@sanket1729
Copy link
Member Author

@apoelstra, we could also remove the MiniscriptKey::RawPkH completely. And make it fixed hash160::Hash. I don't see any specific reason why we would want to reason about raw things in an abstract.

But on the other hand, we already have the code. So part of me wants to keep it in case we need it in the future after partial descriptors are officially supported.

@apoelstra
Copy link
Member

Yeah, let's keep it for now.

@sanket1729
Copy link
Member Author

@tcharding , @apoelstra , ready for review again.

apoelstra
apoelstra previously approved these changes Jun 18, 2022
Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK e49b6d8

@sanket1729
Copy link
Member Author

Rebased after #417 .

@sanket1729
Copy link
Member Author

sanket1729 commented Jun 19, 2022

Another problem that I am noting with merging the imports is that there are always conflicts when merging PRs that touch the same file.

PR1:

use crate::{A, B, SomethingFromPR1, T, U};

PR2:

use crate::{A, AnotherThingFromPR2, B, T, U};

These two PRs would conflict.

While previously it were no conflicts

use crate::SomethingFromPR1;
use crate::AnotherThingFromPR2;

@tcharding
Copy link
Member

tcharding commented Jun 19, 2022

Another problem that I am noting with merging the imports is that there are always conflicts when merging PRs that touch the same file.

Yes you are correct. Its a trade off right, the more you merge the imports (not at all, merge last module, merge crate use foo::bar::{{baz::A, B}, C}) the more conflicts we get. The less we merge imports the more lines if code. There is no 'correct'. I personally like the imports_granularity = "Module" level, but its totally subjective.

Although my view was formed in projects that do not use the '2 explicit acks to merge' policy so perhaps the additional merge conflicts are not good in the rust-bitcoin stack?

@sanket1729
Copy link
Member Author

Although my view was formed in projects that do not use the '2 explicit acks to merge' policy so perhaps the additional merge conflicts are not good in the rust-bitcoin stack?

I tend to agree. I think we should have this in the rust-bitcoin/rust-bitcoin.

  1. It has more open PRs
  2. Requires 2 ACKs

Let us keep the merging import feature in rust-miniscript for a few more weeks and learn a few more things.

tcharding
tcharding previously approved these changes Jun 21, 2022
Copy link
Member

@tcharding tcharding left a comment

Choose a reason for hiding this comment

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

ACK 9d83a8f

Implement a new hash type that does not displat/fromstr in backwards
direction.
We need support for support for double hashing, but if we use upstream
sha256d::Hash, our FromString/Display requirements break
Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 905c5dc

@sanket1729 sanket1729 merged commit e2e8e77 into rust-bitcoin:master Jun 21, 2022
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