cmd: add initial gossip pull
This commit is contained in:
parent
b4c108cc5c
commit
cddcfc155d
|
@ -0,0 +1,97 @@
|
||||||
|
// Pull downloads CRDS from a peer.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/rand"
|
||||||
|
"flag"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/certusone/radiance/pkg/gossip"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagAddr = flag.String("addr", "", "Address to ping (<host>:<port>)")
|
||||||
|
)
|
||||||
|
|
||||||
|
var target netip.AddrPort
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
klog.InitFlags(nil)
|
||||||
|
flag.Parse()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if *flagAddr == "" {
|
||||||
|
klog.Exit("No address specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
udpAddr, err := net.ResolveUDPAddr("udp", *flagAddr)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exitf("invalid target address: %s", err)
|
||||||
|
}
|
||||||
|
target = udpAddr.AddrPort()
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
_, identity, err := ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.ListenUDP("udp", nil)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exit(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pingClient := gossip.NewPingClient(identity, conn)
|
||||||
|
pingServer := gossip.NewPingServer(identity, conn)
|
||||||
|
pullClient := gossip.NewPullClient(identity, conn)
|
||||||
|
handler := &gossip.Handler{
|
||||||
|
PingClient: pingClient,
|
||||||
|
PingServer: pingServer,
|
||||||
|
PullClient: pullClient,
|
||||||
|
}
|
||||||
|
client := gossip.NewDriver(handler, conn)
|
||||||
|
|
||||||
|
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
|
||||||
|
defer cancel()
|
||||||
|
group, ctx := errgroup.WithContext(ctx)
|
||||||
|
group.Go(func() error {
|
||||||
|
return client.Run(ctx)
|
||||||
|
})
|
||||||
|
group.Go(func() error {
|
||||||
|
_, _, err := pingClient.Ping(ctx, target)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exitf("ping ignored: %s", err)
|
||||||
|
}
|
||||||
|
klog.Info("Pinged")
|
||||||
|
err = pullClient.Pull(target)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exitf("failed to send pull request: %s", err)
|
||||||
|
}
|
||||||
|
err = pullClient.Pull(target)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exitf("failed to send pull request: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
err = pullClient.Pull(target)
|
||||||
|
if err != nil {
|
||||||
|
klog.Exitf("failed to send pull request: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
return context.Canceled // done
|
||||||
|
})
|
||||||
|
_ = group.Wait()
|
||||||
|
_ = conn.Close()
|
||||||
|
}
|
2
go.mod
2
go.mod
|
@ -18,6 +18,7 @@ require (
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/twmb/franz-go v1.6.0
|
github.com/twmb/franz-go v1.6.0
|
||||||
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c
|
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c
|
||||||
google.golang.org/protobuf v1.28.1
|
google.golang.org/protobuf v1.28.1
|
||||||
k8s.io/klog/v2 v2.60.1
|
k8s.io/klog/v2 v2.60.1
|
||||||
|
@ -95,7 +96,6 @@ require (
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
|
||||||
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect
|
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
|
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb // indirect
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
|
|
||||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
|
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/tools v0.1.10 // indirect
|
golang.org/x/tools v0.1.10 // indirect
|
||||||
|
|
|
@ -14,6 +14,8 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MaxBloomSize = 928
|
||||||
|
|
||||||
func NewBloom(numBits uint64, keys []uint64) *Bloom {
|
func NewBloom(numBits uint64, keys []uint64) *Bloom {
|
||||||
bits := make([]uint64, (numBits+63)/64)
|
bits := make([]uint64, (numBits+63)/64)
|
||||||
ret := &Bloom{
|
ret := &Bloom{
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package gossip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ed25519"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const PacketSize = 1232
|
||||||
|
|
||||||
|
// PullClient implements the stateful client (initiator) side of the gossip pull protocol.
|
||||||
|
type PullClient struct {
|
||||||
|
identity ed25519.PrivateKey
|
||||||
|
so udpSender
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPullClient(identity ed25519.PrivateKey, so udpSender) *PullClient {
|
||||||
|
return &PullClient{
|
||||||
|
identity: identity,
|
||||||
|
so: so,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PullClient) Pull(target netip.AddrPort) error {
|
||||||
|
filters := NewCrdsFilterSet(65536, MaxBloomSize)
|
||||||
|
for _, filter := range filters {
|
||||||
|
if err := p.sendPullRequest(target, filter); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PullClient) sendPullRequest(target netip.AddrPort, filter CrdsFilter) error {
|
||||||
|
msg := &Message__PullRequest{
|
||||||
|
Filter: filter,
|
||||||
|
Value: CrdsValue{
|
||||||
|
Data: &CrdsData__ContactInfo{
|
||||||
|
Value: ContactInfo{
|
||||||
|
Wallclock: uint64(time.Now().UnixMilli()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
err := msg.Value.Sign(p.identity)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to sign pull request: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
packet, err := msg.BincodeSerialize()
|
||||||
|
if err != nil {
|
||||||
|
panic("failed to serialize packet: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = p.so.WriteToUDPAddrPort(packet, target)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PullClient) HandlePullResponse(msg *Message__PullResponse, _ netip.AddrPort) {
|
||||||
|
jsonBuf, _ := json.MarshalIndent(msg, "", "\t")
|
||||||
|
fmt.Println(string(jsonBuf))
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package gossip
|
||||||
|
|
||||||
|
import "github.com/gagliardetto/solana-go"
|
||||||
|
|
||||||
|
func (p Pubkey) MarshalText() ([]byte, error) {
|
||||||
|
return solana.PublicKey(p).MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hash) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(solana.Hash(h).String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Signature) MarshalText() ([]byte, error) {
|
||||||
|
return []byte(solana.Signature(s).String()), nil
|
||||||
|
}
|
Loading…
Reference in New Issue