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

Make uint types (un)serializable #511

Merged
merged 7 commits into from Feb 5, 2021

Conversation

shesek
Copy link
Contributor

@shesek shesek commented Nov 3, 2020

No description provided.

shesek added a commit to shesek/gdk that referenced this pull request Nov 3, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
shesek added a commit to shesek/gdk that referenced this pull request Nov 3, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
apoelstra
apoelstra previously approved these changes Nov 3, 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.

utack

@elichai
Copy link
Member

elichai commented Nov 3, 2020

We don't use serde_derive so sadly you'll have to impl it yourself (I recommend either via one of the macros here: https://github.com/rust-bitcoin/rust-bitcoin/blob/7c47c9a341f5665f89d0c1ab6e958e365bff949b/src/internal_macros.rs or if nothing fits (I don't remember what's in there anymore) using macro-expand and then prettifying it)

@shesek
Copy link
Contributor Author

shesek commented Nov 4, 2020

@elichai ah-ah, I see. It was working when I tried because serde_derive is in the dev-dependencies. Will look into changing that to use one of the existing macros.

@shesek
Copy link
Contributor Author

shesek commented Nov 4, 2020

@elichai None of the existing macros seem to fit, I ended up implementing a custom serializer/deserializer by hand at 0e9672e.

shesek added a commit to shesek/gdk that referenced this pull request Nov 7, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
shesek added a commit to shesek/gdk that referenced this pull request Nov 7, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
@apoelstra
Copy link
Member

Can you add a unit test which parses some fixed json vectors? And covers some error/edge cases?

@shesek
Copy link
Contributor Author

shesek commented Nov 10, 2020

@apoelstra Added some fixed vectors and error cases. Did you have any particular edge cases to test in mind?

shesek added a commit to shesek/gdk that referenced this pull request Nov 12, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
@shesek
Copy link
Contributor Author

shesek commented Dec 17, 2020

Is there anything else needed to get this through? :)

shesek added a commit to shesek/gdk that referenced this pull request Dec 17, 2020
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
Copy link
Contributor

@sgeisler sgeisler left a comment

Choose a reason for hiding this comment

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

What's the motivation for using our internal representation (64bit words) for the serde implementation? This could lead to some weird mixed-endianess in binary serde implementations and doesn't look pretty as json. I think treating these bignum types as byte arrays with a hex representations in human redable serde backends would be best if there are no other compatibility requirements.

Also: travis doesn't seem happy, something failed for rust 1.29.0.

@shesek shesek force-pushed the 202011-uint-serde branch 2 times, most recently from 6d089b2 to 1e9705a Compare December 30, 2020 04:36
@shesek
Copy link
Contributor Author

shesek commented Dec 30, 2020

@sgeisler No particular reason, I like hex representation better too. I changed to it and fixed compatibility with Rust 1.29. (forced-pushed over the previous implementation, which is available for reference at 202011-uint-serde-jsonarray.)

I wasn't sure whether the new from_be_slice() should enforce the length and how. I kept the commit that changed it to return a Result separate, let me know what you think and I'll squash it in if it seems acceptable.

An alternative to adding from_be_slice() is to change the existing from_be_bytes() to take an AsRef<u8> which will work for both slices and arrays, but this will lose the type checking for the array length.

@shesek
Copy link
Contributor Author

shesek commented Dec 30, 2020

Travis appears to be stuck due to some unrelated issue, it works on my fork.

@sgeisler sgeisler closed this Jan 4, 2021
@sgeisler sgeisler reopened this Jan 4, 2021
src/util/uint.rs Outdated
S: $crate::serde::Serializer,
{
use $crate::hashes::hex::ToHex;
serializer.serialize_str(&self.to_be_bytes().to_hex())
Copy link
Contributor

Choose a reason for hiding this comment

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

This appears to always serialize as a string, even if the output format is binary. This results in suboptimal encodings. We avoid this in other areas of the code by switching the encoding strategy based on the human readability.

Copy link
Contributor Author

@shesek shesek Jan 5, 2021

Choose a reason for hiding this comment

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

Agreed, implemented in d0eed01.

Testing this required introducing a new (dev only) dependency on a serde binary serializer (bincode). I wasn't sure if that's desirable or not so I kept it in a separate commit for now, will squash if it is.

shesek added a commit to shesek/gdk that referenced this pull request Jan 6, 2021
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
sgeisler
sgeisler previously approved these changes Jan 10, 2021
Copy link
Contributor

@sgeisler sgeisler left a comment

Choose a reason for hiding this comment

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

Looks good now. I don't think a new dev-dependency is much of a problem, especially since it seems to build fine with 1.29.0.

ACK 1be22c3

Copy link
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

Sorry for being late, but I see space for further improvements over a type system here. Had a lot of issues with my own code when rust-bitcoin does not implement errors properly.

src/util/uint.rs Outdated
);
}

construct_uint!(Uint256, 4);
construct_uint!(Uint128, 2);

/// Uint error
#[derive(Debug)]
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 we can be opportunistic here, as Rust API guidelines suggest:

Suggested change
#[derive(Debug)]
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy, Hash)]

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, I always forget theses derives myself 🙈 do you know if there is some way to warn about missing (standard) derives?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Even if there is a way, I never heard of it :(

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh no, maybe clippy may help?

src/util/uint.rs Outdated Show resolved Hide resolved
src/util/uint.rs Show resolved Hide resolved
@shesek
Copy link
Contributor Author

shesek commented Jan 14, 2021

I switched to a single-variant error type and implemented the suggested traits, apart from Error which I noticed isn't implemented anywhere else in rust-bitcoin. Should I implement that too? (#511 (comment))

src/util/uint.rs Outdated Show resolved Hide resolved
src/util/uint.rs Show resolved Hide resolved
@dr-orlovsky
Copy link
Collaborator

dr-orlovsky commented Jan 14, 2021

Not sure about Error whether it would compile on 1.29. I assume yes, and the reason it is absent everywhere is that it was not present before we upgraded to 1.29

@thomaseizinger
Copy link
Contributor

thomaseizinger commented Jan 14, 2021

apart from Error which I noticed isn't implemented anywhere else in rust-bitcoin

That doesn't seem to be true? GitHub search returns 12 results for "impl error::Error": https://github.com/rust-bitcoin/rust-bitcoin/search?q=%22impl+error%3A%3AError%22 (and that might be missing some where it is imported differently)

Please implement std::error::Error otherwise working with libraries like anyhow downstream is quite painful.

@shesek
Copy link
Contributor Author

shesek commented Jan 15, 2021

@thomaseizinger Oops, you're of course correct, not sure how my search missed that. I will implement this and the other suggested changes.

@shesek
Copy link
Contributor Author

shesek commented Jan 16, 2021

I implemented Error and Eq.

Copy link
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

I still believe we need Ord when we have Eq and PartialOrd. The rest looks fine for me now

@sgeisler
Copy link
Contributor

@dr-orlovsky I don't think that's the case mathematically speaking (it probably still makes sense practically in this case if it's possible).

Let's imagine the set of all binary strings. Eq is implemented as expected: compare bit values (and implicitly legth). PartialOrd is implemented that it returns Some(Equal) if a == b, Some(Greater) if a is a prefix of b, Some(Less) if b is a prefix of a and None otherwise. This is a valid impl as it's both asymmetric and transitive, compatible with the Eq impl, but not Ord.

That's obviously a contrived example, but I don't see a strict requirement for Ord just because we have Eq and PartialOrd.

@sanket1729
Copy link
Member

On one side, if we can derive something for free, we should derive it.

On the other side, Display, Clone, Debug, Error, and Eq(implying PartialEq) are the only traits that I can foresee being used.

I don't think it's important what we end up doing, but we should decide one thing and be consistent with that for all the Error types in the repo. This would help when we wrap Error of one type as an enum variant of another Enum and try to auto derive on that.

@dr-orlovsky
Copy link
Collaborator

dr-orlovsky commented Jan 18, 2021

The use for Ord are the situations where you need to collect errors from multiple attempts of processing into a HashMap, mapping them to the item. Thus, if we can derive Ord I think we should do it, and not only here, but on all Error types - which is a matter of other PRs of course (I did one already #551)

@sgeisler thanks for explanation, that is a valid case.

@sanket1729
Copy link
Member

sanket1729 commented Jan 21, 2021

I think HashMap should only Hash and Eq, but BTreeMap will require Ord. It may be possible that we have extra work for manually impl Ord because the error contains f64 for example.

That being said, we can try everything and see how it goes. We can continue this in #555

@dr-orlovsky
Copy link
Collaborator

I do agree with @apoelstra in #555 (comment) that we should implement both Ord (and PartialOrd of course) where is possible - and this is also Rust API Guidelines recommendation.

Had plenty of pain not being able to use datatypes in BTree* when I need to put them there.

@shesek
Copy link
Contributor Author

shesek commented Jan 21, 2021

I added Ord. I see that Hash and Default were also mentioned in #555, are they relevant for error types?

Copy link
Collaborator

@dr-orlovsky dr-orlovsky left a comment

Choose a reason for hiding this comment

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

Thank you and sorry for being insistent. utACK 55657cb

@dr-orlovsky
Copy link
Collaborator

I think here Default just makes not sense: you cen't have a "default" Error. And the type already has Hash derived on it

@dr-orlovsky dr-orlovsky added this to the 0.26.1 milestone Jan 30, 2021
Copy link
Member

@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.

tACk a1e98a6

Copy link
Contributor

@sgeisler sgeisler left a comment

Choose a reason for hiding this comment

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

utACK a1e98a6

@sanket1729 are you still against merging without a more thorough test than CI (=currently @apoelstra's test suite)? I'm currently building my own setup (cargo-all-features and some bash, not as fancy but I'll understand it xD). So I hope we can get stuff merged again soon.

@sanket1729
Copy link
Member

Yeah, let's merge this.

@sgeisler sgeisler merged commit 90f3529 into rust-bitcoin:master Feb 5, 2021
shesek added a commit to shesek/gdk that referenced this pull request Feb 27, 2021
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
shesek added a commit to shesek/gdk that referenced this pull request Feb 27, 2021
And keep the latest validation status on the store cache.

NOTE: This commit depends on a rust-bitcoin fork with serializable uint types.
A PR was sent upstream: rust-bitcoin/rust-bitcoin#511
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

7 participants