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

feat!: add Noise Extensions and update deps #215

Merged

Conversation

MarcoPolo
Copy link
Contributor

@MarcoPolo MarcoPolo commented Sep 27, 2022

  • Updates some deps
  • Adds the Noise Extensions registry

The Noise extensions is used by https://github.com/libp2p/js-libp2p-webtransport/

BREAKING CHANGE: earlyData option is replaced by noise extensions

@MarcoPolo MarcoPolo requested a review from a team as a code owner September 27, 2022 21:56
@CLAassistant
Copy link

CLAassistant commented Sep 27, 2022

CLA assistant check
All committers have signed the CLA.

@MarcoPolo MarcoPolo changed the title Add Noise Extensions and update deps feat: add Noise Extensions and update deps Sep 27, 2022
@MarcoPolo MarcoPolo force-pushed the marco/update-deps-and-noise-extension branch from c591ea8 to 5d12bf9 Compare September 27, 2022 21:58
@MarcoPolo
Copy link
Contributor Author

cc @achingbrain since I'm not sure who to tag here for a review.

@MarcoPolo MarcoPolo force-pushed the marco/update-deps-and-noise-extension branch from 5d12bf9 to df5c1b3 Compare September 27, 2022 22:35
Copy link
Member

@mpetrunic mpetrunic left a comment

Choose a reason for hiding this comment

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

Thnx for the effort 👍🏻
We are removing data/early data which is a breaking change so the title and description should be updated accordingly.

We should merge this after libp2p/js-libp2p-interfaces#293 is released

src/proto/payload.proto Outdated Show resolved Hide resolved
src/noise.ts Outdated Show resolved Hide resolved
@@ -1,8 +1,12 @@
syntax = "proto3";
package pb;
syntax = "proto2";
Copy link
Member

Choose a reason for hiding this comment

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

please leave syntax to be proto3, protons library is not supporting proto2 officially and can sometimes generate weird results. In proto3 fields are optional by default so you can omit optional keywords.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is on purpose. The spec recently changed to go to proto2 since proto3 has some unwanted semantics: libp2p/specs#456

Copy link
Member

@mpetrunic mpetrunic Sep 30, 2022

Choose a reason for hiding this comment

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

I understand that but it also says it's compatible with proto3. And I would rather not switch to proto2 because of : ipfs/protons#34

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The old protobuf was compatible with proto3 i.e this one:

message NoiseHandshakePayload {
  bytes identity_key = 1;
  bytes identity_sig = 2;
  bytes data         = 3;
}

I don't think this is binary compatible with proto3. Namely the optional NoiseExtensions extensions = 4; is represented as a oneof in proto3. I think we could make this

message NoiseHandshakePayload {
  bytes identity_key = 1;
  bytes identity_sig = 2;
  NoiseExtensions extensions = 4;
}

and I think it would be binary compatible, but it's a bit of a hack.

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

optional NoiseExtensions extensions = 4; is represented as a oneof in proto3

go-libp2p's older noise .proto file with protobuf v3 doesn't have the oneof keyword. I don't think it's implicit if not set so I'm not sure this is correct. Am I missing something?

but it's a bit of a hack.

Is this because the field identifier is non-sequential? I think this is a feature of protocol buffers, any non-defined field should be skipped by the parser so this seems ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

optional NoiseExtensions extensions = 4; is represented as a oneof in proto3

go-libp2p's older noise .proto file with protobuf v3 doesn't have the oneof keyword. I don't think it's implicit if not set so I'm not sure this is correct. Am I missing something?

Sorry I didn't explain this fully. I'll explain more in a bit

but it's a bit of a hack.

Is this because the field identifier is non-sequential? I think this is a feature of protocol buffers, any non-defined field should be skipped by the parser so this seems ok.

It's a hack because the real definition is proto2 but we're using a proto3 definition to workaround a protobuf-compiler bug.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In proto3 fields are optional by default so you can omit optional keywords.

