gossip-relay

command
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2024 License: Apache-2.0, MIT Imports: 9 Imported by: 0

README

Table of Contents

Drand Pubsub Relay

A program that relays drand randomness rounds over libp2p pubsub (gossipsub) from a gRPC, HTTP, or gossipsub source (labeled as drand gossipsub relay in this diagram):

              +-------------------------------+
              |                               |
              |         drand server          |
              |                               |
              +-------------------------------+
              |  gRPC API   |--|   HTTP API   |
              +------^-+------------^-+-------+
                     | |            | |
                     | |            | |
                     | |            | |
                  +--+-v------------+-v---+
                  | drand gossipsub relay |
                  +----------+------------+
                             |
                             |
Publish topic=/drand/pubsub/v0.0.0/<chain-hash> data={randomness}
                             |
                             |
                 +-----------v--------------+
                 |                          |
                 | libp2p gossipsub network |
                 |                          |
                 +--+--------------------+--+
                    |                    |
                    |                    |
        Subscribe topic=/drand/pubsub/v0.0.0/<chain-hash>
                    |                    |
                    |                    |
   +----------------v--------+   +-------v-----------------+
   | drand client WithPubsub |   | drand client WithPubsub |
   +-------------------------+   +-------------------------+

Install

# Clone this repo
git clone https://github.com/drand/go-clients.git
cd drand
# Build the executable
make relay-gossip-relay
# Outputs a `drand-relay-gossip-relay` executable to the current directory.

Usage

In general, you should specify either a -hash-list or -group-conf-list flag in order for your client to validate the randomness it receives is from the correct chain.

Note: You can provide multiple values to both -hash-list and-group-conf-list flags to support multiple beacons.

Relay gRPC

drand-relay-gossip-relay run -grpc-connect=127.0.0.1:3000 \
                       -cert=/path/to/grpc-drand-cert

If you do not have gRPC transport credentials, you can use the -insecure flag:

drand-relay-gossip-relay run -grpc-connect=127.0.0.1:3000 \
                       -insecure

Or, with a hashlist:

 drand-relay-gossip-relay run -grpc-connect=127.0.0.1:3000 \
                       -insecure \
                       -hash-list=6093f9e4320c285ac4aab50ba821cd5678ec7c5015d3d9d11ef89e2a99741e83,dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493

Relay HTTP

The gossip relay can also relay directly from an HTTP API. You can specify multiple endpoints to enable failover.

drand-relay-gossip-relay run -url=https://api.drand.sh \
                       -url=https://api2.drand.sh \
                       -hash-list=dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493

Relay Gossipsub

The gossip relay can also relay directly from other gossip relays. You can specify multiple peers to directly connect with. In this case, a group configuration file must be specified since there's no way to retrieve chain information over pubsub.

drand-relay-gossip-relay run -relay=/ip4/127.0.0.1/tcp/44544/p2p/QmPeerID0 \
                       -relay=/ip4/127.0.0.1/tcp/44545/p2p/QmPeerID1 \
                       -group-conf-list=/home/user/.drand/groups/drand_group.toml

Alternatively, you can provide URL(s) of HTTP API(s) that can be contacted to retrieve chain information. In this case we must provide the chain -hash to verify the information we retrieve is for the chain we expect (or provide the -insecure flag):

drand-relay-gossip-relay run -relay=/ip4/127.0.0.1/tcp/44544/p2p/QmPeerID0 \
                       -relay=/ip4/127.0.0.1/tcp/44545/p2p/QmPeerID1 \
                       -url=http://127.0.0.1:3002 \
                       -hash-list=6093f9e4320c285ac4aab50ba821cd5678ec7c5015d3d9d11ef89e2a99741e83

If you want to verify multiple networks, you can provide the -hash-list flag, e.g.:

drand-relay-gossip-relay run -relay=/ip4/127.0.0.1/tcp/44544/p2p/QmPeerID0 \
                       -relay=/ip4/127.0.0.1/tcp/44545/p2p/QmPeerID1 \
                       -url=http://127.0.0.1:3002 \
                       -hash-list=dbd506d6ef76e5f386f41c651dcb808c5bcbd75471cc4eafa3f4df7ad4e4c493,8990e7a9aaed2ffed73dbd7092123d6f289930540d7651336225dc172e51b2ce

Other options

Bootstrap peers

If there is a set of peers the gossip relay should connect with and stay connected to then the -peer-with flag can be used to specify one or more peer multiaddrs for this purpose.

Failover

The -url flag provides the URL(s) of alternative HTTP API endpoints that may be able to provide randomness in the event of a failure of the gRPC connection/libp2p pubsub network. Each randomness round is raced with the HTTP endpoints when it becomes available such that if gRPC or pubsub take too long to deliver the round it'll be provided over HTTP e.g.

drand-relay-gossip-relay run -grpc-connect=127.0.0.1:3000 \
                       -insecure \
                       -url=http://127.0.0.1:3102
drand-relay-gossip-relay run -relay=/ip4/127.0.0.1/tcp/44544/p2p/QmPeerID0 \
                       -relay=/ip4/127.0.0.1/tcp/44545/p2p/QmPeerID1 \
                       -hash-list=6093f9e4320c285ac4aab50ba821cd5678ec7c5015d3d9d11ef89e2a99741e83 \
                       -url=http://127.0.0.1:3102
Configuring the libp2p pubsub node

Starting a relay will spawn a libp2p pubsub node listening on /ip4/0.0.0.0/tcp/44544 by default. Use the -listen flag to change. To effectively relay drand randomness, your node must be publicly accessible on the network.

If not specified a libp2p identity will be generated and stored in an identity.key file in the current working directory. Use the -identity flag to override the location.

Usage from a golang drand client

With Group TOML or Chain Info
package main

import (
	"context"
	"fmt"

	clock "github.com/jonboulle/clockwork"

	"github.com/drand/go-clients/client"
	p2pClient "github.com/drand/go-clients/client/lp2p"
	"github.com/drand/drand/v2/common/chain"
	"github.com/drand/drand/v2/common/log"
)

const (
	// listenAddr is the multiaddr the local libp2p node should listen on.
	listenAddr = "/ip4/0.0.0.0/tcp/4453"
	// relayP2PAddr is the p2p multiaddr of the drand gossipsub relay node to connect to.
	relayP2PAddr = "/ip4/192.168.1.124/tcp/44544/p2p/QmPeerID"
	// groupTOMLPath is the path to the group configuration information (in TOML format).
	groupTOMLPath = "/home/user/.drand/groups/drand_group.toml"
)

func main() {
	ctx := context.Background()
	l := log.DefaultLogger()
	clk := clock.NewRealClock()

	// Create libp2p pubsub
	ps, err := p2pClient.NewPubsub(ctx, listenAddr, relayP2PAddr)
	if err != nil {
		l.Panicw("while creating new p2pClient.NewPubsub", "err", err)
	}

	// Extract chain info from group TOML
	info, err := chain.InfoFromGroupTOML(l, groupTOMLPath)
	if err != nil {
		l.Panicw("while extracting info from groupTOML", "err", err)
	}

	c, err := client.New(ctx, l, p2pClient.WithPubsub(l, ps, clk, p2pClient.DefaultBufferSize), client.WithChainInfo(info))
	if err != nil {
		l.Panicw("while creating a new client", "err", err)
	}

	for res := range c.Watch(ctx) {
		fmt.Printf("round=%v randomness=%v\n", res.Round(), res.Randomness())
	}
}
With Known Chain Hash

You do not need to know the full group info to use the pubsub client if you know the chain hash and an HTTP endpoint then you can request the chain info from the HTTP endpoint, verifying it with the known chain hash:

package main

import (
  "context"
  "encoding/hex"
  "fmt"

  clock "github.com/jonboulle/clockwork"

  "github.com/drand/go-clients/client"
  "github.com/drand/go-clients/client/http"
  gclient "github.com/drand/go-clients/client/lp2p"
  "github.com/drand/drand/v2/common/log"
)

const (
  // listenAddr is the multiaddr the local libp2p node should listen on.
  listenAddr = "/ip4/0.0.0.0/tcp/4453"
  // relayP2PAddr is the p2p multiaddr of the drand gossipsub relay node to connect to.
  relayP2PAddr = "/ip4/192.168.1.124/tcp/44544/p2p/12D3KooWAe637xuWdRCYkuaZZce13P1F9zJX5gzGUPWZJpsUGUSH"
  // chainHash is a hash of the group chain information.
  chainHash = "c599c267a0dd386606f7d6132da8327d57e1004760897c9dd4fb8495c29942b2"
  // httpRelayURL is the URL of a drand HTTP API endpoint.
  httpRelayURL = "http://127.0.0.1:3002"
)

func main() {
  ctx := context.Background()
  lg := log.New(nil, log.DebugLevel, true)
  clk := clock.NewRealClock()

  // Create libp2p pubsub
  ps, err := gclient.NewPubsub(ctx, listenAddr, relayP2PAddr)
  if err != nil {
    panic(err)
  }

  // Chain hash is used to verify endpoints
  hash, err := hex.DecodeString(chainHash)
  if err != nil {
    panic(err)
  }

  c, err := client.New(ctx, lg,
    gclient.WithPubsub(lg, ps, clk, gclient.DefaultBufferSize),
    client.WithChainHash(hash),
    client.From(http.ForURLs(ctx, lg, []string{httpRelayURL}, hash)...),
  )
  if err != nil {
    panic(err)
  }

  for res := range c.Watch(ctx) {
    fmt.Printf("round=%v randomness=%v\n", res.Round(), res.Randomness())
  }
}

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL