Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

feat: add lazy select #18

Merged
merged 4 commits into from
Oct 12, 2022
Merged

Conversation

alanshaw
Copy link
Member

@alanshaw alanshaw commented Aug 8, 2022

Implements lazy select as seen in go-multistream (https://github.com/multiformats/go-multistream/blob/master/lazyClient.go) and rust libp2p (libp2p/rust-libp2p#1855)

Can be used to avoid a round trip when the dialer has only a single protocol to select from.

@achingbrain
Copy link
Member

Thanks for opening this, it looks good. Can you add some tests please?

I wonder if there's any value in the handshake when there's only one protocol we want to speak? We could just send the protocol and immediately start sending data, then the remote would close the stream if it doesn't support the protocol.

@alanshaw
Copy link
Member Author

I wonder if there's any value in the handshake when there's only one protocol we want to speak? We could just send the protocol and immediately start sending data, then the remote would close the stream if it doesn't support the protocol.

That's urh, exactly what this does...unless I'm misunderstanding what you mean.

Lazy select does this:

sequenceDiagram
    participant initiator
    participant receiver
    initiator->>receiver: /multistream/1.0.0 /bitswap/1.2.0 DATA
    receiver->>initiator: /multistream/1.0.0 /bitswap/1.2.0
Loading

VS regular select:

sequenceDiagram
    participant initiator
    participant receiver
    initiator->>receiver: /multistream/1.0.0 /bitswap/1.2.0
    receiver->>initiator: /multistream/1.0.0 /bitswap/1.2.0
     initiator->>receiver: DATA
Loading

In lazy select the receiver will respond with na if not supported and then the stream will be closed by the initiator. The receiver may receive some data but 🤷‍♂️.

In my fork I expose this to users via a lazy option so you can do libp2p.dialProtocol('/bitswap', ma, { lazy: true }) but things have changed around a bit so I think the upgrader would do that logic now...

https://github.com/web3-storage/js-libp2p-multistream-select/blob/15ac7f3f632df9dadf71b975857cc18bc9dc57a6/src/index.ts#L43-L45

@achingbrain
Copy link
Member

Yeah, I just mean you have to explicitly select to be lazy - it looks like lazy is better since there are fewer round-trips involved, so why not default to that instead of doing the whole handshake dance.

@achingbrain
Copy link
Member

I'm just thinking out loud, not a requirement for merging this PR!

@alanshaw
Copy link
Member Author

Ah ok, because you have to know in advance that DATA doesn't begin with a valid multistream message like /bitswap/2.0.0. In the case where the receiver responds na, DATA could be misconstrued as a continuation of the multistream negotiation.

@alanshaw
Copy link
Member Author

The remaining theoretical pitfall whereby application data gets misinterpreted as another protocol proposal by a listener remains, however unlikely.
libp2p/rust-libp2p#1855

src/select.ts Outdated Show resolved Hide resolved
test/integration.spec.ts Outdated Show resolved Hide resolved
test/integration.spec.ts Outdated Show resolved Hide resolved
src/select.ts Outdated Show resolved Hide resolved
src/select.ts Outdated Show resolved Hide resolved
@achingbrain achingbrain merged commit d3bff7c into libp2p:master Oct 12, 2022
github-actions bot pushed a commit that referenced this pull request Oct 12, 2022
## [3.1.0](v3.0.0...v3.1.0) (2022-10-12)

### Features

* add lazy select ([#18](#18)) ([d3bff7c](d3bff7c))

### Trivial Changes

* Update .github/workflows/stale.yml [skip ci] ([ba9ea12](ba9ea12))

### Dependencies

* bump uint8arrays from 3.x.x to 4.x.x ([#22](#22)) ([cfb887b](cfb887b))
@github-actions
Copy link

🎉 This PR is included in version 3.1.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants