github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/config/p2p.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	peer "github.com/libp2p/go-libp2p-core/peer"
     8  	ma "github.com/multiformats/go-multiaddr"
     9  
    10  	"github.com/qri-io/jsonschema"
    11  )
    12  
    13  // P2P encapsulates configuration options for qri peer-2-peer communication
    14  type P2P struct {
    15  	// Enabled is a flag for weather this node should connect
    16  	// to the distributed network
    17  	Enabled bool `json:"enabled"`
    18  
    19  	// PeerID is this nodes peer identifier
    20  	PeerID string `json:"peerid"`
    21  
    22  	PrivKey string `json:"privkey"`
    23  
    24  	// Port default port to bind a tcp listener to
    25  	// ignored if Addrs is supplied
    26  	Port int `json:"port"`
    27  
    28  	// List of multiaddresses to listen on
    29  	Addrs []ma.Multiaddr `json:"addrs"`
    30  
    31  	// QriBootstrapAddrs lists addresses to bootstrap qri node from
    32  	QriBootstrapAddrs []string `json:"qribootstrapaddrs"`
    33  
    34  	// list of addresses to bootsrap qri peers on
    35  	BootstrapAddrs []string `json:"bootstrapaddrs"`
    36  
    37  	// Enable AutoNAT service. unless you're hosting a server, leave this as false
    38  	AutoNAT bool `json:"autoNAT"`
    39  }
    40  
    41  // SetArbitrary is an interface implementation of base/fill/struct in order to safely
    42  // consume config files that have definitions beyond those specified in the struct.
    43  // This simply ignores all additional fields at read time.
    44  func (cfg *P2P) SetArbitrary(key string, val interface{}) error {
    45  	return nil
    46  }
    47  
    48  // DefaultP2P generates a p2p struct with only bootstrap addresses set
    49  func DefaultP2P() *P2P {
    50  	p2p := &P2P{
    51  		Enabled: true,
    52  		// DefaultBootstrapAddresses follows the pattern of IPFS boostrapping off known "gateways".
    53  		// This boostrapping is specific to finding qri peers, which are IPFS peers that also
    54  		// support the qri protocol.
    55  		// (we also perform standard IPFS boostrapping when IPFS networking is enabled, and it's almost always enabled).
    56  		// These are addresses to public qri nodes hosted by qri, inc.
    57  		// One day it would be super nice to bootstrap from a stored history & only
    58  		// use these for first-round bootstrapping.
    59  		QriBootstrapAddrs: []string{
    60  			"/ip4/35.231.230.13/tcp/4001/ipfs/QmdpGkbqDYRPCcwLYnEm8oYGz2G9aUZn9WwPjqvqw3XUAc",  // red
    61  			"/ip4/34.75.40.163/tcp/4001/ipfs/QmTRqTLbKndFC2rp6VzpyApxHCLrFV35setF1DQZaRWPVf",   // orange
    62  			"/ip4/35.237.172.74/tcp/4001/ipfs/QmegNYmwHUQFc3v3eemsYUVf3WiSg4RcMrh3hovA5LncJ2",  // yellow
    63  			"/ip4/35.231.155.111/tcp/4001/ipfs/QmessbA6uGLJ7HTwbUJ2niE49WbdPfzi27tdYXdAaGRB4G", // green
    64  			"/ip4/35.237.232.64/tcp/4001/ipfs/Qmc353gHY5Wx5iHKHPYj3QDqHP4hVA1MpoSsT6hwSyVx3r",  // blue
    65  			"/ip4/35.185.20.61/tcp/4001/ipfs/QmT9YHJF2YkysLqWhhiVTL5526VFtavic3bVueF9rCsjVi",   // indigo
    66  			"/ip4/35.231.246.50/tcp/4001/ipfs/QmQS2ryqZrjJtPKDy9VTkdPwdUSpTi1TdpGUaqAVwfxcNh",  // violet
    67  		},
    68  	}
    69  	return p2p
    70  }
    71  
    72  // DecodePeerID takes P2P.ID (a string), and decodes it into a peer.ID
    73  func (cfg *P2P) DecodePeerID() (peer.ID, error) {
    74  	if string(cfg.PeerID) == "" {
    75  		return peer.ID(""), fmt.Errorf("empty string for peer ID")
    76  	}
    77  	return peer.IDB58Decode(cfg.PeerID)
    78  }
    79  
    80  // Validate validates all fields of p2p returning all errors found.
    81  func (cfg P2P) Validate() error {
    82  	schema := jsonschema.Must(`{
    83      "$schema": "http://json-schema.org/draft-06/schema#",
    84      "title": "P2P",
    85      "description": "Config for the p2p",
    86      "type": "object",
    87      "required": ["enabled", "peerid", "privkey", "port", "addrs", "qribootstrapaddrs"],
    88      "properties": {
    89        "enabled": {
    90          "description": "When true, peer to peer communication is allowed",
    91          "type": "boolean"
    92        },
    93        "peerid": {
    94          "description": "The peerid is this nodes peer identifier",
    95          "type": "string"
    96        },
    97        "privkey": {
    98          "description": "",
    99          "type": "string"
   100        },
   101        "port": {
   102          "description": "Port to bind a tcp lister to. Field is ignored if addrs is supplied",
   103          "type": "integer"
   104        },
   105        "addrs": {
   106          "description": "List of multiaddresses to listen on",
   107          "anyOf": [
   108            {"type": "array"},
   109            {"type": "null"}
   110          ],
   111          "items": {
   112            "type": "string"
   113          }
   114        },
   115        "qribootstrapaddrs": {
   116          "description": "List of addresses to bootstrap the qri node from",
   117          "type": "array",
   118          "items": {
   119            "type": "string"
   120          }
   121        },
   122        "bootstrapaddrs": {
   123          "description": "List of addresses to bootstrap qri peers on",
   124          "anyOf": [
   125            {"type": "array"},
   126            {"type": "null"}
   127          ],
   128          "items": {
   129            "type": "string"
   130          }
   131        }
   132      }
   133    }`)
   134  	return validate(schema, &cfg)
   135  }
   136  
   137  // Copy returns a deep copy of a p2p struct
   138  func (cfg *P2P) Copy() *P2P {
   139  	res := &P2P{
   140  		Enabled: cfg.Enabled,
   141  		PeerID:  cfg.PeerID,
   142  		PrivKey: cfg.PrivKey,
   143  		Port:    cfg.Port,
   144  	}
   145  
   146  	if cfg.QriBootstrapAddrs != nil {
   147  		res.QriBootstrapAddrs = make([]string, len(cfg.QriBootstrapAddrs))
   148  		reflect.Copy(reflect.ValueOf(res.QriBootstrapAddrs), reflect.ValueOf(cfg.QriBootstrapAddrs))
   149  	}
   150  
   151  	if cfg.BootstrapAddrs != nil {
   152  		res.BootstrapAddrs = make([]string, len(cfg.BootstrapAddrs))
   153  		reflect.Copy(reflect.ValueOf(res.BootstrapAddrs), reflect.ValueOf(cfg.BootstrapAddrs))
   154  	}
   155  
   156  	return res
   157  }