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 Inventory::network_hash() method #515

Merged
merged 1 commit into from Apr 13, 2023

Conversation

stevenroose
Copy link
Collaborator

I'm not positive we won't ever had inv items that are not sha256d::Hash, though. I would expect them to stay like that, but we never know.

Would accept that as a reasonable objection against this helper.

apoelstra
apoelstra previously approved these changes Nov 9, 2020
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.

seems reasonable to me. I might argue for returning a [u8; 32] which is super easy to convert to any 32-byte hash type, and also we avoid returning the 0 "hash"

@stevenroose
Copy link
Collaborator Author

Well, tbh before the Inventory refactor, the type was simply a tuple of (InvType, sha256d::Hash) which I think it's also kinda how it's represented in Core. (Even though Core has uint256..)

/// Return the item value represented as a SHA256-d hash.
pub fn hash(&self) -> sha256d::Hash {
match *self {
Inventory::Error => sha256d::Hash::default(),
Copy link
Contributor

@sgeisler sgeisler Dec 15, 2020

Choose a reason for hiding this comment

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

I feel a bit uneasy about returning an all-zero "hash". I don't know how exactly you'd misuse this in a dangerous manner that isn't already misguided without that fact, but there might exist one. Would it be too bad to return a Result<Hash, Error>? Or is this just stupid in this context (I'm not entirely sure what you want to use the fn for)?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it can be done through Option<sha256d::Hash> return type

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, right, the error type would only have a single instance anyway.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hmm, fair enough, though in the protocol, the Error variant is represented by 32 0-bytes as well. So maybe "hash" isn't the right name in that case, maybe we'd do an as_bytes() -> [u8; 32] even though using sha256d::Hash is just so much more convenient. Not to speak about hex representation and it's reversal problems etc.

/// Return the item value represented as a SHA256-d hash.
pub fn hash(&self) -> sha256d::Hash {
match *self {
Inventory::Error => sha256d::Hash::default(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it can be done through Option<sha256d::Hash> return type

@@ -43,6 +43,20 @@ pub enum Inventory {
WitnessBlock(BlockHash),
}

impl Inventory {
/// Return the item value represented as a SHA256-d hash.
pub fn hash(&self) -> sha256d::Hash {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure this is a good name for the function taking into account collision with non-bitcoin Hash trait (non-critical, but may be still important). It could be that From<Inventory> for sha256d::Hash will work better; or if we'd like to support optional, a try_as_hash() as a function name

@apoelstra
Copy link
Member

apoelstra commented Dec 20, 2021

What if we compromised and just called the method network_hash(), which would no longer use the hash name which tends to collide in Rust, and maybe hints to the user that this is a weird sort of "hash" which might be all zeros? (Or at least, is there for use on the network and not necessarily as a general-purpose hash.)

@stevenroose
Copy link
Collaborator Author

Addressed comments and rebased.

tcharding
tcharding previously approved these changes Apr 10, 2023
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 06b14f7

@apoelstra
Copy link
Member

If we're returning an Option anyway would it make sense to return an actual hash type rather than a [u8; 32] array?

Alternately, since this is an object that users expect might be represented as all-zeroes, would it make sense to return a [u8;32] that might be all zeroes rather than an Option?

I'd be fine either way.

@stevenroose
Copy link
Collaborator Author

If we're returning an Option anyway would it make sense to return an actual hash type rather than a [u8; 32] array?

I think not because there is no guarantee that we won't have inventory items in the future that use different hashes. Like single sha256 instead of double.

Alternately, since this is an object that users expect might be represented as all-zeroes, would it make sense to return a [u8;32] that might be all zeroes rather than an Option?

I'd be fine either way.

Hmm, not sure what users expect here. Tbh if you want all zeroes in the Error variant, you can simply do unwrap_or_default. Maybe I could document that it only returns None for the Error variant, but I would expect that to be trivial..

@stevenroose stevenroose changed the title Add Inventory::hash() method Add Inventory::network_hash() method Apr 10, 2023
Copy link
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Concept ACK, would a separate newtype make sense? Looks like it wouldn't?

Error being mapped to None rather than [0; 32] looks better to me.

bitcoin/src/network/message_blockdata.rs Outdated Show resolved Hide resolved
@@ -42,6 +42,22 @@ pub enum Inventory {
},
}

impl Inventory {
/// Return the item value represented as a SHA256-d hash.
Copy link
Collaborator

Choose a reason for hiding this comment

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

None should be documented.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed

@stevenroose
Copy link
Collaborator Author

Yeah I don't think a newtype makes much sense. Protocol-level it could mean anything. I would be something like InventoryItemInner which is kinda silly.

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 3d524e0

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 3d524e0

@apoelstra apoelstra merged commit 3795f60 into rust-bitcoin:master Apr 13, 2023
22 checks passed
Davidson-Souza pushed a commit to Davidson-Souza/rust-bitcoin that referenced this pull request Jul 12, 2023
9850550 Move AsRef impl block next to Index (Tobin C. Harding)
4d42e8e Derive Copy and Clone (Tobin C. Harding)
b38ae97 Implement stable comparison functionality (Tobin C. Harding)
630fc1f Remove len and is_empty from impl_array_newtype macros (Tobin C. Harding)
9788b6d Remove leading colons from impl_array_newtype methods (Tobin C. Harding)
2bb08c2 Remove as_[mut_]ptr from impl_array_newtype macros (Tobin C. Harding)
3e28070 Duplicate impl_array_newtype (Tobin C. Harding)
6358903 Add newline to end of file (Tobin C. Harding)

Pull request description:

  Supersedes rust-bitcoin#515

  The primary aim of this PR is to fix the fact that we currently implement various comparison traits (`Ord`, `PartialEq`) by comparing the inner byte arrays. These bytes are meant to be opaque and are not guaranteed across versions of `libsecp256k1`.

  This PR is a bit involved because I had to detangle all the various types (across both `secp256k1` and `secp256k1-sys`) that use the `impl_array_newtype` macro.

  - Patch 1: is trivial cleanup
  - Patch 2: Step one of the PR is duplicating the macro into both crates so we can tease them apart.
  - Patch 3-5: Are cleanup of the now duplicated `impl_array_newtype` macros
  - Patch 6: Is the meat and potatoes
  - Patch 7,8: Further minor clean ups to the macro

  I had a lot of fun with this PR, I hope you enjoy it too.

  Fix: rust-bitcoin#463

ACKs for top commit:
  apoelstra:
    ACK 9850550

Tree-SHA512: 160381e53972ff882ceb1d2d47bac56a7301a2d13bfe75d3f6ff658ab2c6fbe516ad856587c4d23f98524205918ca1a5f9b737e35c23c7a01b476c92d8d1792f
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.

None yet

6 participants