@mpetrunic They're singluar by default so we need the optional keyword - https://developers.google.com/protocol-buffers/docs/proto3#specifying_field_rules

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These two protobufs generate the same exact code (which is probably a separate bug since a proto2 encoder should write empty bytes if set. See libp2p/specs#465 for a discussion around proto2 vs proto3):

syntax = "proto2";

message NoiseExtensions {
    repeated bytes webtransport_certhashes = 1;
}

message NoiseHandshakePayload {
  optional bytes identity_key = 1;
  optional bytes identity_sig = 2;
  optional NoiseExtensions extensions = 4;
}
syntax = "proto3";

message NoiseExtensions {
    repeated bytes webtransport_certhashes = 1;
}

message NoiseHandshakePayload {
  bytes identity_key = 1;
  bytes identity_sig = 2;
  NoiseExtensions extensions = 4;
}

I think it may make sense to use proto3 long term here, but we still need to discuss that. For the mean time, I can set this as a proto3 definition that I've manually validated is compatible with proto2 parsers: https://github.com/MarcoPolo/proto2and3-playground/blob/9eb3987c04b348d64d825104813ad27c4df691e7/src/main.rs#L14

@MarcoPolo MarcoPolo changed the title feat: add Noise Extensions and update deps BREAKING CHANGE: add Noise Extensions and update deps Sep 28, 2022
@MarcoPolo MarcoPolo changed the title BREAKING CHANGE: add Noise Extensions and update deps feat!: add Noise Extensions and update deps Oct 1, 2022
@mpetrunic
Copy link
Member

@MarcoPolo interfaces are released so when you get a chance please update PR.

@MarcoPolo MarcoPolo force-pushed the marco/update-deps-and-noise-extension branch from 4f706b3 to 25c7fe4 Compare October 4, 2022 16:46
@MarcoPolo
Copy link
Contributor Author

@MarcoPolo interfaces are released so when you get a chance please update PR.

Rebased

@MarcoPolo
Copy link
Contributor Author

Let me fix the ts-expect-errors

@MarcoPolo
Copy link
Contributor Author

@mpetrunic Ready again :)

@MarcoPolo MarcoPolo requested a review from mpetrunic October 4, 2022 20:59
@mpetrunic
Copy link
Member

@MarcoPolo Had to mark extensions as optional in the proto file otherwise interop tests with the old proto file would fail with "Protocol error: value for required field "extensions" was not found in protobuf".

@achingbrain But according to the proto3 language guide this shouldn't happen for singular fields, right? Would that mean that protons is deserializing incorrectly?

@MarcoPolo
Copy link
Contributor Author

@MarcoPolo Had to mark extensions as optional in the proto file otherwise interop tests with the old proto file would fail with "Protocol error: value for required field "extensions" was not found in protobuf".

The interop test is probably wrong because extensions was never required and proto3 doesn't have a notion of required fields.

@achingbrain But according to the proto3 language guide this shouldn't happen for singular fields, right?

Correct.

Would that mean that protons is deserializing incorrectly?

I'm not sure. I'd have to look into it a bit closer. Could you link the failing test please?

@MarcoPolo
Copy link
Contributor Author

It should be safe to mark extensions as optional since either way explicit presence is tracked: https://github.com/protocolbuffers/protobuf/blob/main/docs/field_presence.md#presence-in-proto3-apis.

@mpetrunic
Copy link
Member

mpetrunic commented Oct 6, 2022

I'm not sure. I'd have to look into it a bit closer. Could you link the failing test please?

https://github.com/ChainSafe/js-libp2p-noise/blob/master/test/interop.ts It tries to handshake go node (running old proto because go daemon is not updated probably).

I'm fine with merging this, but it would be nice to get @achingbrain input on why protons error on missing singular field. This is removed line after adding optional (but it shouldn't be here for singular field): 06f5673#diff-398a29cfaac5308d03639c7c0db977fdd195792a880c7672af6c7c4632c1f957L104

@achingbrain
Copy link
Collaborator

why protons error on missing singular field

It's a bug, I've nearly got a PR ready to fix it

@mpetrunic mpetrunic merged commit ed3e16b into ChainSafe:master Oct 6, 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