package main import ( "bytes" "context" "encoding/json" "fmt" "github.com/filecoin-project/lotus/build" "github.com/ipfs/go-car" "github.com/ipfs/go-datastore" blockstore "github.com/ipfs/go-ipfs-blockstore" "net/http" "strings" rice "github.com/GeertJohan/go.rice" "github.com/gorilla/websocket" "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p-core/peer" pnet "github.com/libp2p/go-libp2p-pnet" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/filecoin-project/lotus/node/modules/lp2p" ) var topic = "/fil/headnotifs/" func init() { genBytes := build.MaybeGenesis() bs := blockstore.NewBlockstore(datastore.NewMapDatastore()) c, err := car.LoadCar(bs, bytes.NewReader(genBytes)) if err != nil { panic(err) } if len(c.Roots) != 1 { panic("expected genesis file to have one root") } fmt.Printf("Genesis CID: %s\n", c.Roots[0]) topic = topic + c.Roots[0].String() } var upgrader = websocket.Upgrader{ WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, } func main() { ctx := context.Background() protec, err := pnet.NewProtector(strings.NewReader(lp2p.LotusKey)) if err != nil { panic(err) } host, err := libp2p.New( ctx, libp2p.Defaults, libp2p.PrivateNetwork(protec), ) if err != nil { panic(err) } ps, err := pubsub.NewGossipSub(ctx, host) if err != nil { panic(err) } pi, err := build.BuiltinBootstrap() if err != nil { panic(err) } if err := host.Connect(ctx, pi[0]); err != nil { panic(err) } http.HandleFunc("/sub", handler(ps)) http.Handle("/", http.FileServer(rice.MustFindBox("townhall/build").HTTPBox())) fmt.Println("listening on http://localhost:2975") if err := http.ListenAndServe("0.0.0.0:2975", nil); err != nil { panic(err) } } type update struct { From peer.ID Update json.RawMessage } func handler(ps *pubsub.PubSub) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") if r.Header.Get("Sec-WebSocket-Protocol") != "" { w.Header().Set("Sec-WebSocket-Protocol", r.Header.Get("Sec-WebSocket-Protocol")) } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } sub, err := ps.Subscribe(topic) if err != nil { return } for { msg, err := sub.Next(r.Context()) if err != nil { return } fmt.Println(msg) if err := conn.WriteJSON(update{ From: peer.ID(msg.From), Update: msg.Data, }); err != nil { return } } } }