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: resolve multiaddrs before dial #782

Merged
merged 4 commits into from
Nov 4, 2020

Conversation

vasco-santos
Copy link
Member

@vasco-santos vasco-santos commented Oct 13, 2020

This PR adds the ability to resolve multiaddrs before dialling. The multiaddr resolvers are customizable within the dialer configuration and come with a default for dnsaddr. At this moment, we do not resolve dns4 and dns6 per #772 (comment) . I will make sure to create an issue to track this.

Needs:

* @param {Multiaddr} ma
* @returns {Promise<Array<Multiaddr>>}
*/
async _resolve (ma) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Once we support recursion in multiaddr, as well as dns4+dns6 resolution, we will not need this function, only the function below

*/
async _resolve (ma) {
// TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
const resolvableProto = ma.protos().find((p) => p.resolvable)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should simplify this for now and only resolve if ma.protoNames().includes('dnsaddr'). The checks below don't account for dns addresses. If new resolvable addresses are added, we may need to account for them further, so I would just simplify this for now.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, I agree!

@vasco-santos
Copy link
Member Author

Just tested this out with a direct dial from libp2p: /dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN and it resolved correctly to /dns4/sjc-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN. I could not test the examples from #772 at this moment, as without the multiaddr + mafmt releases, the bootstrap module uses different versions that I can link here. It should just work once we do the releases


const addrs = []
for (const a of knownAddrs) {
const resolvedAddrs = await this._resolve(a)
Copy link
Contributor

Choose a reason for hiding this comment

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

resolve can throw, we shouldn't let a single address failure stop the whole dial, we need to catch it

src/dialer/index.js Show resolved Hide resolved
return [ma]
}

const resolvedMultiaddrs = await this._resolveRecord(ma)
Copy link
Contributor

Choose a reason for hiding this comment

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

This can throw which will stop the whole dial, we should let individual addresses fail.

[`dnsaddr=${relayedAddr(peerId)}`]
]

describe('Dialing (resolvable addresses)', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a test where the resolve throws for and address to ensure we can still succeed if others pass.

@vasco-santos vasco-santos force-pushed the feat/resolve-multiaddrs-before-dial branch from 5ae4f29 to 4e0a78e Compare October 27, 2020 14:40
@vasco-santos vasco-santos force-pushed the feat/resolve-multiaddrs-before-dial branch from 4e0a78e to 2019f74 Compare October 28, 2020 09:45
@vasco-santos vasco-santos force-pushed the feat/resolve-multiaddrs-before-dial branch from 2019f74 to 389d0db Compare October 30, 2020 09:16
@vasco-santos vasco-santos marked this pull request as ready for review October 30, 2020 10:18
@vasco-santos vasco-santos force-pushed the feat/resolve-multiaddrs-before-dial branch from 3b3911b to 336ee0c Compare October 30, 2020 11:31
@vasco-santos
Copy link
Member Author

I merged in @mburns PR and tested out the example with the new dnsaddr. We get the peers connected, but it seems we have some unreachable addresses?

image

@vasco-santos
Copy link
Member Author

vasco-santos commented Nov 2, 2020

@mburns

dig +short TXT _dnsaddr.nyc-2.bootstrap.libp2p.io
"dnsaddr=/ip4/104.236.76.40/udp/4001/quic/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip4/104.236.76.40/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip6/2604:a880:800:10::4a:5001/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip6/2604:a880:800:10::4a:5001/udp/4001/quic/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/dns6/nyc-2.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip6/2604:a880:800:10::4a:5001/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"

Per #772 (comment) we should get the ip4 and ip6 addresses with ws out. These addresses will fail on the certificate validation. Regarding the unreachable addresses I am not sure about the issue

@mburns
Copy link
Contributor

mburns commented Nov 4, 2020

$ dig +short TXT _dnsaddr.nyc-2.bootstrap.libp2p.io
"dnsaddr=/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/dns6/nyc-2.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip4/104.236.76.40/udp/4001/quic/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip6/2604:a880:800:10::4a:5001/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"
"dnsaddr=/ip6/2604:a880:800:10::4a:5001/udp/4001/quic/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64"

Still investigating the unreachable hosts, they should be back up shortly.

@vasco-santos
Copy link
Member Author

Thanks @mburns ! Everything seems great not 🎉

image

Copy link
Contributor

@jacobheun jacobheun left a comment

Choose a reason for hiding this comment

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

LGTM just two minor nits

src/dialer/index.js Outdated Show resolved Hide resolved
Comment on lines 145 to 160
let firstCall = false
let secondCall = false

const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
stub.callsFake(() => {
if (!firstCall) {
firstCall = true
// Return an array of dnsaddr
return Promise.resolve(getDnsaddrStub(remoteId))
} else if (!secondCall) {
secondCall = true
// Address failed to resolve
return Promise.reject(new Error())
}
return Promise.resolve(getDnsRelayedAddrStub(remoteId))
})
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to use sinon to simplify this a bit, something like:

Suggested change
let firstCall = false
let secondCall = false
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
stub.callsFake(() => {
if (!firstCall) {
firstCall = true
// Return an array of dnsaddr
return Promise.resolve(getDnsaddrStub(remoteId))
} else if (!secondCall) {
secondCall = true
// Address failed to resolve
return Promise.reject(new Error())
}
return Promise.resolve(getDnsRelayedAddrStub(remoteId))
})
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
stub.onCall(0).callsFake(() => Promise.resolve(getDnsaddrStub(remoteId)))
stub.onCall(1).callsFake(() => Promise.reject(new Error()))
stub.callsFake(() => Promise.resolve(getDnsRelayedAddrStub(remoteId)))

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice, that works. I did not understand that I could use callsFake for the "other" calls, which was making things difficult 👍

@vasco-santos vasco-santos force-pushed the feat/resolve-multiaddrs-before-dial branch from ff56987 to 33fac9a Compare November 4, 2020 12:36
@vasco-santos vasco-santos merged commit 093c0ea into master Nov 4, 2020
@vasco-santos vasco-santos deleted the feat/resolve-multiaddrs-before-dial branch November 4, 2020 12:55
achingbrain pushed a commit to ipfs/js-ipfs that referenced this pull request Nov 6, 2020
Adds the new `dnsaddr` multiaddrs for browser bootstrapping peers per libp2p/js-libp2p#772 and libp2p/js-libp2p#782
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.

3 participants