Skip to content

Make uint types (un)serializable#511

Merged
sgeisler merged 7 commits intorust-bitcoin:masterfrom
shesek:202011-uint-serde
Feb 5, 2021
Merged

Make uint types (un)serializable#511
sgeisler merged 7 commits intorust-bitcoin:masterfrom
shesek:202011-uint-serde

Conversation

@shesek
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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 shesek force-pushed the 202011-uint-serde branch from 0e9672e to 4a18151 Compare November 7, 2020 01:07
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
Copy Markdown
Member

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

@shesek
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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 1be22c3ab355845de360111e32ccbe30efe3db24

Copy link
Copy Markdown
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!(Uint128, 2);

/// Uint error
#[derive(Debug)]
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Collaborator

@dr-orlovsky dr-orlovsky Jan 14, 2021

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
Copy Markdown
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?

@shesek
Copy link
Copy Markdown
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))

@dr-orlovsky
Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
Contributor Author

shesek commented Jan 16, 2021

I implemented Error and Eq.

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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.

7 participants