Share known peers between network

Hello. Could I share known peers between the network in some way?

N - node.

N3 connect to N2.

N2 connect to N1.

After all connection, I can run node.stats.peers() command:
N1 will print only N2 ID
N2 will print N1 and N3 IDs.

In my case, I want to have that N1 know about N2 and N3. So, N2 should share all know peers to N1.

Code N1

/* eslint-disable no-console */
‘use strict’

const libp2p = require('../../')
const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const KadDHT = require('libp2p-kad-dht')
const defaultsDeep = require('@nodeutils/defaults-deep')
const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const MulticastDNS = require('libp2p-mdns')
const PeerId = require('peer-id')
let node2 = '';

class MyBundle extends libp2p {
  constructor (_options) {
const defaults = {
  modules: {
    transport: [ TCP ],
    streamMuxer: [ Mplex ],
    connEncryption: [ SECIO ],
    // we add the DHT module that will enable Peer and Content Routing
    dht: KadDHT,
    // peerDiscovery: [ MulticastDNS ],
  },
  config: {
    dht: {
      enabled: true,
      kBucketSize: 20
    },
    relay: {                      // Circuit Relay options
      enabled: true,
      hop: {
        enabled: false,
        active: false
      }
    },
  }
}

super(defaultsDeep(_options, defaults))
  }
}

function createNode (callback) {
  let node

  let peerId = {
"id": "QmTjVr1nFZNKLQvZBYmathCDUnuYWJHuSdWfjPzcX5n6jB",
"privKey": `CAAS4AQwggJcAgEAAoGBAKMDfgSRPZdoz2+X+YJ+ElpGcD2XgahORaa
  G75KuviRPLLS6OuUwxxQpEpgowSDvioFIkOUP4kHfY0wSg8LttuRHKanAsaAIbEvhd+td
  TzJy6uiIKyps8zswZnI/e+sCbjPJVARgY93q5QQmV5/n5BHK3M5nHxVh1YA+cGzExI2PA
  gMBAAECgYBlCewZDqEbcOZqJ8uKW3QqqlA1jOvbkzBOqIJj65WFUeHG30tT9ajfURnqYB
  BcxryVp5HPuMmnxLt6UluC/e6GkFEj/bd3/QnC+XDNWtPmvpFkCvWTC84iqEzHNbfP10d
  5qWvMw1cTr1i8wTYuc3BPrDON2xDC87OJja3pX8L7aQJBANI4czVqTA3QAxMJaAP4i9R5
  iZzl/bFnYGBdArJP7OX+o0PyI6GAklUhcXvQIOL4Ym5HbvUZy0lsZk/8wRd4cAUCQQDGg
  1BnGFQR/jnmhriRFfShYPmacos//2VGToXqKPoG1hhAU6CoenimKnLfP0thuK/uklJ9lM
  u4tyoezizy6j+DAkEAijfXeB1l2AcWnmOm4kV/Grq2glSt0wDXW0SMS1VFu4sLKdeBGeU
  BUbvlc7TKirEpdry89aZ6BNKjCqBzDM2BSQJAXL+lpUV8ohuBue9f9ImpjmzcsgiqfvA4
  xSyS7ODQULlfA08PVShDjn9uxFeyRKohqPm8iOgodtk9WL9DyQshOQJAAcMBrlXisTXx9
  +6EzQHUeVR3kD5D/xy/OOgZIP44x3Y72bilCPhSBHoJbXFITjYgeuKXnjjs/l5fQP7fAwduMg==`,
"pubKey": `CAASogEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKMDfgSRPZdoz2+X+YJ+ElpGcD2XgahORaaG75KuviRPLLS6OuUwxxQpEpgowSDvioFIkOUP4kHfY0wSg8LttuRHKanAsaAIbEvhd+tdTzJy6uiIKyps8zswZnI/e+sCbjPJVARgY93q5QQmV5/n5BHK3M5nHxVh1YA+cGzExI2PAgMBAAE=`
  }

  waterfall([
(cb) => PeerInfo.create(peerId,cb),
(peerInfo, cb) => {
  peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/5000')
  node = new MyBundle({
    peerInfo
  })
  node.start(cb)
}
  ], (err) => callback(err, node))
}

parallel([
  (cb) => createNode(cb),
], (err, nodes) => {
  if (err) { throw err }

  const node1 = nodes[0]

  node1.on('peer:connect', (peer) => {
  console.log('connected:');
}
  );

  node1.on('peer:discovery', (peer) => {
console.log('discover:');
  }
);

  parallel([
(cb) => setTimeout(cb, 10000)
  ], (err) => {
if (err) { throw err }
console.log(node1.stats.peers())

// node1.peerRouting.findPeer(, (err, peer) => {
//   if (err) { throw err }

//   console.log('Found it, multiaddrs are:')
//   peer.multiaddrs.forEach((ma) => console.log(ma.toString()))
// })
  })
})
Code N2
/* eslint-disable no-console */
'use strict'
const PeerId = require('peer-id')
const libp2p = require('../../')
const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const KadDHT = require('libp2p-kad-dht')
const defaultsDeep = require('@nodeutils/defaults-deep')
const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const MulticastDNS = require('libp2p-mdns')
const multiaddr = require('multiaddr')

let node2 = '';

class MyBundle extends libp2p {
  constructor (_options) {
    const defaults = {
      modules: {
        transport: [ TCP ],
        streamMuxer: [ Mplex ],
        connEncryption: [ SECIO ],
        // we add the DHT module that will enable Peer and Content Routing
        dht: KadDHT,
        // peerDiscovery: [ MulticastDNS ],
      },
      config: {
        dht: {
          enabled: false,
          kBucketSize: 20
        },
        relay: {                      // Circuit Relay options
          enabled: true,
          hop: {
            enabled: false,
            active: false
          }
        },
        // peerDiscovery: {
        //   autoDial: true,      
        //   mdns: {
        //     interval: 20e3,
        //     enabled: true
        //   }
        // },
      }
    }

    super(defaultsDeep(_options, defaults))
  }
}

function createNode (callback) {
  let node
  let peerId = {
    "id": "QmYvXgyzjLEvLyA98JK92uYuMX4Y5KhvhmtqgAzQ95h7UN",
    "privKey": `CAAS4wQwggJfAgEAAoGBANg2caIFmqLT2s23ac4Y8Zi
  wnkbs2h7TYCr9C12G0TFM3W2cQ6nAOCUwrrARPWXfdGuUoik1BGA8GCBz
  XwfQUqt21FI0BGBZ1Mh7KT9tjToXdmifWPPs8JwZDOTDtCgNWRScB17L9
  2rQ84/ufDi1pj5mw29TdR0lz8WPkxWu0719AgMBAAECgYEAmYG+F+ymp6
  iGlrv8EOnAzknHdk+/ZVdp1dum8BZB/CC4rZPermzc7/qqbDMxRlzqSV9
  T6rHLk4/XCWMgO2n65ped09/Tr6MJaFOo4Wu6SSRJCiCeRS4RYy2V2Pmc
  Dfq8QLf2GiFJiVXg1EPl/s+8xgiH467OnltZTgM2I+Q/qcECQQD2eRtz4
  /f3hF0HTH3SEPaLqiI9otH7X8MoKuAqIlvIrw5FqpWSFBJZJQvGIAm9DM
  HfagGBgL3tXuAroF/KSdQlAkEA4JHnotkpe7GeVq9cOjQm8cdgQ6ASRcY
  N4psCIIYPLVXLd3T4uKQX2MUeSvcT+Dd6aKka8qI+yvqAEOFzYm8YeQJB
  AOKJdZ4TDjrFweuPdqW5SaIdAdO871soLWuh3N9dLRdLLscBfvAA2sxsr
  GGx2MGWFCuQd0ncVrTx2wC+Ksz3BrECQQDF6TAn/5Skk1OE98Si8uVDfT
  9kOcUAwtvn0k4claj4fjzziR3Ns6fkfUwGKxvpTBNP+4BpRv1p6zxEJDyJCnmZAkEAm/kbB1P8GSvZuQ98T1bPv9drR25f2A1FRdVD6tJ/U2Na9qVWA7Ioxz72pC+80HJ/Q/05BE3JCuPWLE43pw3SMg==`,
    "pubKey": "CAASogEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANg2caIFmqLT2s23ac4Y8Ziwnkbs2h7TYCr9C12G0TFM3W2cQ6nAOCUwrrARPWXfdGuUoik1BGA8GCBzXwfQUqt21FI0BGBZ1Mh7KT9tjToXdmifWPPs8JwZDOTDtCgNWRScB17L92rQ84/ufDi1pj5mw29TdR0lz8WPkxWu0719AgMBAAE="
  }

  waterfall([
    (cb) => PeerInfo.create(peerId, cb),
    (peerInfo, cb) => {
      peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/5002')
      node = new MyBundle({
        peerInfo
      })
      
      node.start(cb)
     
    }
  ], (err) => callback(err, node))
}

parallel([
  (cb) => createNode(cb),
], (err, nodes) => {
  if (err) { throw err }

  const node1 = nodes[0]

  node1.on('peer:discovery', (peer) => {
      console.log('Discovered');
    }
  );

  node1.on('peer:connect', (peer) => {
    console.log('connect');
    node2 = peer.id;
    node1.stats.emit('update')
    console.log(node1.stats.peers())
  });

  

  setTimeout(() => {
    const addr = multiaddr('/ip4/127.0.0.1/tcp/5000/p2p/QmTjVr1nFZNKLQvZBYmathCDUnuYWJHuSdWfjPzcX5n6jB')
  node1.dial(addr, (err, info) => console.log('connected'))
  }, 5000)
})
Code N3
/* eslint-disable no-console */
'use strict'

const libp2p = require('../../')
const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr')
const MulticastDNS = require('libp2p-mdns')
const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const defaultsDeep = require('@nodeutils/defaults-deep')
const PeerId = require('peer-id')

class MyBundle extends libp2p {
  constructor (_options) {
    const defaults = {
      modules: {
        transport: [ TCP ],
        streamMuxer: [ Mplex ],
        connEncryption: [ SECIO ],
        peerDiscovery: [ MulticastDNS ]
      },
      config: {
        relay: {                      // Circuit Relay options
          enabled: true,
          hop: {
            enabled: false,
            active: false
          }
        },
      }
    }

    super(defaultsDeep(_options, defaults))
  }
}

function createNode (callback) {
  let node
  let peerId = {
    "id": "QmRj9KEa2PUzafH5wmseRTdHN9jSGZ8riZmRuy7c8M4j1Q",
    "privKey": `CAAS4gQwggJeAgEAAoGBALsZWHXj84YE
  dakdVt9ajOaLLeP75FOk5VxRotSFOYK0xbFnO8tC6USZ1Z
  5OJQYbQcTD19h/LwNiTss8uEVeOX29aX6eS1s9DWrztKLp
  G4r/N8EtCXbeFu/BcXvlIhLdII3jhAqX7DotNX7+xOZ74G
  MuJrwGLL03WBO8wxUEejsxAgMBAAECgYEAqj5wyKzHnO2X
  5m7k6k1poimIc0dzxkxnyy4ZPMmQwAcfT8JAnT5gJWTZBL
  fUZo8MtC8Dy2JG9AxS6AlzHuOS6O7VO3nSUq4wLJEFVbEI
  vdfog+R0Jlsw5q+6OyuJBdaSnl5Ie1xIWBJto05Tk/iZ9M
  WekJK6cRqFGZF5G5lOGjUCQQD3axdZaPQS5BnrDnJOPRfW
  yb9GEVuEQpAs5qRvJV4Z/MOHTrcbqLyxA+T4oGMgImqCxI
  fslaZf2Vrwc6s49kH7AkEAwZaoxBj1qW8ypLFxXuhlpkv3
  I9afcnCX6vsScCb35ZJHGaJfSr3hRD2zRDxqM3hv7/UUsRDkotzlOARMtWmbwwJBAJwThFE0sfNQzUDIhjbwtx8ZeX276V1PmB+bB1PN4MTH/JhYgY4DLbUE3eYxVxaoX0RKsev+o0uHk6RnczWlsw0CQHUczqYrL1q8IZgOnLY8w1nSNQWiTj1uLgmCsEnW2Tsxvf+dAib2LfQZm3yZS+otXxJ8YnMn9BkupyC3QSyyYf8CQQCeXST41NIF8vAYU0ZJruj6974GlT7r7Dfc5s89izLRCM+pJrzWjPsoPIhNyQ++j4ZlnK78xU3n4OyDNRz4E4XK`,
    "pubKey": "CAASogEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsZWHXj84YEdakdVt9ajOaLLeP75FOk5VxRotSFOYK0xbFnO8tC6USZ1Z5OJQYbQcTD19h/LwNiTss8uEVeOX29aX6eS1s9DWrztKLpG4r/N8EtCXbeFu/BcXvlIhLdII3jhAqX7DotNX7+xOZ74GMuJrwGLL03WBO8wxUEejsxAgMBAAE="
  }

  waterfall([
    (cb) => PeerInfo.create(peerId, cb),
    (peerInfo, cb) => {
      peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/5003')
      node = new MyBundle({
        peerInfo
      })
      node.start(cb)
      node.stats.computeThrottleTimeout = 100
    }
  ], (err) => callback(err, node))
}

parallel([
  (cb) => createNode(cb),
], (err, nodes) => {
  if (err) { throw err }

  const node1 = nodes[0]

  node1.on('peer:connect', (peer) => {
    console.log('connect');
  });


  const addr = multiaddr('/ip4/127.0.0.1/tcp/5002/p2p/QmYvXgyzjLEvLyA98JK92uYuMX4Y5KhvhmtqgAzQ95h7UN')
  node1.dial(addr, (err, info) => console.log('connected'))
})

There are several ways you could do this. Do you have something specific in mind that you’re trying to accomplish? The goal would help determine the best way to do that.

My plan is to create a distributed network and I hope that libp2p can help me.
Each node can generate some data and this data should be sent in the network via a socket connection. The main proposal is to use topology like this to reduce network connections (right now I have p2p topology, each node connected to each one via sockets)

What I want to do:

@jacobheun

What I have right now:

Depending on the type/size of data you’re trying to communicate there are different ways about going about this.

Exchanging Small Datasets

If you need to exchange small amount of data and send that across the network to all of your peers, this is something that Gossipsub is ideal for, as it will limit the number of peers you need to connect to, to broadcast to your network. There is an implementation in JS at ChainSafe/gossipsub-js that is close to being finished. You could leverage floodsub in the interim, as the transition should be simple once Gossipsub is ready. Adding https://github.com/libp2p/js-libp2p/blob/v0.25.4/examples/pubsub/1.js#L31-L33 to your node configs will allow you to leverage the libp2p.pubsub endpoints.

Exchanging Larger Datasets

If you need to exchange larger data sets, pubsub is not the way to do this, as it’s very inefficient doing so. However, you can leverage pubsub to notify peers about the existence of the data and then leverage direct connections to pull that data as needed.

1 Like

@jacobheun Thanks for the answer.

This is a kind of network, that can allow you to send any data, so it can be used for large datasets too.

I have a way how to send data via a network, but I don’t have enough experience with libp2p to create such a distributed network. Maybe you have some code example of how to make that topology?

Libp2p does support the topology you’re looking at, although not to that degree of cleanliness. When you have a lower number of nodes on the network, your nodes will likely be able to connect to all them, which is why you’ll see what you currently have. However, as the connection limits are exceeded, the network is naturally going to prune connections that are seeing less activity.

Networks are currently pretty reliant on a Bootstrap node to join, so you will most likely see the largest number of connections going there. Below is a local example where I have explicitly limited nodes to 1-4 peers, except for a Bootstrap node, so you can get a better idea what this might look like scaled. Depending on your use cases, nodes may have upwards of 50 (browser) - 300+ connected peers.