-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
first hack at a nice libp2p constructor #241
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
libp2p.go
Outdated
|
||
func DefaultConfig() *Config { | ||
// Create a multiaddress | ||
addr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not be 0.0.0.0
? Maybe, to just accept the address as a parameter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel very uneasy about having defaults which open your ports to the world. AWS warns about it, systemd gets shitstorms about it, and anyone building something on top should probably not use the default anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyone building something on top should probably not use the default anyway.
Then, IMO, it should be called "testing" or something like that. In this case, you're setting up a service that's supposed to be accessible from the internet. Users will be very confused if it doesn't listen on a public address by default. However, IMO, using a default address probably isn't the best idea anyways as there's no reasonable default port.
libp2p.go
Outdated
yamux "github.com/whyrusleeping/go-smux-yamux" | ||
) | ||
|
||
type Config struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be kind of nice if this (or some subset with the key etc.) could be serialized/deserialized easily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... that would be nice. Definitely something that can be done later though, As i think it deserves a bit more thought.
libp2p.go
Outdated
Reporter metrics.Reporter | ||
} | ||
|
||
func Construct(ctx context.Context, cfg *Config) (host.Host, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if having New(ctx) and NewWithConfig(ctx, cfg) would be nicer. At least for me as a new user it would be more straightforward to understand what those methods do anf how they work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind of useful but note it introduces duality for "defaults" that will be harder to maintain. swarm.NewNetwork*
provides a way of getting a default swarm. This provides a second parallel way.
// Set up stream multiplexer | ||
tpt := msmux.NewBlankTransport() | ||
|
||
// By default, support yamux and multiplex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It strikes me that here the supported transports are slightly different than here: https://github.com/libp2p/go-libp2p-swarm/blob/master/swarm.go
I thought that swarm.NewNetworkWithProtector
would be the default way of doing things so any updates to that should happen in swarm
?
At first sight, it seems that this function is just re-doing what PSTransport provides:
// PSTransport is the default peerstream transport that will be used by
// any libp2p swarms.
var PSTransport pst.Transport
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, I'm actually thinking the best path forward here is to remove that logic from the swarm code, and make this place be the default. The reason being that swarm is much deeper in the dependency tree, and making it depend on extra packages makes it harder to update those packages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds good to me 👍
I want to try and pull some wisdom from this blog post into this PR: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis |
I'm just not sure what to make the functions operate on |
From my understanding this would be something like this // current version in the example
basicHost, err := libp2p.NewWithCfg(ctx, &libp2p.Config{
ListenAddrs: []ma.Multiaddr{addr},
})
// functional version
basicHost, err := libp2p.New(ctx, libp2p.ListenAddrs(addr))
// functional config - default config
basicHost, err := libp2p.New(ctx) with impl being something like this func ListenAddrs(addrs ...ma.Multiaddr) func (*Config) error {
return func (c *Config) error {
c.ListenAddrs = addrs
}
}
func New(ctx context.Context, options ...func(*Config) error) (host, error) {
cfg := Config{}
for _, option := range options {
err := option(cfg)
// handle err
}
return NewWithCfg(ctx, cfg)
} |
@dignifiedquire yeah, having things operate on the config seems like the most reasonable way forward. I'll start on that. What do you think about still having the option to use the config directly? I'm not really sure because it adds extra things for the user to have to think about. |
Yeah I would drop that option for users to avoid confusion. We can use |
There, how does that look? |
libp2p.go
Outdated
|
||
type Option func(cfg *Config) error | ||
|
||
func Transports(tpts []transport.Transport) Option { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function signatures are inconsistent, would be nice if they all either take an array or varargs, as currently two of them (Transports and ListenAddrs) take an array but ListenAddrStrings takes varargs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have been a little tired writing this... >.>
libp2p.go
Outdated
} | ||
} | ||
|
||
func NoSecio(cfg *Config) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to have a Secio
or WithSecio
one as well, such that you can make it explicit to always use it, independent of the defaults
libp2p.go
Outdated
return nil | ||
} | ||
|
||
func WithMuxer(m mux.Transport) Option { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are these called With<>
and Transports
not WithTransports
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we overload the term Transports
. Transports also applies to things like tcp, quic, websockets, etc
You might like my ideas for this constructor API, but they're pretty different. Most of the option functions can be simplified as loaders for certain kinds of
About the default config: why not make it a separate package? We can have import (
libp2p "github.com/libp2p/go-libp2p"
cfg "github.com/libp2p/go-libp2p-default"
)
func main() {
h, err := libp2p.New(context.TODO(), cfg.Config()...)
} Also at a later point, I'd like to be able to construct a node simply by StrTransports("/ws/1.0.0", "/secio/1.0.0", "/mplex/6.3.0")
StrDiscovery("/mdns/1.0.0", "/udp/1.0.0")
// libp2p modules register themselves similar to how multiaddr protocols do it. But that's really not neccessary at the moment. |
@lgierth there, updated with some of your input |
Is this go-ish? I don't think I've seen these constructs in Go before. I find it innovative, kind of javascrip-ty. It's fancy, I might like it, but I find the NewWithCfg initialization way more natural and straightforward in the end (and require less code). Perhaps I'm old fashioned... but let's keep that method exported in any case. |
oh, just saw the dave cheney post, I guess it's go-ish then :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:):):)
0f5ab37
to
dabae69
Compare
dabae69
to
5824305
Compare
alright, gonna merge this for now. The next step is to try out using it in go-ipfs to construct our libp2p node. |
* bump go.mod to Go 1.17 and run go fix * update .github/workflows/automerge.yml * update .github/workflows/go-test.yml * update .github/workflows/go-check.yml * remove unneeded nil check in ECDSAPublicKey.Verify Co-authored-by: web3-bot <[email protected]> Co-authored-by: Marten Seemann <[email protected]>
Trying to make using go-libp2p as simple as possible