package config import ( "encoding/base64" "errors" "fmt" "io" "time" ci "github.com/libp2p/go-libp2p-core/crypto" peer "github.com/libp2p/go-libp2p-core/peer" ) func Init(out io.Writer, nBitsForKeypair int) (*Config, error) { identity, err := identityConfig(out, nBitsForKeypair) if err != nil { return nil, err } bootstrapPeers, err := DefaultBootstrapPeers() if err != nil { return nil, err } datastore := DefaultDatastoreConfig() conf := &Config{ API: API{ HTTPHeaders: map[string][]string{}, }, // setup the node's default addresses. // NOTE: two swarm listen addrs, one tcp, one utp. Addresses: addressesConfig(), Datastore: datastore, Bootstrap: BootstrapPeerStrings(bootstrapPeers), Identity: identity, Discovery: Discovery{ MDNS: MDNS{ Enabled: true, Interval: 10, }, }, Routing: Routing{ Type: "dht", }, // setup the node mount points. Mounts: Mounts{ IPFS: "/ipfs", IPNS: "/ipns", }, Ipns: Ipns{ ResolveCacheSize: 128, }, Gateway: Gateway{ RootRedirect: "", Writable: false, NoFetch: false, PathPrefixes: []string{}, HTTPHeaders: map[string][]string{ "Access-Control-Allow-Origin": []string{"*"}, "Access-Control-Allow-Methods": []string{"GET"}, "Access-Control-Allow-Headers": []string{"X-Requested-With", "Range", "User-Agent"}, }, APICommands: []string{}, }, Reprovider: Reprovider{ Interval: "12h", Strategy: "all", }, Swarm: SwarmConfig{ ConnMgr: ConnMgr{ LowWater: DefaultConnMgrLowWater, HighWater: DefaultConnMgrHighWater, GracePeriod: DefaultConnMgrGracePeriod.String(), Type: "basic", }, }, } return conf, nil } // DefaultConnMgrHighWater is the default value for the connection managers // 'high water' mark const DefaultConnMgrHighWater = 900 // DefaultConnMgrLowWater is the default value for the connection managers 'low // water' mark const DefaultConnMgrLowWater = 600 // DefaultConnMgrGracePeriod is the default value for the connection managers // grace period const DefaultConnMgrGracePeriod = time.Second * 20 func addressesConfig() Addresses { return Addresses{ Swarm: []string{ "/ip4/0.0.0.0/tcp/4001", // "/ip4/0.0.0.0/udp/4002/utp", // disabled for now. "/ip6/::/tcp/4001", }, Announce: []string{}, NoAnnounce: []string{}, API: Strings{"/ip4/127.0.0.1/tcp/5001"}, Gateway: Strings{"/ip4/127.0.0.1/tcp/8080"}, } } // DefaultDatastoreConfig is an internal function exported to aid in testing. func DefaultDatastoreConfig() Datastore { return Datastore{ StorageMax: "10GB", StorageGCWatermark: 90, // 90% GCPeriod: "1h", BloomFilterSize: 0, Spec: map[string]interface{}{ "type": "mount", "mounts": []interface{}{ map[string]interface{}{ "mountpoint": "/blocks", "type": "measure", "prefix": "flatfs.datastore", "child": map[string]interface{}{ "type": "flatfs", "path": "blocks", "sync": true, "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2", }, }, map[string]interface{}{ "mountpoint": "/", "type": "measure", "prefix": "leveldb.datastore", "child": map[string]interface{}{ "type": "levelds", "path": "datastore", "compression": "none", }, }, }, }, } } // identityConfig initializes a new identity. func identityConfig(out io.Writer, nbits int) (Identity, error) { // TODO guard higher up ident := Identity{} if nbits < 1024 { return ident, errors.New("bitsize less than 1024 is considered unsafe") } fmt.Fprintf(out, "generating %v-bit RSA keypair...", nbits) sk, pk, err := ci.GenerateKeyPair(ci.RSA, nbits) if err != nil { return ident, err } fmt.Fprintf(out, "done\n") // currently storing key unencrypted. in the future we need to encrypt it. // TODO(security) skbytes, err := sk.Bytes() if err != nil { return ident, err } ident.PrivKey = base64.StdEncoding.EncodeToString(skbytes) id, err := peer.IDFromPublicKey(pk) if err != nil { return ident, err } ident.PeerID = id.Pretty() fmt.Fprintf(out, "peer identity: %s\n", ident.PeerID) return ident, nil }