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

Rebased version of [Alternative] Allow deserializing from owned types + support for new schnorr module #270

Merged
merged 5 commits into from
Apr 21, 2021

Conversation

thomaseizinger
Copy link
Contributor

@thomaseizinger thomaseizinger commented Jan 12, 2021

This PR is a rebase of #218 that uses the new visitor module for schnorr signatures and public keys.

The way we call the visitor module is slightly different in all the call-sites:

  • sometimes we pass the bytes slice by indexing: &self[..]
  • sometimes we call serialize()
  • sometimes we call serialize_der()

For the deserialization, all the expectation strings are obviously different.

It would be possible to work around these differences in a macro and thereby reduce the code duplication. However, I hesitated to do so because it creates even more indirection which makes it IMO harder to understand what is going on. In the end, the implementations are only forwarding to the visitor module.

I decided to squash all commits of #218 together to make sure it is still an atomic commit. This one also uses the new visitor module for the newly added schnorr keys and signatures. 1f08a31 therefore represents the state of #218 modulo the schnorr additions.

The remaining two patches are minor refactorings and additional tests on top of this.

elichai and others added 3 commits January 12, 2021 11:51
Co-authored-by: Elichai Turkel <elichai.turkel@gmail.com>
Co-authored-by: Sebastian Geisler <sebastian@blockstream.io>
These tests are testing more than just the signature serialization.
@elichai
Copy link
Member

elichai commented Jan 12, 2021

I guess serialization of KeyPair is blocked by bitcoin-core/secp256k1#845

sgeisler
sgeisler previously approved these changes Jan 12, 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.

Thank you for taking the time to rework this PR, this seems to have become a real team effort ^^ I think removing the macros is nice for readability and jumping around in the source and comes at a low enough price in LOC.

src/serde_util.rs Outdated Show resolved Hide resolved
The visitor works with all types that implement `FromStr`. Whether or
not that ends up being hex encoding depends on the implementation
of `FromStr`.
This visitor is meant to deserialize strings using `FromStr` not
bytes.
@thomaseizinger
Copy link
Contributor Author

@sgeisler @elichai I renamed the visitor to FromStrVisitor which seems more appropriate.

While doing that, I noticed that FromStrVisitor overrides visit_bytes which IMO is not correct. Removing it shows that we don't have any tests that cover this implementation so I went ahead and committed that as well. Any objections?

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.

Except for the long paths, and for what its worth, looks good to me.

impl<'de> ::serde::Deserialize<'de> for SecretKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
if d.is_human_readable() {
d.deserialize_str(super::serde_util::FromStrVisitor::new(
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps remove super:: and add a use statement that imports using the fully qualified path (although I would remove serde_util:: also). Then we can remove super:: at no additional cost all the way through this PR. (I'm still singing the same old tune :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not sure how useful a use statement will be.

This code is feature-gated so I would either have to feature-gate the use statement at the top of the file as well or accept that rustc will issue a dead-code warning if we compile without the serde feature flag.

For feature-gated code, I usually err on the side of having full-qualified paths, esp. if they only occur once within the code that is gated.

We could potentially include a use super::serde_util; at the beginning of the function and then reference both FromStrVisitor and BytesVisitor as serde_util::FromStrVisitor.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the response, I didn't catch the feature gated nuance when I commented. Not sure which part of the comment @sgeisler is ok'ing but I like use statement inside the function option. Its pretty minor though, so don't sweat it :)

@thomaseizinger
Copy link
Contributor Author

@apoelstra friendly ping to review this please :)

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 c2fd5ce

Something missing here that should ideally be discussed as a separate PR before the next release since it would probably derail this PR again: schnorr secret key serialization.

@thomaseizinger
Copy link
Contributor Author

utACK c2fd5ce

Something missing here that should ideally be discussed as a separate PR before the next release since it would probably derail this PR again: schnorr secret key serialization.

Yes please! This PR fixes a bug whereas schnorr secret key serialization is "simply" a missing feature.

We just happen to touch the schnorr module in these patches to remain moderately consistent :)

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 c2fd5ce

This looks great! Thanks for removing the macros. This is much cleaner than what we had before (though a bit more repetitive).

I think merging should be blocked on #288 because the build is broken in current Rust nightly and we need to fix that.

Comment on lines +449 to +451
d.deserialize_bytes(super::serde_util::BytesVisitor::new(
"a bytestring representing a public key",
PublicKey::from_slice
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this a breaking change? currently bytes will deserialize as hex: https://github.com/rust-bitcoin/rust-secp256k1/blob/master/src/macros.rs#L116-L125

(I'm not saying it's bad, just trying to know if this might break downstream users)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it is!

The lines you commented on are within the else branch of d.is_human_readable whereas the code you linked to is within d.is_human_readable.

Also, I think the linked piece of code was never actually called because I deleted a legacy of it in c2fd5ce and all tests still pass!

Copy link
Member

Choose a reason for hiding this comment

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

hmm I see, you're right.

@thomaseizinger
Copy link
Contributor Author

Now that #288 is closed as a result of #290 being merged, any chance we can get this in? :)

Copy link
Member

@elichai elichai left a comment

Choose a reason for hiding this comment

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

Verified that this produces the same result as before and deserializes to the same result on these serializations:

  • serde_json
  • bincode
  • serde_cbor
  • serde_yaml
  • rmp-serde
  • toml
  • serde-pickle
  • ron
  • bson
  • json5
  • flexbuffers

This also fixed deserialization for these:

  • serde_yaml
  • serde-pickle
  • json5
  • bson

The code I've used to verify: https://github.com/elichai/rust-secp256k1-serde-test

@elichai elichai merged commit 3c2bee3 into rust-bitcoin:master Apr 21, 2021
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.

5 participants